@zcomb/programs-sdk 1.5.1 → 1.7.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/dist/futarchy/client.d.ts +19 -4
- package/dist/futarchy/client.js +68 -19
- package/dist/generated/idls/index.d.ts +1 -0
- package/dist/generated/idls/index.js +4 -2
- package/dist/generated/idls/svault.json +2228 -0
- package/dist/generated/types/index.d.ts +1 -0
- package/dist/generated/types/index.js +1 -1
- package/dist/generated/types/svault.d.ts +2234 -0
- package/dist/generated/types/svault.js +3 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +28 -3
- package/dist/svault/client.d.ts +1231 -0
- package/dist/svault/client.js +190 -0
- package/dist/svault/constants.d.ts +7 -0
- package/dist/svault/constants.js +20 -0
- package/dist/svault/index.d.ts +5 -0
- package/dist/svault/index.js +22 -0
- package/dist/svault/instructions.d.ts +1204 -0
- package/dist/svault/instructions.js +172 -0
- package/dist/svault/types.d.ts +46 -0
- package/dist/svault/types.js +7 -0
- package/dist/svault/utils.d.ts +32 -0
- package/dist/svault/utils.js +86 -0
- package/package.json +1 -1
- package/src/futarchy/client.ts +87 -19
- package/src/generated/idls/index.ts +1 -0
- package/src/generated/idls/svault.json +2228 -0
- package/src/generated/types/index.ts +1 -0
- package/src/generated/types/svault.ts +2234 -0
- package/src/index.ts +43 -1
- package/src/svault/client.ts +401 -0
- package/src/svault/constants.ts +23 -0
- package/src/svault/index.ts +5 -0
- package/src/svault/instructions.ts +258 -0
- package/src/svault/types.ts +45 -0
- package/src/svault/utils.ts +145 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Low-level instruction builders for the SVault program.
|
|
4
|
+
* These are thin wrappers around the program methods - use SVaultClient for higher-level operations.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.FEE_AUTHORITY = void 0;
|
|
8
|
+
exports.initializeStakingVault = initializeStakingVault;
|
|
9
|
+
exports.stake = stake;
|
|
10
|
+
exports.initiateUnstake = initiateUnstake;
|
|
11
|
+
exports.withdraw = withdraw;
|
|
12
|
+
exports.postRewards = postRewards;
|
|
13
|
+
exports.claimRewards = claimRewards;
|
|
14
|
+
exports.setConfig = setConfig;
|
|
15
|
+
exports.slash = slash;
|
|
16
|
+
exports.addDelegate = addDelegate;
|
|
17
|
+
exports.removeDelegate = removeDelegate;
|
|
18
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
19
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
20
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
21
|
+
const utils_1 = require("./utils");
|
|
22
|
+
/* Fee Authority (same as AMM program) */
|
|
23
|
+
exports.FEE_AUTHORITY = new web3_js_1.PublicKey("FEEnkcCNE2623LYCPtLf63LFzXpCFigBLTu4qZovRGZC");
|
|
24
|
+
function initializeStakingVault(program, admin, tokenMint, unstakingPeriod, volumeWindow, nonce) {
|
|
25
|
+
const unstakingPeriodBN = typeof unstakingPeriod === "number" ? new anchor_1.BN(unstakingPeriod) : unstakingPeriod;
|
|
26
|
+
const volumeWindowBN = typeof volumeWindow === "number" ? new anchor_1.BN(volumeWindow) : volumeWindow;
|
|
27
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
28
|
+
const [stakeVault] = (0, utils_1.deriveStakeVaultPDA)(configPda, program.programId);
|
|
29
|
+
const [rewardVault] = (0, utils_1.deriveRewardVaultPDA)(configPda, program.programId);
|
|
30
|
+
return program.methods
|
|
31
|
+
.initializeStakingVault(unstakingPeriodBN, volumeWindowBN, nonce)
|
|
32
|
+
.accountsPartial({
|
|
33
|
+
admin,
|
|
34
|
+
tokenMint,
|
|
35
|
+
config: configPda,
|
|
36
|
+
stakeVault,
|
|
37
|
+
rewardVault,
|
|
38
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function stake(program, user, tokenMint, nonce, amount) {
|
|
42
|
+
const amountBN = typeof amount === "number" ? new anchor_1.BN(amount) : amount;
|
|
43
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
44
|
+
const [userStakePda] = (0, utils_1.deriveUserStakePDA)(configPda, user, program.programId);
|
|
45
|
+
const [stakeVault] = (0, utils_1.deriveStakeVaultPDA)(configPda, program.programId);
|
|
46
|
+
const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
|
|
47
|
+
return program.methods.stake(amountBN).accountsPartial({
|
|
48
|
+
user,
|
|
49
|
+
tokenMint,
|
|
50
|
+
config: configPda,
|
|
51
|
+
userStake: userStakePda,
|
|
52
|
+
stakeVault,
|
|
53
|
+
userTokenAccount,
|
|
54
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function initiateUnstake(program, user, tokenMint, nonce, amount) {
|
|
58
|
+
const amountBN = typeof amount === "number" ? new anchor_1.BN(amount) : amount;
|
|
59
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
60
|
+
const [userStakePda] = (0, utils_1.deriveUserStakePDA)(configPda, user, program.programId);
|
|
61
|
+
return program.methods.initiateUnstake(amountBN).accountsPartial({
|
|
62
|
+
user,
|
|
63
|
+
tokenMint,
|
|
64
|
+
config: configPda,
|
|
65
|
+
userStake: userStakePda,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function withdraw(program, user, tokenMint, nonce) {
|
|
69
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
70
|
+
const [userStakePda] = (0, utils_1.deriveUserStakePDA)(configPda, user, program.programId);
|
|
71
|
+
const [stakeVault] = (0, utils_1.deriveStakeVaultPDA)(configPda, program.programId);
|
|
72
|
+
const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
|
|
73
|
+
return program.methods.withdraw().accountsPartial({
|
|
74
|
+
user,
|
|
75
|
+
tokenMint,
|
|
76
|
+
config: configPda,
|
|
77
|
+
userStake: userStakePda,
|
|
78
|
+
stakeVault,
|
|
79
|
+
userTokenAccount,
|
|
80
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function postRewards(program, admin, tokenMint, nonce, merkleRoot, totalAmount) {
|
|
84
|
+
const merkleRootArray = merkleRoot;
|
|
85
|
+
const totalAmountBN = typeof totalAmount === "number" ? new anchor_1.BN(totalAmount) : totalAmount;
|
|
86
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
87
|
+
const [rewardVault] = (0, utils_1.deriveRewardVaultPDA)(configPda, program.programId);
|
|
88
|
+
const adminTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, admin);
|
|
89
|
+
return program.methods
|
|
90
|
+
.postRewards(merkleRootArray, totalAmountBN)
|
|
91
|
+
.accountsPartial({
|
|
92
|
+
admin,
|
|
93
|
+
tokenMint,
|
|
94
|
+
config: configPda,
|
|
95
|
+
rewardVault,
|
|
96
|
+
adminTokenAccount,
|
|
97
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function claimRewards(program, user, tokenMint, nonce, cumulativeAmount, proof) {
|
|
101
|
+
const cumulativeAmountBN = typeof cumulativeAmount === "number" ? new anchor_1.BN(cumulativeAmount) : cumulativeAmount;
|
|
102
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
103
|
+
const [userStakePda] = (0, utils_1.deriveUserStakePDA)(configPda, user, program.programId);
|
|
104
|
+
const [rewardVault] = (0, utils_1.deriveRewardVaultPDA)(configPda, program.programId);
|
|
105
|
+
const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
|
|
106
|
+
return program.methods
|
|
107
|
+
.claimRewards(cumulativeAmountBN, proof)
|
|
108
|
+
.accountsPartial({
|
|
109
|
+
user,
|
|
110
|
+
tokenMint,
|
|
111
|
+
config: configPda,
|
|
112
|
+
userStake: userStakePda,
|
|
113
|
+
rewardVault,
|
|
114
|
+
userTokenAccount,
|
|
115
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function setConfig(program, admin, tokenMint, nonce, unstakingPeriod, volumeWindow) {
|
|
119
|
+
const unstakingPeriodArg = unstakingPeriod === null
|
|
120
|
+
? null
|
|
121
|
+
: typeof unstakingPeriod === "number"
|
|
122
|
+
? new anchor_1.BN(unstakingPeriod)
|
|
123
|
+
: unstakingPeriod;
|
|
124
|
+
const volumeWindowArg = volumeWindow === null
|
|
125
|
+
? null
|
|
126
|
+
: typeof volumeWindow === "number"
|
|
127
|
+
? new anchor_1.BN(volumeWindow)
|
|
128
|
+
: volumeWindow;
|
|
129
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
130
|
+
return program.methods
|
|
131
|
+
.setConfig(unstakingPeriodArg, volumeWindowArg)
|
|
132
|
+
.accountsPartial({
|
|
133
|
+
admin,
|
|
134
|
+
config: configPda,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function slash(program, admin, tokenMint, nonce, userStakePda, basisPoints) {
|
|
138
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
139
|
+
const [stakeVault] = (0, utils_1.deriveStakeVaultPDA)(configPda, program.programId);
|
|
140
|
+
const feeVault = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, exports.FEE_AUTHORITY);
|
|
141
|
+
return program.methods.slash(basisPoints).accountsPartial({
|
|
142
|
+
admin,
|
|
143
|
+
tokenMint,
|
|
144
|
+
config: configPda,
|
|
145
|
+
userStake: userStakePda,
|
|
146
|
+
stakeVault,
|
|
147
|
+
feeVault,
|
|
148
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function addDelegate(program, staker, delegateWallet, tokenMint, nonce) {
|
|
152
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
153
|
+
const [userStakePda] = (0, utils_1.deriveUserStakePDA)(configPda, staker, program.programId);
|
|
154
|
+
const [delegatePda] = (0, utils_1.deriveDelegatePDA)(configPda, delegateWallet, program.programId);
|
|
155
|
+
return program.methods.addDelegate().accountsPartial({
|
|
156
|
+
staker,
|
|
157
|
+
delegateWallet,
|
|
158
|
+
config: configPda,
|
|
159
|
+
userStake: userStakePda,
|
|
160
|
+
delegate: delegatePda,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function removeDelegate(program, staker, delegateWallet, tokenMint, nonce) {
|
|
164
|
+
const [configPda] = (0, utils_1.deriveStakingConfigPDA)(tokenMint, nonce, program.programId);
|
|
165
|
+
const [delegatePda] = (0, utils_1.deriveDelegatePDA)(configPda, delegateWallet, program.programId);
|
|
166
|
+
return program.methods.removeDelegate().accountsPartial({
|
|
167
|
+
staker,
|
|
168
|
+
config: configPda,
|
|
169
|
+
delegate: delegatePda,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1Y3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N2YXVsdC9pbnN0cnVjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBaUJILHdEQXlCQztBQUVELHNCQXVCQztBQUVELDBDQWtCQztBQUVELDRCQW9CQztBQUVELGtDQXlCQztBQUVELG9DQTBCQztBQUVELDhCQTRCQztBQUVELHNCQXFCQztBQUVELGtDQWtCQztBQUVELHdDQWVDO0FBNVBELDhDQUFnRDtBQUNoRCw2Q0FBNEM7QUFDNUMsaURBQW9GO0FBRXBGLG1DQU1pQjtBQUVqQix5Q0FBeUM7QUFDNUIsUUFBQSxhQUFhLEdBQUcsSUFBSSxtQkFBUyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7QUFFM0YsU0FBZ0Isc0JBQXNCLENBQ3BDLE9BQXdCLEVBQ3hCLEtBQWdCLEVBQ2hCLFNBQW9CLEVBQ3BCLGVBQTRCLEVBQzVCLFlBQXlCLEVBQ3pCLEtBQWE7SUFFYixNQUFNLGlCQUFpQixHQUFHLE9BQU8sZUFBZSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztJQUMxRyxNQUFNLGNBQWMsR0FBRyxPQUFPLFlBQVksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksV0FBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUM7SUFFOUYsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUEsOEJBQXNCLEVBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLElBQUEsMkJBQW1CLEVBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2RSxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBQSw0QkFBb0IsRUFBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRXpFLE9BQU8sT0FBTyxDQUFDLE9BQU87U0FDbkIsc0JBQXNCLENBQUMsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLEtBQUssQ0FBQztTQUNoRSxlQUFlLENBQUM7UUFDZixLQUFLO1FBQ0wsU0FBUztRQUNULE1BQU0sRUFBRSxTQUFTO1FBQ2pCLFVBQVU7UUFDVixXQUFXO1FBQ1gsWUFBWSxFQUFFLDRCQUFnQjtLQUMvQixDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQsU0FBZ0IsS0FBSyxDQUNuQixPQUF3QixFQUN4QixJQUFlLEVBQ2YsU0FBb0IsRUFDcEIsS0FBYSxFQUNiLE1BQW1CO0lBRW5CLE1BQU0sUUFBUSxHQUFHLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUV0RSxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBQSw4QkFBc0IsRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBQSwwQkFBa0IsRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM5RSxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsSUFBQSwyQkFBbUIsRUFBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSx5Q0FBNkIsRUFBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFeEUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxlQUFlLENBQUM7UUFDckQsSUFBSTtRQUNKLFNBQVM7UUFDVCxNQUFNLEVBQUUsU0FBUztRQUNqQixTQUFTLEVBQUUsWUFBWTtRQUN2QixVQUFVO1FBQ1YsZ0JBQWdCO1FBQ2hCLFlBQVksRUFBRSw0QkFBZ0I7S0FDL0IsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQWdCLGVBQWUsQ0FDN0IsT0FBd0IsRUFDeEIsSUFBZSxFQUNmLFNBQW9CLEVBQ3BCLEtBQWEsRUFDYixNQUFtQjtJQUVuQixNQUFNLFFBQVEsR0FBRyxPQUFPLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksV0FBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFFdEUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUEsOEJBQXNCLEVBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEYsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLElBQUEsMEJBQWtCLEVBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFOUUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxlQUFlLENBQUM7UUFDL0QsSUFBSTtRQUNKLFNBQVM7UUFDVCxNQUFNLEVBQUUsU0FBUztRQUNqQixTQUFTLEVBQUUsWUFBWTtLQUN4QixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBZ0IsUUFBUSxDQUN0QixPQUF3QixFQUN4QixJQUFlLEVBQ2YsU0FBb0IsRUFDcEIsS0FBYTtJQUViLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFBLDhCQUFzQixFQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxJQUFBLDBCQUFrQixFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlFLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFBLDJCQUFtQixFQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkUsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLHlDQUE2QixFQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RSxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsZUFBZSxDQUFDO1FBQ2hELElBQUk7UUFDSixTQUFTO1FBQ1QsTUFBTSxFQUFFLFNBQVM7UUFDakIsU0FBUyxFQUFFLFlBQVk7UUFDdkIsVUFBVTtRQUNWLGdCQUFnQjtRQUNoQixZQUFZLEVBQUUsNEJBQWdCO0tBQy9CLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFnQixXQUFXLENBQ3pCLE9BQXdCLEVBQ3hCLEtBQWdCLEVBQ2hCLFNBQW9CLEVBQ3BCLEtBQWEsRUFDYixVQUFvQixFQUNwQixXQUF3QjtJQUV4QixNQUFNLGVBQWUsR0FBRyxVQUFzQixDQUFDO0lBQy9DLE1BQU0sYUFBYSxHQUFHLE9BQU8sV0FBVyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztJQUUxRixNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBQSw4QkFBc0IsRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRixNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBQSw0QkFBb0IsRUFBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0saUJBQWlCLEdBQUcsSUFBQSx5Q0FBNkIsRUFBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFMUUsT0FBTyxPQUFPLENBQUMsT0FBTztTQUNuQixXQUFXLENBQUMsZUFBZSxFQUFFLGFBQWEsQ0FBQztTQUMzQyxlQUFlLENBQUM7UUFDZixLQUFLO1FBQ0wsU0FBUztRQUNULE1BQU0sRUFBRSxTQUFTO1FBQ2pCLFdBQVc7UUFDWCxpQkFBaUI7UUFDakIsWUFBWSxFQUFFLDRCQUFnQjtLQUMvQixDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQsU0FBZ0IsWUFBWSxDQUMxQixPQUF3QixFQUN4QixJQUFlLEVBQ2YsU0FBb0IsRUFDcEIsS0FBYSxFQUNiLGdCQUE2QixFQUM3QixLQUFpQjtJQUVqQixNQUFNLGtCQUFrQixHQUFHLE9BQU8sZ0JBQWdCLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQztJQUU5RyxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBQSw4QkFBc0IsRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBQSwwQkFBa0IsRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM5RSxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBQSw0QkFBb0IsRUFBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSx5Q0FBNkIsRUFBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFeEUsT0FBTyxPQUFPLENBQUMsT0FBTztTQUNuQixZQUFZLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDO1NBQ3ZDLGVBQWUsQ0FBQztRQUNmLElBQUk7UUFDSixTQUFTO1FBQ1QsTUFBTSxFQUFFLFNBQVM7UUFDakIsU0FBUyxFQUFFLFlBQVk7UUFDdkIsV0FBVztRQUNYLGdCQUFnQjtRQUNoQixZQUFZLEVBQUUsNEJBQWdCO0tBQy9CLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxTQUFnQixTQUFTLENBQ3ZCLE9BQXdCLEVBQ3hCLEtBQWdCLEVBQ2hCLFNBQW9CLEVBQ3BCLEtBQWEsRUFDYixlQUFtQyxFQUNuQyxZQUFnQztJQUVoQyxNQUFNLGtCQUFrQixHQUFHLGVBQWUsS0FBSyxJQUFJO1FBQ2pELENBQUMsQ0FBQyxJQUFJO1FBQ04sQ0FBQyxDQUFDLE9BQU8sZUFBZSxLQUFLLFFBQVE7WUFDbkMsQ0FBQyxDQUFDLElBQUksV0FBRSxDQUFDLGVBQWUsQ0FBQztZQUN6QixDQUFDLENBQUMsZUFBZSxDQUFDO0lBRXRCLE1BQU0sZUFBZSxHQUFHLFlBQVksS0FBSyxJQUFJO1FBQzNDLENBQUMsQ0FBQyxJQUFJO1FBQ04sQ0FBQyxDQUFDLE9BQU8sWUFBWSxLQUFLLFFBQVE7WUFDaEMsQ0FBQyxDQUFDLElBQUksV0FBRSxDQUFDLFlBQVksQ0FBQztZQUN0QixDQUFDLENBQUMsWUFBWSxDQUFDO0lBRW5CLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFBLDhCQUFzQixFQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRWhGLE9BQU8sT0FBTyxDQUFDLE9BQU87U0FDbkIsU0FBUyxDQUFDLGtCQUFrQixFQUFFLGVBQWUsQ0FBQztTQUM5QyxlQUFlLENBQUM7UUFDZixLQUFLO1FBQ0wsTUFBTSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELFNBQWdCLEtBQUssQ0FDbkIsT0FBd0IsRUFDeEIsS0FBZ0IsRUFDaEIsU0FBb0IsRUFDcEIsS0FBYSxFQUNiLFlBQXVCLEVBQ3ZCLFdBQW1CO0lBRW5CLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFBLDhCQUFzQixFQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFBLDJCQUFtQixFQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkUsTUFBTSxRQUFRLEdBQUcsSUFBQSx5Q0FBNkIsRUFBQyxTQUFTLEVBQUUscUJBQWEsQ0FBQyxDQUFDO0lBRXpFLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsZUFBZSxDQUFDO1FBQ3hELEtBQUs7UUFDTCxTQUFTO1FBQ1QsTUFBTSxFQUFFLFNBQVM7UUFDakIsU0FBUyxFQUFFLFlBQVk7UUFDdkIsVUFBVTtRQUNWLFFBQVE7UUFDUixZQUFZLEVBQUUsNEJBQWdCO0tBQy9CLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFnQixXQUFXLENBQ3pCLE9BQXdCLEVBQ3hCLE1BQWlCLEVBQ2pCLGNBQXlCLEVBQ3pCLFNBQW9CLEVBQ3BCLEtBQWE7SUFFYixNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBQSw4QkFBc0IsRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBQSwwQkFBa0IsRUFBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRixNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBQSx5QkFBaUIsRUFBQyxTQUFTLEVBQUUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUV0RixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsZUFBZSxDQUFDO1FBQ25ELE1BQU07UUFDTixjQUFjO1FBQ2QsTUFBTSxFQUFFLFNBQVM7UUFDakIsU0FBUyxFQUFFLFlBQVk7UUFDdkIsUUFBUSxFQUFFLFdBQVc7S0FDdEIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQWdCLGNBQWMsQ0FDNUIsT0FBd0IsRUFDeEIsTUFBaUIsRUFDakIsY0FBeUIsRUFDekIsU0FBb0IsRUFDcEIsS0FBYTtJQUViLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFBLDhCQUFzQixFQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxJQUFBLHlCQUFpQixFQUFDLFNBQVMsRUFBRSxjQUFjLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRXRGLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxlQUFlLENBQUM7UUFDdEQsTUFBTTtRQUNOLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLFFBQVEsRUFBRSxXQUFXO0tBQ3RCLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogTG93LWxldmVsIGluc3RydWN0aW9uIGJ1aWxkZXJzIGZvciB0aGUgU1ZhdWx0IHByb2dyYW0uXG4gKiBUaGVzZSBhcmUgdGhpbiB3cmFwcGVycyBhcm91bmQgdGhlIHByb2dyYW0gbWV0aG9kcyAtIHVzZSBTVmF1bHRDbGllbnQgZm9yIGhpZ2hlci1sZXZlbCBvcGVyYXRpb25zLlxuICovXG5cbmltcG9ydCB7IFByb2dyYW0sIEJOIH0gZnJvbSBcIkBjb3JhbC14eXovYW5jaG9yXCI7XG5pbXBvcnQgeyBQdWJsaWNLZXkgfSBmcm9tIFwiQHNvbGFuYS93ZWIzLmpzXCI7XG5pbXBvcnQgeyBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYywgVE9LRU5fUFJPR1JBTV9JRCB9IGZyb20gXCJAc29sYW5hL3NwbC10b2tlblwiO1xuaW1wb3J0IHsgU3ZhdWx0IH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7XG4gIGRlcml2ZVN0YWtpbmdDb25maWdQREEsXG4gIGRlcml2ZVVzZXJTdGFrZVBEQSxcbiAgZGVyaXZlU3Rha2VWYXVsdFBEQSxcbiAgZGVyaXZlUmV3YXJkVmF1bHRQREEsXG4gIGRlcml2ZURlbGVnYXRlUERBLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKiBGZWUgQXV0aG9yaXR5IChzYW1lIGFzIEFNTSBwcm9ncmFtKSAqL1xuZXhwb3J0IGNvbnN0IEZFRV9BVVRIT1JJVFkgPSBuZXcgUHVibGljS2V5KFwiRkVFbmtjQ05FMjYyM0xZQ1B0TGY2M0xGelhwQ0ZpZ0JMVHU0cVpvdlJHWkNcIik7XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplU3Rha2luZ1ZhdWx0KFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIGFkbWluOiBQdWJsaWNLZXksXG4gIHRva2VuTWludDogUHVibGljS2V5LFxuICB1bnN0YWtpbmdQZXJpb2Q6IEJOIHwgbnVtYmVyLFxuICB2b2x1bWVXaW5kb3c6IEJOIHwgbnVtYmVyLFxuICBub25jZTogbnVtYmVyXG4pIHtcbiAgY29uc3QgdW5zdGFraW5nUGVyaW9kQk4gPSB0eXBlb2YgdW5zdGFraW5nUGVyaW9kID09PSBcIm51bWJlclwiID8gbmV3IEJOKHVuc3Rha2luZ1BlcmlvZCkgOiB1bnN0YWtpbmdQZXJpb2Q7XG4gIGNvbnN0IHZvbHVtZVdpbmRvd0JOID0gdHlwZW9mIHZvbHVtZVdpbmRvdyA9PT0gXCJudW1iZXJcIiA/IG5ldyBCTih2b2x1bWVXaW5kb3cpIDogdm9sdW1lV2luZG93O1xuXG4gIGNvbnN0IFtjb25maWdQZGFdID0gZGVyaXZlU3Rha2luZ0NvbmZpZ1BEQSh0b2tlbk1pbnQsIG5vbmNlLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFtzdGFrZVZhdWx0XSA9IGRlcml2ZVN0YWtlVmF1bHRQREEoY29uZmlnUGRhLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFtyZXdhcmRWYXVsdF0gPSBkZXJpdmVSZXdhcmRWYXVsdFBEQShjb25maWdQZGEsIHByb2dyYW0ucHJvZ3JhbUlkKTtcblxuICByZXR1cm4gcHJvZ3JhbS5tZXRob2RzXG4gICAgLmluaXRpYWxpemVTdGFraW5nVmF1bHQodW5zdGFraW5nUGVyaW9kQk4sIHZvbHVtZVdpbmRvd0JOLCBub25jZSlcbiAgICAuYWNjb3VudHNQYXJ0aWFsKHtcbiAgICAgIGFkbWluLFxuICAgICAgdG9rZW5NaW50LFxuICAgICAgY29uZmlnOiBjb25maWdQZGEsXG4gICAgICBzdGFrZVZhdWx0LFxuICAgICAgcmV3YXJkVmF1bHQsXG4gICAgICB0b2tlblByb2dyYW06IFRPS0VOX1BST0dSQU1fSUQsXG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFrZShcbiAgcHJvZ3JhbTogUHJvZ3JhbTxTdmF1bHQ+LFxuICB1c2VyOiBQdWJsaWNLZXksXG4gIHRva2VuTWludDogUHVibGljS2V5LFxuICBub25jZTogbnVtYmVyLFxuICBhbW91bnQ6IEJOIHwgbnVtYmVyXG4pIHtcbiAgY29uc3QgYW1vdW50Qk4gPSB0eXBlb2YgYW1vdW50ID09PSBcIm51bWJlclwiID8gbmV3IEJOKGFtb3VudCkgOiBhbW91bnQ7XG5cbiAgY29uc3QgW2NvbmZpZ1BkYV0gPSBkZXJpdmVTdGFraW5nQ29uZmlnUERBKHRva2VuTWludCwgbm9uY2UsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgW3VzZXJTdGFrZVBkYV0gPSBkZXJpdmVVc2VyU3Rha2VQREEoY29uZmlnUGRhLCB1c2VyLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFtzdGFrZVZhdWx0XSA9IGRlcml2ZVN0YWtlVmF1bHRQREEoY29uZmlnUGRhLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IHVzZXJUb2tlbkFjY291bnQgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh0b2tlbk1pbnQsIHVzZXIpO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHMuc3Rha2UoYW1vdW50Qk4pLmFjY291bnRzUGFydGlhbCh7XG4gICAgdXNlcixcbiAgICB0b2tlbk1pbnQsXG4gICAgY29uZmlnOiBjb25maWdQZGEsXG4gICAgdXNlclN0YWtlOiB1c2VyU3Rha2VQZGEsXG4gICAgc3Rha2VWYXVsdCxcbiAgICB1c2VyVG9rZW5BY2NvdW50LFxuICAgIHRva2VuUHJvZ3JhbTogVE9LRU5fUFJPR1JBTV9JRCxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWF0ZVVuc3Rha2UoXG4gIHByb2dyYW06IFByb2dyYW08U3ZhdWx0PixcbiAgdXNlcjogUHVibGljS2V5LFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlcixcbiAgYW1vdW50OiBCTiB8IG51bWJlclxuKSB7XG4gIGNvbnN0IGFtb3VudEJOID0gdHlwZW9mIGFtb3VudCA9PT0gXCJudW1iZXJcIiA/IG5ldyBCTihhbW91bnQpIDogYW1vdW50O1xuXG4gIGNvbnN0IFtjb25maWdQZGFdID0gZGVyaXZlU3Rha2luZ0NvbmZpZ1BEQSh0b2tlbk1pbnQsIG5vbmNlLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFt1c2VyU3Rha2VQZGFdID0gZGVyaXZlVXNlclN0YWtlUERBKGNvbmZpZ1BkYSwgdXNlciwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHMuaW5pdGlhdGVVbnN0YWtlKGFtb3VudEJOKS5hY2NvdW50c1BhcnRpYWwoe1xuICAgIHVzZXIsXG4gICAgdG9rZW5NaW50LFxuICAgIGNvbmZpZzogY29uZmlnUGRhLFxuICAgIHVzZXJTdGFrZTogdXNlclN0YWtlUGRhLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpdGhkcmF3KFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIHVzZXI6IFB1YmxpY0tleSxcbiAgdG9rZW5NaW50OiBQdWJsaWNLZXksXG4gIG5vbmNlOiBudW1iZXJcbikge1xuICBjb25zdCBbY29uZmlnUGRhXSA9IGRlcml2ZVN0YWtpbmdDb25maWdQREEodG9rZW5NaW50LCBub25jZSwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuICBjb25zdCBbdXNlclN0YWtlUGRhXSA9IGRlcml2ZVVzZXJTdGFrZVBEQShjb25maWdQZGEsIHVzZXIsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgW3N0YWtlVmF1bHRdID0gZGVyaXZlU3Rha2VWYXVsdFBEQShjb25maWdQZGEsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgdXNlclRva2VuQWNjb3VudCA9IGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKHRva2VuTWludCwgdXNlcik7XG5cbiAgcmV0dXJuIHByb2dyYW0ubWV0aG9kcy53aXRoZHJhdygpLmFjY291bnRzUGFydGlhbCh7XG4gICAgdXNlcixcbiAgICB0b2tlbk1pbnQsXG4gICAgY29uZmlnOiBjb25maWdQZGEsXG4gICAgdXNlclN0YWtlOiB1c2VyU3Rha2VQZGEsXG4gICAgc3Rha2VWYXVsdCxcbiAgICB1c2VyVG9rZW5BY2NvdW50LFxuICAgIHRva2VuUHJvZ3JhbTogVE9LRU5fUFJPR1JBTV9JRCxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwb3N0UmV3YXJkcyhcbiAgcHJvZ3JhbTogUHJvZ3JhbTxTdmF1bHQ+LFxuICBhZG1pbjogUHVibGljS2V5LFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlcixcbiAgbWVya2xlUm9vdDogbnVtYmVyW10sXG4gIHRvdGFsQW1vdW50OiBCTiB8IG51bWJlclxuKSB7XG4gIGNvbnN0IG1lcmtsZVJvb3RBcnJheSA9IG1lcmtsZVJvb3QgYXMgbnVtYmVyW107XG4gIGNvbnN0IHRvdGFsQW1vdW50Qk4gPSB0eXBlb2YgdG90YWxBbW91bnQgPT09IFwibnVtYmVyXCIgPyBuZXcgQk4odG90YWxBbW91bnQpIDogdG90YWxBbW91bnQ7XG5cbiAgY29uc3QgW2NvbmZpZ1BkYV0gPSBkZXJpdmVTdGFraW5nQ29uZmlnUERBKHRva2VuTWludCwgbm9uY2UsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgW3Jld2FyZFZhdWx0XSA9IGRlcml2ZVJld2FyZFZhdWx0UERBKGNvbmZpZ1BkYSwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuICBjb25zdCBhZG1pblRva2VuQWNjb3VudCA9IGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKHRva2VuTWludCwgYWRtaW4pO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHNcbiAgICAucG9zdFJld2FyZHMobWVya2xlUm9vdEFycmF5LCB0b3RhbEFtb3VudEJOKVxuICAgIC5hY2NvdW50c1BhcnRpYWwoe1xuICAgICAgYWRtaW4sXG4gICAgICB0b2tlbk1pbnQsXG4gICAgICBjb25maWc6IGNvbmZpZ1BkYSxcbiAgICAgIHJld2FyZFZhdWx0LFxuICAgICAgYWRtaW5Ub2tlbkFjY291bnQsXG4gICAgICB0b2tlblByb2dyYW06IFRPS0VOX1BST0dSQU1fSUQsXG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGFpbVJld2FyZHMoXG4gIHByb2dyYW06IFByb2dyYW08U3ZhdWx0PixcbiAgdXNlcjogUHVibGljS2V5LFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlcixcbiAgY3VtdWxhdGl2ZUFtb3VudDogQk4gfCBudW1iZXIsXG4gIHByb29mOiBudW1iZXJbXVtdXG4pIHtcbiAgY29uc3QgY3VtdWxhdGl2ZUFtb3VudEJOID0gdHlwZW9mIGN1bXVsYXRpdmVBbW91bnQgPT09IFwibnVtYmVyXCIgPyBuZXcgQk4oY3VtdWxhdGl2ZUFtb3VudCkgOiBjdW11bGF0aXZlQW1vdW50O1xuXG4gIGNvbnN0IFtjb25maWdQZGFdID0gZGVyaXZlU3Rha2luZ0NvbmZpZ1BEQSh0b2tlbk1pbnQsIG5vbmNlLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFt1c2VyU3Rha2VQZGFdID0gZGVyaXZlVXNlclN0YWtlUERBKGNvbmZpZ1BkYSwgdXNlciwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuICBjb25zdCBbcmV3YXJkVmF1bHRdID0gZGVyaXZlUmV3YXJkVmF1bHRQREEoY29uZmlnUGRhLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IHVzZXJUb2tlbkFjY291bnQgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh0b2tlbk1pbnQsIHVzZXIpO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHNcbiAgICAuY2xhaW1SZXdhcmRzKGN1bXVsYXRpdmVBbW91bnRCTiwgcHJvb2YpXG4gICAgLmFjY291bnRzUGFydGlhbCh7XG4gICAgICB1c2VyLFxuICAgICAgdG9rZW5NaW50LFxuICAgICAgY29uZmlnOiBjb25maWdQZGEsXG4gICAgICB1c2VyU3Rha2U6IHVzZXJTdGFrZVBkYSxcbiAgICAgIHJld2FyZFZhdWx0LFxuICAgICAgdXNlclRva2VuQWNjb3VudCxcbiAgICAgIHRva2VuUHJvZ3JhbTogVE9LRU5fUFJPR1JBTV9JRCxcbiAgICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldENvbmZpZyhcbiAgcHJvZ3JhbTogUHJvZ3JhbTxTdmF1bHQ+LFxuICBhZG1pbjogUHVibGljS2V5LFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlcixcbiAgdW5zdGFraW5nUGVyaW9kOiBCTiB8IG51bWJlciB8IG51bGwsXG4gIHZvbHVtZVdpbmRvdzogQk4gfCBudW1iZXIgfCBudWxsXG4pIHtcbiAgY29uc3QgdW5zdGFraW5nUGVyaW9kQXJnID0gdW5zdGFraW5nUGVyaW9kID09PSBudWxsXG4gICAgPyBudWxsXG4gICAgOiB0eXBlb2YgdW5zdGFraW5nUGVyaW9kID09PSBcIm51bWJlclwiXG4gICAgICA/IG5ldyBCTih1bnN0YWtpbmdQZXJpb2QpXG4gICAgICA6IHVuc3Rha2luZ1BlcmlvZDtcblxuICBjb25zdCB2b2x1bWVXaW5kb3dBcmcgPSB2b2x1bWVXaW5kb3cgPT09IG51bGxcbiAgICA/IG51bGxcbiAgICA6IHR5cGVvZiB2b2x1bWVXaW5kb3cgPT09IFwibnVtYmVyXCJcbiAgICAgID8gbmV3IEJOKHZvbHVtZVdpbmRvdylcbiAgICAgIDogdm9sdW1lV2luZG93O1xuXG4gIGNvbnN0IFtjb25maWdQZGFdID0gZGVyaXZlU3Rha2luZ0NvbmZpZ1BEQSh0b2tlbk1pbnQsIG5vbmNlLCBwcm9ncmFtLnByb2dyYW1JZCk7XG5cbiAgcmV0dXJuIHByb2dyYW0ubWV0aG9kc1xuICAgIC5zZXRDb25maWcodW5zdGFraW5nUGVyaW9kQXJnLCB2b2x1bWVXaW5kb3dBcmcpXG4gICAgLmFjY291bnRzUGFydGlhbCh7XG4gICAgICBhZG1pbixcbiAgICAgIGNvbmZpZzogY29uZmlnUGRhLFxuICAgIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2xhc2goXG4gIHByb2dyYW06IFByb2dyYW08U3ZhdWx0PixcbiAgYWRtaW46IFB1YmxpY0tleSxcbiAgdG9rZW5NaW50OiBQdWJsaWNLZXksXG4gIG5vbmNlOiBudW1iZXIsXG4gIHVzZXJTdGFrZVBkYTogUHVibGljS2V5LFxuICBiYXNpc1BvaW50czogbnVtYmVyXG4pIHtcbiAgY29uc3QgW2NvbmZpZ1BkYV0gPSBkZXJpdmVTdGFraW5nQ29uZmlnUERBKHRva2VuTWludCwgbm9uY2UsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgW3N0YWtlVmF1bHRdID0gZGVyaXZlU3Rha2VWYXVsdFBEQShjb25maWdQZGEsIHByb2dyYW0ucHJvZ3JhbUlkKTtcbiAgY29uc3QgZmVlVmF1bHQgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh0b2tlbk1pbnQsIEZFRV9BVVRIT1JJVFkpO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHMuc2xhc2goYmFzaXNQb2ludHMpLmFjY291bnRzUGFydGlhbCh7XG4gICAgYWRtaW4sXG4gICAgdG9rZW5NaW50LFxuICAgIGNvbmZpZzogY29uZmlnUGRhLFxuICAgIHVzZXJTdGFrZTogdXNlclN0YWtlUGRhLFxuICAgIHN0YWtlVmF1bHQsXG4gICAgZmVlVmF1bHQsXG4gICAgdG9rZW5Qcm9ncmFtOiBUT0tFTl9QUk9HUkFNX0lELFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZERlbGVnYXRlKFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIHN0YWtlcjogUHVibGljS2V5LFxuICBkZWxlZ2F0ZVdhbGxldDogUHVibGljS2V5LFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlclxuKSB7XG4gIGNvbnN0IFtjb25maWdQZGFdID0gZGVyaXZlU3Rha2luZ0NvbmZpZ1BEQSh0b2tlbk1pbnQsIG5vbmNlLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFt1c2VyU3Rha2VQZGFdID0gZGVyaXZlVXNlclN0YWtlUERBKGNvbmZpZ1BkYSwgc3Rha2VyLCBwcm9ncmFtLnByb2dyYW1JZCk7XG4gIGNvbnN0IFtkZWxlZ2F0ZVBkYV0gPSBkZXJpdmVEZWxlZ2F0ZVBEQShjb25maWdQZGEsIGRlbGVnYXRlV2FsbGV0LCBwcm9ncmFtLnByb2dyYW1JZCk7XG5cbiAgcmV0dXJuIHByb2dyYW0ubWV0aG9kcy5hZGREZWxlZ2F0ZSgpLmFjY291bnRzUGFydGlhbCh7XG4gICAgc3Rha2VyLFxuICAgIGRlbGVnYXRlV2FsbGV0LFxuICAgIGNvbmZpZzogY29uZmlnUGRhLFxuICAgIHVzZXJTdGFrZTogdXNlclN0YWtlUGRhLFxuICAgIGRlbGVnYXRlOiBkZWxlZ2F0ZVBkYSxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVEZWxlZ2F0ZShcbiAgcHJvZ3JhbTogUHJvZ3JhbTxTdmF1bHQ+LFxuICBzdGFrZXI6IFB1YmxpY0tleSxcbiAgZGVsZWdhdGVXYWxsZXQ6IFB1YmxpY0tleSxcbiAgdG9rZW5NaW50OiBQdWJsaWNLZXksXG4gIG5vbmNlOiBudW1iZXJcbikge1xuICBjb25zdCBbY29uZmlnUGRhXSA9IGRlcml2ZVN0YWtpbmdDb25maWdQREEodG9rZW5NaW50LCBub25jZSwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuICBjb25zdCBbZGVsZWdhdGVQZGFdID0gZGVyaXZlRGVsZWdhdGVQREEoY29uZmlnUGRhLCBkZWxlZ2F0ZVdhbGxldCwgcHJvZ3JhbS5wcm9ncmFtSWQpO1xuXG4gIHJldHVybiBwcm9ncmFtLm1ldGhvZHMucmVtb3ZlRGVsZWdhdGUoKS5hY2NvdW50c1BhcnRpYWwoe1xuICAgIHN0YWtlcixcbiAgICBjb25maWc6IGNvbmZpZ1BkYSxcbiAgICBkZWxlZ2F0ZTogZGVsZWdhdGVQZGEsXG4gIH0pO1xufVxuIl19
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IdlAccounts, IdlEvents } from "@coral-xyz/anchor";
|
|
2
|
+
import { TxOptions } from "../utils";
|
|
3
|
+
export { Svault } from "../generated/types";
|
|
4
|
+
import type { Svault } from "../generated/types";
|
|
5
|
+
export type StakingConfigAccount = IdlAccounts<Svault>["stakingConfig"];
|
|
6
|
+
export type UserStakeAccount = IdlAccounts<Svault>["userStake"];
|
|
7
|
+
export type DelegateAccount = IdlAccounts<Svault>["delegate"];
|
|
8
|
+
export type StakingVaultInitializedEvent = IdlEvents<Svault>["stakingVaultInitialized"];
|
|
9
|
+
export type StakedEvent = IdlEvents<Svault>["staked"];
|
|
10
|
+
export type UnstakeInitiatedEvent = IdlEvents<Svault>["unstakeInitiated"];
|
|
11
|
+
export type WithdrawnEvent = IdlEvents<Svault>["withdrawn"];
|
|
12
|
+
export type RewardsPostedEvent = IdlEvents<Svault>["rewardsPosted"];
|
|
13
|
+
export type RewardsClaimedEvent = IdlEvents<Svault>["rewardsClaimed"];
|
|
14
|
+
export type SlashedEvent = IdlEvents<Svault>["slashed"];
|
|
15
|
+
export type DelegateAddedEvent = IdlEvents<Svault>["delegateAdded"];
|
|
16
|
+
export type DelegateRemovedEvent = IdlEvents<Svault>["delegateRemoved"];
|
|
17
|
+
export type SVaultEvent = {
|
|
18
|
+
name: "StakingVaultInitialized";
|
|
19
|
+
data: StakingVaultInitializedEvent;
|
|
20
|
+
} | {
|
|
21
|
+
name: "Staked";
|
|
22
|
+
data: StakedEvent;
|
|
23
|
+
} | {
|
|
24
|
+
name: "UnstakeInitiated";
|
|
25
|
+
data: UnstakeInitiatedEvent;
|
|
26
|
+
} | {
|
|
27
|
+
name: "Withdrawn";
|
|
28
|
+
data: WithdrawnEvent;
|
|
29
|
+
} | {
|
|
30
|
+
name: "RewardsPosted";
|
|
31
|
+
data: RewardsPostedEvent;
|
|
32
|
+
} | {
|
|
33
|
+
name: "RewardsClaimed";
|
|
34
|
+
data: RewardsClaimedEvent;
|
|
35
|
+
} | {
|
|
36
|
+
name: "Slashed";
|
|
37
|
+
data: SlashedEvent;
|
|
38
|
+
} | {
|
|
39
|
+
name: "DelegateAdded";
|
|
40
|
+
data: DelegateAddedEvent;
|
|
41
|
+
} | {
|
|
42
|
+
name: "DelegateRemoved";
|
|
43
|
+
data: DelegateRemovedEvent;
|
|
44
|
+
};
|
|
45
|
+
export interface SVaultTxOptions extends TxOptions {
|
|
46
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Type definitions for the SVault program.
|
|
4
|
+
* Exports IDL-derived types and SDK-friendly enums.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3ZhdWx0L3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0ciLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogVHlwZSBkZWZpbml0aW9ucyBmb3IgdGhlIFNWYXVsdCBwcm9ncmFtLlxuICogRXhwb3J0cyBJREwtZGVyaXZlZCB0eXBlcyBhbmQgU0RLLWZyaWVuZGx5IGVudW1zLlxuICovXG5cbmltcG9ydCB7IElkbEFjY291bnRzLCBJZGxFdmVudHMgfSBmcm9tIFwiQGNvcmFsLXh5ei9hbmNob3JcIjtcbmltcG9ydCB7IFR4T3B0aW9ucyB9IGZyb20gXCIuLi91dGlsc1wiO1xuXG5leHBvcnQgeyBTdmF1bHQgfSBmcm9tIFwiLi4vZ2VuZXJhdGVkL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IFN2YXVsdCB9IGZyb20gXCIuLi9nZW5lcmF0ZWQvdHlwZXNcIjtcblxuLyogSURMLWRlcml2ZWQgQWNjb3VudCBUeXBlcyAqL1xuXG5leHBvcnQgdHlwZSBTdGFraW5nQ29uZmlnQWNjb3VudCA9IElkbEFjY291bnRzPFN2YXVsdD5bXCJzdGFraW5nQ29uZmlnXCJdO1xuZXhwb3J0IHR5cGUgVXNlclN0YWtlQWNjb3VudCA9IElkbEFjY291bnRzPFN2YXVsdD5bXCJ1c2VyU3Rha2VcIl07XG5leHBvcnQgdHlwZSBEZWxlZ2F0ZUFjY291bnQgPSBJZGxBY2NvdW50czxTdmF1bHQ+W1wiZGVsZWdhdGVcIl07XG5cbi8qIElETC1kZXJpdmVkIEV2ZW50IFR5cGVzICovXG5cbmV4cG9ydCB0eXBlIFN0YWtpbmdWYXVsdEluaXRpYWxpemVkRXZlbnQgPSBJZGxFdmVudHM8U3ZhdWx0PltcInN0YWtpbmdWYXVsdEluaXRpYWxpemVkXCJdO1xuZXhwb3J0IHR5cGUgU3Rha2VkRXZlbnQgPSBJZGxFdmVudHM8U3ZhdWx0PltcInN0YWtlZFwiXTtcbmV4cG9ydCB0eXBlIFVuc3Rha2VJbml0aWF0ZWRFdmVudCA9IElkbEV2ZW50czxTdmF1bHQ+W1widW5zdGFrZUluaXRpYXRlZFwiXTtcbmV4cG9ydCB0eXBlIFdpdGhkcmF3bkV2ZW50ID0gSWRsRXZlbnRzPFN2YXVsdD5bXCJ3aXRoZHJhd25cIl07XG5leHBvcnQgdHlwZSBSZXdhcmRzUG9zdGVkRXZlbnQgPSBJZGxFdmVudHM8U3ZhdWx0PltcInJld2FyZHNQb3N0ZWRcIl07XG5leHBvcnQgdHlwZSBSZXdhcmRzQ2xhaW1lZEV2ZW50ID0gSWRsRXZlbnRzPFN2YXVsdD5bXCJyZXdhcmRzQ2xhaW1lZFwiXTtcbmV4cG9ydCB0eXBlIFNsYXNoZWRFdmVudCA9IElkbEV2ZW50czxTdmF1bHQ+W1wic2xhc2hlZFwiXTtcbmV4cG9ydCB0eXBlIERlbGVnYXRlQWRkZWRFdmVudCA9IElkbEV2ZW50czxTdmF1bHQ+W1wiZGVsZWdhdGVBZGRlZFwiXTtcbmV4cG9ydCB0eXBlIERlbGVnYXRlUmVtb3ZlZEV2ZW50ID0gSWRsRXZlbnRzPFN2YXVsdD5bXCJkZWxlZ2F0ZVJlbW92ZWRcIl07XG5cbi8qIEV2ZW50IFVuaW9uIFR5cGUgKi9cblxuZXhwb3J0IHR5cGUgU1ZhdWx0RXZlbnQgPVxuICB8IHsgbmFtZTogXCJTdGFraW5nVmF1bHRJbml0aWFsaXplZFwiOyBkYXRhOiBTdGFraW5nVmF1bHRJbml0aWFsaXplZEV2ZW50IH1cbiAgfCB7IG5hbWU6IFwiU3Rha2VkXCI7IGRhdGE6IFN0YWtlZEV2ZW50IH1cbiAgfCB7IG5hbWU6IFwiVW5zdGFrZUluaXRpYXRlZFwiOyBkYXRhOiBVbnN0YWtlSW5pdGlhdGVkRXZlbnQgfVxuICB8IHsgbmFtZTogXCJXaXRoZHJhd25cIjsgZGF0YTogV2l0aGRyYXduRXZlbnQgfVxuICB8IHsgbmFtZTogXCJSZXdhcmRzUG9zdGVkXCI7IGRhdGE6IFJld2FyZHNQb3N0ZWRFdmVudCB9XG4gIHwgeyBuYW1lOiBcIlJld2FyZHNDbGFpbWVkXCI7IGRhdGE6IFJld2FyZHNDbGFpbWVkRXZlbnQgfVxuICB8IHsgbmFtZTogXCJTbGFzaGVkXCI7IGRhdGE6IFNsYXNoZWRFdmVudCB9XG4gIHwgeyBuYW1lOiBcIkRlbGVnYXRlQWRkZWRcIjsgZGF0YTogRGVsZWdhdGVBZGRlZEV2ZW50IH1cbiAgfCB7IG5hbWU6IFwiRGVsZWdhdGVSZW1vdmVkXCI7IGRhdGE6IERlbGVnYXRlUmVtb3ZlZEV2ZW50IH07XG5cbi8qIENsaWVudCBPcHRpb25zICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgU1ZhdWx0VHhPcHRpb25zIGV4dGVuZHMgVHhPcHRpb25zIHt9XG4iXX0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Program } from "@coral-xyz/anchor";
|
|
2
|
+
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
import { Svault, StakingConfigAccount, UserStakeAccount, DelegateAccount } from "./types";
|
|
4
|
+
export declare function deriveStakingConfigPDA(tokenMint: PublicKey, nonce: number, programId?: PublicKey): [PublicKey, number];
|
|
5
|
+
export declare function deriveUserStakePDA(stakingConfig: PublicKey, user: PublicKey, programId?: PublicKey): [PublicKey, number];
|
|
6
|
+
export declare function deriveDelegatePDA(stakingConfig: PublicKey, delegate: PublicKey, programId?: PublicKey): [PublicKey, number];
|
|
7
|
+
export declare function deriveStakeVaultPDA(stakingConfig: PublicKey, programId?: PublicKey): [PublicKey, number];
|
|
8
|
+
export declare function deriveRewardVaultPDA(stakingConfig: PublicKey, programId?: PublicKey): [PublicKey, number];
|
|
9
|
+
export declare function fetchStakingConfigAccount(program: Program<Svault>, pda: PublicKey): Promise<StakingConfigAccount>;
|
|
10
|
+
export declare function fetchUserStakeAccount(program: Program<Svault>, pda: PublicKey): Promise<UserStakeAccount>;
|
|
11
|
+
export declare function fetchDelegateAccount(program: Program<Svault>, pda: PublicKey): Promise<DelegateAccount>;
|
|
12
|
+
/**
|
|
13
|
+
* Compute when withdrawal will be available based on unstake initiation time.
|
|
14
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
15
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
16
|
+
* @returns Date when withdrawal becomes available
|
|
17
|
+
*/
|
|
18
|
+
export declare function computeWithdrawAvailableAt(unstakeInitiatedAt: number, unstakingPeriodDays: number): Date;
|
|
19
|
+
/**
|
|
20
|
+
* Check if withdrawal is currently available.
|
|
21
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
22
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
23
|
+
* @returns true if unstaking period has elapsed
|
|
24
|
+
*/
|
|
25
|
+
export declare function isWithdrawAvailable(unstakeInitiatedAt: number, unstakingPeriodDays: number): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Compute the time remaining until withdrawal is available.
|
|
28
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
29
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
30
|
+
* @returns Seconds remaining, or 0 if already available
|
|
31
|
+
*/
|
|
32
|
+
export declare function getTimeUntilWithdraw(unstakeInitiatedAt: number, unstakingPeriodDays: number): number;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Utility functions for the SVault program.
|
|
4
|
+
* PDA derivation, state parsing, and account fetching.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.deriveStakingConfigPDA = deriveStakingConfigPDA;
|
|
8
|
+
exports.deriveUserStakePDA = deriveUserStakePDA;
|
|
9
|
+
exports.deriveDelegatePDA = deriveDelegatePDA;
|
|
10
|
+
exports.deriveStakeVaultPDA = deriveStakeVaultPDA;
|
|
11
|
+
exports.deriveRewardVaultPDA = deriveRewardVaultPDA;
|
|
12
|
+
exports.fetchStakingConfigAccount = fetchStakingConfigAccount;
|
|
13
|
+
exports.fetchUserStakeAccount = fetchUserStakeAccount;
|
|
14
|
+
exports.fetchDelegateAccount = fetchDelegateAccount;
|
|
15
|
+
exports.computeWithdrawAvailableAt = computeWithdrawAvailableAt;
|
|
16
|
+
exports.isWithdrawAvailable = isWithdrawAvailable;
|
|
17
|
+
exports.getTimeUntilWithdraw = getTimeUntilWithdraw;
|
|
18
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
19
|
+
const constants_1 = require("./constants");
|
|
20
|
+
/* PDA Derivation */
|
|
21
|
+
function deriveStakingConfigPDA(tokenMint, nonce, programId = constants_1.PROGRAM_ID) {
|
|
22
|
+
const nonceBuffer = Buffer.alloc(2);
|
|
23
|
+
nonceBuffer.writeUInt16LE(nonce);
|
|
24
|
+
return web3_js_1.PublicKey.findProgramAddressSync([constants_1.STAKING_CONFIG_SEED, tokenMint.toBuffer(), nonceBuffer], programId);
|
|
25
|
+
}
|
|
26
|
+
function deriveUserStakePDA(stakingConfig, user, programId = constants_1.PROGRAM_ID) {
|
|
27
|
+
return web3_js_1.PublicKey.findProgramAddressSync([constants_1.USER_STAKE_SEED, stakingConfig.toBuffer(), user.toBuffer()], programId);
|
|
28
|
+
}
|
|
29
|
+
function deriveDelegatePDA(stakingConfig, delegate, programId = constants_1.PROGRAM_ID) {
|
|
30
|
+
// Uses USER_STAKE_SEED to prevent delegate from also being a staker
|
|
31
|
+
return web3_js_1.PublicKey.findProgramAddressSync([constants_1.USER_STAKE_SEED, stakingConfig.toBuffer(), delegate.toBuffer()], programId);
|
|
32
|
+
}
|
|
33
|
+
function deriveStakeVaultPDA(stakingConfig, programId = constants_1.PROGRAM_ID) {
|
|
34
|
+
return web3_js_1.PublicKey.findProgramAddressSync([constants_1.STAKE_VAULT_SEED, stakingConfig.toBuffer()], programId);
|
|
35
|
+
}
|
|
36
|
+
function deriveRewardVaultPDA(stakingConfig, programId = constants_1.PROGRAM_ID) {
|
|
37
|
+
return web3_js_1.PublicKey.findProgramAddressSync([constants_1.REWARD_VAULT_SEED, stakingConfig.toBuffer()], programId);
|
|
38
|
+
}
|
|
39
|
+
/* Fetchers */
|
|
40
|
+
async function fetchStakingConfigAccount(program, pda) {
|
|
41
|
+
return program.account.stakingConfig.fetch(pda);
|
|
42
|
+
}
|
|
43
|
+
async function fetchUserStakeAccount(program, pda) {
|
|
44
|
+
return program.account.userStake.fetch(pda);
|
|
45
|
+
}
|
|
46
|
+
async function fetchDelegateAccount(program, pda) {
|
|
47
|
+
return program.account.delegate.fetch(pda);
|
|
48
|
+
}
|
|
49
|
+
/* Helpers */
|
|
50
|
+
/**
|
|
51
|
+
* Compute when withdrawal will be available based on unstake initiation time.
|
|
52
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
53
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
54
|
+
* @returns Date when withdrawal becomes available
|
|
55
|
+
*/
|
|
56
|
+
function computeWithdrawAvailableAt(unstakeInitiatedAt, unstakingPeriodDays) {
|
|
57
|
+
const availableAtSeconds = unstakeInitiatedAt + unstakingPeriodDays * constants_1.SECONDS_PER_DAY;
|
|
58
|
+
return new Date(availableAtSeconds * 1000);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if withdrawal is currently available.
|
|
62
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
63
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
64
|
+
* @returns true if unstaking period has elapsed
|
|
65
|
+
*/
|
|
66
|
+
function isWithdrawAvailable(unstakeInitiatedAt, unstakingPeriodDays) {
|
|
67
|
+
if (unstakeInitiatedAt === 0)
|
|
68
|
+
return false;
|
|
69
|
+
const now = Math.floor(Date.now() / 1000);
|
|
70
|
+
const availableAt = unstakeInitiatedAt + unstakingPeriodDays * constants_1.SECONDS_PER_DAY;
|
|
71
|
+
return now >= availableAt;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compute the time remaining until withdrawal is available.
|
|
75
|
+
* @param unstakeInitiatedAt Unix timestamp when unstake was initiated (seconds)
|
|
76
|
+
* @param unstakingPeriodDays Number of days in unstaking period
|
|
77
|
+
* @returns Seconds remaining, or 0 if already available
|
|
78
|
+
*/
|
|
79
|
+
function getTimeUntilWithdraw(unstakeInitiatedAt, unstakingPeriodDays) {
|
|
80
|
+
if (unstakeInitiatedAt === 0)
|
|
81
|
+
return 0;
|
|
82
|
+
const now = Math.floor(Date.now() / 1000);
|
|
83
|
+
const availableAt = unstakeInitiatedAt + unstakingPeriodDays * constants_1.SECONDS_PER_DAY;
|
|
84
|
+
return Math.max(0, availableAt - now);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3ZhdWx0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7O0FBZ0JILHdEQVdDO0FBRUQsZ0RBU0M7QUFFRCw4Q0FVQztBQUVELGtEQVFDO0FBRUQsb0RBUUM7QUFJRCw4REFLQztBQUVELHNEQUtDO0FBRUQsb0RBS0M7QUFVRCxnRUFNQztBQVFELGtEQVFDO0FBUUQsb0RBUUM7QUExSUQsNkNBQTRDO0FBQzVDLDJDQU9xQjtBQUdyQixvQkFBb0I7QUFFcEIsU0FBZ0Isc0JBQXNCLENBQ3BDLFNBQW9CLEVBQ3BCLEtBQWEsRUFDYixZQUF1QixzQkFBVTtJQUVqQyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BDLFdBQVcsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsT0FBTyxtQkFBUyxDQUFDLHNCQUFzQixDQUNyQyxDQUFDLCtCQUFtQixFQUFFLFNBQVMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxXQUFXLENBQUMsRUFDeEQsU0FBUyxDQUNWLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBZ0Isa0JBQWtCLENBQ2hDLGFBQXdCLEVBQ3hCLElBQWUsRUFDZixZQUF1QixzQkFBVTtJQUVqQyxPQUFPLG1CQUFTLENBQUMsc0JBQXNCLENBQ3JDLENBQUMsMkJBQWUsRUFBRSxhQUFhLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQzVELFNBQVMsQ0FDVixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQWdCLGlCQUFpQixDQUMvQixhQUF3QixFQUN4QixRQUFtQixFQUNuQixZQUF1QixzQkFBVTtJQUVqQyxvRUFBb0U7SUFDcEUsT0FBTyxtQkFBUyxDQUFDLHNCQUFzQixDQUNyQyxDQUFDLDJCQUFlLEVBQUUsYUFBYSxDQUFDLFFBQVEsRUFBRSxFQUFFLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUNoRSxTQUFTLENBQ1YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQixtQkFBbUIsQ0FDakMsYUFBd0IsRUFDeEIsWUFBdUIsc0JBQVU7SUFFakMsT0FBTyxtQkFBUyxDQUFDLHNCQUFzQixDQUNyQyxDQUFDLDRCQUFnQixFQUFFLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUM1QyxTQUFTLENBQ1YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQixvQkFBb0IsQ0FDbEMsYUFBd0IsRUFDeEIsWUFBdUIsc0JBQVU7SUFFakMsT0FBTyxtQkFBUyxDQUFDLHNCQUFzQixDQUNyQyxDQUFDLDZCQUFpQixFQUFFLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUM3QyxTQUFTLENBQ1YsQ0FBQztBQUNKLENBQUM7QUFFRCxjQUFjO0FBRVAsS0FBSyxVQUFVLHlCQUF5QixDQUM3QyxPQUF3QixFQUN4QixHQUFjO0lBRWQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUVNLEtBQUssVUFBVSxxQkFBcUIsQ0FDekMsT0FBd0IsRUFDeEIsR0FBYztJQUVkLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFTSxLQUFLLFVBQVUsb0JBQW9CLENBQ3hDLE9BQXdCLEVBQ3hCLEdBQWM7SUFFZCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUM3QyxDQUFDO0FBRUQsYUFBYTtBQUViOzs7OztHQUtHO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQ3hDLGtCQUEwQixFQUMxQixtQkFBMkI7SUFFM0IsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsR0FBRyxtQkFBbUIsR0FBRywyQkFBZSxDQUFDO0lBQ3RGLE9BQU8sSUFBSSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQ2pDLGtCQUEwQixFQUMxQixtQkFBMkI7SUFFM0IsSUFBSSxrQkFBa0IsS0FBSyxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDMUMsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLEdBQUcsbUJBQW1CLEdBQUcsMkJBQWUsQ0FBQztJQUMvRSxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0Isb0JBQW9CLENBQ2xDLGtCQUEwQixFQUMxQixtQkFBMkI7SUFFM0IsSUFBSSxrQkFBa0IsS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDMUMsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLEdBQUcsbUJBQW1CLEdBQUcsMkJBQWUsQ0FBQztJQUMvRSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFdBQVcsR0FBRyxHQUFHLENBQUMsQ0FBQztBQUN4QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgU1ZhdWx0IHByb2dyYW0uXG4gKiBQREEgZGVyaXZhdGlvbiwgc3RhdGUgcGFyc2luZywgYW5kIGFjY291bnQgZmV0Y2hpbmcuXG4gKi9cblxuaW1wb3J0IHsgUHJvZ3JhbSB9IGZyb20gXCJAY29yYWwteHl6L2FuY2hvclwiO1xuaW1wb3J0IHsgUHVibGljS2V5IH0gZnJvbSBcIkBzb2xhbmEvd2ViMy5qc1wiO1xuaW1wb3J0IHtcbiAgU1RBS0lOR19DT05GSUdfU0VFRCxcbiAgVVNFUl9TVEFLRV9TRUVELFxuICBTVEFLRV9WQVVMVF9TRUVELFxuICBSRVdBUkRfVkFVTFRfU0VFRCxcbiAgUFJPR1JBTV9JRCxcbiAgU0VDT05EU19QRVJfREFZLFxufSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFN2YXVsdCwgU3Rha2luZ0NvbmZpZ0FjY291bnQsIFVzZXJTdGFrZUFjY291bnQsIERlbGVnYXRlQWNjb3VudCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qIFBEQSBEZXJpdmF0aW9uICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVTdGFraW5nQ29uZmlnUERBKFxuICB0b2tlbk1pbnQ6IFB1YmxpY0tleSxcbiAgbm9uY2U6IG51bWJlcixcbiAgcHJvZ3JhbUlkOiBQdWJsaWNLZXkgPSBQUk9HUkFNX0lEXG4pOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgY29uc3Qgbm9uY2VCdWZmZXIgPSBCdWZmZXIuYWxsb2MoMik7XG4gIG5vbmNlQnVmZmVyLndyaXRlVUludDE2TEUobm9uY2UpO1xuICByZXR1cm4gUHVibGljS2V5LmZpbmRQcm9ncmFtQWRkcmVzc1N5bmMoXG4gICAgW1NUQUtJTkdfQ09ORklHX1NFRUQsIHRva2VuTWludC50b0J1ZmZlcigpLCBub25jZUJ1ZmZlcl0sXG4gICAgcHJvZ3JhbUlkXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVVc2VyU3Rha2VQREEoXG4gIHN0YWtpbmdDb25maWc6IFB1YmxpY0tleSxcbiAgdXNlcjogUHVibGljS2V5LFxuICBwcm9ncmFtSWQ6IFB1YmxpY0tleSA9IFBST0dSQU1fSURcbik6IFtQdWJsaWNLZXksIG51bWJlcl0ge1xuICByZXR1cm4gUHVibGljS2V5LmZpbmRQcm9ncmFtQWRkcmVzc1N5bmMoXG4gICAgW1VTRVJfU1RBS0VfU0VFRCwgc3Rha2luZ0NvbmZpZy50b0J1ZmZlcigpLCB1c2VyLnRvQnVmZmVyKCldLFxuICAgIHByb2dyYW1JZFxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVyaXZlRGVsZWdhdGVQREEoXG4gIHN0YWtpbmdDb25maWc6IFB1YmxpY0tleSxcbiAgZGVsZWdhdGU6IFB1YmxpY0tleSxcbiAgcHJvZ3JhbUlkOiBQdWJsaWNLZXkgPSBQUk9HUkFNX0lEXG4pOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgLy8gVXNlcyBVU0VSX1NUQUtFX1NFRUQgdG8gcHJldmVudCBkZWxlZ2F0ZSBmcm9tIGFsc28gYmVpbmcgYSBzdGFrZXJcbiAgcmV0dXJuIFB1YmxpY0tleS5maW5kUHJvZ3JhbUFkZHJlc3NTeW5jKFxuICAgIFtVU0VSX1NUQUtFX1NFRUQsIHN0YWtpbmdDb25maWcudG9CdWZmZXIoKSwgZGVsZWdhdGUudG9CdWZmZXIoKV0sXG4gICAgcHJvZ3JhbUlkXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVTdGFrZVZhdWx0UERBKFxuICBzdGFraW5nQ29uZmlnOiBQdWJsaWNLZXksXG4gIHByb2dyYW1JZDogUHVibGljS2V5ID0gUFJPR1JBTV9JRFxuKTogW1B1YmxpY0tleSwgbnVtYmVyXSB7XG4gIHJldHVybiBQdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICBbU1RBS0VfVkFVTFRfU0VFRCwgc3Rha2luZ0NvbmZpZy50b0J1ZmZlcigpXSxcbiAgICBwcm9ncmFtSWRcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZVJld2FyZFZhdWx0UERBKFxuICBzdGFraW5nQ29uZmlnOiBQdWJsaWNLZXksXG4gIHByb2dyYW1JZDogUHVibGljS2V5ID0gUFJPR1JBTV9JRFxuKTogW1B1YmxpY0tleSwgbnVtYmVyXSB7XG4gIHJldHVybiBQdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICBbUkVXQVJEX1ZBVUxUX1NFRUQsIHN0YWtpbmdDb25maWcudG9CdWZmZXIoKV0sXG4gICAgcHJvZ3JhbUlkXG4gICk7XG59XG5cbi8qIEZldGNoZXJzICovXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFN0YWtpbmdDb25maWdBY2NvdW50KFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIHBkYTogUHVibGljS2V5XG4pOiBQcm9taXNlPFN0YWtpbmdDb25maWdBY2NvdW50PiB7XG4gIHJldHVybiBwcm9ncmFtLmFjY291bnQuc3Rha2luZ0NvbmZpZy5mZXRjaChwZGEpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hVc2VyU3Rha2VBY2NvdW50KFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIHBkYTogUHVibGljS2V5XG4pOiBQcm9taXNlPFVzZXJTdGFrZUFjY291bnQ+IHtcbiAgcmV0dXJuIHByb2dyYW0uYWNjb3VudC51c2VyU3Rha2UuZmV0Y2gocGRhKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoRGVsZWdhdGVBY2NvdW50KFxuICBwcm9ncmFtOiBQcm9ncmFtPFN2YXVsdD4sXG4gIHBkYTogUHVibGljS2V5XG4pOiBQcm9taXNlPERlbGVnYXRlQWNjb3VudD4ge1xuICByZXR1cm4gcHJvZ3JhbS5hY2NvdW50LmRlbGVnYXRlLmZldGNoKHBkYSk7XG59XG5cbi8qIEhlbHBlcnMgKi9cblxuLyoqXG4gKiBDb21wdXRlIHdoZW4gd2l0aGRyYXdhbCB3aWxsIGJlIGF2YWlsYWJsZSBiYXNlZCBvbiB1bnN0YWtlIGluaXRpYXRpb24gdGltZS5cbiAqIEBwYXJhbSB1bnN0YWtlSW5pdGlhdGVkQXQgVW5peCB0aW1lc3RhbXAgd2hlbiB1bnN0YWtlIHdhcyBpbml0aWF0ZWQgKHNlY29uZHMpXG4gKiBAcGFyYW0gdW5zdGFraW5nUGVyaW9kRGF5cyBOdW1iZXIgb2YgZGF5cyBpbiB1bnN0YWtpbmcgcGVyaW9kXG4gKiBAcmV0dXJucyBEYXRlIHdoZW4gd2l0aGRyYXdhbCBiZWNvbWVzIGF2YWlsYWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVdpdGhkcmF3QXZhaWxhYmxlQXQoXG4gIHVuc3Rha2VJbml0aWF0ZWRBdDogbnVtYmVyLFxuICB1bnN0YWtpbmdQZXJpb2REYXlzOiBudW1iZXJcbik6IERhdGUge1xuICBjb25zdCBhdmFpbGFibGVBdFNlY29uZHMgPSB1bnN0YWtlSW5pdGlhdGVkQXQgKyB1bnN0YWtpbmdQZXJpb2REYXlzICogU0VDT05EU19QRVJfREFZO1xuICByZXR1cm4gbmV3IERhdGUoYXZhaWxhYmxlQXRTZWNvbmRzICogMTAwMCk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgd2l0aGRyYXdhbCBpcyBjdXJyZW50bHkgYXZhaWxhYmxlLlxuICogQHBhcmFtIHVuc3Rha2VJbml0aWF0ZWRBdCBVbml4IHRpbWVzdGFtcCB3aGVuIHVuc3Rha2Ugd2FzIGluaXRpYXRlZCAoc2Vjb25kcylcbiAqIEBwYXJhbSB1bnN0YWtpbmdQZXJpb2REYXlzIE51bWJlciBvZiBkYXlzIGluIHVuc3Rha2luZyBwZXJpb2RcbiAqIEByZXR1cm5zIHRydWUgaWYgdW5zdGFraW5nIHBlcmlvZCBoYXMgZWxhcHNlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXaXRoZHJhd0F2YWlsYWJsZShcbiAgdW5zdGFrZUluaXRpYXRlZEF0OiBudW1iZXIsXG4gIHVuc3Rha2luZ1BlcmlvZERheXM6IG51bWJlclxuKTogYm9vbGVhbiB7XG4gIGlmICh1bnN0YWtlSW5pdGlhdGVkQXQgPT09IDApIHJldHVybiBmYWxzZTtcbiAgY29uc3Qgbm93ID0gTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCk7XG4gIGNvbnN0IGF2YWlsYWJsZUF0ID0gdW5zdGFrZUluaXRpYXRlZEF0ICsgdW5zdGFraW5nUGVyaW9kRGF5cyAqIFNFQ09ORFNfUEVSX0RBWTtcbiAgcmV0dXJuIG5vdyA+PSBhdmFpbGFibGVBdDtcbn1cblxuLyoqXG4gKiBDb21wdXRlIHRoZSB0aW1lIHJlbWFpbmluZyB1bnRpbCB3aXRoZHJhd2FsIGlzIGF2YWlsYWJsZS5cbiAqIEBwYXJhbSB1bnN0YWtlSW5pdGlhdGVkQXQgVW5peCB0aW1lc3RhbXAgd2hlbiB1bnN0YWtlIHdhcyBpbml0aWF0ZWQgKHNlY29uZHMpXG4gKiBAcGFyYW0gdW5zdGFraW5nUGVyaW9kRGF5cyBOdW1iZXIgb2YgZGF5cyBpbiB1bnN0YWtpbmcgcGVyaW9kXG4gKiBAcmV0dXJucyBTZWNvbmRzIHJlbWFpbmluZywgb3IgMCBpZiBhbHJlYWR5IGF2YWlsYWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGltZVVudGlsV2l0aGRyYXcoXG4gIHVuc3Rha2VJbml0aWF0ZWRBdDogbnVtYmVyLFxuICB1bnN0YWtpbmdQZXJpb2REYXlzOiBudW1iZXJcbik6IG51bWJlciB7XG4gIGlmICh1bnN0YWtlSW5pdGlhdGVkQXQgPT09IDApIHJldHVybiAwO1xuICBjb25zdCBub3cgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKTtcbiAgY29uc3QgYXZhaWxhYmxlQXQgPSB1bnN0YWtlSW5pdGlhdGVkQXQgKyB1bnN0YWtpbmdQZXJpb2REYXlzICogU0VDT05EU19QRVJfREFZO1xuICByZXR1cm4gTWF0aC5tYXgoMCwgYXZhaWxhYmxlQXQgLSBub3cpO1xufVxuIl19
|
package/package.json
CHANGED
package/src/futarchy/client.ts
CHANGED
|
@@ -606,13 +606,19 @@ export class FutarchyClient {
|
|
|
606
606
|
|
|
607
607
|
// Create ALT
|
|
608
608
|
const createTx = new Transaction().add(createIx);
|
|
609
|
-
|
|
609
|
+
const { blockhash: createBlockhash, lastValidBlockHeight: createLastValidBlockHeight } =
|
|
610
|
+
await provider.connection.getLatestBlockhash('confirmed');
|
|
611
|
+
createTx.recentBlockhash = createBlockhash;
|
|
610
612
|
createTx.feePayer = creator;
|
|
611
613
|
const signedTx = await provider.wallet.signTransaction(createTx);
|
|
612
614
|
const sig = await provider.connection.sendRawTransaction(signedTx.serialize(), {
|
|
613
615
|
skipPreflight: true,
|
|
614
616
|
});
|
|
615
|
-
await provider.connection.confirmTransaction(
|
|
617
|
+
await provider.connection.confirmTransaction({
|
|
618
|
+
signature: sig,
|
|
619
|
+
blockhash: createBlockhash,
|
|
620
|
+
lastValidBlockHeight: createLastValidBlockHeight,
|
|
621
|
+
}, "confirmed");
|
|
616
622
|
|
|
617
623
|
// Extend ALT with addresses
|
|
618
624
|
// Use skipPreflight to avoid race condition where simulation sees stale state
|
|
@@ -627,13 +633,19 @@ export class FutarchyClient {
|
|
|
627
633
|
addresses: chunk,
|
|
628
634
|
});
|
|
629
635
|
const extendTx = new Transaction().add(extendIx);
|
|
630
|
-
|
|
636
|
+
const { blockhash: extendBlockhash, lastValidBlockHeight: extendLastValidBlockHeight } =
|
|
637
|
+
await provider.connection.getLatestBlockhash('confirmed');
|
|
638
|
+
extendTx.recentBlockhash = extendBlockhash;
|
|
631
639
|
extendTx.feePayer = creator;
|
|
632
640
|
const signedExtendTx = await provider.wallet.signTransaction(extendTx);
|
|
633
641
|
const extendSig = await provider.connection.sendRawTransaction(signedExtendTx.serialize(), {
|
|
634
642
|
skipPreflight: true,
|
|
635
643
|
});
|
|
636
|
-
await provider.connection.confirmTransaction(
|
|
644
|
+
await provider.connection.confirmTransaction({
|
|
645
|
+
signature: extendSig,
|
|
646
|
+
blockhash: extendBlockhash,
|
|
647
|
+
lastValidBlockHeight: extendLastValidBlockHeight,
|
|
648
|
+
}, "confirmed");
|
|
637
649
|
}
|
|
638
650
|
|
|
639
651
|
return { altAddress };
|
|
@@ -646,13 +658,19 @@ export class FutarchyClient {
|
|
|
646
658
|
* @param creator - The user redeeming
|
|
647
659
|
* @param proposalPda - The proposal PDA
|
|
648
660
|
* @param altAddress - Optional ALT address (will be created if not provided for 3+ options)
|
|
649
|
-
* @returns Unsigned versioned transaction, ALT address,
|
|
661
|
+
* @returns Unsigned versioned transaction, ALT address, number of options, and blockhash info for confirmation
|
|
650
662
|
*/
|
|
651
663
|
async redeemLiquidityVersioned(
|
|
652
664
|
creator: PublicKey,
|
|
653
665
|
proposalPda: PublicKey,
|
|
654
666
|
altAddress?: PublicKey,
|
|
655
|
-
): Promise<{
|
|
667
|
+
): Promise<{
|
|
668
|
+
versionedTx: VersionedTransaction;
|
|
669
|
+
altAddress: PublicKey;
|
|
670
|
+
numOptions: number;
|
|
671
|
+
blockhash: string;
|
|
672
|
+
lastValidBlockHeight: number;
|
|
673
|
+
}> {
|
|
656
674
|
const provider = this.program.provider as AnchorProvider;
|
|
657
675
|
const { builder, numOptions } = await this.redeemLiquidity(creator, proposalPda);
|
|
658
676
|
|
|
@@ -710,8 +728,8 @@ export class FutarchyClient {
|
|
|
710
728
|
const instruction = await builder.instruction();
|
|
711
729
|
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 });
|
|
712
730
|
|
|
713
|
-
// Get fresh blockhash
|
|
714
|
-
const { blockhash } = await provider.connection.getLatestBlockhash();
|
|
731
|
+
// Get fresh blockhash with lastValidBlockHeight for confirmation tracking
|
|
732
|
+
const { blockhash, lastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
|
|
715
733
|
|
|
716
734
|
// Build versioned transaction using the verified ALT (no re-fetch)
|
|
717
735
|
const versionedTx = this.buildVersionedTxWithALT(
|
|
@@ -721,23 +739,56 @@ export class FutarchyClient {
|
|
|
721
739
|
blockhash,
|
|
722
740
|
);
|
|
723
741
|
|
|
724
|
-
// Return the versioned transaction
|
|
742
|
+
// Return the versioned transaction along with blockhash info for proper confirmation
|
|
725
743
|
// This allows the caller to use their own signing mechanism (e.g., keypair.sign)
|
|
726
|
-
return { versionedTx, altAddress: altPubkey, numOptions };
|
|
744
|
+
return { versionedTx, altAddress: altPubkey, numOptions, blockhash, lastValidBlockHeight };
|
|
727
745
|
}
|
|
728
746
|
|
|
729
747
|
/**
|
|
730
|
-
* Helper to send a signed versioned transaction.
|
|
748
|
+
* Helper to send a signed versioned transaction with robust confirmation handling.
|
|
749
|
+
* Uses blockhash-based confirmation to properly detect transaction expiration
|
|
750
|
+
* instead of relying on a fixed timeout.
|
|
751
|
+
*
|
|
752
|
+
* @param signedTx - The signed versioned transaction to send
|
|
753
|
+
* @param confirmationInfo - Optional blockhash info from when the transaction was built.
|
|
754
|
+
* If not provided, a fresh blockhash will be fetched (less accurate).
|
|
731
755
|
*/
|
|
732
756
|
async sendVersionedTransaction(
|
|
733
757
|
signedTx: VersionedTransaction,
|
|
758
|
+
confirmationInfo?: { blockhash: string; lastValidBlockHeight: number },
|
|
734
759
|
): Promise<string> {
|
|
735
760
|
const provider = this.program.provider as AnchorProvider;
|
|
761
|
+
|
|
762
|
+
// Use provided blockhash info or fetch fresh one
|
|
763
|
+
// Using the original blockhash is more accurate for detecting expiration
|
|
764
|
+
let blockhash: string;
|
|
765
|
+
let lastValidBlockHeight: number;
|
|
766
|
+
|
|
767
|
+
if (confirmationInfo) {
|
|
768
|
+
blockhash = confirmationInfo.blockhash;
|
|
769
|
+
lastValidBlockHeight = confirmationInfo.lastValidBlockHeight;
|
|
770
|
+
} else {
|
|
771
|
+
// Fallback: get fresh blockhash (may wait longer than necessary if tx already expired)
|
|
772
|
+
const latestBlockhash = await provider.connection.getLatestBlockhash('confirmed');
|
|
773
|
+
blockhash = latestBlockhash.blockhash;
|
|
774
|
+
lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
|
|
775
|
+
}
|
|
776
|
+
|
|
736
777
|
const signature = await provider.connection.sendTransaction(signedTx, {
|
|
737
778
|
skipPreflight: false,
|
|
738
779
|
preflightCommitment: 'confirmed',
|
|
739
780
|
});
|
|
740
|
-
|
|
781
|
+
|
|
782
|
+
// Use blockhash-based confirmation which waits until either:
|
|
783
|
+
// 1. Transaction is confirmed
|
|
784
|
+
// 2. Blockhash expires (lastValidBlockHeight passed)
|
|
785
|
+
// This is more robust than a fixed timeout on congested networks
|
|
786
|
+
await provider.connection.confirmTransaction({
|
|
787
|
+
signature,
|
|
788
|
+
blockhash,
|
|
789
|
+
lastValidBlockHeight,
|
|
790
|
+
}, 'confirmed');
|
|
791
|
+
|
|
741
792
|
return signature;
|
|
742
793
|
}
|
|
743
794
|
|
|
@@ -810,13 +861,19 @@ export class FutarchyClient {
|
|
|
810
861
|
|
|
811
862
|
// Send create transaction immediately, skip preflight to avoid slot timing issues
|
|
812
863
|
const createTx = new Transaction().add(createIx);
|
|
813
|
-
|
|
864
|
+
const { blockhash: createBlockhash, lastValidBlockHeight: createLastValidBlockHeight } =
|
|
865
|
+
await provider.connection.getLatestBlockhash('confirmed');
|
|
866
|
+
createTx.recentBlockhash = createBlockhash;
|
|
814
867
|
createTx.feePayer = creator;
|
|
815
868
|
const signedTx = await provider.wallet.signTransaction(createTx);
|
|
816
869
|
const sig = await provider.connection.sendRawTransaction(signedTx.serialize(), {
|
|
817
870
|
skipPreflight: true,
|
|
818
871
|
});
|
|
819
|
-
await provider.connection.confirmTransaction(
|
|
872
|
+
await provider.connection.confirmTransaction({
|
|
873
|
+
signature: sig,
|
|
874
|
+
blockhash: createBlockhash,
|
|
875
|
+
lastValidBlockHeight: createLastValidBlockHeight,
|
|
876
|
+
}, "confirmed");
|
|
820
877
|
|
|
821
878
|
// Split addresses into chunks to avoid transaction size limits
|
|
822
879
|
// Each address is 32 bytes, ~20 addresses per extend instruction is safe
|
|
@@ -832,13 +889,19 @@ export class FutarchyClient {
|
|
|
832
889
|
addresses: chunk,
|
|
833
890
|
});
|
|
834
891
|
const extendTx = new Transaction().add(extendIx);
|
|
835
|
-
|
|
892
|
+
const { blockhash: extendBlockhash, lastValidBlockHeight: extendLastValidBlockHeight } =
|
|
893
|
+
await provider.connection.getLatestBlockhash('confirmed');
|
|
894
|
+
extendTx.recentBlockhash = extendBlockhash;
|
|
836
895
|
extendTx.feePayer = creator;
|
|
837
896
|
const signedExtendTx = await provider.wallet.signTransaction(extendTx);
|
|
838
897
|
const extendSig = await provider.connection.sendRawTransaction(signedExtendTx.serialize(), {
|
|
839
898
|
skipPreflight: true,
|
|
840
899
|
});
|
|
841
|
-
await provider.connection.confirmTransaction(
|
|
900
|
+
await provider.connection.confirmTransaction({
|
|
901
|
+
signature: extendSig,
|
|
902
|
+
blockhash: extendBlockhash,
|
|
903
|
+
lastValidBlockHeight: extendLastValidBlockHeight,
|
|
904
|
+
}, "confirmed");
|
|
842
905
|
}
|
|
843
906
|
|
|
844
907
|
return { altAddress };
|
|
@@ -856,11 +919,16 @@ export class FutarchyClient {
|
|
|
856
919
|
payer: PublicKey,
|
|
857
920
|
instructions: TransactionInstruction[],
|
|
858
921
|
altAddress: PublicKey,
|
|
859
|
-
): Promise<
|
|
922
|
+
): Promise<{
|
|
923
|
+
versionedTx: VersionedTransaction;
|
|
924
|
+
blockhash: string;
|
|
925
|
+
lastValidBlockHeight: number;
|
|
926
|
+
}> {
|
|
860
927
|
const provider = this.program.provider as AnchorProvider;
|
|
861
928
|
const alt = await this.fetchALT(altAddress);
|
|
862
|
-
const { blockhash } = await provider.connection.getLatestBlockhash();
|
|
863
|
-
|
|
929
|
+
const { blockhash, lastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
|
|
930
|
+
const versionedTx = this.buildVersionedTxWithALT(payer, instructions, alt, blockhash);
|
|
931
|
+
return { versionedTx, blockhash, lastValidBlockHeight };
|
|
864
932
|
}
|
|
865
933
|
|
|
866
934
|
buildVersionedTxWithALT(
|