@zemyth/raise-sdk 0.1.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/README.md +416 -0
- package/dist/accounts/index.cjs +258 -0
- package/dist/accounts/index.cjs.map +1 -0
- package/dist/accounts/index.d.cts +115 -0
- package/dist/accounts/index.d.ts +115 -0
- package/dist/accounts/index.js +245 -0
- package/dist/accounts/index.js.map +1 -0
- package/dist/constants/index.cjs +174 -0
- package/dist/constants/index.cjs.map +1 -0
- package/dist/constants/index.d.cts +143 -0
- package/dist/constants/index.d.ts +143 -0
- package/dist/constants/index.js +158 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/errors/index.cjs +177 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +83 -0
- package/dist/errors/index.d.ts +83 -0
- package/dist/errors/index.js +170 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.cjs +2063 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +680 -0
- package/dist/index.d.ts +680 -0
- package/dist/index.js +1926 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions/index.cjs +852 -0
- package/dist/instructions/index.cjs.map +1 -0
- package/dist/instructions/index.d.cts +452 -0
- package/dist/instructions/index.d.ts +452 -0
- package/dist/instructions/index.js +809 -0
- package/dist/instructions/index.js.map +1 -0
- package/dist/pdas/index.cjs +241 -0
- package/dist/pdas/index.cjs.map +1 -0
- package/dist/pdas/index.d.cts +171 -0
- package/dist/pdas/index.d.ts +171 -0
- package/dist/pdas/index.js +217 -0
- package/dist/pdas/index.js.map +1 -0
- package/dist/types/index.cjs +44 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +229 -0
- package/dist/types/index.d.ts +229 -0
- package/dist/types/index.js +39 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +130 -0
- package/src/accounts/index.ts +329 -0
- package/src/client.ts +715 -0
- package/src/constants/index.ts +205 -0
- package/src/errors/index.ts +222 -0
- package/src/events/index.ts +256 -0
- package/src/index.ts +253 -0
- package/src/instructions/index.ts +1504 -0
- package/src/pdas/index.ts +404 -0
- package/src/types/index.ts +267 -0
- package/src/utils/index.ts +277 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1926 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, ComputeBudgetProgram, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';
|
|
2
|
+
export { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { BN, AnchorError } from '@coral-xyz/anchor';
|
|
4
|
+
export { BN } from '@coral-xyz/anchor';
|
|
5
|
+
import { getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
6
|
+
|
|
7
|
+
// src/pdas/index.ts
|
|
8
|
+
|
|
9
|
+
// src/constants/index.ts
|
|
10
|
+
var SEEDS = {
|
|
11
|
+
PROJECT: "project",
|
|
12
|
+
MILESTONE: "milestone",
|
|
13
|
+
INVESTMENT: "investment",
|
|
14
|
+
VOTE: "vote",
|
|
15
|
+
ESCROW: "escrow",
|
|
16
|
+
PIVOT: "pivot",
|
|
17
|
+
PIVOT_PROPOSAL: "pivot_proposal",
|
|
18
|
+
TGE_ESCROW: "tge_escrow",
|
|
19
|
+
TGE_ESCROW_VAULT: "tge_escrow_vault",
|
|
20
|
+
SCAM_REPORT: "scam_report",
|
|
21
|
+
ADMIN_CONFIG: "admin-config",
|
|
22
|
+
NFT_MINT: "nft_mint",
|
|
23
|
+
AUTHORITY: "authority"
|
|
24
|
+
};
|
|
25
|
+
var VALIDATION = {
|
|
26
|
+
/** Minimum number of milestones per project */
|
|
27
|
+
MIN_MILESTONES: 2,
|
|
28
|
+
/** Maximum number of milestones per project */
|
|
29
|
+
MAX_MILESTONES: 10,
|
|
30
|
+
/** Milestone percentages must sum to this value */
|
|
31
|
+
MILESTONE_PERCENTAGE_SUM: 100,
|
|
32
|
+
/** Maximum funding buffer (110% of goal) */
|
|
33
|
+
MAX_FUNDING_BUFFER_PERCENT: 110,
|
|
34
|
+
/** Maximum metadata URI length */
|
|
35
|
+
MAX_METADATA_URI_LENGTH: 200,
|
|
36
|
+
/** Maximum pivot description length */
|
|
37
|
+
MAX_PIVOT_DESCRIPTION_LEN: 256,
|
|
38
|
+
/** Maximum pivot vision length */
|
|
39
|
+
MAX_PIVOT_VISION_LEN: 512,
|
|
40
|
+
/** Maximum pivot justification length */
|
|
41
|
+
MAX_PIVOT_JUSTIFICATION_LEN: 512
|
|
42
|
+
};
|
|
43
|
+
var TIMING = {
|
|
44
|
+
/** Production voting period (14 days) */
|
|
45
|
+
VOTING_PERIOD_SECONDS: 1209600,
|
|
46
|
+
/** Production hold period (7 days) */
|
|
47
|
+
HOLD_PERIOD_SECONDS: 604800,
|
|
48
|
+
/** Inactivity timeout (90 days) */
|
|
49
|
+
INACTIVITY_TIMEOUT_SECONDS: 7776e3,
|
|
50
|
+
/** Abandonment timeout (90 days) */
|
|
51
|
+
ABANDONMENT_TIMEOUT_SECONDS: 7776e3,
|
|
52
|
+
/** Refund window (14 days) */
|
|
53
|
+
REFUND_WINDOW_SECONDS: 1209600,
|
|
54
|
+
/** Pivot withdrawal window (7 days) */
|
|
55
|
+
PIVOT_WITHDRAWAL_WINDOW_SECONDS: 604800,
|
|
56
|
+
/** Minimum TGE date (15 days from now) */
|
|
57
|
+
TGE_MIN_DAYS: 1296e3,
|
|
58
|
+
/** Maximum TGE date (90 days from now) */
|
|
59
|
+
TGE_MAX_DAYS: 7776e3,
|
|
60
|
+
/** Post-TGE holdback period (30 days) */
|
|
61
|
+
POST_TGE_HOLDBACK_DAYS: 2592e3
|
|
62
|
+
};
|
|
63
|
+
var TIER_CONSTRAINTS = {
|
|
64
|
+
/** Minimum number of tiers */
|
|
65
|
+
MIN_TIERS: 1,
|
|
66
|
+
/** Maximum number of tiers */
|
|
67
|
+
MAX_TIERS: 10,
|
|
68
|
+
/** Minimum tier amount (10 USDC in lamports) */
|
|
69
|
+
MIN_TIER_AMOUNT: 10000000n,
|
|
70
|
+
/** Minimum max_lots per tier */
|
|
71
|
+
MIN_TIER_MAX_LOTS: 1,
|
|
72
|
+
/** Minimum token ratio */
|
|
73
|
+
MIN_TIER_TOKEN_RATIO: 1n,
|
|
74
|
+
/** Minimum vote multiplier (100 = 1.0x) */
|
|
75
|
+
MIN_TIER_VOTE_MULTIPLIER: 100
|
|
76
|
+
};
|
|
77
|
+
var InvestmentTier = /* @__PURE__ */ ((InvestmentTier2) => {
|
|
78
|
+
InvestmentTier2["Bronze"] = "Bronze";
|
|
79
|
+
InvestmentTier2["Silver"] = "Silver";
|
|
80
|
+
InvestmentTier2["Gold"] = "Gold";
|
|
81
|
+
InvestmentTier2["Platinum"] = "Platinum";
|
|
82
|
+
InvestmentTier2["Diamond"] = "Diamond";
|
|
83
|
+
return InvestmentTier2;
|
|
84
|
+
})(InvestmentTier || {});
|
|
85
|
+
var TIER_MINIMUMS = {
|
|
86
|
+
["Bronze" /* Bronze */]: 100000000n,
|
|
87
|
+
// 100 USDC
|
|
88
|
+
["Silver" /* Silver */]: 500000000n,
|
|
89
|
+
// 500 USDC
|
|
90
|
+
["Gold" /* Gold */]: 1000000000n,
|
|
91
|
+
// 1,000 USDC
|
|
92
|
+
["Platinum" /* Platinum */]: 5000000000n,
|
|
93
|
+
// 5,000 USDC
|
|
94
|
+
["Diamond" /* Diamond */]: 10000000000n
|
|
95
|
+
// 10,000 USDC
|
|
96
|
+
};
|
|
97
|
+
var TIER_VOTE_MULTIPLIERS = {
|
|
98
|
+
["Bronze" /* Bronze */]: 100,
|
|
99
|
+
// 1.0x
|
|
100
|
+
["Silver" /* Silver */]: 120,
|
|
101
|
+
// 1.2x
|
|
102
|
+
["Gold" /* Gold */]: 150,
|
|
103
|
+
// 1.5x
|
|
104
|
+
["Platinum" /* Platinum */]: 200,
|
|
105
|
+
// 2.0x
|
|
106
|
+
["Diamond" /* Diamond */]: 300
|
|
107
|
+
// 3.0x
|
|
108
|
+
};
|
|
109
|
+
var TIER_TOKEN_MULTIPLIERS = {
|
|
110
|
+
["Bronze" /* Bronze */]: 100,
|
|
111
|
+
["Silver" /* Silver */]: 120,
|
|
112
|
+
["Gold" /* Gold */]: 150,
|
|
113
|
+
["Platinum" /* Platinum */]: 200,
|
|
114
|
+
["Diamond" /* Diamond */]: 300
|
|
115
|
+
};
|
|
116
|
+
function getTierFromAmount(amount) {
|
|
117
|
+
if (amount >= TIER_MINIMUMS["Diamond" /* Diamond */]) return "Diamond" /* Diamond */;
|
|
118
|
+
if (amount >= TIER_MINIMUMS["Platinum" /* Platinum */]) return "Platinum" /* Platinum */;
|
|
119
|
+
if (amount >= TIER_MINIMUMS["Gold" /* Gold */]) return "Gold" /* Gold */;
|
|
120
|
+
if (amount >= TIER_MINIMUMS["Silver" /* Silver */]) return "Silver" /* Silver */;
|
|
121
|
+
return "Bronze" /* Bronze */;
|
|
122
|
+
}
|
|
123
|
+
function getVoteMultiplier(amount) {
|
|
124
|
+
const tier = getTierFromAmount(amount);
|
|
125
|
+
return TIER_VOTE_MULTIPLIERS[tier] / 100;
|
|
126
|
+
}
|
|
127
|
+
function getTokenMultiplier(amount) {
|
|
128
|
+
const tier = getTierFromAmount(amount);
|
|
129
|
+
return TIER_TOKEN_MULTIPLIERS[tier] / 100;
|
|
130
|
+
}
|
|
131
|
+
function findTierIndex(tiers, amount) {
|
|
132
|
+
for (let i = tiers.length - 1; i >= 0; i--) {
|
|
133
|
+
if (amount >= tiers[i].amount) {
|
|
134
|
+
return i;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
var GOVERNANCE = {
|
|
140
|
+
/** Scam report threshold (30%) */
|
|
141
|
+
SCAM_THRESHOLD_PERCENT: 30,
|
|
142
|
+
/** Consecutive milestone failures before exit window eligible */
|
|
143
|
+
CONSECUTIVE_FAILURES_THRESHOLD: 3,
|
|
144
|
+
/** Milestone approval threshold (>50% weighted approval per whitepaper voting.md:100-101) */
|
|
145
|
+
MILESTONE_APPROVAL_THRESHOLD_PERCENT: 50
|
|
146
|
+
};
|
|
147
|
+
var NFT = {
|
|
148
|
+
/** NFT symbol */
|
|
149
|
+
SYMBOL: "SNI",
|
|
150
|
+
/** NFT name prefix */
|
|
151
|
+
NAME_PREFIX: "Raise Investment #",
|
|
152
|
+
/** Royalty basis points (2%) */
|
|
153
|
+
ROYALTY_BASIS_POINTS: 200
|
|
154
|
+
};
|
|
155
|
+
var USDC = {
|
|
156
|
+
/** USDC decimals */
|
|
157
|
+
DECIMALS: 6,
|
|
158
|
+
/** Convert USDC to lamports */
|
|
159
|
+
toAmount: (usdc) => BigInt(Math.floor(usdc * 10 ** 6)),
|
|
160
|
+
/** Convert lamports to USDC */
|
|
161
|
+
fromAmount: (lamports) => Number(lamports) / 10 ** 6
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/pdas/index.ts
|
|
165
|
+
function ensureBN(value) {
|
|
166
|
+
if (value && typeof value.toArrayLike === "function") {
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
return new BN(String(value));
|
|
170
|
+
}
|
|
171
|
+
function getProjectPDA(projectId, programId) {
|
|
172
|
+
const projectIdBN = ensureBN(projectId);
|
|
173
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
174
|
+
[Buffer.from(SEEDS.PROJECT), projectIdBN.toArrayLike(Buffer, "le", 8)],
|
|
175
|
+
programId
|
|
176
|
+
);
|
|
177
|
+
return pda;
|
|
178
|
+
}
|
|
179
|
+
function getEscrowPDA(projectId, programId) {
|
|
180
|
+
const projectIdBN = ensureBN(projectId);
|
|
181
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
182
|
+
[Buffer.from(SEEDS.ESCROW), projectIdBN.toArrayLike(Buffer, "le", 8)],
|
|
183
|
+
programId
|
|
184
|
+
);
|
|
185
|
+
return pda;
|
|
186
|
+
}
|
|
187
|
+
function getMilestonePDA(projectPda, milestoneIndex, programId) {
|
|
188
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
189
|
+
[
|
|
190
|
+
Buffer.from(SEEDS.MILESTONE),
|
|
191
|
+
projectPda.toBuffer(),
|
|
192
|
+
Buffer.from([milestoneIndex])
|
|
193
|
+
],
|
|
194
|
+
programId
|
|
195
|
+
);
|
|
196
|
+
return pda;
|
|
197
|
+
}
|
|
198
|
+
function getInvestmentPDA(projectPda, nftMint, programId) {
|
|
199
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
200
|
+
[
|
|
201
|
+
Buffer.from(SEEDS.INVESTMENT),
|
|
202
|
+
projectPda.toBuffer(),
|
|
203
|
+
nftMint.toBuffer()
|
|
204
|
+
],
|
|
205
|
+
programId
|
|
206
|
+
);
|
|
207
|
+
return pda;
|
|
208
|
+
}
|
|
209
|
+
function getVotePDA(milestonePda, voterKey, votingRound, programId) {
|
|
210
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
211
|
+
[Buffer.from(SEEDS.VOTE), milestonePda.toBuffer(), voterKey.toBuffer(), Buffer.from([votingRound])],
|
|
212
|
+
programId
|
|
213
|
+
);
|
|
214
|
+
return pda;
|
|
215
|
+
}
|
|
216
|
+
function getPivotProposalPDA(projectPda, pivotCount, programId) {
|
|
217
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
218
|
+
[
|
|
219
|
+
Buffer.from(SEEDS.PIVOT),
|
|
220
|
+
// Use PIVOT seed, not PIVOT_PROPOSAL
|
|
221
|
+
projectPda.toBuffer(),
|
|
222
|
+
Buffer.from([pivotCount])
|
|
223
|
+
// pivot_count is u8 (1 byte) on-chain
|
|
224
|
+
],
|
|
225
|
+
programId
|
|
226
|
+
);
|
|
227
|
+
return pda;
|
|
228
|
+
}
|
|
229
|
+
function getTgeEscrowPDA(projectPda, programId) {
|
|
230
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
231
|
+
[Buffer.from(SEEDS.TGE_ESCROW), projectPda.toBuffer()],
|
|
232
|
+
programId
|
|
233
|
+
);
|
|
234
|
+
return pda;
|
|
235
|
+
}
|
|
236
|
+
function getTgeEscrowVaultPDA(projectPda, programId) {
|
|
237
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
238
|
+
[Buffer.from(SEEDS.TGE_ESCROW_VAULT), projectPda.toBuffer()],
|
|
239
|
+
programId
|
|
240
|
+
);
|
|
241
|
+
return pda;
|
|
242
|
+
}
|
|
243
|
+
function getTokenVaultPDA(projectPda, programId) {
|
|
244
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
245
|
+
[Buffer.from("token_vault"), projectPda.toBuffer()],
|
|
246
|
+
programId
|
|
247
|
+
);
|
|
248
|
+
return pda;
|
|
249
|
+
}
|
|
250
|
+
function getScamReportPDA(projectPda, nftMint, programId) {
|
|
251
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
252
|
+
[
|
|
253
|
+
Buffer.from(SEEDS.SCAM_REPORT),
|
|
254
|
+
projectPda.toBuffer(),
|
|
255
|
+
nftMint.toBuffer()
|
|
256
|
+
],
|
|
257
|
+
programId
|
|
258
|
+
);
|
|
259
|
+
return pda;
|
|
260
|
+
}
|
|
261
|
+
function getAdminConfigPDA(programId) {
|
|
262
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
263
|
+
[Buffer.from(SEEDS.ADMIN_CONFIG)],
|
|
264
|
+
programId
|
|
265
|
+
);
|
|
266
|
+
return pda;
|
|
267
|
+
}
|
|
268
|
+
function getNftMintPDA(projectId, investor, investmentCount, programId) {
|
|
269
|
+
const projectIdBN = ensureBN(projectId);
|
|
270
|
+
const countBN = ensureBN(investmentCount);
|
|
271
|
+
return PublicKey.findProgramAddressSync(
|
|
272
|
+
[
|
|
273
|
+
Buffer.from(SEEDS.NFT_MINT),
|
|
274
|
+
projectIdBN.toArrayLike(Buffer, "le", 8),
|
|
275
|
+
investor.toBuffer(),
|
|
276
|
+
countBN.toArrayLike(Buffer, "le", 8)
|
|
277
|
+
// u64 is 8 bytes LE
|
|
278
|
+
],
|
|
279
|
+
programId
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
function getProgramAuthorityPDA(programId) {
|
|
283
|
+
return PublicKey.findProgramAddressSync(
|
|
284
|
+
[Buffer.from(SEEDS.AUTHORITY)],
|
|
285
|
+
programId
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
function getProjectPDAs(projectId, programId) {
|
|
289
|
+
const project = getProjectPDA(projectId, programId);
|
|
290
|
+
const escrow = getEscrowPDA(projectId, programId);
|
|
291
|
+
return { project, escrow };
|
|
292
|
+
}
|
|
293
|
+
function getTokenomicsPDA(projectPda, programId) {
|
|
294
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
295
|
+
[Buffer.from("tokenomics"), projectPda.toBuffer()],
|
|
296
|
+
programId
|
|
297
|
+
);
|
|
298
|
+
return pda;
|
|
299
|
+
}
|
|
300
|
+
function getTokenMintPDA(projectPda, programId) {
|
|
301
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
302
|
+
[Buffer.from("token_mint"), projectPda.toBuffer()],
|
|
303
|
+
programId
|
|
304
|
+
);
|
|
305
|
+
return pda;
|
|
306
|
+
}
|
|
307
|
+
function getVaultAuthorityPDA(projectPda, programId) {
|
|
308
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
309
|
+
[Buffer.from("vault_authority"), projectPda.toBuffer()],
|
|
310
|
+
programId
|
|
311
|
+
);
|
|
312
|
+
return pda;
|
|
313
|
+
}
|
|
314
|
+
function getInvestorVaultPDA(projectPda, programId) {
|
|
315
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
316
|
+
[Buffer.from("investor_vault"), projectPda.toBuffer()],
|
|
317
|
+
programId
|
|
318
|
+
);
|
|
319
|
+
return pda;
|
|
320
|
+
}
|
|
321
|
+
function getFounderVaultPDA(projectPda, programId) {
|
|
322
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
323
|
+
[Buffer.from("founder_vault"), projectPda.toBuffer()],
|
|
324
|
+
programId
|
|
325
|
+
);
|
|
326
|
+
return pda;
|
|
327
|
+
}
|
|
328
|
+
function getLpTokenVaultPDA(projectPda, programId) {
|
|
329
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
330
|
+
[Buffer.from("lp_token_vault"), projectPda.toBuffer()],
|
|
331
|
+
programId
|
|
332
|
+
);
|
|
333
|
+
return pda;
|
|
334
|
+
}
|
|
335
|
+
function getTreasuryVaultPDA(projectPda, programId) {
|
|
336
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
337
|
+
[Buffer.from("treasury_vault"), projectPda.toBuffer()],
|
|
338
|
+
programId
|
|
339
|
+
);
|
|
340
|
+
return pda;
|
|
341
|
+
}
|
|
342
|
+
function getLpUsdcVaultPDA(projectPda, programId) {
|
|
343
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
344
|
+
[Buffer.from("lp_usdc_vault"), projectPda.toBuffer()],
|
|
345
|
+
programId
|
|
346
|
+
);
|
|
347
|
+
return pda;
|
|
348
|
+
}
|
|
349
|
+
function getFounderVestingPDA(projectPda, programId) {
|
|
350
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
351
|
+
[Buffer.from("founder_vesting"), projectPda.toBuffer()],
|
|
352
|
+
programId
|
|
353
|
+
);
|
|
354
|
+
return pda;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/accounts/index.ts
|
|
358
|
+
function getAccountNamespace(program) {
|
|
359
|
+
return program.account;
|
|
360
|
+
}
|
|
361
|
+
async function fetchProject(program, projectId) {
|
|
362
|
+
try {
|
|
363
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
364
|
+
return await getAccountNamespace(program).project.fetch(projectPda);
|
|
365
|
+
} catch (error) {
|
|
366
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function fetchProjectByPda(program, projectPda) {
|
|
373
|
+
try {
|
|
374
|
+
return await getAccountNamespace(program).project.fetch(projectPda);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async function fetchMilestone(program, projectId, milestoneIndex) {
|
|
383
|
+
try {
|
|
384
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
385
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
386
|
+
return await getAccountNamespace(program).milestone.fetch(milestonePda);
|
|
387
|
+
} catch (error) {
|
|
388
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async function fetchAllMilestones(program, projectId) {
|
|
395
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
396
|
+
const milestones = await getAccountNamespace(program).milestone.all([
|
|
397
|
+
{
|
|
398
|
+
memcmp: {
|
|
399
|
+
offset: 8,
|
|
400
|
+
// Skip discriminator
|
|
401
|
+
bytes: projectPda.toBase58()
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
]);
|
|
405
|
+
return milestones.map((m) => ({
|
|
406
|
+
publicKey: m.publicKey,
|
|
407
|
+
account: m.account
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
async function fetchInvestment(program, projectId, nftMint) {
|
|
411
|
+
try {
|
|
412
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
413
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
|
|
414
|
+
return await getAccountNamespace(program).investment.fetch(investmentPda);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async function fetchAllInvestments(program, projectId) {
|
|
423
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
424
|
+
const investments = await getAccountNamespace(program).investment.all([
|
|
425
|
+
{
|
|
426
|
+
memcmp: {
|
|
427
|
+
offset: 8,
|
|
428
|
+
// Skip discriminator
|
|
429
|
+
bytes: projectPda.toBase58()
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
]);
|
|
433
|
+
return investments.map((inv) => ({
|
|
434
|
+
publicKey: inv.publicKey,
|
|
435
|
+
account: inv.account
|
|
436
|
+
}));
|
|
437
|
+
}
|
|
438
|
+
async function fetchVote(program, projectId, milestoneIndex, voterKey, votingRound) {
|
|
439
|
+
try {
|
|
440
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
441
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
442
|
+
const votePda = getVotePDA(milestonePda, voterKey, votingRound, program.programId);
|
|
443
|
+
return await getAccountNamespace(program).vote.fetch(votePda);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async function fetchAllVotes(program, projectId, milestoneIndex) {
|
|
452
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
453
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
454
|
+
const votes = await getAccountNamespace(program).vote.all([
|
|
455
|
+
{
|
|
456
|
+
memcmp: {
|
|
457
|
+
offset: 8,
|
|
458
|
+
// Skip discriminator
|
|
459
|
+
bytes: milestonePda.toBase58()
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
]);
|
|
463
|
+
return votes.map((v) => ({
|
|
464
|
+
publicKey: v.publicKey,
|
|
465
|
+
account: v.account
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
async function fetchPivotProposal(program, projectId) {
|
|
469
|
+
try {
|
|
470
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
471
|
+
const projectAccount = await getAccountNamespace(program).project.fetch(projectPda);
|
|
472
|
+
let pivotPda;
|
|
473
|
+
if (projectAccount.activePivot) {
|
|
474
|
+
pivotPda = projectAccount.activePivot;
|
|
475
|
+
} else {
|
|
476
|
+
const pivotCount = projectAccount.pivotCount || 0;
|
|
477
|
+
pivotPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
|
|
478
|
+
}
|
|
479
|
+
return await getAccountNamespace(program).pivotProposal.fetch(pivotPda);
|
|
480
|
+
} catch (error) {
|
|
481
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
throw error;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async function fetchTgeEscrow(program, projectId) {
|
|
488
|
+
try {
|
|
489
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
490
|
+
const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
|
|
491
|
+
return await getAccountNamespace(program).tgeEscrow.fetch(tgeEscrowPda);
|
|
492
|
+
} catch (error) {
|
|
493
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
throw error;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
async function fetchAdminConfig(program) {
|
|
500
|
+
const adminConfigPda = getAdminConfigPDA(program.programId);
|
|
501
|
+
return await getAccountNamespace(program).adminConfig.fetch(adminConfigPda);
|
|
502
|
+
}
|
|
503
|
+
async function accountExists(program, accountType, pda) {
|
|
504
|
+
try {
|
|
505
|
+
await program.account[accountType].fetch(pda);
|
|
506
|
+
return true;
|
|
507
|
+
} catch {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
var TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
|
|
512
|
+
function ensurePublicKey(value) {
|
|
513
|
+
if (value instanceof PublicKey) {
|
|
514
|
+
return value;
|
|
515
|
+
}
|
|
516
|
+
return new PublicKey(String(value));
|
|
517
|
+
}
|
|
518
|
+
function getMethods(program) {
|
|
519
|
+
return program.methods;
|
|
520
|
+
}
|
|
521
|
+
function getAccountNamespace2(program) {
|
|
522
|
+
return program.account;
|
|
523
|
+
}
|
|
524
|
+
async function initializeAdmin(program, admin, payer) {
|
|
525
|
+
return getMethods(program).initializeAdmin().accounts({
|
|
526
|
+
admin,
|
|
527
|
+
payer
|
|
528
|
+
}).rpc();
|
|
529
|
+
}
|
|
530
|
+
async function transferAdmin(program, adminKeypair, newAdmin) {
|
|
531
|
+
return getMethods(program).transferAdmin().accounts({
|
|
532
|
+
authority: adminKeypair.publicKey,
|
|
533
|
+
newAdmin
|
|
534
|
+
}).signers([adminKeypair]).rpc();
|
|
535
|
+
}
|
|
536
|
+
async function acceptAdmin(program, newAuthority) {
|
|
537
|
+
return getMethods(program).acceptAdmin().accounts({
|
|
538
|
+
newAuthority
|
|
539
|
+
}).rpc();
|
|
540
|
+
}
|
|
541
|
+
function symbolToBytes(symbol) {
|
|
542
|
+
const bytes = new Array(8).fill(0);
|
|
543
|
+
const chars = symbol.toUpperCase().slice(0, 8);
|
|
544
|
+
for (let i = 0; i < chars.length; i++) {
|
|
545
|
+
bytes[i] = chars.charCodeAt(i);
|
|
546
|
+
}
|
|
547
|
+
return bytes;
|
|
548
|
+
}
|
|
549
|
+
var MIN_DEADLINE_DURATION_SECONDS_PROD = 604800;
|
|
550
|
+
var MIN_DEADLINE_DURATION_SECONDS_DEV = 60;
|
|
551
|
+
var MAX_DEADLINE_DURATION_SECONDS = 31536e3;
|
|
552
|
+
function calculateDeadline(daysFromNow, isDev = false) {
|
|
553
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
554
|
+
const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
|
|
555
|
+
const daysInSeconds = daysFromNow * 24 * 60 * 60;
|
|
556
|
+
const deadlineSeconds = nowSeconds + Math.max(daysInSeconds, minDuration);
|
|
557
|
+
const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
|
|
558
|
+
return new BN(Math.min(deadlineSeconds, maxDeadline));
|
|
559
|
+
}
|
|
560
|
+
function minDeadline(isDev = false) {
|
|
561
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
562
|
+
const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
|
|
563
|
+
return new BN(nowSeconds + minDuration + 1);
|
|
564
|
+
}
|
|
565
|
+
function validateDeadline(deadline, isDev = false) {
|
|
566
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
567
|
+
const deadlineSeconds = deadline.toNumber();
|
|
568
|
+
const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
|
|
569
|
+
const minDeadline2 = nowSeconds + minDuration;
|
|
570
|
+
const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
|
|
571
|
+
if (deadlineSeconds < minDeadline2) {
|
|
572
|
+
const minDays = isDev ? "60 seconds" : "7 days";
|
|
573
|
+
return {
|
|
574
|
+
valid: false,
|
|
575
|
+
error: `Deadline must be at least ${minDays} from now`
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
if (deadlineSeconds > maxDeadline) {
|
|
579
|
+
return {
|
|
580
|
+
valid: false,
|
|
581
|
+
error: "Deadline must be within 1 year from now"
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
return { valid: true };
|
|
585
|
+
}
|
|
586
|
+
async function initializeProject(program, args, founder) {
|
|
587
|
+
return getMethods(program).initializeProject({
|
|
588
|
+
projectId: args.projectId,
|
|
589
|
+
fundingGoal: args.fundingGoal,
|
|
590
|
+
metadataUri: args.metadataUri,
|
|
591
|
+
tiers: args.tiers,
|
|
592
|
+
tokenomics: {
|
|
593
|
+
tokenSymbol: args.tokenomics.tokenSymbol,
|
|
594
|
+
totalSupply: args.tokenomics.totalSupply,
|
|
595
|
+
investorAllocationBps: args.tokenomics.investorAllocationBps,
|
|
596
|
+
lpTokenAllocationBps: args.tokenomics.lpTokenAllocationBps,
|
|
597
|
+
lpUsdcAllocationBps: args.tokenomics.lpUsdcAllocationBps,
|
|
598
|
+
founderAllocationBps: args.tokenomics.founderAllocationBps ?? null,
|
|
599
|
+
treasuryAllocationBps: args.tokenomics.treasuryAllocationBps ?? null,
|
|
600
|
+
founderWallet: args.tokenomics.founderWallet ?? null,
|
|
601
|
+
vestingDurationMonths: args.tokenomics.vestingDurationMonths ?? null,
|
|
602
|
+
cliffMonths: args.tokenomics.cliffMonths ?? null
|
|
603
|
+
},
|
|
604
|
+
milestone1Deadline: args.milestone1Deadline
|
|
605
|
+
}).accounts({
|
|
606
|
+
founder
|
|
607
|
+
}).rpc();
|
|
608
|
+
}
|
|
609
|
+
async function submitForApproval(program, projectId, founder) {
|
|
610
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
611
|
+
return getMethods(program).submitForApproval().accounts({
|
|
612
|
+
project: projectPda,
|
|
613
|
+
founder
|
|
614
|
+
}).rpc();
|
|
615
|
+
}
|
|
616
|
+
async function approveProject(program, args, adminKeypair) {
|
|
617
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
618
|
+
const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
|
|
619
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
620
|
+
const tokenMintPda = getTokenMintPDA(projectPda, program.programId);
|
|
621
|
+
const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
|
|
622
|
+
const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
|
|
623
|
+
const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
|
|
624
|
+
const lpTokenVaultPda = getLpTokenVaultPDA(projectPda, program.programId);
|
|
625
|
+
const treasuryVaultPda = getTreasuryVaultPDA(projectPda, program.programId);
|
|
626
|
+
const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
|
|
627
|
+
return getMethods(program).approveProject().accounts({
|
|
628
|
+
project: projectPda,
|
|
629
|
+
tokenomics: tokenomicsPda,
|
|
630
|
+
tokenVault: tokenVaultPda,
|
|
631
|
+
tokenMint: tokenMintPda,
|
|
632
|
+
vaultAuthority: vaultAuthorityPda,
|
|
633
|
+
investorVault: investorVaultPda,
|
|
634
|
+
founderVault: founderVaultPda,
|
|
635
|
+
lpTokenVault: lpTokenVaultPda,
|
|
636
|
+
treasuryVault: treasuryVaultPda,
|
|
637
|
+
lpUsdcVault: lpUsdcVaultPda,
|
|
638
|
+
usdcMint: args.usdcMint,
|
|
639
|
+
authority: adminKeypair.publicKey,
|
|
640
|
+
payer: adminKeypair.publicKey
|
|
641
|
+
}).signers([adminKeypair]).rpc();
|
|
642
|
+
}
|
|
643
|
+
async function createMilestone(program, args, founder) {
|
|
644
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
645
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
646
|
+
return getMethods(program).createMilestone({
|
|
647
|
+
milestoneIndex: args.milestoneIndex,
|
|
648
|
+
percentage: args.percentage,
|
|
649
|
+
description: args.description
|
|
650
|
+
}).accounts({
|
|
651
|
+
project: projectPda,
|
|
652
|
+
milestone: milestonePda,
|
|
653
|
+
founder
|
|
654
|
+
}).rpc();
|
|
655
|
+
}
|
|
656
|
+
async function submitMilestone(program, projectId, milestoneIndex, founder) {
|
|
657
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
658
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
659
|
+
return getMethods(program).submitMilestone().accounts({
|
|
660
|
+
project: projectPda,
|
|
661
|
+
milestone: milestonePda,
|
|
662
|
+
founder
|
|
663
|
+
}).rpc();
|
|
664
|
+
}
|
|
665
|
+
async function voteOnMilestone(program, args, voter) {
|
|
666
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
667
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
668
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
669
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
670
|
+
const milestone = await getAccountNamespace2(program).milestone.fetch(milestonePda);
|
|
671
|
+
const votingRound = milestone.votingRound ?? 0;
|
|
672
|
+
const votePda = getVotePDA(milestonePda, voter, votingRound, program.programId);
|
|
673
|
+
const voterNftAccount = getAssociatedTokenAddressSync(
|
|
674
|
+
nftMintPubkey,
|
|
675
|
+
voter,
|
|
676
|
+
false,
|
|
677
|
+
// allowOwnerOffCurve
|
|
678
|
+
TOKEN_PROGRAM_ID
|
|
679
|
+
);
|
|
680
|
+
return getMethods(program).voteOnMilestone({ choice: args.choice }).accounts({
|
|
681
|
+
milestone: milestonePda,
|
|
682
|
+
project: projectPda,
|
|
683
|
+
investment: investmentPda,
|
|
684
|
+
vote: votePda,
|
|
685
|
+
nftMint: nftMintPubkey,
|
|
686
|
+
voterNftAccount,
|
|
687
|
+
voter
|
|
688
|
+
}).rpc();
|
|
689
|
+
}
|
|
690
|
+
async function finalizeVoting(program, projectId, milestoneIndex) {
|
|
691
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
692
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
693
|
+
return getMethods(program).finalizeVoting().accounts({
|
|
694
|
+
project: projectPda,
|
|
695
|
+
milestone: milestonePda
|
|
696
|
+
}).rpc();
|
|
697
|
+
}
|
|
698
|
+
async function claimMilestoneFunds(program, args, founder) {
|
|
699
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
700
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
701
|
+
const escrowPda = getEscrowPDA(args.projectId, program.programId);
|
|
702
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
703
|
+
const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
|
|
704
|
+
const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
|
|
705
|
+
const nextMilestonePda = args.nextMilestonePda ?? (args.nextMilestoneDeadline.gt(new BN(0)) ? getMilestonePDA(projectPda, args.milestoneIndex + 1, program.programId) : null);
|
|
706
|
+
return getMethods(program).claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).accounts({
|
|
707
|
+
milestone: milestonePda,
|
|
708
|
+
project: projectPda,
|
|
709
|
+
founder,
|
|
710
|
+
projectEscrow: args.escrowTokenAccount,
|
|
711
|
+
founderUsdcAccount: args.founderUsdcAccount,
|
|
712
|
+
escrowPda,
|
|
713
|
+
tokenVault: tokenVaultPda,
|
|
714
|
+
tokenomics: tokenomicsPda,
|
|
715
|
+
lpUsdcVault: lpUsdcVaultPda,
|
|
716
|
+
nextMilestone: nextMilestonePda,
|
|
717
|
+
systemProgram: SystemProgram.programId,
|
|
718
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
719
|
+
}).rpc();
|
|
720
|
+
}
|
|
721
|
+
async function resubmitMilestone(program, args, founder) {
|
|
722
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
723
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
724
|
+
return getMethods(program).resubmitMilestone().accounts({
|
|
725
|
+
project: projectPda,
|
|
726
|
+
milestone: milestonePda,
|
|
727
|
+
founder
|
|
728
|
+
}).rpc();
|
|
729
|
+
}
|
|
730
|
+
async function setMilestoneDeadline(program, args, founder) {
|
|
731
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
732
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
733
|
+
return getMethods(program).setMilestoneDeadline({
|
|
734
|
+
milestoneIndex: args.milestoneIndex,
|
|
735
|
+
deadline: args.deadline
|
|
736
|
+
}).accounts({
|
|
737
|
+
project: projectPda,
|
|
738
|
+
milestone: milestonePda,
|
|
739
|
+
founder
|
|
740
|
+
}).rpc();
|
|
741
|
+
}
|
|
742
|
+
async function extendMilestoneDeadline(program, args, founder) {
|
|
743
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
744
|
+
const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
|
|
745
|
+
return getMethods(program).extendMilestoneDeadline({
|
|
746
|
+
milestoneIndex: args.milestoneIndex,
|
|
747
|
+
newDeadline: args.newDeadline
|
|
748
|
+
}).accounts({
|
|
749
|
+
project: projectPda,
|
|
750
|
+
milestone: milestonePda,
|
|
751
|
+
founder
|
|
752
|
+
}).rpc();
|
|
753
|
+
}
|
|
754
|
+
function getMetadataPDA(mint) {
|
|
755
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
756
|
+
[
|
|
757
|
+
Buffer.from("metadata"),
|
|
758
|
+
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
|
|
759
|
+
mint.toBuffer()
|
|
760
|
+
],
|
|
761
|
+
TOKEN_METADATA_PROGRAM_ID
|
|
762
|
+
);
|
|
763
|
+
return pda;
|
|
764
|
+
}
|
|
765
|
+
function getMasterEditionPDA(mint) {
|
|
766
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
767
|
+
[
|
|
768
|
+
Buffer.from("metadata"),
|
|
769
|
+
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
|
|
770
|
+
mint.toBuffer(),
|
|
771
|
+
Buffer.from("edition")
|
|
772
|
+
],
|
|
773
|
+
TOKEN_METADATA_PROGRAM_ID
|
|
774
|
+
);
|
|
775
|
+
return pda;
|
|
776
|
+
}
|
|
777
|
+
async function invest(program, args, investor) {
|
|
778
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
779
|
+
const [nftMint] = getNftMintPDA(args.projectId, investor, args.investmentCount, program.programId);
|
|
780
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
|
|
781
|
+
const investorNftAccount = getAssociatedTokenAddressSync(nftMint, investor);
|
|
782
|
+
const metadataAccount = getMetadataPDA(nftMint);
|
|
783
|
+
const masterEdition = getMasterEditionPDA(nftMint);
|
|
784
|
+
const [programAuthority] = getProgramAuthorityPDA(program.programId);
|
|
785
|
+
const firstMilestonePda = getMilestonePDA(projectPda, 0, program.programId);
|
|
786
|
+
return getMethods(program).invest({ amount: args.amount }).accounts({
|
|
787
|
+
project: projectPda,
|
|
788
|
+
firstMilestone: firstMilestonePda,
|
|
789
|
+
nftMint,
|
|
790
|
+
investment: investmentPda,
|
|
791
|
+
investorNftAccount,
|
|
792
|
+
metadataAccount,
|
|
793
|
+
masterEdition,
|
|
794
|
+
escrowTokenAccount: args.escrowTokenAccount,
|
|
795
|
+
investorTokenAccount: args.investorTokenAccount,
|
|
796
|
+
programAuthority,
|
|
797
|
+
investor,
|
|
798
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
799
|
+
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
800
|
+
systemProgram: SystemProgram.programId,
|
|
801
|
+
rent: SYSVAR_RENT_PUBKEY,
|
|
802
|
+
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
|
|
803
|
+
sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY
|
|
804
|
+
}).preInstructions([
|
|
805
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 })
|
|
806
|
+
]).rpc();
|
|
807
|
+
}
|
|
808
|
+
async function cancelInvestment(program, args, investor) {
|
|
809
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
810
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
811
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
812
|
+
const escrowPda = getEscrowPDA(args.projectId, program.programId);
|
|
813
|
+
return getMethods(program).cancelInvestment().accounts({
|
|
814
|
+
investor,
|
|
815
|
+
project: projectPda,
|
|
816
|
+
investment: investmentPda,
|
|
817
|
+
nftMint: nftMintPubkey,
|
|
818
|
+
investorNftAccount: args.investorNftAccount,
|
|
819
|
+
projectEscrow: args.escrowTokenAccount,
|
|
820
|
+
investorUsdcAccount: args.investorUsdcAccount,
|
|
821
|
+
escrowPda
|
|
822
|
+
}).rpc();
|
|
823
|
+
}
|
|
824
|
+
async function proposePivot(program, args, founder) {
|
|
825
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
826
|
+
const projectAccount = await getAccountNamespace2(program).project.fetch(projectPda);
|
|
827
|
+
const pivotCount = projectAccount.pivotCount || 0;
|
|
828
|
+
const pivotProposalPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
|
|
829
|
+
return getMethods(program).proposePivot({
|
|
830
|
+
newMetadataUri: args.newMetadataUri,
|
|
831
|
+
newMilestones: args.newMilestones
|
|
832
|
+
}).accounts({
|
|
833
|
+
project: projectPda,
|
|
834
|
+
founder,
|
|
835
|
+
pivotProposal: pivotProposalPda,
|
|
836
|
+
systemProgram: SystemProgram.programId,
|
|
837
|
+
clock: SYSVAR_CLOCK_PUBKEY
|
|
838
|
+
}).rpc();
|
|
839
|
+
}
|
|
840
|
+
async function approvePivot(program, projectId, adminKeypair) {
|
|
841
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
842
|
+
const projectAccount = await getAccountNamespace2(program).project.fetch(projectPda);
|
|
843
|
+
let pivotProposalPda;
|
|
844
|
+
if (projectAccount.activePivot) {
|
|
845
|
+
pivotProposalPda = projectAccount.activePivot;
|
|
846
|
+
} else {
|
|
847
|
+
const pivotCount = projectAccount.pivotCount || 0;
|
|
848
|
+
pivotProposalPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
|
|
849
|
+
}
|
|
850
|
+
return getMethods(program).approvePivot().accounts({
|
|
851
|
+
moderator: adminKeypair.publicKey,
|
|
852
|
+
project: projectPda,
|
|
853
|
+
pivotProposal: pivotProposalPda
|
|
854
|
+
}).signers([adminKeypair]).rpc();
|
|
855
|
+
}
|
|
856
|
+
async function withdrawFromPivot(program, args, investor) {
|
|
857
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
858
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
859
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
860
|
+
const escrowPda = getEscrowPDA(args.projectId, program.programId);
|
|
861
|
+
const pivotProposalPda = getPivotProposalPDA(projectPda, args.pivotCount, program.programId);
|
|
862
|
+
const investorNftAccount = getAssociatedTokenAddressSync(
|
|
863
|
+
nftMintPubkey,
|
|
864
|
+
investor,
|
|
865
|
+
false,
|
|
866
|
+
TOKEN_PROGRAM_ID
|
|
867
|
+
);
|
|
868
|
+
const remainingAccounts = args.milestoneAccounts.map((pubkey) => ({
|
|
869
|
+
pubkey: ensurePublicKey(pubkey),
|
|
870
|
+
isSigner: false,
|
|
871
|
+
isWritable: false
|
|
872
|
+
}));
|
|
873
|
+
return getMethods(program).withdrawFromPivot().accounts({
|
|
874
|
+
investor,
|
|
875
|
+
project: projectPda,
|
|
876
|
+
pivotProposal: pivotProposalPda,
|
|
877
|
+
investment: investmentPda,
|
|
878
|
+
nftMint: nftMintPubkey,
|
|
879
|
+
investorNftAccount,
|
|
880
|
+
escrowTokenAccount: args.escrowTokenAccount,
|
|
881
|
+
investorTokenAccount: args.investorTokenAccount,
|
|
882
|
+
escrow: escrowPda
|
|
883
|
+
}).remainingAccounts(remainingAccounts).rpc();
|
|
884
|
+
}
|
|
885
|
+
async function finalizePivot(program, args, authority) {
|
|
886
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
887
|
+
const pivotProposalPda = getPivotProposalPDA(projectPda, args.pivotCount, program.programId);
|
|
888
|
+
const remainingAccounts = args.milestoneAccounts.map((pubkey) => ({
|
|
889
|
+
pubkey,
|
|
890
|
+
isSigner: false,
|
|
891
|
+
isWritable: true
|
|
892
|
+
}));
|
|
893
|
+
return getMethods(program).finalizePivot().accounts({
|
|
894
|
+
authority,
|
|
895
|
+
project: projectPda,
|
|
896
|
+
pivotProposal: pivotProposalPda
|
|
897
|
+
}).remainingAccounts(remainingAccounts).rpc();
|
|
898
|
+
}
|
|
899
|
+
async function setTgeDate(program, args, founder) {
|
|
900
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
901
|
+
return getMethods(program).setTgeDate({
|
|
902
|
+
tgeDate: args.tgeDate,
|
|
903
|
+
tokenMint: args.tokenMint
|
|
904
|
+
}).accounts({
|
|
905
|
+
project: projectPda,
|
|
906
|
+
founder
|
|
907
|
+
}).rpc();
|
|
908
|
+
}
|
|
909
|
+
async function depositTokens(program, args, founder) {
|
|
910
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
911
|
+
return getMethods(program).depositTokens({ amount: args.amount }).accounts({
|
|
912
|
+
project: projectPda,
|
|
913
|
+
tokenMint: args.tokenMint,
|
|
914
|
+
founderTokenAccount: args.founderTokenAccount,
|
|
915
|
+
founder
|
|
916
|
+
}).rpc();
|
|
917
|
+
}
|
|
918
|
+
async function claimTokens(program, args, investor) {
|
|
919
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
920
|
+
const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
|
|
921
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
922
|
+
return getMethods(program).claimTokens().accounts({
|
|
923
|
+
investor,
|
|
924
|
+
project: projectPda,
|
|
925
|
+
investment: investmentPda,
|
|
926
|
+
investorNftAccount: args.investorNftAccount,
|
|
927
|
+
projectTokenVault: args.projectTokenVault,
|
|
928
|
+
investorTokenAccount: args.investorTokenAccount,
|
|
929
|
+
tokenVaultPda,
|
|
930
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
931
|
+
}).rpc();
|
|
932
|
+
}
|
|
933
|
+
async function reportScam(program, args, reporter) {
|
|
934
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
935
|
+
const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
|
|
936
|
+
const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
|
|
937
|
+
return getMethods(program).reportScam().accounts({
|
|
938
|
+
tgeEscrow: tgeEscrowPda,
|
|
939
|
+
project: projectPda,
|
|
940
|
+
investment: investmentPda,
|
|
941
|
+
nftMint: args.nftMint,
|
|
942
|
+
reporter
|
|
943
|
+
}).rpc();
|
|
944
|
+
}
|
|
945
|
+
async function releaseHoldback(program, args) {
|
|
946
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
947
|
+
const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
|
|
948
|
+
return getMethods(program).releaseHoldback().accounts({
|
|
949
|
+
tgeEscrow: tgeEscrowPda,
|
|
950
|
+
project: projectPda,
|
|
951
|
+
founderTokenAccount: args.founderTokenAccount
|
|
952
|
+
}).rpc();
|
|
953
|
+
}
|
|
954
|
+
async function checkAbandonment(program, projectId, milestoneIndex = 0) {
|
|
955
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
956
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
957
|
+
return getMethods(program).checkAbandonment().accounts({
|
|
958
|
+
project: projectPda,
|
|
959
|
+
milestone: milestonePda
|
|
960
|
+
}).rpc();
|
|
961
|
+
}
|
|
962
|
+
async function claimRefund(program, args, investor) {
|
|
963
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
964
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
965
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
966
|
+
const milestoneCount = args.milestoneCount ?? 1;
|
|
967
|
+
const remainingAccounts = [];
|
|
968
|
+
for (let i = 0; i < milestoneCount; i++) {
|
|
969
|
+
const milestonePda = getMilestonePDA(projectPda, i, program.programId);
|
|
970
|
+
remainingAccounts.push({
|
|
971
|
+
pubkey: milestonePda,
|
|
972
|
+
isWritable: false,
|
|
973
|
+
isSigner: false
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
return getMethods(program).claimRefund().accounts({
|
|
977
|
+
project: projectPda,
|
|
978
|
+
investment: investmentPda,
|
|
979
|
+
nftMint: nftMintPubkey,
|
|
980
|
+
investorNftAccount: args.investorNftAccount,
|
|
981
|
+
investor,
|
|
982
|
+
investorTokenAccount: args.investorUsdcAccount,
|
|
983
|
+
escrowTokenAccount: args.escrowTokenAccount
|
|
984
|
+
}).remainingAccounts(remainingAccounts).rpc();
|
|
985
|
+
}
|
|
986
|
+
async function claimInvestorTokens(program, args, investor) {
|
|
987
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
988
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
989
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
990
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
991
|
+
const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
|
|
992
|
+
const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
|
|
993
|
+
const investorNftAccount = getAssociatedTokenAddressSync(
|
|
994
|
+
nftMintPubkey,
|
|
995
|
+
investor,
|
|
996
|
+
false,
|
|
997
|
+
TOKEN_PROGRAM_ID
|
|
998
|
+
);
|
|
999
|
+
return getMethods(program).claimInvestorTokens({ milestoneIndex: args.milestoneIndex }).accounts({
|
|
1000
|
+
investor,
|
|
1001
|
+
project: projectPda,
|
|
1002
|
+
tokenVault: tokenVaultPda,
|
|
1003
|
+
investment: investmentPda,
|
|
1004
|
+
nftMint: nftMintPubkey,
|
|
1005
|
+
investorNftAccount,
|
|
1006
|
+
investorVault: investorVaultPda,
|
|
1007
|
+
investorTokenAccount: args.investorTokenAccount,
|
|
1008
|
+
vaultAuthority: vaultAuthorityPda,
|
|
1009
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
1010
|
+
}).rpc();
|
|
1011
|
+
}
|
|
1012
|
+
async function distributeTokens(program, args, payer) {
|
|
1013
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1014
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1015
|
+
const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
|
|
1016
|
+
const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
|
|
1017
|
+
const remainingAccounts = args.investments.flatMap((inv) => [
|
|
1018
|
+
{ pubkey: inv.investmentPda, isSigner: false, isWritable: true },
|
|
1019
|
+
{ pubkey: inv.investorTokenAccount, isSigner: false, isWritable: true }
|
|
1020
|
+
]);
|
|
1021
|
+
return getMethods(program).distributeTokens({ milestoneIndex: args.milestoneIndex }).accounts({
|
|
1022
|
+
project: projectPda,
|
|
1023
|
+
tokenVault: tokenVaultPda,
|
|
1024
|
+
investorVault: investorVaultPda,
|
|
1025
|
+
vaultAuthority: vaultAuthorityPda,
|
|
1026
|
+
payer,
|
|
1027
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
1028
|
+
}).remainingAccounts(remainingAccounts).rpc();
|
|
1029
|
+
}
|
|
1030
|
+
async function completeDistribution(program, args, payer) {
|
|
1031
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1032
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1033
|
+
return getMethods(program).completeDistribution({ milestoneIndex: args.milestoneIndex }).accounts({
|
|
1034
|
+
project: projectPda,
|
|
1035
|
+
tokenVault: tokenVaultPda,
|
|
1036
|
+
payer
|
|
1037
|
+
}).rpc();
|
|
1038
|
+
}
|
|
1039
|
+
async function claimExitWindowRefund(program, args, investor) {
|
|
1040
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1041
|
+
const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
|
|
1042
|
+
const escrowPda = getEscrowPDA(args.projectId, program.programId);
|
|
1043
|
+
const remainingAccounts = (args.milestoneAccounts || []).map((pubkey) => ({
|
|
1044
|
+
pubkey,
|
|
1045
|
+
isSigner: false,
|
|
1046
|
+
isWritable: false
|
|
1047
|
+
}));
|
|
1048
|
+
return getMethods(program).claimExitWindowRefund().accountsPartial({
|
|
1049
|
+
project: projectPda,
|
|
1050
|
+
investment: investmentPda,
|
|
1051
|
+
nftMint: args.nftMint,
|
|
1052
|
+
investorNftAccount: args.investorNftAccount,
|
|
1053
|
+
escrowTokenAccount: args.escrowTokenAccount,
|
|
1054
|
+
investorTokenAccount: args.investorTokenAccount,
|
|
1055
|
+
escrowPda,
|
|
1056
|
+
investor
|
|
1057
|
+
}).remainingAccounts(remainingAccounts).rpc();
|
|
1058
|
+
}
|
|
1059
|
+
async function initializeFounderVesting(program, args, payer) {
|
|
1060
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1061
|
+
const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
|
|
1062
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1063
|
+
const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
|
|
1064
|
+
return getMethods(program).initializeFounderVesting().accounts({
|
|
1065
|
+
project: projectPda,
|
|
1066
|
+
tokenomics: tokenomicsPda,
|
|
1067
|
+
tokenVault: tokenVaultPda,
|
|
1068
|
+
founderVesting: founderVestingPda,
|
|
1069
|
+
payer,
|
|
1070
|
+
systemProgram: SystemProgram.programId
|
|
1071
|
+
}).rpc();
|
|
1072
|
+
}
|
|
1073
|
+
async function claimVestedTokens(program, args, founder) {
|
|
1074
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1075
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1076
|
+
const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
|
|
1077
|
+
const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
|
|
1078
|
+
const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
|
|
1079
|
+
return getMethods(program).claimVestedTokens().accounts({
|
|
1080
|
+
project: projectPda,
|
|
1081
|
+
tokenVault: tokenVaultPda,
|
|
1082
|
+
founderVesting: founderVestingPda,
|
|
1083
|
+
founderVault: founderVaultPda,
|
|
1084
|
+
vaultAuthority: vaultAuthorityPda,
|
|
1085
|
+
founderTokenAccount: args.founderTokenAccount,
|
|
1086
|
+
founder,
|
|
1087
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
1088
|
+
}).rpc();
|
|
1089
|
+
}
|
|
1090
|
+
async function forceCompleteDistribution(program, args, adminKeypair) {
|
|
1091
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1092
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1093
|
+
const adminConfigPda = getAdminConfigPDA(program.programId);
|
|
1094
|
+
return getMethods(program).forceCompleteDistribution().accounts({
|
|
1095
|
+
admin: adminKeypair.publicKey,
|
|
1096
|
+
adminConfig: adminConfigPda,
|
|
1097
|
+
project: projectPda,
|
|
1098
|
+
tokenVault: tokenVaultPda
|
|
1099
|
+
}).signers([adminKeypair]).rpc();
|
|
1100
|
+
}
|
|
1101
|
+
async function claimMissedUnlock(program, args, claimer) {
|
|
1102
|
+
const nftMintPubkey = ensurePublicKey(args.nftMint);
|
|
1103
|
+
const projectPda = getProjectPDA(args.projectId, program.programId);
|
|
1104
|
+
const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
|
|
1105
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
|
|
1106
|
+
const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
|
|
1107
|
+
const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
|
|
1108
|
+
const claimerNftAccount = getAssociatedTokenAddressSync(
|
|
1109
|
+
nftMintPubkey,
|
|
1110
|
+
claimer,
|
|
1111
|
+
false,
|
|
1112
|
+
TOKEN_PROGRAM_ID
|
|
1113
|
+
);
|
|
1114
|
+
return getMethods(program).claimMissedUnlock({ milestoneIndex: args.milestoneIndex }).accounts({
|
|
1115
|
+
claimer,
|
|
1116
|
+
project: projectPda,
|
|
1117
|
+
tokenVault: tokenVaultPda,
|
|
1118
|
+
investment: investmentPda,
|
|
1119
|
+
nftMint: nftMintPubkey,
|
|
1120
|
+
claimerNftAccount,
|
|
1121
|
+
investorVault: investorVaultPda,
|
|
1122
|
+
claimerTokenAccount: args.claimerTokenAccount,
|
|
1123
|
+
vaultAuthority: vaultAuthorityPda,
|
|
1124
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
1125
|
+
}).rpc();
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// src/client.ts
|
|
1129
|
+
var RaiseClient = class _RaiseClient {
|
|
1130
|
+
/**
|
|
1131
|
+
* Create a new RaiseClient
|
|
1132
|
+
*
|
|
1133
|
+
* @param program - Anchor program instance
|
|
1134
|
+
* @param provider - Anchor provider
|
|
1135
|
+
*/
|
|
1136
|
+
constructor(program, provider) {
|
|
1137
|
+
this.program = program;
|
|
1138
|
+
this.provider = provider;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Load a new RaiseClient instance
|
|
1142
|
+
*
|
|
1143
|
+
* @param connection - Solana connection
|
|
1144
|
+
* @param wallet - Wallet instance
|
|
1145
|
+
* @param programId - Optional program ID override
|
|
1146
|
+
* @returns Initialized RaiseClient
|
|
1147
|
+
*
|
|
1148
|
+
* @example
|
|
1149
|
+
* ```typescript
|
|
1150
|
+
* const client = RaiseClient.load(connection, wallet);
|
|
1151
|
+
* ```
|
|
1152
|
+
*/
|
|
1153
|
+
static load(_connection, _wallet, _programId) {
|
|
1154
|
+
throw new Error(
|
|
1155
|
+
"RaiseClient.load requires IDL. Use RaiseClient.fromProgram instead, or ensure the IDL is bundled with your application."
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Create client from an existing program instance
|
|
1160
|
+
*
|
|
1161
|
+
* @param program - Anchor program instance
|
|
1162
|
+
* @returns Initialized RaiseClient
|
|
1163
|
+
*
|
|
1164
|
+
* @example
|
|
1165
|
+
* ```typescript
|
|
1166
|
+
* import idl from './idl/raise.json';
|
|
1167
|
+
*
|
|
1168
|
+
* const provider = new AnchorProvider(connection, wallet, {});
|
|
1169
|
+
* const program = new Program(idl, provider);
|
|
1170
|
+
* const client = RaiseClient.fromProgram(program);
|
|
1171
|
+
* ```
|
|
1172
|
+
*/
|
|
1173
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1174
|
+
static fromProgram(program) {
|
|
1175
|
+
const provider = program.provider;
|
|
1176
|
+
return new _RaiseClient(program, provider);
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Get the program ID
|
|
1180
|
+
*/
|
|
1181
|
+
get programId() {
|
|
1182
|
+
return this.program.programId;
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Get the connected wallet public key
|
|
1186
|
+
*/
|
|
1187
|
+
get walletPublicKey() {
|
|
1188
|
+
return this.provider.wallet.publicKey;
|
|
1189
|
+
}
|
|
1190
|
+
// ===========================================================================
|
|
1191
|
+
// PDA Helpers
|
|
1192
|
+
// ===========================================================================
|
|
1193
|
+
getProjectPDA(projectId) {
|
|
1194
|
+
return getProjectPDA(projectId, this.programId);
|
|
1195
|
+
}
|
|
1196
|
+
getEscrowPDA(projectId) {
|
|
1197
|
+
return getEscrowPDA(projectId, this.programId);
|
|
1198
|
+
}
|
|
1199
|
+
getMilestonePDA(projectPda, milestoneIndex) {
|
|
1200
|
+
return getMilestonePDA(projectPda, milestoneIndex, this.programId);
|
|
1201
|
+
}
|
|
1202
|
+
getInvestmentPDA(projectPda, nftMint) {
|
|
1203
|
+
return getInvestmentPDA(projectPda, nftMint, this.programId);
|
|
1204
|
+
}
|
|
1205
|
+
getVotePDA(milestonePda, voterKey, votingRound) {
|
|
1206
|
+
return getVotePDA(milestonePda, voterKey, votingRound, this.programId);
|
|
1207
|
+
}
|
|
1208
|
+
getPivotProposalPDA(projectPda, pivotCount) {
|
|
1209
|
+
return getPivotProposalPDA(projectPda, pivotCount, this.programId);
|
|
1210
|
+
}
|
|
1211
|
+
getTgeEscrowPDA(projectPda) {
|
|
1212
|
+
return getTgeEscrowPDA(projectPda, this.programId);
|
|
1213
|
+
}
|
|
1214
|
+
getTgeEscrowVaultPDA(projectPda) {
|
|
1215
|
+
return getTgeEscrowVaultPDA(projectPda, this.programId);
|
|
1216
|
+
}
|
|
1217
|
+
getAdminConfigPDA() {
|
|
1218
|
+
return getAdminConfigPDA(this.programId);
|
|
1219
|
+
}
|
|
1220
|
+
// ===========================================================================
|
|
1221
|
+
// Account Fetchers
|
|
1222
|
+
// ===========================================================================
|
|
1223
|
+
async fetchProject(projectId) {
|
|
1224
|
+
return fetchProject(this.program, projectId);
|
|
1225
|
+
}
|
|
1226
|
+
async fetchMilestone(projectId, milestoneIndex) {
|
|
1227
|
+
return fetchMilestone(this.program, projectId, milestoneIndex);
|
|
1228
|
+
}
|
|
1229
|
+
async fetchAllMilestones(projectId) {
|
|
1230
|
+
return fetchAllMilestones(this.program, projectId);
|
|
1231
|
+
}
|
|
1232
|
+
async fetchInvestment(projectId, nftMint) {
|
|
1233
|
+
return fetchInvestment(this.program, projectId, nftMint);
|
|
1234
|
+
}
|
|
1235
|
+
async fetchAllInvestments(projectId) {
|
|
1236
|
+
return fetchAllInvestments(this.program, projectId);
|
|
1237
|
+
}
|
|
1238
|
+
async fetchVote(projectId, milestoneIndex, voterKey, votingRound) {
|
|
1239
|
+
return fetchVote(this.program, projectId, milestoneIndex, voterKey, votingRound);
|
|
1240
|
+
}
|
|
1241
|
+
async fetchAllVotes(projectId, milestoneIndex) {
|
|
1242
|
+
return fetchAllVotes(this.program, projectId, milestoneIndex);
|
|
1243
|
+
}
|
|
1244
|
+
async fetchPivotProposal(projectId) {
|
|
1245
|
+
return fetchPivotProposal(this.program, projectId);
|
|
1246
|
+
}
|
|
1247
|
+
async fetchTgeEscrow(projectId) {
|
|
1248
|
+
return fetchTgeEscrow(this.program, projectId);
|
|
1249
|
+
}
|
|
1250
|
+
async fetchAdminConfig() {
|
|
1251
|
+
return fetchAdminConfig(this.program);
|
|
1252
|
+
}
|
|
1253
|
+
// ===========================================================================
|
|
1254
|
+
// Admin Instructions
|
|
1255
|
+
// ===========================================================================
|
|
1256
|
+
async initializeAdmin(admin) {
|
|
1257
|
+
return initializeAdmin(
|
|
1258
|
+
this.program,
|
|
1259
|
+
admin,
|
|
1260
|
+
this.walletPublicKey
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
async transferAdmin(newAdmin, adminKeypair) {
|
|
1264
|
+
return transferAdmin(
|
|
1265
|
+
this.program,
|
|
1266
|
+
adminKeypair,
|
|
1267
|
+
newAdmin
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
async acceptAdmin() {
|
|
1271
|
+
return acceptAdmin(
|
|
1272
|
+
this.program,
|
|
1273
|
+
this.walletPublicKey
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
// ===========================================================================
|
|
1277
|
+
// Project Instructions
|
|
1278
|
+
// ===========================================================================
|
|
1279
|
+
async initializeProject(args) {
|
|
1280
|
+
return initializeProject(
|
|
1281
|
+
this.program,
|
|
1282
|
+
args,
|
|
1283
|
+
this.walletPublicKey
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
async submitForApproval(projectId) {
|
|
1287
|
+
return submitForApproval(
|
|
1288
|
+
this.program,
|
|
1289
|
+
projectId,
|
|
1290
|
+
this.walletPublicKey
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
async approveProject(args, adminKeypair) {
|
|
1294
|
+
return approveProject(
|
|
1295
|
+
this.program,
|
|
1296
|
+
args,
|
|
1297
|
+
adminKeypair
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
// ===========================================================================
|
|
1301
|
+
// Milestone Instructions
|
|
1302
|
+
// ===========================================================================
|
|
1303
|
+
async createMilestone(args) {
|
|
1304
|
+
return createMilestone(
|
|
1305
|
+
this.program,
|
|
1306
|
+
args,
|
|
1307
|
+
this.walletPublicKey
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
async submitMilestone(projectId, milestoneIndex) {
|
|
1311
|
+
return submitMilestone(
|
|
1312
|
+
this.program,
|
|
1313
|
+
projectId,
|
|
1314
|
+
milestoneIndex,
|
|
1315
|
+
this.walletPublicKey
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
async voteOnMilestone(args) {
|
|
1319
|
+
return voteOnMilestone(
|
|
1320
|
+
this.program,
|
|
1321
|
+
args,
|
|
1322
|
+
this.walletPublicKey
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
async finalizeVoting(projectId, milestoneIndex) {
|
|
1326
|
+
return finalizeVoting(
|
|
1327
|
+
this.program,
|
|
1328
|
+
projectId,
|
|
1329
|
+
milestoneIndex
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Claim milestone funds (ZTM v2.0)
|
|
1334
|
+
* - Regular milestones: Full payout to founder
|
|
1335
|
+
* - Final milestone: LP USDC reserved for PCL, triggers MAE
|
|
1336
|
+
*
|
|
1337
|
+
* @param nextMilestoneDeadline - Deadline for next milestone (required for non-final milestones)
|
|
1338
|
+
* Set to BN(0) for final milestone claims (no next milestone exists)
|
|
1339
|
+
*/
|
|
1340
|
+
async claimMilestoneFunds(args) {
|
|
1341
|
+
return claimMilestoneFunds(
|
|
1342
|
+
this.program,
|
|
1343
|
+
args,
|
|
1344
|
+
this.walletPublicKey
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Resubmit a failed milestone for rework (Failed → InProgress)
|
|
1349
|
+
*
|
|
1350
|
+
* Allows founders to iterate on failed milestones. Clears voting state
|
|
1351
|
+
* for a fresh voting cycle. consecutive_failures is NOT reset.
|
|
1352
|
+
*/
|
|
1353
|
+
async resubmitMilestone(args) {
|
|
1354
|
+
return resubmitMilestone(
|
|
1355
|
+
this.program,
|
|
1356
|
+
args,
|
|
1357
|
+
this.walletPublicKey
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Set milestone deadline for founder to commit submission date
|
|
1362
|
+
*
|
|
1363
|
+
* Founders must set deadlines for milestones to provide visibility to investors.
|
|
1364
|
+
* Deadline must be at least 7 days from now and at most 1 year from now.
|
|
1365
|
+
*/
|
|
1366
|
+
async setMilestoneDeadline(args) {
|
|
1367
|
+
return setMilestoneDeadline(
|
|
1368
|
+
this.program,
|
|
1369
|
+
args,
|
|
1370
|
+
this.walletPublicKey
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Extend milestone deadline (max 3 extensions per milestone)
|
|
1375
|
+
*
|
|
1376
|
+
* Founders can extend a deadline up to 3 times before it passes.
|
|
1377
|
+
* Must be called BEFORE the current deadline passes.
|
|
1378
|
+
*/
|
|
1379
|
+
async extendMilestoneDeadline(args) {
|
|
1380
|
+
return extendMilestoneDeadline(
|
|
1381
|
+
this.program,
|
|
1382
|
+
args,
|
|
1383
|
+
this.walletPublicKey
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
// ===========================================================================
|
|
1387
|
+
// Investment Instructions
|
|
1388
|
+
// ===========================================================================
|
|
1389
|
+
async invest(args) {
|
|
1390
|
+
return invest(
|
|
1391
|
+
this.program,
|
|
1392
|
+
args,
|
|
1393
|
+
this.walletPublicKey
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
async cancelInvestment(args) {
|
|
1397
|
+
return cancelInvestment(
|
|
1398
|
+
this.program,
|
|
1399
|
+
args,
|
|
1400
|
+
this.walletPublicKey
|
|
1401
|
+
);
|
|
1402
|
+
}
|
|
1403
|
+
// ===========================================================================
|
|
1404
|
+
// Pivot Instructions
|
|
1405
|
+
// ===========================================================================
|
|
1406
|
+
async proposePivot(args) {
|
|
1407
|
+
return proposePivot(
|
|
1408
|
+
this.program,
|
|
1409
|
+
args,
|
|
1410
|
+
this.walletPublicKey
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
async approvePivot(projectId, adminKeypair) {
|
|
1414
|
+
return approvePivot(
|
|
1415
|
+
this.program,
|
|
1416
|
+
projectId,
|
|
1417
|
+
adminKeypair
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
async withdrawFromPivot(args) {
|
|
1421
|
+
return withdrawFromPivot(
|
|
1422
|
+
this.program,
|
|
1423
|
+
args,
|
|
1424
|
+
this.walletPublicKey
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
async finalizePivot(args) {
|
|
1428
|
+
return finalizePivot(
|
|
1429
|
+
this.program,
|
|
1430
|
+
args,
|
|
1431
|
+
this.walletPublicKey
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
// ===========================================================================
|
|
1435
|
+
// TGE Instructions
|
|
1436
|
+
// ===========================================================================
|
|
1437
|
+
async setTgeDate(args) {
|
|
1438
|
+
return setTgeDate(
|
|
1439
|
+
this.program,
|
|
1440
|
+
args,
|
|
1441
|
+
this.walletPublicKey
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
async depositTokens(args) {
|
|
1445
|
+
return depositTokens(
|
|
1446
|
+
this.program,
|
|
1447
|
+
args,
|
|
1448
|
+
this.walletPublicKey
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
async claimTokens(args) {
|
|
1452
|
+
return claimTokens(
|
|
1453
|
+
this.program,
|
|
1454
|
+
args,
|
|
1455
|
+
this.walletPublicKey
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
async reportScam(args) {
|
|
1459
|
+
return reportScam(
|
|
1460
|
+
this.program,
|
|
1461
|
+
args,
|
|
1462
|
+
this.walletPublicKey
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
async releaseHoldback(args) {
|
|
1466
|
+
return releaseHoldback(
|
|
1467
|
+
this.program,
|
|
1468
|
+
args
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
// ===========================================================================
|
|
1472
|
+
// ZTM v2.0 Token Distribution Instructions
|
|
1473
|
+
// ===========================================================================
|
|
1474
|
+
/**
|
|
1475
|
+
* Claim investor tokens from a passed milestone (whitepaper: manual claim model)
|
|
1476
|
+
*
|
|
1477
|
+
* ZTM v2.0: Per whitepaper, investors manually claim their tokens after a milestone passes.
|
|
1478
|
+
* This replaces the batch distribution model with investor-initiated per-NFT claims.
|
|
1479
|
+
*/
|
|
1480
|
+
async claimInvestorTokens(args) {
|
|
1481
|
+
return claimInvestorTokens(
|
|
1482
|
+
this.program,
|
|
1483
|
+
args,
|
|
1484
|
+
this.walletPublicKey
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Distribute tokens to NFT holders for a milestone
|
|
1489
|
+
*
|
|
1490
|
+
* ZTM v2.0: Called by cranker after finalize_voting sets distribution_pending = true.
|
|
1491
|
+
* Processes batch of investments, transferring unlocked tokens to NFT holders.
|
|
1492
|
+
* Max batch size: 10 investments per call.
|
|
1493
|
+
*
|
|
1494
|
+
* @deprecated Use claimInvestorTokens instead (whitepaper manual claim model)
|
|
1495
|
+
*/
|
|
1496
|
+
async distributeTokens(args) {
|
|
1497
|
+
return distributeTokens(
|
|
1498
|
+
this.program,
|
|
1499
|
+
args,
|
|
1500
|
+
this.walletPublicKey
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Complete token distribution for a milestone
|
|
1505
|
+
*
|
|
1506
|
+
* ZTM v2.0: Marks distribution as complete after all batches have been processed.
|
|
1507
|
+
* Permissionless - anyone can call this to finalize a distribution.
|
|
1508
|
+
*/
|
|
1509
|
+
async completeDistribution(args) {
|
|
1510
|
+
return completeDistribution(
|
|
1511
|
+
this.program,
|
|
1512
|
+
args,
|
|
1513
|
+
this.walletPublicKey
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
// ===========================================================================
|
|
1517
|
+
// ZTM v2.0: Founder Vesting Instructions
|
|
1518
|
+
// ===========================================================================
|
|
1519
|
+
/**
|
|
1520
|
+
* Initialize founder vesting after MAE (Market Access Event)
|
|
1521
|
+
*
|
|
1522
|
+
* ZTM v2.0: Creates FounderVesting PDA with vesting schedule from Tokenomics.
|
|
1523
|
+
* Must be called after project reaches Completed state (all milestones done).
|
|
1524
|
+
* Permissionless - anyone can pay to initialize.
|
|
1525
|
+
*/
|
|
1526
|
+
async initializeFounderVesting(args) {
|
|
1527
|
+
return initializeFounderVesting(
|
|
1528
|
+
this.program,
|
|
1529
|
+
args,
|
|
1530
|
+
this.walletPublicKey
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Claim vested tokens from founder vault
|
|
1535
|
+
*
|
|
1536
|
+
* ZTM v2.0: Founder claims tokens based on linear vesting schedule.
|
|
1537
|
+
* Requires cliff period to pass before any tokens can be claimed.
|
|
1538
|
+
*/
|
|
1539
|
+
async claimVestedTokens(args) {
|
|
1540
|
+
return claimVestedTokens(
|
|
1541
|
+
this.program,
|
|
1542
|
+
args,
|
|
1543
|
+
this.walletPublicKey
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
// ===========================================================================
|
|
1547
|
+
// ZTM v2.0: Circuit Breaker Instructions
|
|
1548
|
+
// ===========================================================================
|
|
1549
|
+
/**
|
|
1550
|
+
* Force complete a stuck distribution (admin only)
|
|
1551
|
+
*
|
|
1552
|
+
* ZTM v2.0: Circuit breaker for when token distribution is stuck for >7 days.
|
|
1553
|
+
* Marks distribution as complete so project can continue.
|
|
1554
|
+
* Affected investors can use claimMissedUnlock to get their tokens.
|
|
1555
|
+
*/
|
|
1556
|
+
async forceCompleteDistribution(args, adminKeypair) {
|
|
1557
|
+
return forceCompleteDistribution(
|
|
1558
|
+
this.program,
|
|
1559
|
+
args,
|
|
1560
|
+
adminKeypair
|
|
1561
|
+
);
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Claim missed token unlock after force-complete distribution
|
|
1565
|
+
*
|
|
1566
|
+
* ZTM v2.0: Allows investors to claim tokens they missed during a stuck
|
|
1567
|
+
* distribution that was force-completed by admin.
|
|
1568
|
+
*/
|
|
1569
|
+
async claimMissedUnlock(args) {
|
|
1570
|
+
return claimMissedUnlock(
|
|
1571
|
+
this.program,
|
|
1572
|
+
args,
|
|
1573
|
+
this.walletPublicKey
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
// ===========================================================================
|
|
1577
|
+
// Abandonment Instructions
|
|
1578
|
+
// ===========================================================================
|
|
1579
|
+
async checkAbandonment(projectId, milestoneIndex = 0) {
|
|
1580
|
+
return checkAbandonment(
|
|
1581
|
+
this.program,
|
|
1582
|
+
projectId,
|
|
1583
|
+
milestoneIndex
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
async claimRefund(args) {
|
|
1587
|
+
return claimRefund(
|
|
1588
|
+
this.program,
|
|
1589
|
+
args,
|
|
1590
|
+
this.walletPublicKey
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
|
|
1595
|
+
// src/types/index.ts
|
|
1596
|
+
var ProjectState = /* @__PURE__ */ ((ProjectState2) => {
|
|
1597
|
+
ProjectState2["Draft"] = "draft";
|
|
1598
|
+
ProjectState2["PendingApproval"] = "pendingApproval";
|
|
1599
|
+
ProjectState2["Open"] = "open";
|
|
1600
|
+
ProjectState2["Funded"] = "funded";
|
|
1601
|
+
ProjectState2["InProgress"] = "inProgress";
|
|
1602
|
+
ProjectState2["Completed"] = "completed";
|
|
1603
|
+
ProjectState2["Abandoned"] = "abandoned";
|
|
1604
|
+
ProjectState2["Failed"] = "failed";
|
|
1605
|
+
ProjectState2["TGEFailed"] = "tgeFailed";
|
|
1606
|
+
ProjectState2["Cancelled"] = "cancelled";
|
|
1607
|
+
return ProjectState2;
|
|
1608
|
+
})(ProjectState || {});
|
|
1609
|
+
var MilestoneState = /* @__PURE__ */ ((MilestoneState2) => {
|
|
1610
|
+
MilestoneState2["Proposed"] = "proposed";
|
|
1611
|
+
MilestoneState2["Approved"] = "approved";
|
|
1612
|
+
MilestoneState2["InProgress"] = "inProgress";
|
|
1613
|
+
MilestoneState2["UnderReview"] = "underReview";
|
|
1614
|
+
MilestoneState2["Passed"] = "passed";
|
|
1615
|
+
MilestoneState2["Failed"] = "failed";
|
|
1616
|
+
MilestoneState2["Unlocked"] = "unlocked";
|
|
1617
|
+
return MilestoneState2;
|
|
1618
|
+
})(MilestoneState || {});
|
|
1619
|
+
var VoteChoice = /* @__PURE__ */ ((VoteChoice2) => {
|
|
1620
|
+
VoteChoice2["Good"] = "good";
|
|
1621
|
+
VoteChoice2["Bad"] = "bad";
|
|
1622
|
+
return VoteChoice2;
|
|
1623
|
+
})(VoteChoice || {});
|
|
1624
|
+
var PivotState = /* @__PURE__ */ ((PivotState2) => {
|
|
1625
|
+
PivotState2["PendingModeratorApproval"] = "pendingModeratorApproval";
|
|
1626
|
+
PivotState2["ApprovedAwaitingInvestorWindow"] = "approvedAwaitingInvestorWindow";
|
|
1627
|
+
PivotState2["Finalized"] = "finalized";
|
|
1628
|
+
return PivotState2;
|
|
1629
|
+
})(PivotState || {});
|
|
1630
|
+
var ERROR_CODES = {
|
|
1631
|
+
// State Transition Errors (6000-6099)
|
|
1632
|
+
InvalidStateTransition: 6e3,
|
|
1633
|
+
ProjectNotInOpenState: 6001,
|
|
1634
|
+
ProjectNotInProgress: 6002,
|
|
1635
|
+
MilestoneNotUnderReview: 6003,
|
|
1636
|
+
VotingPeriodEnded: 6004,
|
|
1637
|
+
VotingPeriodNotEnded: 6005,
|
|
1638
|
+
MilestoneNotPassed: 6006,
|
|
1639
|
+
MilestoneAlreadyUnlocked: 6007,
|
|
1640
|
+
ProjectAlreadyFunded: 6008,
|
|
1641
|
+
ProjectNotFunded: 6009,
|
|
1642
|
+
// Authorization Errors (6100-6199)
|
|
1643
|
+
UnauthorizedFounder: 6100,
|
|
1644
|
+
UnauthorizedAdmin: 6101,
|
|
1645
|
+
NotInvestor: 6102,
|
|
1646
|
+
AlreadyVoted: 6103,
|
|
1647
|
+
// Investment Errors (6200-6299)
|
|
1648
|
+
InvestmentBelowMinimum: 6200,
|
|
1649
|
+
FundingGoalExceeded: 6201,
|
|
1650
|
+
InvalidTier: 6202,
|
|
1651
|
+
CoolingOffPeriodActive: 6203,
|
|
1652
|
+
CoolingOffPeriodExpired: 6204,
|
|
1653
|
+
// Milestone Errors (6300-6399)
|
|
1654
|
+
InvalidMilestoneIndex: 6300,
|
|
1655
|
+
MilestonePercentageInvalid: 6301,
|
|
1656
|
+
TotalPercentageExceeded: 6302,
|
|
1657
|
+
MilestoneNotInProgress: 6303,
|
|
1658
|
+
MilestoneNotApproved: 6304,
|
|
1659
|
+
// TGE Errors (6400-6499)
|
|
1660
|
+
TgeDateNotSet: 6400,
|
|
1661
|
+
TgeDateAlreadySet: 6401,
|
|
1662
|
+
TgeDateTooSoon: 6402,
|
|
1663
|
+
TgeDateTooLate: 6403,
|
|
1664
|
+
TgeNotReached: 6404,
|
|
1665
|
+
TokensAlreadyClaimed: 6405,
|
|
1666
|
+
InsufficientTokensDeposited: 6406,
|
|
1667
|
+
// Pivot Errors (6500-6599)
|
|
1668
|
+
PivotAlreadyProposed: 6500,
|
|
1669
|
+
NoPivotProposed: 6501,
|
|
1670
|
+
PivotNotApproved: 6502,
|
|
1671
|
+
PivotWindowNotEnded: 6503,
|
|
1672
|
+
PivotWindowEnded: 6504,
|
|
1673
|
+
AlreadyWithdrawnFromPivot: 6505,
|
|
1674
|
+
// Refund Errors (6800-6899)
|
|
1675
|
+
RefundAlreadyClaimed: 6800,
|
|
1676
|
+
RefundNotAvailable: 6801,
|
|
1677
|
+
ProjectNotAbandoned: 6802,
|
|
1678
|
+
// Scam Errors (6900-6999)
|
|
1679
|
+
ScamReportPeriodEnded: 6900,
|
|
1680
|
+
ScamAlreadyReported: 6901,
|
|
1681
|
+
ScamNotConfirmed: 6902,
|
|
1682
|
+
HoldbackAlreadyReleased: 6903,
|
|
1683
|
+
HoldbackPeriodNotEnded: 6904
|
|
1684
|
+
};
|
|
1685
|
+
var ERROR_MESSAGES = {
|
|
1686
|
+
// State Transition Errors
|
|
1687
|
+
[ERROR_CODES.InvalidStateTransition]: "Invalid project state transition",
|
|
1688
|
+
[ERROR_CODES.ProjectNotInOpenState]: "Project must be in Open state to accept investments",
|
|
1689
|
+
[ERROR_CODES.ProjectNotInProgress]: "Project must be InProgress to perform this action",
|
|
1690
|
+
[ERROR_CODES.MilestoneNotUnderReview]: "Milestone must be under review to vote",
|
|
1691
|
+
[ERROR_CODES.VotingPeriodEnded]: "Voting period has ended",
|
|
1692
|
+
[ERROR_CODES.VotingPeriodNotEnded]: "Voting period has not ended yet",
|
|
1693
|
+
[ERROR_CODES.MilestoneNotPassed]: "Milestone did not pass voting",
|
|
1694
|
+
[ERROR_CODES.MilestoneAlreadyUnlocked]: "Milestone funds already unlocked",
|
|
1695
|
+
[ERROR_CODES.ProjectAlreadyFunded]: "Project has already reached funding goal",
|
|
1696
|
+
[ERROR_CODES.ProjectNotFunded]: "Project has not reached funding goal",
|
|
1697
|
+
// Authorization Errors
|
|
1698
|
+
[ERROR_CODES.UnauthorizedFounder]: "Only the project founder can perform this action",
|
|
1699
|
+
[ERROR_CODES.UnauthorizedAdmin]: "Only the admin can perform this action",
|
|
1700
|
+
[ERROR_CODES.NotInvestor]: "You must be an investor to perform this action",
|
|
1701
|
+
[ERROR_CODES.AlreadyVoted]: "You have already voted on this",
|
|
1702
|
+
// Investment Errors
|
|
1703
|
+
[ERROR_CODES.InvestmentBelowMinimum]: "Investment amount below minimum tier requirement",
|
|
1704
|
+
[ERROR_CODES.FundingGoalExceeded]: "Investment would exceed funding goal",
|
|
1705
|
+
[ERROR_CODES.InvalidTier]: "Invalid investment tier",
|
|
1706
|
+
[ERROR_CODES.CoolingOffPeriodActive]: "Investment is within 24-hour cooling-off period",
|
|
1707
|
+
[ERROR_CODES.CoolingOffPeriodExpired]: "Cooling-off period has expired, cannot cancel",
|
|
1708
|
+
// Milestone Errors
|
|
1709
|
+
[ERROR_CODES.InvalidMilestoneIndex]: "Invalid milestone index",
|
|
1710
|
+
[ERROR_CODES.MilestonePercentageInvalid]: "Milestone percentage must be between 1-100",
|
|
1711
|
+
[ERROR_CODES.TotalPercentageExceeded]: "Total milestone percentages exceed 100%",
|
|
1712
|
+
[ERROR_CODES.MilestoneNotInProgress]: "Milestone must be in progress",
|
|
1713
|
+
[ERROR_CODES.MilestoneNotApproved]: "Milestone must be approved first",
|
|
1714
|
+
// TGE Errors
|
|
1715
|
+
[ERROR_CODES.TgeDateNotSet]: "TGE date has not been set",
|
|
1716
|
+
[ERROR_CODES.TgeDateAlreadySet]: "TGE date has already been set",
|
|
1717
|
+
[ERROR_CODES.TgeDateTooSoon]: "TGE date must be at least 15 days in the future",
|
|
1718
|
+
[ERROR_CODES.TgeDateTooLate]: "TGE date must be within 90 days",
|
|
1719
|
+
[ERROR_CODES.TgeNotReached]: "TGE date has not been reached",
|
|
1720
|
+
[ERROR_CODES.TokensAlreadyClaimed]: "Tokens have already been claimed",
|
|
1721
|
+
[ERROR_CODES.InsufficientTokensDeposited]: "Insufficient tokens deposited by founder",
|
|
1722
|
+
// Pivot Errors
|
|
1723
|
+
[ERROR_CODES.PivotAlreadyProposed]: "A pivot is already pending",
|
|
1724
|
+
[ERROR_CODES.NoPivotProposed]: "No pivot has been proposed",
|
|
1725
|
+
[ERROR_CODES.PivotNotApproved]: "Pivot has not been approved by admin",
|
|
1726
|
+
[ERROR_CODES.PivotWindowNotEnded]: "7-day withdrawal window has not ended",
|
|
1727
|
+
[ERROR_CODES.PivotWindowEnded]: "7-day withdrawal window has ended",
|
|
1728
|
+
[ERROR_CODES.AlreadyWithdrawnFromPivot]: "Already withdrawn from this pivot",
|
|
1729
|
+
// Refund Errors
|
|
1730
|
+
[ERROR_CODES.RefundAlreadyClaimed]: "Refund has already been claimed",
|
|
1731
|
+
[ERROR_CODES.RefundNotAvailable]: "Refund is not available",
|
|
1732
|
+
[ERROR_CODES.ProjectNotAbandoned]: "Project has not been abandoned",
|
|
1733
|
+
// Scam Errors
|
|
1734
|
+
[ERROR_CODES.ScamReportPeriodEnded]: "30-day scam report period has ended",
|
|
1735
|
+
[ERROR_CODES.ScamAlreadyReported]: "Already reported this project for scam",
|
|
1736
|
+
[ERROR_CODES.ScamNotConfirmed]: "Scam has not been confirmed",
|
|
1737
|
+
[ERROR_CODES.HoldbackAlreadyReleased]: "Holdback has already been released",
|
|
1738
|
+
[ERROR_CODES.HoldbackPeriodNotEnded]: "30-day holdback period has not ended"
|
|
1739
|
+
};
|
|
1740
|
+
var RaiseError = class _RaiseError extends Error {
|
|
1741
|
+
constructor(code, message, logs) {
|
|
1742
|
+
super(message);
|
|
1743
|
+
this.code = code;
|
|
1744
|
+
this.logs = logs;
|
|
1745
|
+
this.name = "RaiseError";
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Create from an Anchor error
|
|
1749
|
+
*/
|
|
1750
|
+
static fromAnchorError(error) {
|
|
1751
|
+
const code = error.error.errorCode.number;
|
|
1752
|
+
const message = ERROR_MESSAGES[code] || error.error.errorMessage;
|
|
1753
|
+
return new _RaiseError(code, message, error.logs);
|
|
1754
|
+
}
|
|
1755
|
+
/**
|
|
1756
|
+
* Check if this is a specific error type
|
|
1757
|
+
*/
|
|
1758
|
+
is(errorCode) {
|
|
1759
|
+
return this.code === errorCode;
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
function parseError(error) {
|
|
1763
|
+
if (error instanceof AnchorError) {
|
|
1764
|
+
return RaiseError.fromAnchorError(error);
|
|
1765
|
+
}
|
|
1766
|
+
if (error instanceof Error) {
|
|
1767
|
+
return error;
|
|
1768
|
+
}
|
|
1769
|
+
return new Error(String(error));
|
|
1770
|
+
}
|
|
1771
|
+
function isRaiseError(error, code) {
|
|
1772
|
+
if (!(error instanceof RaiseError)) {
|
|
1773
|
+
return false;
|
|
1774
|
+
}
|
|
1775
|
+
if (code !== void 0) {
|
|
1776
|
+
return error.code === code;
|
|
1777
|
+
}
|
|
1778
|
+
return true;
|
|
1779
|
+
}
|
|
1780
|
+
function getErrorMessage(error) {
|
|
1781
|
+
if (error instanceof RaiseError) {
|
|
1782
|
+
return error.message;
|
|
1783
|
+
}
|
|
1784
|
+
if (error instanceof AnchorError) {
|
|
1785
|
+
const code = error.error.errorCode.number;
|
|
1786
|
+
return ERROR_MESSAGES[code] || error.error.errorMessage;
|
|
1787
|
+
}
|
|
1788
|
+
if (error instanceof Error) {
|
|
1789
|
+
return error.message;
|
|
1790
|
+
}
|
|
1791
|
+
return "An unknown error occurred";
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
// src/events/index.ts
|
|
1795
|
+
var EVENT_NAMES = {
|
|
1796
|
+
ProjectCreated: "ProjectCreated",
|
|
1797
|
+
ProjectApproved: "ProjectApproved",
|
|
1798
|
+
ProjectFunded: "ProjectFunded",
|
|
1799
|
+
InvestmentMade: "InvestmentMade",
|
|
1800
|
+
InvestmentCancelled: "InvestmentCancelled",
|
|
1801
|
+
MilestoneCreated: "MilestoneCreated",
|
|
1802
|
+
MilestoneSubmitted: "MilestoneSubmitted",
|
|
1803
|
+
VoteCast: "VoteCast",
|
|
1804
|
+
MilestoneVoteFinalized: "MilestoneVoteFinalized",
|
|
1805
|
+
FundsUnlocked: "FundsUnlocked",
|
|
1806
|
+
TgeDateSet: "TgeDateSet",
|
|
1807
|
+
TokensDeposited: "TokensDeposited",
|
|
1808
|
+
TokensClaimed: "TokensClaimed",
|
|
1809
|
+
RefundClaimed: "RefundClaimed",
|
|
1810
|
+
PivotProposed: "PivotProposed",
|
|
1811
|
+
PivotApproved: "PivotApproved",
|
|
1812
|
+
PivotFinalized: "PivotFinalized",
|
|
1813
|
+
MilestoneReworked: "MilestoneReworked"
|
|
1814
|
+
};
|
|
1815
|
+
function filterEventsByName(events, name) {
|
|
1816
|
+
return events.filter((e) => e.name === name);
|
|
1817
|
+
}
|
|
1818
|
+
function findEvent(events, name) {
|
|
1819
|
+
return events.find((e) => e.name === name);
|
|
1820
|
+
}
|
|
1821
|
+
async function confirmTransaction(connection, signature, commitment = "confirmed") {
|
|
1822
|
+
const latestBlockhash = await connection.getLatestBlockhash();
|
|
1823
|
+
return connection.confirmTransaction(
|
|
1824
|
+
{
|
|
1825
|
+
signature,
|
|
1826
|
+
blockhash: latestBlockhash.blockhash,
|
|
1827
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
|
|
1828
|
+
},
|
|
1829
|
+
commitment
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
async function getTransactionWithRetry(connection, signature, maxRetries = 3) {
|
|
1833
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
1834
|
+
const tx = await connection.getTransaction(signature, {
|
|
1835
|
+
maxSupportedTransactionVersion: 0
|
|
1836
|
+
});
|
|
1837
|
+
if (tx) {
|
|
1838
|
+
return tx;
|
|
1839
|
+
}
|
|
1840
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 * (i + 1)));
|
|
1841
|
+
}
|
|
1842
|
+
throw new Error(`Transaction ${signature} not found after ${maxRetries} retries`);
|
|
1843
|
+
}
|
|
1844
|
+
function bnToNumber(bn) {
|
|
1845
|
+
const num = bn.toNumber();
|
|
1846
|
+
if (!Number.isSafeInteger(num)) {
|
|
1847
|
+
throw new Error(`BN value ${bn.toString()} is too large to convert to number`);
|
|
1848
|
+
}
|
|
1849
|
+
return num;
|
|
1850
|
+
}
|
|
1851
|
+
function bnToBigInt(bn) {
|
|
1852
|
+
return BigInt(bn.toString());
|
|
1853
|
+
}
|
|
1854
|
+
function bigIntToBN(value) {
|
|
1855
|
+
return new BN(value.toString());
|
|
1856
|
+
}
|
|
1857
|
+
function getCurrentTimestamp() {
|
|
1858
|
+
return Math.floor(Date.now() / 1e3);
|
|
1859
|
+
}
|
|
1860
|
+
function timestampToDate(timestamp) {
|
|
1861
|
+
const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
|
|
1862
|
+
return new Date(ts * 1e3);
|
|
1863
|
+
}
|
|
1864
|
+
function hasTimestampPassed(timestamp) {
|
|
1865
|
+
const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
|
|
1866
|
+
return getCurrentTimestamp() > ts;
|
|
1867
|
+
}
|
|
1868
|
+
function timeRemaining(timestamp) {
|
|
1869
|
+
const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
|
|
1870
|
+
const remaining = ts - getCurrentTimestamp();
|
|
1871
|
+
return remaining > 0 ? remaining : 0;
|
|
1872
|
+
}
|
|
1873
|
+
function formatDuration(seconds) {
|
|
1874
|
+
if (seconds <= 0) return "0s";
|
|
1875
|
+
const days = Math.floor(seconds / 86400);
|
|
1876
|
+
const hours = Math.floor(seconds % 86400 / 3600);
|
|
1877
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
1878
|
+
const secs = seconds % 60;
|
|
1879
|
+
const parts = [];
|
|
1880
|
+
if (days > 0) parts.push(`${days}d`);
|
|
1881
|
+
if (hours > 0) parts.push(`${hours}h`);
|
|
1882
|
+
if (minutes > 0) parts.push(`${minutes}m`);
|
|
1883
|
+
if (secs > 0 && days === 0) parts.push(`${secs}s`);
|
|
1884
|
+
return parts.join(" ") || "0s";
|
|
1885
|
+
}
|
|
1886
|
+
function bpsToPercent(bps) {
|
|
1887
|
+
return bps / 1e4;
|
|
1888
|
+
}
|
|
1889
|
+
function percentToBps(percent) {
|
|
1890
|
+
return Math.floor(percent * 1e4);
|
|
1891
|
+
}
|
|
1892
|
+
function percentageOf(amount, percentage) {
|
|
1893
|
+
return amount * BigInt(Math.floor(percentage * 100)) / 10000n;
|
|
1894
|
+
}
|
|
1895
|
+
function validateMilestonePercentages(percentages) {
|
|
1896
|
+
const sum = percentages.reduce((acc, p) => acc + p, 0);
|
|
1897
|
+
return sum === 100;
|
|
1898
|
+
}
|
|
1899
|
+
function validateMetadataUri(uri, maxLength = 200) {
|
|
1900
|
+
if (uri.length > maxLength) return false;
|
|
1901
|
+
try {
|
|
1902
|
+
new URL(uri);
|
|
1903
|
+
return true;
|
|
1904
|
+
} catch {
|
|
1905
|
+
return false;
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
function isValidPublicKey(pubkey) {
|
|
1909
|
+
try {
|
|
1910
|
+
if (typeof pubkey === "string") {
|
|
1911
|
+
new PublicKey(pubkey);
|
|
1912
|
+
}
|
|
1913
|
+
return true;
|
|
1914
|
+
} catch {
|
|
1915
|
+
return false;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
function shortenPublicKey(pubkey, chars = 4) {
|
|
1919
|
+
const str = pubkey.toString();
|
|
1920
|
+
if (str.length <= chars * 2 + 3) return str;
|
|
1921
|
+
return `${str.slice(0, chars)}...${str.slice(-chars)}`;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
export { ERROR_CODES, ERROR_MESSAGES, EVENT_NAMES, GOVERNANCE, InvestmentTier, MAX_DEADLINE_DURATION_SECONDS, MIN_DEADLINE_DURATION_SECONDS_DEV, MIN_DEADLINE_DURATION_SECONDS_PROD, MilestoneState, NFT, PivotState, ProjectState, RaiseClient, RaiseError, SEEDS, TIER_CONSTRAINTS, TIER_MINIMUMS, TIER_TOKEN_MULTIPLIERS, TIER_VOTE_MULTIPLIERS, TIMING, USDC, VALIDATION, VoteChoice, acceptAdmin, accountExists, approvePivot, approveProject, bigIntToBN, bnToBigInt, bnToNumber, bpsToPercent, calculateDeadline, cancelInvestment, checkAbandonment, claimExitWindowRefund, claimInvestorTokens, claimMilestoneFunds, claimMissedUnlock, claimRefund, claimTokens, claimVestedTokens, completeDistribution, confirmTransaction, createMilestone, depositTokens, distributeTokens, extendMilestoneDeadline, fetchAdminConfig, fetchAllInvestments, fetchAllMilestones, fetchAllVotes, fetchInvestment, fetchMilestone, fetchPivotProposal, fetchProject, fetchProjectByPda, fetchTgeEscrow, fetchVote, filterEventsByName, finalizePivot, finalizeVoting, findEvent, findTierIndex, forceCompleteDistribution, formatDuration, getAdminConfigPDA, getCurrentTimestamp, getErrorMessage, getEscrowPDA, getFounderVaultPDA, getFounderVestingPDA, getInvestmentPDA, getInvestorVaultPDA, getLpTokenVaultPDA, getLpUsdcVaultPDA, getMilestonePDA, getNftMintPDA, getPivotProposalPDA, getProgramAuthorityPDA, getProjectPDA, getProjectPDAs, getScamReportPDA, getTgeEscrowPDA, getTierFromAmount, getTokenMintPDA, getTokenMultiplier, getTokenVaultPDA, getTokenomicsPDA, getTransactionWithRetry, getTreasuryVaultPDA, getVaultAuthorityPDA, getVoteMultiplier, getVotePDA, hasTimestampPassed, initializeAdmin, initializeFounderVesting, initializeProject, invest, isRaiseError, isValidPublicKey, minDeadline, parseError, percentToBps, percentageOf, proposePivot, releaseHoldback, reportScam, resubmitMilestone, setMilestoneDeadline, setTgeDate, shortenPublicKey, submitForApproval, submitMilestone, symbolToBytes, timeRemaining, timestampToDate, transferAdmin, validateDeadline, validateMetadataUri, validateMilestonePercentages, voteOnMilestone, withdrawFromPivot };
|
|
1925
|
+
//# sourceMappingURL=index.js.map
|
|
1926
|
+
//# sourceMappingURL=index.js.map
|