From b0d2122583105ec3153dd1d16d9fe4057b0350a4 Mon Sep 17 00:00:00 2001 From: Christian Krueger Date: Wed, 27 Nov 2024 09:17:02 -0600 Subject: [PATCH] ixs almost done --- .../accounts/epochRewardRouter.ts | 4 + .../jito_tip_router/accounts/epochSnapshot.ts | 8 +- .../accounts/operatorEpochRewardRouter.ts | 4 + .../js/jito_tip_router/instructions/index.ts | 5 + .../initializeEpochRewardRouter.ts | 288 +++++++++ .../initializeOperatorEpochRewardRouter.ts | 309 +++++++++ .../instructions/processEpochRewardBuckets.ts | 248 +++++++ .../instructions/processEpochRewardPool.ts | 248 +++++++ .../processOperatorEpochRewardPool.ts | 267 ++++++++ .../jito_tip_router/programs/jitoTipRouter.ts | 42 +- .../generated/accounts/epoch_reward_router.rs | 1 + .../src/generated/accounts/epoch_snapshot.rs | 2 +- .../accounts/operator_epoch_reward_router.rs | 1 + .../initialize_epoch_reward_router.rs | 570 ++++++++++++++++ ...initialize_operator_epoch_reward_router.rs | 607 ++++++++++++++++++ .../src/generated/instructions/mod.rs | 15 +- .../process_epoch_reward_buckets.rs | 494 ++++++++++++++ .../instructions/process_epoch_reward_pool.rs | 497 ++++++++++++++ .../process_operator_epoch_reward_pool.rs | 539 ++++++++++++++++ core/src/ballot_box.rs | 12 +- core/src/epoch_reward_router.rs | 82 ++- core/src/epoch_snapshot.rs | 10 +- core/src/fees.rs | 54 +- core/src/instruction.rs | 41 +- core/src/operator_epoch_reward_router.rs | 47 ++ idl/jito_tip_router.json | 254 +++++++- program/src/lib.rs | 32 +- program/src/process_epoch_reward_buckets.rs | 51 ++ program/src/process_epoch_reward_pool.rs | 55 ++ .../src/process_operator_epoch_reward_pool.rs | 75 +++ 30 files changed, 4802 insertions(+), 60 deletions(-) create mode 100644 clients/js/jito_tip_router/instructions/initializeEpochRewardRouter.ts create mode 100644 clients/js/jito_tip_router/instructions/initializeOperatorEpochRewardRouter.ts create mode 100644 clients/js/jito_tip_router/instructions/processEpochRewardBuckets.ts create mode 100644 clients/js/jito_tip_router/instructions/processEpochRewardPool.ts create mode 100644 clients/js/jito_tip_router/instructions/processOperatorEpochRewardPool.ts create mode 100644 clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_reward_router.rs create mode 100644 clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_epoch_reward_router.rs create mode 100644 clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_buckets.rs create mode 100644 clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_pool.rs create mode 100644 clients/rust/jito_tip_router/src/generated/instructions/process_operator_epoch_reward_pool.rs create mode 100644 program/src/process_epoch_reward_buckets.rs create mode 100644 program/src/process_epoch_reward_pool.rs create mode 100644 program/src/process_operator_epoch_reward_pool.rs diff --git a/clients/js/jito_tip_router/accounts/epochRewardRouter.ts b/clients/js/jito_tip_router/accounts/epochRewardRouter.ts index 56a28d6..45c4716 100644 --- a/clients/js/jito_tip_router/accounts/epochRewardRouter.ts +++ b/clients/js/jito_tip_router/accounts/epochRewardRouter.ts @@ -52,6 +52,7 @@ export type EpochRewardRouter = { bump: number; slotCreated: bigint; rewardPool: bigint; + rewardsProcessed: bigint; doaRewards: bigint; reserved: Array; ncnRewardBuckets: Array; @@ -65,6 +66,7 @@ export type EpochRewardRouterArgs = { bump: number; slotCreated: number | bigint; rewardPool: number | bigint; + rewardsProcessed: number | bigint; doaRewards: number | bigint; reserved: Array; ncnRewardBuckets: Array; @@ -79,6 +81,7 @@ export function getEpochRewardRouterEncoder(): Encoder { ['bump', getU8Encoder()], ['slotCreated', getU64Encoder()], ['rewardPool', getU64Encoder()], + ['rewardsProcessed', getU64Encoder()], ['doaRewards', getU64Encoder()], ['reserved', getArrayEncoder(getU8Encoder(), { size: 128 })], [ @@ -97,6 +100,7 @@ export function getEpochRewardRouterDecoder(): Decoder { ['bump', getU8Decoder()], ['slotCreated', getU64Decoder()], ['rewardPool', getU64Decoder()], + ['rewardsProcessed', getU64Decoder()], ['doaRewards', getU64Decoder()], ['reserved', getArrayDecoder(getU8Decoder(), { size: 128 })], [ diff --git a/clients/js/jito_tip_router/accounts/epochSnapshot.ts b/clients/js/jito_tip_router/accounts/epochSnapshot.ts index 16f5aa5..df8e500 100644 --- a/clients/js/jito_tip_router/accounts/epochSnapshot.ts +++ b/clients/js/jito_tip_router/accounts/epochSnapshot.ts @@ -52,7 +52,7 @@ export type EpochSnapshot = { bump: number; slotCreated: bigint; slotFinalized: bigint; - ncnFees: Fees; + fees: Fees; operatorCount: bigint; vaultCount: bigint; operatorsRegistered: bigint; @@ -68,7 +68,7 @@ export type EpochSnapshotArgs = { bump: number; slotCreated: number | bigint; slotFinalized: number | bigint; - ncnFees: FeesArgs; + fees: FeesArgs; operatorCount: number | bigint; vaultCount: number | bigint; operatorsRegistered: number | bigint; @@ -85,7 +85,7 @@ export function getEpochSnapshotEncoder(): Encoder { ['bump', getU8Encoder()], ['slotCreated', getU64Encoder()], ['slotFinalized', getU64Encoder()], - ['ncnFees', getFeesEncoder()], + ['fees', getFeesEncoder()], ['operatorCount', getU64Encoder()], ['vaultCount', getU64Encoder()], ['operatorsRegistered', getU64Encoder()], @@ -103,7 +103,7 @@ export function getEpochSnapshotDecoder(): Decoder { ['bump', getU8Decoder()], ['slotCreated', getU64Decoder()], ['slotFinalized', getU64Decoder()], - ['ncnFees', getFeesDecoder()], + ['fees', getFeesDecoder()], ['operatorCount', getU64Decoder()], ['vaultCount', getU64Decoder()], ['operatorsRegistered', getU64Decoder()], diff --git a/clients/js/jito_tip_router/accounts/operatorEpochRewardRouter.ts b/clients/js/jito_tip_router/accounts/operatorEpochRewardRouter.ts index 241f073..aa298a8 100644 --- a/clients/js/jito_tip_router/accounts/operatorEpochRewardRouter.ts +++ b/clients/js/jito_tip_router/accounts/operatorEpochRewardRouter.ts @@ -49,6 +49,7 @@ export type OperatorEpochRewardRouter = { bump: number; slotCreated: bigint; rewardPool: bigint; + rewardsProcessed: bigint; operatorRewards: bigint; reserved: Array; vaultRewards: Array; @@ -62,6 +63,7 @@ export type OperatorEpochRewardRouterArgs = { bump: number; slotCreated: number | bigint; rewardPool: number | bigint; + rewardsProcessed: number | bigint; operatorRewards: number | bigint; reserved: Array; vaultRewards: Array; @@ -76,6 +78,7 @@ export function getOperatorEpochRewardRouterEncoder(): Encoder = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountBallotBox extends string | IAccountMeta = string, + TAccountEpochRewardRouter extends string | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountRestakingProgramId extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountBallotBox extends string + ? ReadonlyAccount + : TAccountBallotBox, + TAccountEpochRewardRouter extends string + ? ReadonlyAccount + : TAccountEpochRewardRouter, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountRestakingProgramId extends string + ? ReadonlyAccount + : TAccountRestakingProgramId, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type InitializeEpochRewardRouterInstructionData = { + discriminator: number; + firstSlotOfNcnEpoch: Option; +}; + +export type InitializeEpochRewardRouterInstructionDataArgs = { + firstSlotOfNcnEpoch: OptionOrNullable; +}; + +export function getInitializeEpochRewardRouterInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ]), + (value) => ({ + ...value, + discriminator: INITIALIZE_EPOCH_REWARD_ROUTER_DISCRIMINATOR, + }) + ); +} + +export function getInitializeEpochRewardRouterInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ]); +} + +export function getInitializeEpochRewardRouterInstructionDataCodec(): Codec< + InitializeEpochRewardRouterInstructionDataArgs, + InitializeEpochRewardRouterInstructionData +> { + return combineCodec( + getInitializeEpochRewardRouterInstructionDataEncoder(), + getInitializeEpochRewardRouterInstructionDataDecoder() + ); +} + +export type InitializeEpochRewardRouterInput< + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountBallotBox extends string = string, + TAccountEpochRewardRouter extends string = string, + TAccountPayer extends string = string, + TAccountRestakingProgramId extends string = string, + TAccountSystemProgram extends string = string, +> = { + restakingConfig: Address; + ncn: Address; + ballotBox: Address; + epochRewardRouter: Address; + payer: TransactionSigner; + restakingProgramId: Address; + systemProgram?: Address; + firstSlotOfNcnEpoch: InitializeEpochRewardRouterInstructionDataArgs['firstSlotOfNcnEpoch']; +}; + +export function getInitializeEpochRewardRouterInstruction< + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountBallotBox extends string, + TAccountEpochRewardRouter extends string, + TAccountPayer extends string, + TAccountRestakingProgramId extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: InitializeEpochRewardRouterInput< + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): InitializeEpochRewardRouterInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + ballotBox: { value: input.ballotBox ?? null, isWritable: false }, + epochRewardRouter: { + value: input.epochRewardRouter ?? null, + isWritable: false, + }, + payer: { value: input.payer ?? null, isWritable: true }, + restakingProgramId: { + value: input.restakingProgramId ?? 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.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.ballotBox), + getAccountMeta(accounts.epochRewardRouter), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.restakingProgramId), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getInitializeEpochRewardRouterInstructionDataEncoder().encode( + args as InitializeEpochRewardRouterInstructionDataArgs + ), + } as InitializeEpochRewardRouterInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedInitializeEpochRewardRouterInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + restakingConfig: TAccountMetas[0]; + ncn: TAccountMetas[1]; + ballotBox: TAccountMetas[2]; + epochRewardRouter: TAccountMetas[3]; + payer: TAccountMetas[4]; + restakingProgramId: TAccountMetas[5]; + systemProgram: TAccountMetas[6]; + }; + data: InitializeEpochRewardRouterInstructionData; +}; + +export function parseInitializeEpochRewardRouterInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedInitializeEpochRewardRouterInstruction { + if (instruction.accounts.length < 7) { + // 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: { + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + ballotBox: getNextAccount(), + epochRewardRouter: getNextAccount(), + payer: getNextAccount(), + restakingProgramId: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getInitializeEpochRewardRouterInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/initializeOperatorEpochRewardRouter.ts b/clients/js/jito_tip_router/instructions/initializeOperatorEpochRewardRouter.ts new file mode 100644 index 0000000..7af0bfe --- /dev/null +++ b/clients/js/jito_tip_router/instructions/initializeOperatorEpochRewardRouter.ts @@ -0,0 +1,309 @@ +/** + * 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, + getOptionDecoder, + getOptionEncoder, + 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 Option, + type OptionOrNullable, + type ReadonlyAccount, + type TransactionSigner, + type WritableSignerAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const INITIALIZE_OPERATOR_EPOCH_REWARD_ROUTER_DISCRIMINATOR = 11; + +export function getInitializeOperatorEpochRewardRouterDiscriminatorBytes() { + return getU8Encoder().encode( + INITIALIZE_OPERATOR_EPOCH_REWARD_ROUTER_DISCRIMINATOR + ); +} + +export type InitializeOperatorEpochRewardRouterInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountRestakingConfig extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountOperator extends string | IAccountMeta = string, + TAccountBallotBox extends string | IAccountMeta = string, + TAccountOperatorEpochRewardRouter extends + | string + | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountRestakingProgramId extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountOperator extends string + ? ReadonlyAccount + : TAccountOperator, + TAccountBallotBox extends string + ? ReadonlyAccount + : TAccountBallotBox, + TAccountOperatorEpochRewardRouter extends string + ? ReadonlyAccount + : TAccountOperatorEpochRewardRouter, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountRestakingProgramId extends string + ? ReadonlyAccount + : TAccountRestakingProgramId, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type InitializeOperatorEpochRewardRouterInstructionData = { + discriminator: number; + firstSlotOfNcnEpoch: Option; +}; + +export type InitializeOperatorEpochRewardRouterInstructionDataArgs = { + firstSlotOfNcnEpoch: OptionOrNullable; +}; + +export function getInitializeOperatorEpochRewardRouterInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ]), + (value) => ({ + ...value, + discriminator: INITIALIZE_OPERATOR_EPOCH_REWARD_ROUTER_DISCRIMINATOR, + }) + ); +} + +export function getInitializeOperatorEpochRewardRouterInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ]); +} + +export function getInitializeOperatorEpochRewardRouterInstructionDataCodec(): Codec< + InitializeOperatorEpochRewardRouterInstructionDataArgs, + InitializeOperatorEpochRewardRouterInstructionData +> { + return combineCodec( + getInitializeOperatorEpochRewardRouterInstructionDataEncoder(), + getInitializeOperatorEpochRewardRouterInstructionDataDecoder() + ); +} + +export type InitializeOperatorEpochRewardRouterInput< + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountOperator extends string = string, + TAccountBallotBox extends string = string, + TAccountOperatorEpochRewardRouter extends string = string, + TAccountPayer extends string = string, + TAccountRestakingProgramId extends string = string, + TAccountSystemProgram extends string = string, +> = { + restakingConfig: Address; + ncn: Address; + operator: Address; + ballotBox: Address; + operatorEpochRewardRouter: Address; + payer: TransactionSigner; + restakingProgramId: Address; + systemProgram?: Address; + firstSlotOfNcnEpoch: InitializeOperatorEpochRewardRouterInstructionDataArgs['firstSlotOfNcnEpoch']; +}; + +export function getInitializeOperatorEpochRewardRouterInstruction< + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountOperator extends string, + TAccountBallotBox extends string, + TAccountOperatorEpochRewardRouter extends string, + TAccountPayer extends string, + TAccountRestakingProgramId extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: InitializeOperatorEpochRewardRouterInput< + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountBallotBox, + TAccountOperatorEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): InitializeOperatorEpochRewardRouterInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountBallotBox, + TAccountOperatorEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + operator: { value: input.operator ?? null, isWritable: false }, + ballotBox: { value: input.ballotBox ?? null, isWritable: false }, + operatorEpochRewardRouter: { + value: input.operatorEpochRewardRouter ?? null, + isWritable: false, + }, + payer: { value: input.payer ?? null, isWritable: true }, + restakingProgramId: { + value: input.restakingProgramId ?? 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.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.operator), + getAccountMeta(accounts.ballotBox), + getAccountMeta(accounts.operatorEpochRewardRouter), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.restakingProgramId), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getInitializeOperatorEpochRewardRouterInstructionDataEncoder().encode( + args as InitializeOperatorEpochRewardRouterInstructionDataArgs + ), + } as InitializeOperatorEpochRewardRouterInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountBallotBox, + TAccountOperatorEpochRewardRouter, + TAccountPayer, + TAccountRestakingProgramId, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedInitializeOperatorEpochRewardRouterInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + restakingConfig: TAccountMetas[0]; + ncn: TAccountMetas[1]; + operator: TAccountMetas[2]; + ballotBox: TAccountMetas[3]; + operatorEpochRewardRouter: TAccountMetas[4]; + payer: TAccountMetas[5]; + restakingProgramId: TAccountMetas[6]; + systemProgram: TAccountMetas[7]; + }; + data: InitializeOperatorEpochRewardRouterInstructionData; +}; + +export function parseInitializeOperatorEpochRewardRouterInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedInitializeOperatorEpochRewardRouterInstruction< + TProgram, + TAccountMetas +> { + if (instruction.accounts.length < 8) { + // 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: { + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + operator: getNextAccount(), + ballotBox: getNextAccount(), + operatorEpochRewardRouter: getNextAccount(), + payer: getNextAccount(), + restakingProgramId: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getInitializeOperatorEpochRewardRouterInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/processEpochRewardBuckets.ts b/clients/js/jito_tip_router/instructions/processEpochRewardBuckets.ts new file mode 100644 index 0000000..6a50cb8 --- /dev/null +++ b/clients/js/jito_tip_router/instructions/processEpochRewardBuckets.ts @@ -0,0 +1,248 @@ +/** + * 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, + getOptionDecoder, + getOptionEncoder, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type Option, + type OptionOrNullable, + type ReadonlyAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const PROCESS_EPOCH_REWARD_BUCKETS_DISCRIMINATOR = 13; + +export function getProcessEpochRewardBucketsDiscriminatorBytes() { + return getU8Encoder().encode(PROCESS_EPOCH_REWARD_BUCKETS_DISCRIMINATOR); +} + +export type ProcessEpochRewardBucketsInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountRestakingConfig extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountBallotBox extends string | IAccountMeta = string, + TAccountEpochRewardRouter extends string | IAccountMeta = string, + TAccountRestakingProgramId extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountBallotBox extends string + ? ReadonlyAccount + : TAccountBallotBox, + TAccountEpochRewardRouter extends string + ? ReadonlyAccount + : TAccountEpochRewardRouter, + TAccountRestakingProgramId extends string + ? ReadonlyAccount + : TAccountRestakingProgramId, + ...TRemainingAccounts, + ] + >; + +export type ProcessEpochRewardBucketsInstructionData = { + discriminator: number; + firstSlotOfNcnEpoch: Option; +}; + +export type ProcessEpochRewardBucketsInstructionDataArgs = { + firstSlotOfNcnEpoch: OptionOrNullable; +}; + +export function getProcessEpochRewardBucketsInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ]), + (value) => ({ + ...value, + discriminator: PROCESS_EPOCH_REWARD_BUCKETS_DISCRIMINATOR, + }) + ); +} + +export function getProcessEpochRewardBucketsInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ]); +} + +export function getProcessEpochRewardBucketsInstructionDataCodec(): Codec< + ProcessEpochRewardBucketsInstructionDataArgs, + ProcessEpochRewardBucketsInstructionData +> { + return combineCodec( + getProcessEpochRewardBucketsInstructionDataEncoder(), + getProcessEpochRewardBucketsInstructionDataDecoder() + ); +} + +export type ProcessEpochRewardBucketsInput< + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountBallotBox extends string = string, + TAccountEpochRewardRouter extends string = string, + TAccountRestakingProgramId extends string = string, +> = { + restakingConfig: Address; + ncn: Address; + ballotBox: Address; + epochRewardRouter: Address; + restakingProgramId: Address; + firstSlotOfNcnEpoch: ProcessEpochRewardBucketsInstructionDataArgs['firstSlotOfNcnEpoch']; +}; + +export function getProcessEpochRewardBucketsInstruction< + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountBallotBox extends string, + TAccountEpochRewardRouter extends string, + TAccountRestakingProgramId extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ProcessEpochRewardBucketsInput< + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountRestakingProgramId + >, + config?: { programAddress?: TProgramAddress } +): ProcessEpochRewardBucketsInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountRestakingProgramId +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + ballotBox: { value: input.ballotBox ?? null, isWritable: false }, + epochRewardRouter: { + value: input.epochRewardRouter ?? null, + isWritable: false, + }, + restakingProgramId: { + value: input.restakingProgramId ?? null, + isWritable: false, + }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.ballotBox), + getAccountMeta(accounts.epochRewardRouter), + getAccountMeta(accounts.restakingProgramId), + ], + programAddress, + data: getProcessEpochRewardBucketsInstructionDataEncoder().encode( + args as ProcessEpochRewardBucketsInstructionDataArgs + ), + } as ProcessEpochRewardBucketsInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountBallotBox, + TAccountEpochRewardRouter, + TAccountRestakingProgramId + >; + + return instruction; +} + +export type ParsedProcessEpochRewardBucketsInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + restakingConfig: TAccountMetas[0]; + ncn: TAccountMetas[1]; + ballotBox: TAccountMetas[2]; + epochRewardRouter: TAccountMetas[3]; + restakingProgramId: TAccountMetas[4]; + }; + data: ProcessEpochRewardBucketsInstructionData; +}; + +export function parseProcessEpochRewardBucketsInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedProcessEpochRewardBucketsInstruction { + 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: { + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + ballotBox: getNextAccount(), + epochRewardRouter: getNextAccount(), + restakingProgramId: getNextAccount(), + }, + data: getProcessEpochRewardBucketsInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/processEpochRewardPool.ts b/clients/js/jito_tip_router/instructions/processEpochRewardPool.ts new file mode 100644 index 0000000..15319d3 --- /dev/null +++ b/clients/js/jito_tip_router/instructions/processEpochRewardPool.ts @@ -0,0 +1,248 @@ +/** + * 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, + getOptionDecoder, + getOptionEncoder, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type Option, + type OptionOrNullable, + type ReadonlyAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const PROCESS_EPOCH_REWARD_POOL_DISCRIMINATOR = 12; + +export function getProcessEpochRewardPoolDiscriminatorBytes() { + return getU8Encoder().encode(PROCESS_EPOCH_REWARD_POOL_DISCRIMINATOR); +} + +export type ProcessEpochRewardPoolInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountRestakingConfig extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountEpochSnapshot extends string | IAccountMeta = string, + TAccountEpochRewardRouter extends string | IAccountMeta = string, + TAccountRestakingProgramId extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountEpochSnapshot extends string + ? ReadonlyAccount + : TAccountEpochSnapshot, + TAccountEpochRewardRouter extends string + ? ReadonlyAccount + : TAccountEpochRewardRouter, + TAccountRestakingProgramId extends string + ? ReadonlyAccount + : TAccountRestakingProgramId, + ...TRemainingAccounts, + ] + >; + +export type ProcessEpochRewardPoolInstructionData = { + discriminator: number; + firstSlotOfNcnEpoch: Option; +}; + +export type ProcessEpochRewardPoolInstructionDataArgs = { + firstSlotOfNcnEpoch: OptionOrNullable; +}; + +export function getProcessEpochRewardPoolInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ]), + (value) => ({ + ...value, + discriminator: PROCESS_EPOCH_REWARD_POOL_DISCRIMINATOR, + }) + ); +} + +export function getProcessEpochRewardPoolInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ]); +} + +export function getProcessEpochRewardPoolInstructionDataCodec(): Codec< + ProcessEpochRewardPoolInstructionDataArgs, + ProcessEpochRewardPoolInstructionData +> { + return combineCodec( + getProcessEpochRewardPoolInstructionDataEncoder(), + getProcessEpochRewardPoolInstructionDataDecoder() + ); +} + +export type ProcessEpochRewardPoolInput< + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountEpochSnapshot extends string = string, + TAccountEpochRewardRouter extends string = string, + TAccountRestakingProgramId extends string = string, +> = { + restakingConfig: Address; + ncn: Address; + epochSnapshot: Address; + epochRewardRouter: Address; + restakingProgramId: Address; + firstSlotOfNcnEpoch: ProcessEpochRewardPoolInstructionDataArgs['firstSlotOfNcnEpoch']; +}; + +export function getProcessEpochRewardPoolInstruction< + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountEpochSnapshot extends string, + TAccountEpochRewardRouter extends string, + TAccountRestakingProgramId extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ProcessEpochRewardPoolInput< + TAccountRestakingConfig, + TAccountNcn, + TAccountEpochSnapshot, + TAccountEpochRewardRouter, + TAccountRestakingProgramId + >, + config?: { programAddress?: TProgramAddress } +): ProcessEpochRewardPoolInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountEpochSnapshot, + TAccountEpochRewardRouter, + TAccountRestakingProgramId +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + epochSnapshot: { value: input.epochSnapshot ?? null, isWritable: false }, + epochRewardRouter: { + value: input.epochRewardRouter ?? null, + isWritable: false, + }, + restakingProgramId: { + value: input.restakingProgramId ?? null, + isWritable: false, + }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.epochSnapshot), + getAccountMeta(accounts.epochRewardRouter), + getAccountMeta(accounts.restakingProgramId), + ], + programAddress, + data: getProcessEpochRewardPoolInstructionDataEncoder().encode( + args as ProcessEpochRewardPoolInstructionDataArgs + ), + } as ProcessEpochRewardPoolInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountEpochSnapshot, + TAccountEpochRewardRouter, + TAccountRestakingProgramId + >; + + return instruction; +} + +export type ParsedProcessEpochRewardPoolInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + restakingConfig: TAccountMetas[0]; + ncn: TAccountMetas[1]; + epochSnapshot: TAccountMetas[2]; + epochRewardRouter: TAccountMetas[3]; + restakingProgramId: TAccountMetas[4]; + }; + data: ProcessEpochRewardPoolInstructionData; +}; + +export function parseProcessEpochRewardPoolInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedProcessEpochRewardPoolInstruction { + 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: { + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + epochSnapshot: getNextAccount(), + epochRewardRouter: getNextAccount(), + restakingProgramId: getNextAccount(), + }, + data: getProcessEpochRewardPoolInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/processOperatorEpochRewardPool.ts b/clients/js/jito_tip_router/instructions/processOperatorEpochRewardPool.ts new file mode 100644 index 0000000..acea2fc --- /dev/null +++ b/clients/js/jito_tip_router/instructions/processOperatorEpochRewardPool.ts @@ -0,0 +1,267 @@ +/** + * 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, + getOptionDecoder, + getOptionEncoder, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type Option, + type OptionOrNullable, + type ReadonlyAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const PROCESS_OPERATOR_EPOCH_REWARD_POOL_DISCRIMINATOR = 14; + +export function getProcessOperatorEpochRewardPoolDiscriminatorBytes() { + return getU8Encoder().encode( + PROCESS_OPERATOR_EPOCH_REWARD_POOL_DISCRIMINATOR + ); +} + +export type ProcessOperatorEpochRewardPoolInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountRestakingConfig extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountOperator extends string | IAccountMeta = string, + TAccountOperatorSnapshot extends string | IAccountMeta = string, + TAccountOperatorRewardRouter extends string | IAccountMeta = string, + TAccountRestakingProgramId extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountOperator extends string + ? ReadonlyAccount + : TAccountOperator, + TAccountOperatorSnapshot extends string + ? ReadonlyAccount + : TAccountOperatorSnapshot, + TAccountOperatorRewardRouter extends string + ? ReadonlyAccount + : TAccountOperatorRewardRouter, + TAccountRestakingProgramId extends string + ? ReadonlyAccount + : TAccountRestakingProgramId, + ...TRemainingAccounts, + ] + >; + +export type ProcessOperatorEpochRewardPoolInstructionData = { + discriminator: number; + firstSlotOfNcnEpoch: Option; +}; + +export type ProcessOperatorEpochRewardPoolInstructionDataArgs = { + firstSlotOfNcnEpoch: OptionOrNullable; +}; + +export function getProcessOperatorEpochRewardPoolInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ]), + (value) => ({ + ...value, + discriminator: PROCESS_OPERATOR_EPOCH_REWARD_POOL_DISCRIMINATOR, + }) + ); +} + +export function getProcessOperatorEpochRewardPoolInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ]); +} + +export function getProcessOperatorEpochRewardPoolInstructionDataCodec(): Codec< + ProcessOperatorEpochRewardPoolInstructionDataArgs, + ProcessOperatorEpochRewardPoolInstructionData +> { + return combineCodec( + getProcessOperatorEpochRewardPoolInstructionDataEncoder(), + getProcessOperatorEpochRewardPoolInstructionDataDecoder() + ); +} + +export type ProcessOperatorEpochRewardPoolInput< + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountOperator extends string = string, + TAccountOperatorSnapshot extends string = string, + TAccountOperatorRewardRouter extends string = string, + TAccountRestakingProgramId extends string = string, +> = { + restakingConfig: Address; + ncn: Address; + operator: Address; + operatorSnapshot: Address; + operatorRewardRouter: Address; + restakingProgramId: Address; + firstSlotOfNcnEpoch: ProcessOperatorEpochRewardPoolInstructionDataArgs['firstSlotOfNcnEpoch']; +}; + +export function getProcessOperatorEpochRewardPoolInstruction< + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountOperator extends string, + TAccountOperatorSnapshot extends string, + TAccountOperatorRewardRouter extends string, + TAccountRestakingProgramId extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ProcessOperatorEpochRewardPoolInput< + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountOperatorSnapshot, + TAccountOperatorRewardRouter, + TAccountRestakingProgramId + >, + config?: { programAddress?: TProgramAddress } +): ProcessOperatorEpochRewardPoolInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountOperatorSnapshot, + TAccountOperatorRewardRouter, + TAccountRestakingProgramId +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + operator: { value: input.operator ?? null, isWritable: false }, + operatorSnapshot: { + value: input.operatorSnapshot ?? null, + isWritable: false, + }, + operatorRewardRouter: { + value: input.operatorRewardRouter ?? null, + isWritable: false, + }, + restakingProgramId: { + value: input.restakingProgramId ?? null, + isWritable: false, + }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.operator), + getAccountMeta(accounts.operatorSnapshot), + getAccountMeta(accounts.operatorRewardRouter), + getAccountMeta(accounts.restakingProgramId), + ], + programAddress, + data: getProcessOperatorEpochRewardPoolInstructionDataEncoder().encode( + args as ProcessOperatorEpochRewardPoolInstructionDataArgs + ), + } as ProcessOperatorEpochRewardPoolInstruction< + TProgramAddress, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountOperatorSnapshot, + TAccountOperatorRewardRouter, + TAccountRestakingProgramId + >; + + return instruction; +} + +export type ParsedProcessOperatorEpochRewardPoolInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + restakingConfig: TAccountMetas[0]; + ncn: TAccountMetas[1]; + operator: TAccountMetas[2]; + operatorSnapshot: TAccountMetas[3]; + operatorRewardRouter: TAccountMetas[4]; + restakingProgramId: TAccountMetas[5]; + }; + data: ProcessOperatorEpochRewardPoolInstructionData; +}; + +export function parseProcessOperatorEpochRewardPoolInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedProcessOperatorEpochRewardPoolInstruction { + 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: { + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + operator: getNextAccount(), + operatorSnapshot: getNextAccount(), + operatorRewardRouter: getNextAccount(), + restakingProgramId: getNextAccount(), + }, + data: getProcessOperatorEpochRewardPoolInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/programs/jitoTipRouter.ts b/clients/js/jito_tip_router/programs/jitoTipRouter.ts index 8c44076..7d8aa4c 100644 --- a/clients/js/jito_tip_router/programs/jitoTipRouter.ts +++ b/clients/js/jito_tip_router/programs/jitoTipRouter.ts @@ -14,11 +14,16 @@ import { } from '@solana/web3.js'; import { type ParsedAdminUpdateWeightTableInstruction, + type ParsedInitializeEpochRewardRouterInstruction, type ParsedInitializeEpochSnapshotInstruction, type ParsedInitializeNCNConfigInstruction, + type ParsedInitializeOperatorEpochRewardRouterInstruction, type ParsedInitializeOperatorSnapshotInstruction, type ParsedInitializeTrackedMintsInstruction, type ParsedInitializeWeightTableInstruction, + type ParsedProcessEpochRewardBucketsInstruction, + type ParsedProcessEpochRewardPoolInstruction, + type ParsedProcessOperatorEpochRewardPoolInstruction, type ParsedRegisterMintInstruction, type ParsedSetConfigFeesInstruction, type ParsedSetNewAdminInstruction, @@ -50,6 +55,11 @@ export enum JitoTipRouterInstruction { SnapshotVaultOperatorDelegation, RegisterMint, InitializeTrackedMints, + InitializeEpochRewardRouter, + InitializeOperatorEpochRewardRouter, + ProcessEpochRewardPool, + ProcessEpochRewardBuckets, + ProcessOperatorEpochRewardPool, } export function identifyJitoTipRouterInstruction( @@ -86,6 +96,21 @@ export function identifyJitoTipRouterInstruction( if (containsBytes(data, getU8Encoder().encode(9), 0)) { return JitoTipRouterInstruction.InitializeTrackedMints; } + if (containsBytes(data, getU8Encoder().encode(10), 0)) { + return JitoTipRouterInstruction.InitializeEpochRewardRouter; + } + if (containsBytes(data, getU8Encoder().encode(11), 0)) { + return JitoTipRouterInstruction.InitializeOperatorEpochRewardRouter; + } + if (containsBytes(data, getU8Encoder().encode(12), 0)) { + return JitoTipRouterInstruction.ProcessEpochRewardPool; + } + if (containsBytes(data, getU8Encoder().encode(13), 0)) { + return JitoTipRouterInstruction.ProcessEpochRewardBuckets; + } + if (containsBytes(data, getU8Encoder().encode(14), 0)) { + return JitoTipRouterInstruction.ProcessOperatorEpochRewardPool; + } throw new Error( 'The provided instruction could not be identified as a jitoTipRouter instruction.' ); @@ -123,4 +148,19 @@ export type ParsedJitoTipRouterInstruction< } & ParsedRegisterMintInstruction) | ({ instructionType: JitoTipRouterInstruction.InitializeTrackedMints; - } & ParsedInitializeTrackedMintsInstruction); + } & ParsedInitializeTrackedMintsInstruction) + | ({ + instructionType: JitoTipRouterInstruction.InitializeEpochRewardRouter; + } & ParsedInitializeEpochRewardRouterInstruction) + | ({ + instructionType: JitoTipRouterInstruction.InitializeOperatorEpochRewardRouter; + } & ParsedInitializeOperatorEpochRewardRouterInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ProcessEpochRewardPool; + } & ParsedProcessEpochRewardPoolInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ProcessEpochRewardBuckets; + } & ParsedProcessEpochRewardBucketsInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ProcessOperatorEpochRewardPool; + } & ParsedProcessOperatorEpochRewardPoolInstruction); diff --git a/clients/rust/jito_tip_router/src/generated/accounts/epoch_reward_router.rs b/clients/rust/jito_tip_router/src/generated/accounts/epoch_reward_router.rs index 04b564d..5a1c021 100644 --- a/clients/rust/jito_tip_router/src/generated/accounts/epoch_reward_router.rs +++ b/clients/rust/jito_tip_router/src/generated/accounts/epoch_reward_router.rs @@ -22,6 +22,7 @@ pub struct EpochRewardRouter { pub bump: u8, pub slot_created: u64, pub reward_pool: u64, + pub rewards_processed: u64, pub doa_rewards: u64, #[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))] pub reserved: [u8; 128], diff --git a/clients/rust/jito_tip_router/src/generated/accounts/epoch_snapshot.rs b/clients/rust/jito_tip_router/src/generated/accounts/epoch_snapshot.rs index a3d0959..5859d29 100644 --- a/clients/rust/jito_tip_router/src/generated/accounts/epoch_snapshot.rs +++ b/clients/rust/jito_tip_router/src/generated/accounts/epoch_snapshot.rs @@ -22,7 +22,7 @@ pub struct EpochSnapshot { pub bump: u8, pub slot_created: u64, pub slot_finalized: u64, - pub ncn_fees: Fees, + pub fees: Fees, pub operator_count: u64, pub vault_count: u64, pub operators_registered: u64, diff --git a/clients/rust/jito_tip_router/src/generated/accounts/operator_epoch_reward_router.rs b/clients/rust/jito_tip_router/src/generated/accounts/operator_epoch_reward_router.rs index bb6dc1a..74fe3ec 100644 --- a/clients/rust/jito_tip_router/src/generated/accounts/operator_epoch_reward_router.rs +++ b/clients/rust/jito_tip_router/src/generated/accounts/operator_epoch_reward_router.rs @@ -27,6 +27,7 @@ pub struct OperatorEpochRewardRouter { pub bump: u8, pub slot_created: u64, pub reward_pool: u64, + pub rewards_processed: u64, pub operator_rewards: u64, #[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))] pub reserved: [u8; 128], diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_reward_router.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_reward_router.rs new file mode 100644 index 0000000..f35e8ad --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_reward_router.rs @@ -0,0 +1,570 @@ +//! 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 InitializeEpochRewardRouter { + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub ballot_box: solana_program::pubkey::Pubkey, + + pub epoch_reward_router: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub restaking_program_id: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl InitializeEpochRewardRouter { + pub fn instruction( + &self, + args: InitializeEpochRewardRouterInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InitializeEpochRewardRouterInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + 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.ballot_box, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.epoch_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program_id, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InitializeEpochRewardRouterInstructionData::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 InitializeEpochRewardRouterInstructionData { + discriminator: u8, +} + +impl InitializeEpochRewardRouterInstructionData { + pub fn new() -> Self { + Self { discriminator: 10 } + } +} + +impl Default for InitializeEpochRewardRouterInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InitializeEpochRewardRouterInstructionArgs { + pub first_slot_of_ncn_epoch: Option, +} + +/// Instruction builder for `InitializeEpochRewardRouter`. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` ballot_box +/// 3. `[]` epoch_reward_router +/// 4. `[writable, signer]` payer +/// 5. `[]` restaking_program_id +/// 6. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct InitializeEpochRewardRouterBuilder { + restaking_config: Option, + ncn: Option, + ballot_box: Option, + epoch_reward_router: Option, + payer: Option, + restaking_program_id: Option, + system_program: Option, + first_slot_of_ncn_epoch: Option, + __remaining_accounts: Vec, +} + +impl InitializeEpochRewardRouterBuilder { + pub fn new() -> Self { + Self::default() + } + #[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 ballot_box(&mut self, ballot_box: solana_program::pubkey::Pubkey) -> &mut Self { + self.ballot_box = Some(ballot_box); + self + } + #[inline(always)] + pub fn epoch_reward_router( + &mut self, + epoch_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.epoch_reward_router = Some(epoch_reward_router); + 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_id( + &mut self, + restaking_program_id: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program_id = Some(restaking_program_id); + 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 + } + /// `[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); + 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 = InitializeEpochRewardRouter { + restaking_config: self.restaking_config.expect("restaking_config is not set"), + ncn: self.ncn.expect("ncn is not set"), + ballot_box: self.ballot_box.expect("ballot_box is not set"), + epoch_reward_router: self + .epoch_reward_router + .expect("epoch_reward_router is not set"), + payer: self.payer.expect("payer is not set"), + restaking_program_id: self + .restaking_program_id + .expect("restaking_program_id is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = InitializeEpochRewardRouterInstructionArgs { + first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `initialize_epoch_reward_router` CPI accounts. +pub struct InitializeEpochRewardRouterCpiAccounts<'a, 'b> { + pub restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `initialize_epoch_reward_router` CPI instruction. +pub struct InitializeEpochRewardRouterCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'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 ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InitializeEpochRewardRouterInstructionArgs, +} + +impl<'a, 'b> InitializeEpochRewardRouterCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: InitializeEpochRewardRouterCpiAccounts<'a, 'b>, + args: InitializeEpochRewardRouterInstructionArgs, + ) -> Self { + Self { + __program: program, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + ballot_box: accounts.ballot_box, + epoch_reward_router: accounts.epoch_reward_router, + payer: accounts.payer, + restaking_program_id: accounts.restaking_program_id, + 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(7 + remaining_accounts.len()); + 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.ballot_box.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.epoch_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program_id.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 = InitializeEpochRewardRouterInstructionData::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(7 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.ballot_box.clone()); + account_infos.push(self.epoch_reward_router.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.restaking_program_id.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 `InitializeEpochRewardRouter` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` ballot_box +/// 3. `[]` epoch_reward_router +/// 4. `[writable, signer]` payer +/// 5. `[]` restaking_program_id +/// 6. `[]` system_program +#[derive(Clone, Debug)] +pub struct InitializeEpochRewardRouterCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitializeEpochRewardRouterCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitializeEpochRewardRouterCpiBuilderInstruction { + __program: program, + restaking_config: None, + ncn: None, + ballot_box: None, + epoch_reward_router: None, + payer: None, + restaking_program_id: None, + system_program: None, + first_slot_of_ncn_epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[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 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 epoch_reward_router( + &mut self, + epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.epoch_reward_router = Some(epoch_reward_router); + 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_id( + &mut self, + restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program_id = Some(restaking_program_id); + 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 + } + /// `[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); + 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 = InitializeEpochRewardRouterInstructionArgs { + first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + }; + let instruction = InitializeEpochRewardRouterCpi { + __program: self.instruction.__program, + + restaking_config: self + .instruction + .restaking_config + .expect("restaking_config is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + ballot_box: self.instruction.ballot_box.expect("ballot_box is not set"), + + epoch_reward_router: self + .instruction + .epoch_reward_router + .expect("epoch_reward_router is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + restaking_program_id: self + .instruction + .restaking_program_id + .expect("restaking_program_id 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 InitializeEpochRewardRouterCpiBuilderInstruction<'a, 'b> { + __program: &'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>>, + ballot_box: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program_id: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + first_slot_of_ncn_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/initialize_operator_epoch_reward_router.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_epoch_reward_router.rs new file mode 100644 index 0000000..9cffb6f --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_epoch_reward_router.rs @@ -0,0 +1,607 @@ +//! 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 InitializeOperatorEpochRewardRouter { + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub operator: solana_program::pubkey::Pubkey, + + pub ballot_box: solana_program::pubkey::Pubkey, + + pub operator_epoch_reward_router: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub restaking_program_id: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl InitializeOperatorEpochRewardRouter { + pub fn instruction( + &self, + args: InitializeOperatorEpochRewardRouterInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InitializeOperatorEpochRewardRouterInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + 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.ballot_box, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.operator_epoch_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program_id, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InitializeOperatorEpochRewardRouterInstructionData::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 InitializeOperatorEpochRewardRouterInstructionData { + discriminator: u8, +} + +impl InitializeOperatorEpochRewardRouterInstructionData { + pub fn new() -> Self { + Self { discriminator: 11 } + } +} + +impl Default for InitializeOperatorEpochRewardRouterInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InitializeOperatorEpochRewardRouterInstructionArgs { + pub first_slot_of_ncn_epoch: Option, +} + +/// Instruction builder for `InitializeOperatorEpochRewardRouter`. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` operator +/// 3. `[]` ballot_box +/// 4. `[]` operator_epoch_reward_router +/// 5. `[writable, signer]` payer +/// 6. `[]` restaking_program_id +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct InitializeOperatorEpochRewardRouterBuilder { + restaking_config: Option, + ncn: Option, + operator: Option, + ballot_box: Option, + operator_epoch_reward_router: Option, + payer: Option, + restaking_program_id: Option, + system_program: Option, + first_slot_of_ncn_epoch: Option, + __remaining_accounts: Vec, +} + +impl InitializeOperatorEpochRewardRouterBuilder { + pub fn new() -> Self { + Self::default() + } + #[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 ballot_box(&mut self, ballot_box: solana_program::pubkey::Pubkey) -> &mut Self { + self.ballot_box = Some(ballot_box); + self + } + #[inline(always)] + pub fn operator_epoch_reward_router( + &mut self, + operator_epoch_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.operator_epoch_reward_router = Some(operator_epoch_reward_router); + 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_id( + &mut self, + restaking_program_id: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program_id = Some(restaking_program_id); + 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 + } + /// `[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); + 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 = InitializeOperatorEpochRewardRouter { + 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"), + ballot_box: self.ballot_box.expect("ballot_box is not set"), + operator_epoch_reward_router: self + .operator_epoch_reward_router + .expect("operator_epoch_reward_router is not set"), + payer: self.payer.expect("payer is not set"), + restaking_program_id: self + .restaking_program_id + .expect("restaking_program_id is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = InitializeOperatorEpochRewardRouterInstructionArgs { + first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `initialize_operator_epoch_reward_router` CPI accounts. +pub struct InitializeOperatorEpochRewardRouterCpiAccounts<'a, 'b> { + 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 ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `initialize_operator_epoch_reward_router` CPI instruction. +pub struct InitializeOperatorEpochRewardRouterCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'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 ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InitializeOperatorEpochRewardRouterInstructionArgs, +} + +impl<'a, 'b> InitializeOperatorEpochRewardRouterCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: InitializeOperatorEpochRewardRouterCpiAccounts<'a, 'b>, + args: InitializeOperatorEpochRewardRouterInstructionArgs, + ) -> Self { + Self { + __program: program, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + operator: accounts.operator, + ballot_box: accounts.ballot_box, + operator_epoch_reward_router: accounts.operator_epoch_reward_router, + payer: accounts.payer, + restaking_program_id: accounts.restaking_program_id, + 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(8 + remaining_accounts.len()); + 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.ballot_box.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.operator_epoch_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program_id.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 = InitializeOperatorEpochRewardRouterInstructionData::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(8 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.operator.clone()); + account_infos.push(self.ballot_box.clone()); + account_infos.push(self.operator_epoch_reward_router.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.restaking_program_id.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 `InitializeOperatorEpochRewardRouter` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` operator +/// 3. `[]` ballot_box +/// 4. `[]` operator_epoch_reward_router +/// 5. `[writable, signer]` payer +/// 6. `[]` restaking_program_id +/// 7. `[]` system_program +#[derive(Clone, Debug)] +pub struct InitializeOperatorEpochRewardRouterCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitializeOperatorEpochRewardRouterCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitializeOperatorEpochRewardRouterCpiBuilderInstruction { + __program: program, + restaking_config: None, + ncn: None, + operator: None, + ballot_box: None, + operator_epoch_reward_router: None, + payer: None, + restaking_program_id: None, + system_program: None, + first_slot_of_ncn_epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[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 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 operator_epoch_reward_router( + &mut self, + operator_epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.operator_epoch_reward_router = Some(operator_epoch_reward_router); + 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_id( + &mut self, + restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program_id = Some(restaking_program_id); + 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 + } + /// `[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); + 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 = InitializeOperatorEpochRewardRouterInstructionArgs { + first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + }; + let instruction = InitializeOperatorEpochRewardRouterCpi { + __program: self.instruction.__program, + + 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"), + + ballot_box: self.instruction.ballot_box.expect("ballot_box is not set"), + + operator_epoch_reward_router: self + .instruction + .operator_epoch_reward_router + .expect("operator_epoch_reward_router is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + restaking_program_id: self + .instruction + .restaking_program_id + .expect("restaking_program_id 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 InitializeOperatorEpochRewardRouterCpiBuilderInstruction<'a, 'b> { + __program: &'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>>, + ballot_box: Option<&'b solana_program::account_info::AccountInfo<'a>>, + operator_epoch_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program_id: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + first_slot_of_ncn_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/mod.rs b/clients/rust/jito_tip_router/src/generated/instructions/mod.rs index 06b2b50..89ae137 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/mod.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/mod.rs @@ -5,19 +5,26 @@ //! pub(crate) mod r#admin_update_weight_table; +pub(crate) mod r#initialize_epoch_reward_router; pub(crate) mod r#initialize_epoch_snapshot; pub(crate) mod r#initialize_n_c_n_config; +pub(crate) mod r#initialize_operator_epoch_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#process_epoch_reward_buckets; +pub(crate) mod r#process_epoch_reward_pool; +pub(crate) mod r#process_operator_epoch_reward_pool; pub(crate) mod r#register_mint; pub(crate) mod r#set_config_fees; pub(crate) mod r#set_new_admin; pub(crate) mod r#snapshot_vault_operator_delegation; pub use self::{ - r#admin_update_weight_table::*, r#initialize_epoch_snapshot::*, r#initialize_n_c_n_config::*, - r#initialize_operator_snapshot::*, r#initialize_tracked_mints::*, r#initialize_weight_table::*, - r#register_mint::*, r#set_config_fees::*, r#set_new_admin::*, - r#snapshot_vault_operator_delegation::*, + r#admin_update_weight_table::*, r#initialize_epoch_reward_router::*, + r#initialize_epoch_snapshot::*, r#initialize_n_c_n_config::*, + r#initialize_operator_epoch_reward_router::*, r#initialize_operator_snapshot::*, + r#initialize_tracked_mints::*, r#initialize_weight_table::*, r#process_epoch_reward_buckets::*, + r#process_epoch_reward_pool::*, r#process_operator_epoch_reward_pool::*, r#register_mint::*, + r#set_config_fees::*, r#set_new_admin::*, r#snapshot_vault_operator_delegation::*, }; diff --git a/clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_buckets.rs b/clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_buckets.rs new file mode 100644 index 0000000..7307e31 --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_buckets.rs @@ -0,0 +1,494 @@ +//! 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 ProcessEpochRewardBuckets { + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub ballot_box: solana_program::pubkey::Pubkey, + + pub epoch_reward_router: solana_program::pubkey::Pubkey, + + pub restaking_program_id: solana_program::pubkey::Pubkey, +} + +impl ProcessEpochRewardBuckets { + pub fn instruction( + &self, + args: ProcessEpochRewardBucketsInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ProcessEpochRewardBucketsInstructionArgs, + 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.restaking_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ballot_box, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.epoch_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program_id, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ProcessEpochRewardBucketsInstructionData::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 ProcessEpochRewardBucketsInstructionData { + discriminator: u8, +} + +impl ProcessEpochRewardBucketsInstructionData { + pub fn new() -> Self { + Self { discriminator: 13 } + } +} + +impl Default for ProcessEpochRewardBucketsInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProcessEpochRewardBucketsInstructionArgs { + pub first_slot_of_ncn_epoch: Option, +} + +/// Instruction builder for `ProcessEpochRewardBuckets`. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` ballot_box +/// 3. `[]` epoch_reward_router +/// 4. `[]` restaking_program_id +#[derive(Clone, Debug, Default)] +pub struct ProcessEpochRewardBucketsBuilder { + restaking_config: Option, + ncn: Option, + ballot_box: Option, + epoch_reward_router: Option, + restaking_program_id: Option, + first_slot_of_ncn_epoch: Option, + __remaining_accounts: Vec, +} + +impl ProcessEpochRewardBucketsBuilder { + pub fn new() -> Self { + Self::default() + } + #[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 ballot_box(&mut self, ballot_box: solana_program::pubkey::Pubkey) -> &mut Self { + self.ballot_box = Some(ballot_box); + self + } + #[inline(always)] + pub fn epoch_reward_router( + &mut self, + epoch_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.epoch_reward_router = Some(epoch_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessEpochRewardBuckets { + restaking_config: self.restaking_config.expect("restaking_config is not set"), + ncn: self.ncn.expect("ncn is not set"), + ballot_box: self.ballot_box.expect("ballot_box is not set"), + epoch_reward_router: self + .epoch_reward_router + .expect("epoch_reward_router is not set"), + restaking_program_id: self + .restaking_program_id + .expect("restaking_program_id is not set"), + }; + let args = ProcessEpochRewardBucketsInstructionArgs { + first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `process_epoch_reward_buckets` CPI accounts. +pub struct ProcessEpochRewardBucketsCpiAccounts<'a, 'b> { + pub restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `process_epoch_reward_buckets` CPI instruction. +pub struct ProcessEpochRewardBucketsCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'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 ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ProcessEpochRewardBucketsInstructionArgs, +} + +impl<'a, 'b> ProcessEpochRewardBucketsCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ProcessEpochRewardBucketsCpiAccounts<'a, 'b>, + args: ProcessEpochRewardBucketsInstructionArgs, + ) -> Self { + Self { + __program: program, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + ballot_box: accounts.ballot_box, + epoch_reward_router: accounts.epoch_reward_router, + restaking_program_id: accounts.restaking_program_id, + __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.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.ballot_box.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.epoch_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program_id.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 = ProcessEpochRewardBucketsInstructionData::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.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.ballot_box.clone()); + account_infos.push(self.epoch_reward_router.clone()); + account_infos.push(self.restaking_program_id.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 `ProcessEpochRewardBuckets` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` ballot_box +/// 3. `[]` epoch_reward_router +/// 4. `[]` restaking_program_id +#[derive(Clone, Debug)] +pub struct ProcessEpochRewardBucketsCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ProcessEpochRewardBucketsCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ProcessEpochRewardBucketsCpiBuilderInstruction { + __program: program, + restaking_config: None, + ncn: None, + ballot_box: None, + epoch_reward_router: None, + restaking_program_id: None, + first_slot_of_ncn_epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[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 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 epoch_reward_router( + &mut self, + epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.epoch_reward_router = Some(epoch_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessEpochRewardBucketsInstructionArgs { + first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + }; + let instruction = ProcessEpochRewardBucketsCpi { + __program: self.instruction.__program, + + restaking_config: self + .instruction + .restaking_config + .expect("restaking_config is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + ballot_box: self.instruction.ballot_box.expect("ballot_box is not set"), + + epoch_reward_router: self + .instruction + .epoch_reward_router + .expect("epoch_reward_router is not set"), + + restaking_program_id: self + .instruction + .restaking_program_id + .expect("restaking_program_id is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ProcessEpochRewardBucketsCpiBuilderInstruction<'a, 'b> { + __program: &'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>>, + ballot_box: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program_id: Option<&'b solana_program::account_info::AccountInfo<'a>>, + first_slot_of_ncn_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/process_epoch_reward_pool.rs b/clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_pool.rs new file mode 100644 index 0000000..a324841 --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/process_epoch_reward_pool.rs @@ -0,0 +1,497 @@ +//! 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 ProcessEpochRewardPool { + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub epoch_snapshot: solana_program::pubkey::Pubkey, + + pub epoch_reward_router: solana_program::pubkey::Pubkey, + + pub restaking_program_id: solana_program::pubkey::Pubkey, +} + +impl ProcessEpochRewardPool { + pub fn instruction( + &self, + args: ProcessEpochRewardPoolInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ProcessEpochRewardPoolInstructionArgs, + 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.restaking_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.epoch_snapshot, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.epoch_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program_id, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ProcessEpochRewardPoolInstructionData::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 ProcessEpochRewardPoolInstructionData { + discriminator: u8, +} + +impl ProcessEpochRewardPoolInstructionData { + pub fn new() -> Self { + Self { discriminator: 12 } + } +} + +impl Default for ProcessEpochRewardPoolInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProcessEpochRewardPoolInstructionArgs { + pub first_slot_of_ncn_epoch: Option, +} + +/// Instruction builder for `ProcessEpochRewardPool`. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` epoch_snapshot +/// 3. `[]` epoch_reward_router +/// 4. `[]` restaking_program_id +#[derive(Clone, Debug, Default)] +pub struct ProcessEpochRewardPoolBuilder { + restaking_config: Option, + ncn: Option, + epoch_snapshot: Option, + epoch_reward_router: Option, + restaking_program_id: Option, + first_slot_of_ncn_epoch: Option, + __remaining_accounts: Vec, +} + +impl ProcessEpochRewardPoolBuilder { + pub fn new() -> Self { + Self::default() + } + #[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 epoch_snapshot(&mut self, epoch_snapshot: solana_program::pubkey::Pubkey) -> &mut Self { + self.epoch_snapshot = Some(epoch_snapshot); + self + } + #[inline(always)] + pub fn epoch_reward_router( + &mut self, + epoch_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.epoch_reward_router = Some(epoch_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessEpochRewardPool { + restaking_config: self.restaking_config.expect("restaking_config is not set"), + ncn: self.ncn.expect("ncn is not set"), + epoch_snapshot: self.epoch_snapshot.expect("epoch_snapshot is not set"), + epoch_reward_router: self + .epoch_reward_router + .expect("epoch_reward_router is not set"), + restaking_program_id: self + .restaking_program_id + .expect("restaking_program_id is not set"), + }; + let args = ProcessEpochRewardPoolInstructionArgs { + first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `process_epoch_reward_pool` CPI accounts. +pub struct ProcessEpochRewardPoolCpiAccounts<'a, 'b> { + pub restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `process_epoch_reward_pool` CPI instruction. +pub struct ProcessEpochRewardPoolCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'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 epoch_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ProcessEpochRewardPoolInstructionArgs, +} + +impl<'a, 'b> ProcessEpochRewardPoolCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ProcessEpochRewardPoolCpiAccounts<'a, 'b>, + args: ProcessEpochRewardPoolInstructionArgs, + ) -> Self { + Self { + __program: program, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + epoch_snapshot: accounts.epoch_snapshot, + epoch_reward_router: accounts.epoch_reward_router, + restaking_program_id: accounts.restaking_program_id, + __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.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.epoch_snapshot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.epoch_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program_id.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 = ProcessEpochRewardPoolInstructionData::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.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.epoch_snapshot.clone()); + account_infos.push(self.epoch_reward_router.clone()); + account_infos.push(self.restaking_program_id.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 `ProcessEpochRewardPool` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` epoch_snapshot +/// 3. `[]` epoch_reward_router +/// 4. `[]` restaking_program_id +#[derive(Clone, Debug)] +pub struct ProcessEpochRewardPoolCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ProcessEpochRewardPoolCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ProcessEpochRewardPoolCpiBuilderInstruction { + __program: program, + restaking_config: None, + ncn: None, + epoch_snapshot: None, + epoch_reward_router: None, + restaking_program_id: None, + first_slot_of_ncn_epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[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 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 epoch_reward_router( + &mut self, + epoch_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.epoch_reward_router = Some(epoch_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessEpochRewardPoolInstructionArgs { + first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + }; + let instruction = ProcessEpochRewardPoolCpi { + __program: self.instruction.__program, + + restaking_config: self + .instruction + .restaking_config + .expect("restaking_config is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + epoch_snapshot: self + .instruction + .epoch_snapshot + .expect("epoch_snapshot is not set"), + + epoch_reward_router: self + .instruction + .epoch_reward_router + .expect("epoch_reward_router is not set"), + + restaking_program_id: self + .instruction + .restaking_program_id + .expect("restaking_program_id is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ProcessEpochRewardPoolCpiBuilderInstruction<'a, 'b> { + __program: &'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>>, + epoch_snapshot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program_id: Option<&'b solana_program::account_info::AccountInfo<'a>>, + first_slot_of_ncn_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/process_operator_epoch_reward_pool.rs b/clients/rust/jito_tip_router/src/generated/instructions/process_operator_epoch_reward_pool.rs new file mode 100644 index 0000000..1675ae8 --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/process_operator_epoch_reward_pool.rs @@ -0,0 +1,539 @@ +//! 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 ProcessOperatorEpochRewardPool { + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub operator: solana_program::pubkey::Pubkey, + + pub operator_snapshot: solana_program::pubkey::Pubkey, + + pub operator_reward_router: solana_program::pubkey::Pubkey, + + pub restaking_program_id: solana_program::pubkey::Pubkey, +} + +impl ProcessOperatorEpochRewardPool { + pub fn instruction( + &self, + args: ProcessOperatorEpochRewardPoolInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ProcessOperatorEpochRewardPoolInstructionArgs, + 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.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.operator_snapshot, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.operator_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program_id, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ProcessOperatorEpochRewardPoolInstructionData::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 ProcessOperatorEpochRewardPoolInstructionData { + discriminator: u8, +} + +impl ProcessOperatorEpochRewardPoolInstructionData { + pub fn new() -> Self { + Self { discriminator: 14 } + } +} + +impl Default for ProcessOperatorEpochRewardPoolInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProcessOperatorEpochRewardPoolInstructionArgs { + pub first_slot_of_ncn_epoch: Option, +} + +/// Instruction builder for `ProcessOperatorEpochRewardPool`. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` operator +/// 3. `[]` operator_snapshot +/// 4. `[]` operator_reward_router +/// 5. `[]` restaking_program_id +#[derive(Clone, Debug, Default)] +pub struct ProcessOperatorEpochRewardPoolBuilder { + restaking_config: Option, + ncn: Option, + operator: Option, + operator_snapshot: Option, + operator_reward_router: Option, + restaking_program_id: Option, + first_slot_of_ncn_epoch: Option, + __remaining_accounts: Vec, +} + +impl ProcessOperatorEpochRewardPoolBuilder { + pub fn new() -> Self { + Self::default() + } + #[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 operator_snapshot( + &mut self, + operator_snapshot: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.operator_snapshot = Some(operator_snapshot); + self + } + #[inline(always)] + pub fn operator_reward_router( + &mut self, + operator_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.operator_reward_router = Some(operator_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessOperatorEpochRewardPool { + 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"), + operator_snapshot: self + .operator_snapshot + .expect("operator_snapshot is not set"), + operator_reward_router: self + .operator_reward_router + .expect("operator_reward_router is not set"), + restaking_program_id: self + .restaking_program_id + .expect("restaking_program_id is not set"), + }; + let args = ProcessOperatorEpochRewardPoolInstructionArgs { + first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `process_operator_epoch_reward_pool` CPI accounts. +pub struct ProcessOperatorEpochRewardPoolCpiAccounts<'a, 'b> { + 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 operator_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `process_operator_epoch_reward_pool` CPI instruction. +pub struct ProcessOperatorEpochRewardPoolCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'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 operator_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ProcessOperatorEpochRewardPoolInstructionArgs, +} + +impl<'a, 'b> ProcessOperatorEpochRewardPoolCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ProcessOperatorEpochRewardPoolCpiAccounts<'a, 'b>, + args: ProcessOperatorEpochRewardPoolInstructionArgs, + ) -> Self { + Self { + __program: program, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + operator: accounts.operator, + operator_snapshot: accounts.operator_snapshot, + operator_reward_router: accounts.operator_reward_router, + restaking_program_id: accounts.restaking_program_id, + __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.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.operator_snapshot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.operator_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program_id.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 = ProcessOperatorEpochRewardPoolInstructionData::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.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.operator.clone()); + account_infos.push(self.operator_snapshot.clone()); + account_infos.push(self.operator_reward_router.clone()); + account_infos.push(self.restaking_program_id.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 `ProcessOperatorEpochRewardPool` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` restaking_config +/// 1. `[]` ncn +/// 2. `[]` operator +/// 3. `[]` operator_snapshot +/// 4. `[]` operator_reward_router +/// 5. `[]` restaking_program_id +#[derive(Clone, Debug)] +pub struct ProcessOperatorEpochRewardPoolCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ProcessOperatorEpochRewardPoolCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ProcessOperatorEpochRewardPoolCpiBuilderInstruction { + __program: program, + restaking_config: None, + ncn: None, + operator: None, + operator_snapshot: None, + operator_reward_router: None, + restaking_program_id: None, + first_slot_of_ncn_epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[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 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 operator_reward_router( + &mut self, + operator_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.operator_reward_router = Some(operator_reward_router); + self + } + #[inline(always)] + pub fn restaking_program_id( + &mut self, + restaking_program_id: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program_id = Some(restaking_program_id); + 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); + 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 = ProcessOperatorEpochRewardPoolInstructionArgs { + first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + }; + let instruction = ProcessOperatorEpochRewardPoolCpi { + __program: self.instruction.__program, + + 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"), + + operator_snapshot: self + .instruction + .operator_snapshot + .expect("operator_snapshot is not set"), + + operator_reward_router: self + .instruction + .operator_reward_router + .expect("operator_reward_router is not set"), + + restaking_program_id: self + .instruction + .restaking_program_id + .expect("restaking_program_id is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ProcessOperatorEpochRewardPoolCpiBuilderInstruction<'a, 'b> { + __program: &'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>>, + operator_snapshot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + operator_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program_id: Option<&'b solana_program::account_info::AccountInfo<'a>>, + first_slot_of_ncn_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/core/src/ballot_box.rs b/core/src/ballot_box.rs index 036d335..7cecdd3 100644 --- a/core/src/ballot_box.rs +++ b/core/src/ballot_box.rs @@ -239,26 +239,26 @@ impl BallotBox { program_id: &Pubkey, ncn: &Pubkey, ncn_epoch: u64, - epoch_snapshot: &AccountInfo, + account: &AccountInfo, expect_writable: bool, ) -> Result<(), ProgramError> { - if epoch_snapshot.owner.ne(program_id) { + if account.owner.ne(program_id) { msg!("Ballot box account has an invalid owner"); return Err(ProgramError::InvalidAccountOwner); } - if epoch_snapshot.data_is_empty() { + if account.data_is_empty() { msg!("Ballot box account data is empty"); return Err(ProgramError::InvalidAccountData); } - if expect_writable && !epoch_snapshot.is_writable { + if expect_writable && !account.is_writable { msg!("Ballot box account is not writable"); return Err(ProgramError::InvalidAccountData); } - if epoch_snapshot.data.borrow()[0].ne(&Self::DISCRIMINATOR) { + if account.data.borrow()[0].ne(&Self::DISCRIMINATOR) { msg!("Ballot box account discriminator is invalid"); return Err(ProgramError::InvalidAccountData); } - if epoch_snapshot + if account .key .ne(&Self::find_program_address(program_id, ncn, ncn_epoch).0) { diff --git a/core/src/epoch_reward_router.rs b/core/src/epoch_reward_router.rs index 504cc8c..4bb7ebc 100644 --- a/core/src/epoch_reward_router.rs +++ b/core/src/epoch_reward_router.rs @@ -5,8 +5,8 @@ use solana_program::{account_info::AccountInfo, msg, program_error::ProgramError use spl_math::precise_number::PreciseNumber; use crate::{ - ballot_box::BallotBox, discriminators::Discriminators, error::TipRouterError, fees::FeeConfig, - ncn_fee_group::NcnFeeGroup, + ballot_box::BallotBox, discriminators::Discriminators, error::TipRouterError, fees::Fees, + ncn_fee_group::NcnFeeGroup, operator_epoch_reward_router::OperatorEpochRewardRouter, }; #[derive(Debug, Clone, PartialEq, Eq, Copy, Zeroable, ShankType, Pod, ShankType)] @@ -95,6 +95,8 @@ pub struct EpochRewardRouter { reward_pool: PodU64, + rewards_processed: PodU64, + doa_rewards: PodU64, reserved: [u8; 128], @@ -119,6 +121,7 @@ impl EpochRewardRouter { ncn_reward_buckets: [RewardBucket::default(); NcnFeeGroup::FEE_GROUP_COUNT], reward_routes: [RewardRoutes::default(); 32], reward_pool: PodU64::from(0), + rewards_processed: PodU64::from(0), doa_rewards: PodU64::from(0), reserved: [0; 128], } @@ -180,18 +183,26 @@ impl EpochRewardRouter { Ok(()) } - pub fn process_reward_pool( - &mut self, - fee_config: &FeeConfig, - current_epoch: u64, - ) -> Result<(), TipRouterError> { + pub fn process_incoming_rewards(&mut self, account_balance: u64) -> Result<(), TipRouterError> { + let total_rewards = self.total_rewards()?; + + let incoming_rewards = account_balance + .checked_sub(total_rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?; + + self.increment_reward_pool(incoming_rewards)?; + + Ok(()) + } + + pub fn process_reward_pool(&mut self, fee: &Fees) -> Result<(), TipRouterError> { let rewards_to_process: u64 = self.reward_pool(); - let total_fee_bps = fee_config.total_fees_bps(current_epoch)?; + let total_fee_bps = fee.total_fees_bps()?; // DAO Rewards { - let dao_fee = fee_config.dao_fee_bps(current_epoch); + let dao_fee = fee.dao_fee_bps(); let dao_rewards = Self::calculate_bucket_reward(dao_fee, total_fee_bps, rewards_to_process)?; @@ -202,7 +213,7 @@ impl EpochRewardRouter { // Fee Buckets { for group in NcnFeeGroup::all_groups().iter() { - let ncn_group_fee = fee_config.ncn_fee_bps(*group, current_epoch)?; + let ncn_group_fee = fee.ncn_fee_bps(*group)?; let group_reward = Self::calculate_bucket_reward( ncn_group_fee, @@ -226,7 +237,11 @@ impl EpochRewardRouter { Ok(()) } - pub fn process_buckets(&mut self, ballot_box: &BallotBox) -> Result<(), TipRouterError> { + pub fn process_buckets( + &mut self, + ballot_box: &BallotBox, + program_id: &Pubkey, + ) -> Result<(), TipRouterError> { let winning_ballot = ballot_box.get_winning_ballot()?; let winning_stake_weight = winning_ballot.stake_weight(); @@ -247,7 +262,19 @@ impl EpochRewardRouter { rewards_to_process, )?; - self.insert_or_increment_operator_rewards(operator, operator_rewards)?; + let operator_epoch_reward_router = + OperatorEpochRewardRouter::find_program_address( + program_id, + &operator, + &self.ncn, + self.ncn_epoch.into(), + ) + .0; + + self.insert_or_increment_operator_rewards( + operator_epoch_reward_router, + operator_rewards, + )?; self.decrement_ncn_rewards(*group, operator_rewards)?; } } @@ -377,6 +404,19 @@ impl EpochRewardRouter { Err(TipRouterError::OperatorRewardNotFound) } + pub fn total_rewards(&self) -> Result { + let total_rewards = self + .reward_pool() + .checked_add(self.rewards_processed()) + .ok_or(TipRouterError::ArithmeticOverflow)?; + + Ok(total_rewards) + } + + pub fn rewards_processed(&self) -> u64 { + self.rewards_processed.into() + } + pub fn reward_pool(&self) -> u64 { self.reward_pool.into() } @@ -404,6 +444,12 @@ impl EpochRewardRouter { .checked_sub(rewards) .ok_or(TipRouterError::ArithmeticUnderflowError)?, ); + + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_add(rewards) + .ok_or(TipRouterError::ArithmeticOverflow)?, + ); Ok(()) } @@ -434,6 +480,12 @@ impl EpochRewardRouter { .checked_sub(rewards) .ok_or(TipRouterError::ArithmeticUnderflowError)?, ); + + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_sub(rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?, + ); Ok(()) } @@ -479,6 +531,12 @@ impl EpochRewardRouter { .checked_sub(rewards) .ok_or(TipRouterError::ArithmeticUnderflowError)?, ); + + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_sub(rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?, + ); Ok(()) } } diff --git a/core/src/epoch_snapshot.rs b/core/src/epoch_snapshot.rs index 9b586a6..18e398d 100644 --- a/core/src/epoch_snapshot.rs +++ b/core/src/epoch_snapshot.rs @@ -31,7 +31,7 @@ pub struct EpochSnapshot { slot_created: PodU64, slot_finalized: PodU64, - ncn_fees: Fees, + fees: Fees, operator_count: PodU64, vault_count: PodU64, @@ -54,7 +54,7 @@ impl EpochSnapshot { ncn_epoch: u64, bump: u8, current_slot: u64, - ncn_fees: Fees, + fees: Fees, operator_count: u64, vault_count: u64, ) -> Self { @@ -64,7 +64,7 @@ impl EpochSnapshot { slot_created: PodU64::from(current_slot), slot_finalized: PodU64::from(0), bump, - ncn_fees, + fees, operator_count: PodU64::from(operator_count), vault_count: PodU64::from(vault_count), operators_registered: PodU64::from(0), @@ -150,6 +150,10 @@ impl EpochSnapshot { &self.stake_weight } + pub const fn fees(&self) -> &Fees { + &self.fees + } + pub fn finalized(&self) -> bool { self.operators_registered() == self.operator_count() } diff --git a/core/src/fees.rs b/core/src/fees.rs index abbaa15..958a2da 100644 --- a/core/src/fees.rs +++ b/core/src/fees.rs @@ -59,34 +59,16 @@ impl FeeConfig { } pub fn total_fees_bps(&self, current_epoch: u64) -> Result { - let mut total_fees_bps = self.dao_fee_bps(current_epoch); - - for group in NcnFeeGroup::all_groups().iter() { - let ncn_fee_bps = self.ncn_fee_bps(*group, current_epoch)?; - - total_fees_bps = total_fees_bps - .checked_add(ncn_fee_bps) - .ok_or(TipRouterError::ArithmeticOverflow)?; - } - - Ok(total_fees_bps) + let current_fees = self.current_fees(current_epoch); + current_fees.total_fees_bps() } pub fn precise_total_fee_bps( &self, current_epoch: u64, ) -> Result { - let mut precise_total_fees_bps = self.precise_dao_fee_bps(current_epoch)?; - - for group in NcnFeeGroup::all_groups().iter() { - let precise_ncn_fee_bps = self.precise_ncn_fee_bps(*group, current_epoch)?; - - precise_total_fees_bps = precise_total_fees_bps - .checked_add(&precise_ncn_fee_bps) - .ok_or(TipRouterError::ArithmeticOverflow)?; - } - - Ok(precise_total_fees_bps) + let current_fees = self.current_fees(current_epoch); + current_fees.precise_total_fee_bps() } pub fn block_engine_fee_bps(&self, current_epoch: u64) -> u64 { @@ -355,6 +337,34 @@ impl Fees { self.adjusted_precise_fee_bps(fee) } + pub fn total_fees_bps(&self) -> Result { + let mut total_fees_bps = self.dao_fee_bps(); + + for group in NcnFeeGroup::all_groups().iter() { + let ncn_fee_bps = self.ncn_fee_bps(*group)?; + + total_fees_bps = total_fees_bps + .checked_add(ncn_fee_bps) + .ok_or(TipRouterError::ArithmeticOverflow)?; + } + + Ok(total_fees_bps) + } + + pub fn precise_total_fee_bps(&self) -> Result { + let mut precise_total_fees_bps = self.precise_dao_fee_bps()?; + + for group in NcnFeeGroup::all_groups().iter() { + let precise_ncn_fee_bps = self.precise_ncn_fee_bps(*group)?; + + precise_total_fees_bps = precise_total_fees_bps + .checked_add(&precise_ncn_fee_bps) + .ok_or(TipRouterError::ArithmeticOverflow)?; + } + + Ok(precise_total_fees_bps) + } + // ------ Setters ----------------- fn set_activation_epoch(&mut self, value: u64) { self.activation_epoch = PodU64::from(value); diff --git a/core/src/instruction.rs b/core/src/instruction.rs index 01f026c..ae0d9ad 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction.rs @@ -143,25 +143,58 @@ pub enum TipRouterInstruction { InitializeTrackedMints, /// Initializes the epoch reward router account for an NCN - #[account(0, name = "ncn_config")] + #[account(0, name = "restaking_config")] #[account(1, name = "ncn")] #[account(2, name = "ballot_box")] #[account(3, name = "epoch_reward_router")] #[account(4, writable, signer, name = "payer")] - #[account(5, name = "system_program")] + #[account(5, name = "restaking_program_id")] + #[account(6, name = "system_program")] InitializeEpochRewardRouter{ first_slot_of_ncn_epoch: Option, }, /// Initializes the epoch reward router account for an NCN - #[account(0, name = "ncn_config")] + #[account(0, name = "restaking_config")] #[account(1, name = "ncn")] #[account(2, name = "operator")] #[account(3, name = "ballot_box")] #[account(4, name = "operator_epoch_reward_router")] #[account(5, writable, signer, name = "payer")] - #[account(6, name = "system_program")] + #[account(6, name = "restaking_program_id")] + #[account(7, name = "system_program")] InitializeOperatorEpochRewardRouter{ first_slot_of_ncn_epoch: Option, }, + + // restaking_config, ncn, epoch_snapshot, epoch_reward_router, restaking_program + #[account(0, name = "restaking_config")] + #[account(1, name = "ncn")] + #[account(2, name = "epoch_snapshot")] + #[account(3, name = "epoch_reward_router")] + #[account(4, name = "restaking_program_id")] + ProcessEpochRewardPool{ + first_slot_of_ncn_epoch: Option, + }, + + // restaking_config, ncn, ballot_box, epoch_reward_router, restaking_program + #[account(0, name = "restaking_config")] + #[account(1, name = "ncn")] + #[account(2, name = "ballot_box")] + #[account(3, name = "epoch_reward_router")] + #[account(4, name = "restaking_program_id")] + ProcessEpochRewardBuckets{ + first_slot_of_ncn_epoch: Option, + }, + + #[account(0, name = "restaking_config")] + #[account(1, name = "ncn")] + #[account(2, name = "operator")] + #[account(3, name = "operator_snapshot")] + #[account(4, name = "operator_reward_router")] + #[account(5, name = "restaking_program_id")] + ProcessOperatorEpochRewardPool{ + first_slot_of_ncn_epoch: Option, + }, + } diff --git a/core/src/operator_epoch_reward_router.rs b/core/src/operator_epoch_reward_router.rs index f739033..6fff19f 100644 --- a/core/src/operator_epoch_reward_router.rs +++ b/core/src/operator_epoch_reward_router.rs @@ -26,6 +26,8 @@ pub struct OperatorEpochRewardRouter { reward_pool: PodU64, + rewards_processed: PodU64, + operator_rewards: PodU64, reserved: [u8; 128], @@ -48,6 +50,7 @@ impl OperatorEpochRewardRouter { slot_created: PodU64::from(slot_created), vault_rewards: [RewardRoutes::default(); 32], reward_pool: PodU64::from(0), + rewards_processed: PodU64::from(0), operator_rewards: PodU64::from(0), reserved: [0; 128], } @@ -112,6 +115,18 @@ impl OperatorEpochRewardRouter { Ok(()) } + pub fn process_incoming_rewards(&mut self, account_balance: u64) -> Result<(), TipRouterError> { + let total_rewards = self.total_rewards()?; + + let incoming_rewards = account_balance + .checked_sub(total_rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?; + + self.increment_reward_pool(incoming_rewards)?; + + Ok(()) + } + pub fn process_reward_pool( &mut self, operator_snapshot: &OperatorSnapshot, @@ -284,9 +299,28 @@ impl OperatorEpochRewardRouter { } } + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_sub(rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?, + ); + Err(TipRouterError::OperatorRewardNotFound) } + pub fn total_rewards(&self) -> Result { + let total_rewards = self + .reward_pool() + .checked_add(self.rewards_processed()) + .ok_or(TipRouterError::ArithmeticOverflow)?; + + Ok(total_rewards) + } + + pub fn rewards_processed(&self) -> u64 { + self.rewards_processed.into() + } + pub fn reward_pool(&self) -> u64 { self.reward_pool.into() } @@ -314,6 +348,13 @@ impl OperatorEpochRewardRouter { .checked_sub(rewards) .ok_or(TipRouterError::ArithmeticUnderflowError)?, ); + + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_add(rewards) + .ok_or(TipRouterError::ArithmeticOverflow)?, + ); + Ok(()) } @@ -344,6 +385,12 @@ impl OperatorEpochRewardRouter { .checked_sub(rewards) .ok_or(TipRouterError::ArithmeticUnderflowError)?, ); + + self.rewards_processed = PodU64::from( + self.rewards_processed() + .checked_sub(rewards) + .ok_or(TipRouterError::ArithmeticUnderflowError)?, + ); Ok(()) } } diff --git a/idl/jito_tip_router.json b/idl/jito_tip_router.json index 3925165..5dcacfe 100644 --- a/idl/jito_tip_router.json +++ b/idl/jito_tip_router.json @@ -574,6 +574,246 @@ "type": "u8", "value": 9 } + }, + { + "name": "InitializeEpochRewardRouter", + "accounts": [ + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "ballotBox", + "isMut": false, + "isSigner": false + }, + { + "name": "epochRewardRouter", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "restakingProgramId", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "firstSlotOfNcnEpoch", + "type": { + "option": "u64" + } + } + ], + "discriminant": { + "type": "u8", + "value": 10 + } + }, + { + "name": "InitializeOperatorEpochRewardRouter", + "accounts": [ + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "operator", + "isMut": false, + "isSigner": false + }, + { + "name": "ballotBox", + "isMut": false, + "isSigner": false + }, + { + "name": "operatorEpochRewardRouter", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "restakingProgramId", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "firstSlotOfNcnEpoch", + "type": { + "option": "u64" + } + } + ], + "discriminant": { + "type": "u8", + "value": 11 + } + }, + { + "name": "ProcessEpochRewardPool", + "accounts": [ + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "epochSnapshot", + "isMut": false, + "isSigner": false + }, + { + "name": "epochRewardRouter", + "isMut": false, + "isSigner": false + }, + { + "name": "restakingProgramId", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "firstSlotOfNcnEpoch", + "type": { + "option": "u64" + } + } + ], + "discriminant": { + "type": "u8", + "value": 12 + } + }, + { + "name": "ProcessEpochRewardBuckets", + "accounts": [ + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "ballotBox", + "isMut": false, + "isSigner": false + }, + { + "name": "epochRewardRouter", + "isMut": false, + "isSigner": false + }, + { + "name": "restakingProgramId", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "firstSlotOfNcnEpoch", + "type": { + "option": "u64" + } + } + ], + "discriminant": { + "type": "u8", + "value": 13 + } + }, + { + "name": "ProcessOperatorEpochRewardPool", + "accounts": [ + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "operator", + "isMut": false, + "isSigner": false + }, + { + "name": "operatorSnapshot", + "isMut": false, + "isSigner": false + }, + { + "name": "operatorRewardRouter", + "isMut": false, + "isSigner": false + }, + { + "name": "restakingProgramId", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "firstSlotOfNcnEpoch", + "type": { + "option": "u64" + } + } + ], + "discriminant": { + "type": "u8", + "value": 14 + } } ], "accounts": [ @@ -691,6 +931,12 @@ "defined": "PodU64" } }, + { + "name": "rewardsProcessed", + "type": { + "defined": "PodU64" + } + }, { "name": "doaRewards", "type": { @@ -763,7 +1009,7 @@ } }, { - "name": "ncnFees", + "name": "fees", "type": { "defined": "Fees" } @@ -990,6 +1236,12 @@ "defined": "PodU64" } }, + { + "name": "rewardsProcessed", + "type": { + "defined": "PodU64" + } + }, { "name": "operatorRewards", "type": { diff --git a/program/src/lib.rs b/program/src/lib.rs index f0b3af3..76d670b 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -6,6 +6,9 @@ mod initialize_operator_epoch_reward_router; mod initialize_operator_snapshot; mod initialize_tracked_mints; mod initialize_weight_table; +mod process_epoch_reward_buckets; +mod process_epoch_reward_pool; +mod process_operator_epoch_reward_pool; mod register_mint; mod set_config_fees; mod set_new_admin; @@ -30,8 +33,11 @@ use crate::{ initialize_operator_epoch_reward_router::process_initialize_operator_epoch_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, - set_config_fees::process_set_config_fees, + initialize_weight_table::process_initialize_weight_table, + process_epoch_reward_buckets::process_process_epoch_reward_buckets, + process_epoch_reward_pool::process_process_epoch_reward_pool, + process_operator_epoch_reward_pool::process_process_operator_epoch_reward_pool, + register_mint::process_register_mint, set_config_fees::process_set_config_fees, snapshot_vault_operator_delegation::process_snapshot_vault_operator_delegation, }; @@ -162,5 +168,27 @@ pub fn process_instruction( msg!("Instruction: InitializeTrackedMints"); process_initialize_tracked_mints(program_id, accounts) } + TipRouterInstruction::ProcessEpochRewardPool { + first_slot_of_ncn_epoch, + } => { + msg!("Instruction: ProcessEpochRewardPool"); + process_process_epoch_reward_pool(program_id, accounts, first_slot_of_ncn_epoch) + } + TipRouterInstruction::ProcessEpochRewardBuckets { + first_slot_of_ncn_epoch, + } => { + msg!("Instruction: ProcessEpochRewardBuckets"); + process_process_epoch_reward_buckets(program_id, accounts, first_slot_of_ncn_epoch) + } + TipRouterInstruction::ProcessOperatorEpochRewardPool { + first_slot_of_ncn_epoch, + } => { + msg!("Instruction: ProcessOperatorEpochRewardPool"); + process_process_operator_epoch_reward_pool( + program_id, + accounts, + first_slot_of_ncn_epoch, + ) + } } } diff --git a/program/src/process_epoch_reward_buckets.rs b/program/src/process_epoch_reward_buckets.rs new file mode 100644 index 0000000..7900df5 --- /dev/null +++ b/program/src/process_epoch_reward_buckets.rs @@ -0,0 +1,51 @@ +use jito_bytemuck::AccountDeserialize; +use jito_restaking_core::{config::Config, ncn::Ncn}; +use jito_tip_router_core::{ + ballot_box::BallotBox, epoch_reward_router::EpochRewardRouter, loaders::load_ncn_epoch, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, +}; + +/// Initializes a Epoch Reward Router +/// Can be backfilled for previous epochs +pub fn process_process_epoch_reward_buckets( + program_id: &Pubkey, + accounts: &[AccountInfo], + first_slot_of_ncn_epoch: Option, +) -> ProgramResult { + let [restaking_config, ncn, ballot_box, epoch_reward_router, restaking_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); + } + + 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)?; + + BallotBox::load(program_id, ncn.key, ncn_epoch, ballot_box, false)?; + EpochRewardRouter::load(program_id, ncn.key, ncn_epoch, epoch_reward_router, true)?; + + let ballot_box = { + let ballot_box_data = ballot_box.try_borrow_data()?; + let ballot_box_account = BallotBox::try_from_slice_unchecked(&ballot_box_data)?; + + ballot_box_account.clone() + }; + + let mut epoch_reward_router_data = epoch_reward_router.try_borrow_mut_data()?; + let epoch_reward_router_account = + EpochRewardRouter::try_from_slice_unchecked_mut(&mut epoch_reward_router_data)?; + + epoch_reward_router_account.process_buckets(&ballot_box, program_id)?; + + Ok(()) +} diff --git a/program/src/process_epoch_reward_pool.rs b/program/src/process_epoch_reward_pool.rs new file mode 100644 index 0000000..067a90f --- /dev/null +++ b/program/src/process_epoch_reward_pool.rs @@ -0,0 +1,55 @@ +use jito_bytemuck::AccountDeserialize; +use jito_restaking_core::{config::Config, ncn::Ncn}; +use jito_tip_router_core::{ + epoch_reward_router::EpochRewardRouter, epoch_snapshot::EpochSnapshot, loaders::load_ncn_epoch, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, +}; + +/// Initializes a Epoch Reward Router +/// Can be backfilled for previous epochs +pub fn process_process_epoch_reward_pool( + program_id: &Pubkey, + accounts: &[AccountInfo], + first_slot_of_ncn_epoch: Option, +) -> ProgramResult { + let [restaking_config, ncn, epoch_snapshot, epoch_reward_router, restaking_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); + } + + 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)?; + EpochRewardRouter::load(program_id, ncn.key, ncn_epoch, epoch_reward_router, true)?; + + let snapshot_fees = { + let epoch_snapshot_data = epoch_snapshot.try_borrow_data()?; + let epoch_snapshot_account = EpochSnapshot::try_from_slice_unchecked(&epoch_snapshot_data)?; + + epoch_snapshot_account.fees().clone() + }; + + let account_balance = epoch_reward_router.try_borrow_lamports()?.clone(); + + let mut epoch_reward_router_data = epoch_reward_router.try_borrow_mut_data()?; + let epoch_reward_router_account = + EpochRewardRouter::try_from_slice_unchecked_mut(&mut epoch_reward_router_data)?; + + epoch_reward_router_account.process_incoming_rewards(account_balance)?; + + epoch_reward_router_account.process_reward_pool(&snapshot_fees)?; + + Ok(()) +} diff --git a/program/src/process_operator_epoch_reward_pool.rs b/program/src/process_operator_epoch_reward_pool.rs new file mode 100644 index 0000000..93b9ec3 --- /dev/null +++ b/program/src/process_operator_epoch_reward_pool.rs @@ -0,0 +1,75 @@ +use jito_bytemuck::AccountDeserialize; +use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; +use jito_tip_router_core::{ + epoch_reward_router::EpochRewardRouter, epoch_snapshot::OperatorSnapshot, + loaders::load_ncn_epoch, operator_epoch_reward_router::OperatorEpochRewardRouter, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, +}; + +/// Initializes a Epoch Reward Router +/// Can be backfilled for previous epochs +pub fn process_process_operator_epoch_reward_pool( + program_id: &Pubkey, + accounts: &[AccountInfo], + first_slot_of_ncn_epoch: Option, +) -> ProgramResult { + let [restaking_config, ncn, operator, operator_snapshot, operator_epoch_reward_router, restaking_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); + } + + Config::load(restaking_program.key, restaking_config, false)?; + 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)?; + + OperatorSnapshot::load( + program_id, + operator.key, + ncn.key, + ncn_epoch, + operator_snapshot, + false, + )?; + EpochRewardRouter::load( + program_id, + ncn.key, + ncn_epoch, + operator_epoch_reward_router, + true, + )?; + + let operator_snapshot = { + let operator_snapshot_data = operator_snapshot.try_borrow_data()?; + let operator_snapshot_account = + OperatorSnapshot::try_from_slice_unchecked(&operator_snapshot_data)?; + + operator_snapshot_account.clone() + }; + + let account_balance = operator_epoch_reward_router.try_borrow_lamports()?.clone(); + + let mut operator_epoch_reward_router_data = + operator_epoch_reward_router.try_borrow_mut_data()?; + let operator_epoch_reward_router_account = + OperatorEpochRewardRouter::try_from_slice_unchecked_mut( + &mut operator_epoch_reward_router_data, + )?; + + operator_epoch_reward_router_account.process_incoming_rewards(account_balance)?; + + operator_epoch_reward_router_account.process_reward_pool(&operator_snapshot)?; + + Ok(()) +}