@ignitionfi/fogo-stake-pool 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +176 -0
- package/dist/codecs.d.ts +15 -0
- package/dist/constants.d.ts +13 -0
- package/dist/index.browser.cjs.js +2898 -0
- package/dist/index.browser.cjs.js.map +1 -0
- package/dist/index.browser.esm.js +2843 -0
- package/dist/index.browser.esm.js.map +1 -0
- package/dist/index.cjs.js +2898 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +268 -0
- package/dist/index.esm.js +2843 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.iife.js +24083 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.iife.min.js +19 -0
- package/dist/index.iife.min.js.map +1 -0
- package/dist/instructions.d.ts +381 -0
- package/dist/layouts.d.ts +318 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/instruction.d.ts +21 -0
- package/dist/utils/math.d.ts +3 -0
- package/dist/utils/program-address.d.ts +31 -0
- package/dist/utils/stake.d.ts +29 -0
- package/package.json +90 -0
- package/src/codecs.ts +159 -0
- package/src/constants.ts +30 -0
- package/src/index.ts +1823 -0
- package/src/instructions.ts +1439 -0
- package/src/layouts.ts +248 -0
- package/src/types/buffer-layout.d.ts +29 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/instruction.ts +46 -0
- package/src/utils/math.ts +29 -0
- package/src/utils/program-address.ts +125 -0
- package/src/utils/stake.ts +233 -0
package/src/layouts.ts
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js'
|
|
2
|
+
import BN from 'bn.js'
|
|
3
|
+
import { Layout as LayoutCls, struct, u8, u32 } from 'buffer-layout'
|
|
4
|
+
import {
|
|
5
|
+
coerce,
|
|
6
|
+
enums,
|
|
7
|
+
Infer,
|
|
8
|
+
instance,
|
|
9
|
+
nullable,
|
|
10
|
+
number,
|
|
11
|
+
optional,
|
|
12
|
+
string,
|
|
13
|
+
type,
|
|
14
|
+
} from 'superstruct'
|
|
15
|
+
import { Layout, option, publicKey, u64, vec } from './codecs'
|
|
16
|
+
|
|
17
|
+
export interface Fee {
|
|
18
|
+
denominator: BN
|
|
19
|
+
numerator: BN
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const feeFields = [u64('denominator'), u64('numerator')]
|
|
23
|
+
|
|
24
|
+
export enum AccountType {
|
|
25
|
+
Uninitialized,
|
|
26
|
+
StakePool,
|
|
27
|
+
ValidatorList,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const BigNumFromString = coerce(instance(BN), string(), (value) => {
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
return new BN(value, 10)
|
|
33
|
+
}
|
|
34
|
+
throw new Error('invalid big num')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
export const PublicKeyFromString = coerce(
|
|
38
|
+
instance(PublicKey),
|
|
39
|
+
string(),
|
|
40
|
+
value => new PublicKey(value),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export class FutureEpochLayout<T> extends LayoutCls<T | null> {
|
|
44
|
+
layout: Layout<T>
|
|
45
|
+
discriminator: Layout<number>
|
|
46
|
+
|
|
47
|
+
constructor(layout: Layout<T>, property?: string) {
|
|
48
|
+
super(-1, property)
|
|
49
|
+
this.layout = layout
|
|
50
|
+
this.discriminator = u8()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
encode(src: T | null, b: Buffer, offset = 0): number {
|
|
54
|
+
if (src === null || src === undefined) {
|
|
55
|
+
return this.discriminator.encode(0, b, offset)
|
|
56
|
+
}
|
|
57
|
+
// This isn't right, but we don't typically encode outside of tests
|
|
58
|
+
this.discriminator.encode(2, b, offset)
|
|
59
|
+
return this.layout.encode(src, b, offset + 1) + 1
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
decode(b: Buffer, offset = 0): T | null {
|
|
63
|
+
const discriminator = this.discriminator.decode(b, offset)
|
|
64
|
+
if (discriminator === 0) {
|
|
65
|
+
return null
|
|
66
|
+
} else if (discriminator === 1 || discriminator === 2) {
|
|
67
|
+
return this.layout.decode(b, offset + 1)
|
|
68
|
+
}
|
|
69
|
+
throw new Error(`Invalid future epoch ${this.property}`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getSpan(b: Buffer, offset = 0): number {
|
|
73
|
+
const discriminator = this.discriminator.decode(b, offset)
|
|
74
|
+
if (discriminator === 0) {
|
|
75
|
+
return 1
|
|
76
|
+
} else if (discriminator === 1 || discriminator === 2) {
|
|
77
|
+
return this.layout.getSpan(b, offset + 1) + 1
|
|
78
|
+
}
|
|
79
|
+
throw new Error(`Invalid future epoch ${this.property}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function futureEpoch<T>(layout: Layout<T>, property?: string): LayoutCls<T | null> {
|
|
84
|
+
return new FutureEpochLayout<T>(layout, property)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type StakeAccountType = Infer<typeof StakeAccountType>
|
|
88
|
+
export const StakeAccountType = enums(['uninitialized', 'initialized', 'delegated', 'rewardsPool'])
|
|
89
|
+
|
|
90
|
+
export type StakeMeta = Infer<typeof StakeMeta>
|
|
91
|
+
export const StakeMeta = type({
|
|
92
|
+
rentExemptReserve: BigNumFromString,
|
|
93
|
+
authorized: type({
|
|
94
|
+
staker: PublicKeyFromString,
|
|
95
|
+
withdrawer: PublicKeyFromString,
|
|
96
|
+
}),
|
|
97
|
+
lockup: type({
|
|
98
|
+
unixTimestamp: number(),
|
|
99
|
+
epoch: number(),
|
|
100
|
+
custodian: PublicKeyFromString,
|
|
101
|
+
}),
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
export type StakeAccountInfo = Infer<typeof StakeAccountInfo>
|
|
105
|
+
export const StakeAccountInfo = type({
|
|
106
|
+
meta: StakeMeta,
|
|
107
|
+
stake: nullable(
|
|
108
|
+
type({
|
|
109
|
+
delegation: type({
|
|
110
|
+
voter: PublicKeyFromString,
|
|
111
|
+
stake: BigNumFromString,
|
|
112
|
+
activationEpoch: BigNumFromString,
|
|
113
|
+
deactivationEpoch: BigNumFromString,
|
|
114
|
+
warmupCooldownRate: number(),
|
|
115
|
+
}),
|
|
116
|
+
creditsObserved: number(),
|
|
117
|
+
}),
|
|
118
|
+
),
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
export type StakeAccount = Infer<typeof StakeAccount>
|
|
122
|
+
export const StakeAccount = type({
|
|
123
|
+
type: StakeAccountType,
|
|
124
|
+
info: optional(StakeAccountInfo),
|
|
125
|
+
})
|
|
126
|
+
export interface Lockup {
|
|
127
|
+
unixTimestamp: BN
|
|
128
|
+
epoch: BN
|
|
129
|
+
custodian: PublicKey
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface StakePool {
|
|
133
|
+
accountType: AccountType
|
|
134
|
+
manager: PublicKey
|
|
135
|
+
staker: PublicKey
|
|
136
|
+
stakeDepositAuthority: PublicKey
|
|
137
|
+
stakeWithdrawBumpSeed: number
|
|
138
|
+
validatorList: PublicKey
|
|
139
|
+
reserveStake: PublicKey
|
|
140
|
+
poolMint: PublicKey
|
|
141
|
+
managerFeeAccount: PublicKey
|
|
142
|
+
tokenProgramId: PublicKey
|
|
143
|
+
totalLamports: BN
|
|
144
|
+
poolTokenSupply: BN
|
|
145
|
+
lastUpdateEpoch: BN
|
|
146
|
+
lockup: Lockup
|
|
147
|
+
epochFee: Fee
|
|
148
|
+
nextEpochFee?: Fee | undefined
|
|
149
|
+
preferredDepositValidatorVoteAddress?: PublicKey | undefined
|
|
150
|
+
preferredWithdrawValidatorVoteAddress?: PublicKey | undefined
|
|
151
|
+
stakeDepositFee: Fee
|
|
152
|
+
stakeWithdrawalFee: Fee
|
|
153
|
+
nextStakeWithdrawalFee?: Fee | undefined
|
|
154
|
+
stakeReferralFee: number
|
|
155
|
+
solDepositAuthority?: PublicKey | undefined
|
|
156
|
+
solDepositFee: Fee
|
|
157
|
+
solReferralFee: number
|
|
158
|
+
solWithdrawAuthority?: PublicKey | undefined
|
|
159
|
+
solWithdrawalFee: Fee
|
|
160
|
+
nextSolWithdrawalFee?: Fee | undefined
|
|
161
|
+
lastEpochPoolTokenSupply: BN
|
|
162
|
+
lastEpochTotalLamports: BN
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const StakePoolLayout = struct<StakePool>([
|
|
166
|
+
u8('accountType'),
|
|
167
|
+
publicKey('manager'),
|
|
168
|
+
publicKey('staker'),
|
|
169
|
+
publicKey('stakeDepositAuthority'),
|
|
170
|
+
u8('stakeWithdrawBumpSeed'),
|
|
171
|
+
publicKey('validatorList'),
|
|
172
|
+
publicKey('reserveStake'),
|
|
173
|
+
publicKey('poolMint'),
|
|
174
|
+
publicKey('managerFeeAccount'),
|
|
175
|
+
publicKey('tokenProgramId'),
|
|
176
|
+
u64('totalLamports'),
|
|
177
|
+
u64('poolTokenSupply'),
|
|
178
|
+
u64('lastUpdateEpoch'),
|
|
179
|
+
struct([u64('unixTimestamp'), u64('epoch'), publicKey('custodian')], 'lockup'),
|
|
180
|
+
struct(feeFields, 'epochFee'),
|
|
181
|
+
futureEpoch(struct(feeFields), 'nextEpochFee'),
|
|
182
|
+
option(publicKey(), 'preferredDepositValidatorVoteAddress'),
|
|
183
|
+
option(publicKey(), 'preferredWithdrawValidatorVoteAddress'),
|
|
184
|
+
struct(feeFields, 'stakeDepositFee'),
|
|
185
|
+
struct(feeFields, 'stakeWithdrawalFee'),
|
|
186
|
+
futureEpoch(struct(feeFields), 'nextStakeWithdrawalFee'),
|
|
187
|
+
u8('stakeReferralFee'),
|
|
188
|
+
option(publicKey(), 'solDepositAuthority'),
|
|
189
|
+
struct(feeFields, 'solDepositFee'),
|
|
190
|
+
u8('solReferralFee'),
|
|
191
|
+
option(publicKey(), 'solWithdrawAuthority'),
|
|
192
|
+
struct(feeFields, 'solWithdrawalFee'),
|
|
193
|
+
futureEpoch(struct(feeFields), 'nextSolWithdrawalFee'),
|
|
194
|
+
u64('lastEpochPoolTokenSupply'),
|
|
195
|
+
u64('lastEpochTotalLamports'),
|
|
196
|
+
])
|
|
197
|
+
|
|
198
|
+
export enum ValidatorStakeInfoStatus {
|
|
199
|
+
Active,
|
|
200
|
+
DeactivatingTransient,
|
|
201
|
+
ReadyForRemoval,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface ValidatorStakeInfo {
|
|
205
|
+
status: ValidatorStakeInfoStatus
|
|
206
|
+
voteAccountAddress: PublicKey
|
|
207
|
+
activeStakeLamports: BN
|
|
208
|
+
transientStakeLamports: BN
|
|
209
|
+
transientSeedSuffixStart: BN
|
|
210
|
+
transientSeedSuffixEnd: BN
|
|
211
|
+
lastUpdateEpoch: BN
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export const ValidatorStakeInfoLayout = struct<ValidatorStakeInfo>([
|
|
215
|
+
/// Amount of active stake delegated to this validator
|
|
216
|
+
/// Note that if `last_update_epoch` does not match the current epoch then
|
|
217
|
+
/// this field may not be accurate
|
|
218
|
+
u64('activeStakeLamports'),
|
|
219
|
+
/// Amount of transient stake delegated to this validator
|
|
220
|
+
/// Note that if `last_update_epoch` does not match the current epoch then
|
|
221
|
+
/// this field may not be accurate
|
|
222
|
+
u64('transientStakeLamports'),
|
|
223
|
+
/// Last epoch the active and transient stake lamports fields were updated
|
|
224
|
+
u64('lastUpdateEpoch'),
|
|
225
|
+
/// Start of the validator transient account seed suffixes
|
|
226
|
+
u64('transientSeedSuffixStart'),
|
|
227
|
+
/// End of the validator transient account seed suffixes
|
|
228
|
+
u64('transientSeedSuffixEnd'),
|
|
229
|
+
/// Status of the validator stake account
|
|
230
|
+
u8('status'),
|
|
231
|
+
/// Validator vote account address
|
|
232
|
+
publicKey('voteAccountAddress'),
|
|
233
|
+
])
|
|
234
|
+
|
|
235
|
+
export interface ValidatorList {
|
|
236
|
+
/// Account type, must be ValidatorList currently
|
|
237
|
+
accountType: number
|
|
238
|
+
/// Maximum allowable number of validators
|
|
239
|
+
maxValidators: number
|
|
240
|
+
/// List of stake info for each validator in the pool
|
|
241
|
+
validators: ValidatorStakeInfo[]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export const ValidatorListLayout = struct<ValidatorList>([
|
|
245
|
+
u8('accountType'),
|
|
246
|
+
u32('maxValidators'),
|
|
247
|
+
vec(ValidatorStakeInfoLayout, 'validators'),
|
|
248
|
+
])
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare module 'buffer-layout' {
|
|
2
|
+
export class Layout<T = any> {
|
|
3
|
+
span: number
|
|
4
|
+
property?: string
|
|
5
|
+
constructor(span: number, property?: string)
|
|
6
|
+
decode(b: Buffer | undefined, offset?: number): T
|
|
7
|
+
encode(src: T, b: Buffer, offset?: number): number
|
|
8
|
+
getSpan(b: Buffer, offset?: number): number
|
|
9
|
+
replicate(name: string): this
|
|
10
|
+
}
|
|
11
|
+
export function struct<T>(
|
|
12
|
+
fields: Layout<any>[],
|
|
13
|
+
property?: string,
|
|
14
|
+
decodePrefixes?: boolean,
|
|
15
|
+
): Layout<T>
|
|
16
|
+
export function seq<T>(
|
|
17
|
+
elementLayout: Layout<T>,
|
|
18
|
+
count: number | Layout<number>,
|
|
19
|
+
property?: string,
|
|
20
|
+
): Layout<T[]>
|
|
21
|
+
export function offset<T>(layout: Layout<T>, offset?: number, property?: string): Layout<T>
|
|
22
|
+
export function blob(length: number | Layout<number>, property?: string): Layout<Buffer>
|
|
23
|
+
export function s32(property?: string): Layout<number>
|
|
24
|
+
export function u32(property?: string): Layout<number>
|
|
25
|
+
export function s16(property?: string): Layout<number>
|
|
26
|
+
export function u16(property?: string): Layout<number>
|
|
27
|
+
export function s8(property?: string): Layout<number>
|
|
28
|
+
export function u8(property?: string): Layout<number>
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './instruction'
|
|
2
|
+
export * from './math'
|
|
3
|
+
export * from './program-address'
|
|
4
|
+
export * from './stake'
|
|
5
|
+
|
|
6
|
+
export function arrayChunk(array: any[], size: number): any[] {
|
|
7
|
+
const result = []
|
|
8
|
+
for (let i = 0; i < array.length; i += size) {
|
|
9
|
+
result.push(array.slice(i, i + size))
|
|
10
|
+
}
|
|
11
|
+
return result
|
|
12
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer'
|
|
2
|
+
import * as BufferLayout from '@solana/buffer-layout'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export type InstructionType = {
|
|
8
|
+
/** The Instruction index (from solana upstream program) */
|
|
9
|
+
index: number
|
|
10
|
+
/** The BufferLayout to use to build data */
|
|
11
|
+
layout: BufferLayout.Layout<any>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Populate a buffer of instruction data using an InstructionType
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export function encodeData(type: InstructionType, fields?: any): Buffer {
|
|
19
|
+
const allocLength = type.layout.span
|
|
20
|
+
const data = Buffer.alloc(allocLength)
|
|
21
|
+
const layoutFields = Object.assign({ instruction: type.index }, fields)
|
|
22
|
+
type.layout.encode(layoutFields, data)
|
|
23
|
+
|
|
24
|
+
return data
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Decode instruction data buffer using an InstructionType
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export function decodeData(type: InstructionType, buffer: Buffer): any {
|
|
32
|
+
let data
|
|
33
|
+
try {
|
|
34
|
+
data = type.layout.decode(buffer)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
throw new Error(`invalid instruction; ${err}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (data.instruction !== type.index) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`invalid instruction; instruction index mismatch ${data.instruction} != ${type.index}`,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return data
|
|
46
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LAMPORTS_PER_SOL } from '@solana/web3.js'
|
|
2
|
+
import BN from 'bn.js'
|
|
3
|
+
|
|
4
|
+
export function solToLamports(amount: number): number {
|
|
5
|
+
if (isNaN(amount)) {
|
|
6
|
+
return Number(0)
|
|
7
|
+
}
|
|
8
|
+
return Number(amount * LAMPORTS_PER_SOL)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function lamportsToSol(lamports: number | BN | bigint): number {
|
|
12
|
+
if (typeof lamports === 'number') {
|
|
13
|
+
return Math.abs(lamports) / LAMPORTS_PER_SOL
|
|
14
|
+
}
|
|
15
|
+
if (typeof lamports === 'bigint') {
|
|
16
|
+
return Math.abs(Number(lamports)) / LAMPORTS_PER_SOL
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let signMultiplier = 1
|
|
20
|
+
if (lamports.isNeg()) {
|
|
21
|
+
signMultiplier = -1
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const absLamports = lamports.abs()
|
|
25
|
+
const lamportsString = absLamports.toString(10).padStart(10, '0')
|
|
26
|
+
const splitIndex = lamportsString.length - 9
|
|
27
|
+
const solString = `${lamportsString.slice(0, splitIndex)}.${lamportsString.slice(splitIndex)}`
|
|
28
|
+
return signMultiplier * Number.parseFloat(solString)
|
|
29
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer'
|
|
2
|
+
import { PublicKey } from '@solana/web3.js'
|
|
3
|
+
import BN from 'bn.js'
|
|
4
|
+
import {
|
|
5
|
+
EPHEMERAL_STAKE_SEED_PREFIX,
|
|
6
|
+
METADATA_PROGRAM_ID,
|
|
7
|
+
TRANSIENT_STAKE_SEED_PREFIX,
|
|
8
|
+
USER_STAKE_SEED_PREFIX,
|
|
9
|
+
} from '../constants'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates the wSOL transient program address for the stake pool
|
|
13
|
+
*/
|
|
14
|
+
export function findWsolTransientProgramAddress(
|
|
15
|
+
programId: PublicKey,
|
|
16
|
+
userPubkey: PublicKey,
|
|
17
|
+
) {
|
|
18
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
19
|
+
[Buffer.from('transient_wsol'), userPubkey.toBuffer()],
|
|
20
|
+
programId,
|
|
21
|
+
)
|
|
22
|
+
return publicKey
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Generates the withdraw authority program address for the stake pool
|
|
27
|
+
*/
|
|
28
|
+
export async function findWithdrawAuthorityProgramAddress(
|
|
29
|
+
programId: PublicKey,
|
|
30
|
+
stakePoolAddress: PublicKey,
|
|
31
|
+
) {
|
|
32
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
33
|
+
[stakePoolAddress.toBuffer(), Buffer.from('withdraw')],
|
|
34
|
+
programId,
|
|
35
|
+
)
|
|
36
|
+
return publicKey
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generates the stake program address for a validator's vote account
|
|
41
|
+
*/
|
|
42
|
+
export async function findStakeProgramAddress(
|
|
43
|
+
programId: PublicKey,
|
|
44
|
+
voteAccountAddress: PublicKey,
|
|
45
|
+
stakePoolAddress: PublicKey,
|
|
46
|
+
seed?: number,
|
|
47
|
+
) {
|
|
48
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
49
|
+
[
|
|
50
|
+
voteAccountAddress.toBuffer(),
|
|
51
|
+
stakePoolAddress.toBuffer(),
|
|
52
|
+
seed ? new BN(seed).toArrayLike(Buffer, 'le', 4) : Buffer.alloc(0),
|
|
53
|
+
],
|
|
54
|
+
programId,
|
|
55
|
+
)
|
|
56
|
+
return publicKey
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Generates the stake program address for a validator's vote account
|
|
61
|
+
*/
|
|
62
|
+
export async function findTransientStakeProgramAddress(
|
|
63
|
+
programId: PublicKey,
|
|
64
|
+
voteAccountAddress: PublicKey,
|
|
65
|
+
stakePoolAddress: PublicKey,
|
|
66
|
+
seed: BN,
|
|
67
|
+
) {
|
|
68
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
69
|
+
[
|
|
70
|
+
TRANSIENT_STAKE_SEED_PREFIX,
|
|
71
|
+
voteAccountAddress.toBuffer(),
|
|
72
|
+
stakePoolAddress.toBuffer(),
|
|
73
|
+
seed.toArrayLike(Buffer, 'le', 8),
|
|
74
|
+
],
|
|
75
|
+
programId,
|
|
76
|
+
)
|
|
77
|
+
return publicKey
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generates the ephemeral program address for stake pool redelegation
|
|
82
|
+
*/
|
|
83
|
+
export async function findEphemeralStakeProgramAddress(
|
|
84
|
+
programId: PublicKey,
|
|
85
|
+
stakePoolAddress: PublicKey,
|
|
86
|
+
seed: BN,
|
|
87
|
+
) {
|
|
88
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
89
|
+
[EPHEMERAL_STAKE_SEED_PREFIX, stakePoolAddress.toBuffer(), seed.toArrayLike(Buffer, 'le', 8)],
|
|
90
|
+
programId,
|
|
91
|
+
)
|
|
92
|
+
return publicKey
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Generates the metadata program address for the stake pool
|
|
97
|
+
*/
|
|
98
|
+
export function findMetadataAddress(stakePoolMintAddress: PublicKey) {
|
|
99
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
100
|
+
[Buffer.from('metadata'), METADATA_PROGRAM_ID.toBuffer(), stakePoolMintAddress.toBuffer()],
|
|
101
|
+
METADATA_PROGRAM_ID,
|
|
102
|
+
)
|
|
103
|
+
return publicKey
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Generates the user stake account PDA for session-based withdrawals.
|
|
108
|
+
* The PDA is derived from the user's wallet and a unique seed.
|
|
109
|
+
*/
|
|
110
|
+
export function findUserStakeProgramAddress(
|
|
111
|
+
programId: PublicKey,
|
|
112
|
+
userWallet: PublicKey,
|
|
113
|
+
seed: BN | number,
|
|
114
|
+
) {
|
|
115
|
+
const seedBN = typeof seed === 'number' ? new BN(seed) : seed
|
|
116
|
+
const [publicKey] = PublicKey.findProgramAddressSync(
|
|
117
|
+
[
|
|
118
|
+
USER_STAKE_SEED_PREFIX,
|
|
119
|
+
userWallet.toBuffer(),
|
|
120
|
+
seedBN.toArrayLike(Buffer, 'le', 8),
|
|
121
|
+
],
|
|
122
|
+
programId,
|
|
123
|
+
)
|
|
124
|
+
return publicKey
|
|
125
|
+
}
|