@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/README.md
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# @raise/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the Raise Solana program - a decentralized venture funding platform with milestone-based fund releases.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Full Program Coverage** - All 34 instructions wrapped with TypeScript types
|
|
8
|
+
- **PDA Helpers** - Derive all program addresses deterministically
|
|
9
|
+
- **Account Fetchers** - Fetch and decode all account types
|
|
10
|
+
- **Error Handling** - Mapped error codes with helpful messages
|
|
11
|
+
- **Constants** - Investment tiers, timing values, governance parameters
|
|
12
|
+
- **Tree-shakable** - Modular exports for optimal bundle size
|
|
13
|
+
- **Dual Format** - ESM and CJS builds included
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @raise/sdk
|
|
19
|
+
# or
|
|
20
|
+
yarn add @raise/sdk
|
|
21
|
+
# or
|
|
22
|
+
pnpm add @raise/sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Peer Dependencies
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @coral-xyz/anchor @solana/web3.js
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### Initialize Client
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Program, AnchorProvider } from '@coral-xyz/anchor';
|
|
37
|
+
import { Connection } from '@solana/web3.js';
|
|
38
|
+
import { RaiseClient, BN } from '@raise/sdk';
|
|
39
|
+
import idl from './idl/raise.json';
|
|
40
|
+
|
|
41
|
+
// Setup connection and provider
|
|
42
|
+
const connection = new Connection('https://api.devnet.solana.com');
|
|
43
|
+
const provider = new AnchorProvider(connection, wallet, {});
|
|
44
|
+
|
|
45
|
+
// Create program instance
|
|
46
|
+
const program = new Program(idl, provider);
|
|
47
|
+
|
|
48
|
+
// Create SDK client
|
|
49
|
+
const client = RaiseClient.fromProgram(program);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Create a Project
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const projectId = new BN(1);
|
|
56
|
+
|
|
57
|
+
// Initialize project
|
|
58
|
+
const tx = await client.initializeProject({
|
|
59
|
+
projectId,
|
|
60
|
+
fundingGoal: new BN(100_000_000_000), // 100,000 USDC
|
|
61
|
+
metadataUri: 'https://example.com/project.json',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log('Project created:', tx);
|
|
65
|
+
|
|
66
|
+
// Add milestones
|
|
67
|
+
await client.createMilestone({
|
|
68
|
+
projectId,
|
|
69
|
+
milestoneIndex: 0,
|
|
70
|
+
percentage: 30,
|
|
71
|
+
description: 'MVP Development',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await client.createMilestone({
|
|
75
|
+
projectId,
|
|
76
|
+
milestoneIndex: 1,
|
|
77
|
+
percentage: 40,
|
|
78
|
+
description: 'Beta Launch',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
await client.createMilestone({
|
|
82
|
+
projectId,
|
|
83
|
+
milestoneIndex: 2,
|
|
84
|
+
percentage: 30,
|
|
85
|
+
description: 'Production Release',
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Submit for approval
|
|
89
|
+
await client.submitForApproval(projectId);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Invest in a Project
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { USDC, getTierFromAmount, InvestmentTier } from '@raise/sdk';
|
|
96
|
+
|
|
97
|
+
const amount = USDC.toAmount(1000); // 1,000 USDC
|
|
98
|
+
const tier = getTierFromAmount(amount);
|
|
99
|
+
|
|
100
|
+
console.log(`Investing ${USDC.fromAmount(amount)} USDC (${tier} tier)`);
|
|
101
|
+
|
|
102
|
+
const tx = await client.invest({
|
|
103
|
+
projectId,
|
|
104
|
+
amount: new BN(amount.toString()),
|
|
105
|
+
investorTokenAccount: myUsdcAccount,
|
|
106
|
+
escrowTokenAccount: projectEscrow,
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Vote on Milestones
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Vote "Good" on milestone
|
|
114
|
+
await client.voteOnMilestone({
|
|
115
|
+
projectId,
|
|
116
|
+
milestoneIndex: 0,
|
|
117
|
+
nftMint: myInvestmentNft,
|
|
118
|
+
choice: { good: {} },
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Finalize voting after period ends
|
|
122
|
+
await client.finalizeVoting(projectId, 0);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Fetch Account Data
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Fetch project
|
|
129
|
+
const project = await client.fetchProject(projectId);
|
|
130
|
+
console.log('Project state:', project?.state);
|
|
131
|
+
console.log('Amount raised:', project?.amountRaised.toString());
|
|
132
|
+
|
|
133
|
+
// Fetch all investments
|
|
134
|
+
const investments = await client.fetchAllInvestments(projectId);
|
|
135
|
+
console.log(`Total investors: ${investments.length}`);
|
|
136
|
+
|
|
137
|
+
// Fetch top investors (for veto eligibility)
|
|
138
|
+
const topInvestors = await client.fetchTopInvestors(projectId, 3);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Modular Imports
|
|
142
|
+
|
|
143
|
+
Import only what you need for smaller bundles:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// PDAs only
|
|
147
|
+
import { getProjectPDA, getInvestmentPDA } from '@raise/sdk/pdas';
|
|
148
|
+
|
|
149
|
+
// Constants only
|
|
150
|
+
import { TIMING, TIER_MINIMUMS, InvestmentTier } from '@raise/sdk/constants';
|
|
151
|
+
|
|
152
|
+
// Account fetchers only
|
|
153
|
+
import { fetchProject, fetchAllInvestments } from '@raise/sdk/accounts';
|
|
154
|
+
|
|
155
|
+
// Instructions only
|
|
156
|
+
import { invest, voteOnMilestone } from '@raise/sdk/instructions';
|
|
157
|
+
|
|
158
|
+
// Error handling only
|
|
159
|
+
import { parseError, ERROR_CODES } from '@raise/sdk/errors';
|
|
160
|
+
|
|
161
|
+
// Types only
|
|
162
|
+
import type { ProjectAccount, MilestoneAccount } from '@raise/sdk/types';
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Constants Reference
|
|
166
|
+
|
|
167
|
+
### Investment Tiers
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import {
|
|
171
|
+
InvestmentTier,
|
|
172
|
+
TIER_MINIMUMS,
|
|
173
|
+
TIER_VOTE_MULTIPLIERS,
|
|
174
|
+
USDC
|
|
175
|
+
} from '@raise/sdk';
|
|
176
|
+
|
|
177
|
+
// Tier minimums (in lamports)
|
|
178
|
+
console.log(TIER_MINIMUMS[InvestmentTier.Bronze]); // 100_000_000n (100 USDC)
|
|
179
|
+
console.log(TIER_MINIMUMS[InvestmentTier.Silver]); // 500_000_000n (500 USDC)
|
|
180
|
+
console.log(TIER_MINIMUMS[InvestmentTier.Gold]); // 1_000_000_000n (1,000 USDC)
|
|
181
|
+
console.log(TIER_MINIMUMS[InvestmentTier.Platinum]); // 5_000_000_000n (5,000 USDC)
|
|
182
|
+
console.log(TIER_MINIMUMS[InvestmentTier.Diamond]); // 10_000_000_000n (10,000 USDC)
|
|
183
|
+
|
|
184
|
+
// Vote multipliers
|
|
185
|
+
console.log(TIER_VOTE_MULTIPLIERS[InvestmentTier.Bronze]); // 100 (1.0x)
|
|
186
|
+
console.log(TIER_VOTE_MULTIPLIERS[InvestmentTier.Diamond]); // 300 (3.0x)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Timing Constants
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { TIMING } from '@raise/sdk';
|
|
193
|
+
|
|
194
|
+
console.log(TIMING.VOTING_PERIOD_SECONDS); // 1,209,600 (14 days)
|
|
195
|
+
console.log(TIMING.HOLD_PERIOD_SECONDS); // 604,800 (7 days)
|
|
196
|
+
console.log(TIMING.CHALLENGE_PERIOD_SECONDS); // 172,800 (48 hours)
|
|
197
|
+
console.log(TIMING.ABANDONMENT_TIMEOUT_SECONDS); // 7,776,000 (90 days)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Governance Parameters
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { GOVERNANCE } from '@raise/sdk';
|
|
204
|
+
|
|
205
|
+
console.log(GOVERNANCE.MILESTONE_APPROVAL_THRESHOLD_PERCENT); // 50 (>50%)
|
|
206
|
+
console.log(GOVERNANCE.SHUTDOWN_THRESHOLD_BPS); // 6600 (66%)
|
|
207
|
+
console.log(GOVERNANCE.SCAM_THRESHOLD_PERCENT); // 30 (30%)
|
|
208
|
+
console.log(GOVERNANCE.CONSECUTIVE_FAILURES_THRESHOLD); // 4
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Error Handling
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import {
|
|
215
|
+
parseError,
|
|
216
|
+
isRaiseError,
|
|
217
|
+
getErrorMessage,
|
|
218
|
+
ERROR_CODES
|
|
219
|
+
} from '@raise/sdk';
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
await client.invest({ ... });
|
|
223
|
+
} catch (error) {
|
|
224
|
+
const parsed = parseError(error);
|
|
225
|
+
|
|
226
|
+
if (isRaiseError(parsed, ERROR_CODES.InvestmentBelowMinimum)) {
|
|
227
|
+
console.error('Investment too small for minimum tier');
|
|
228
|
+
} else if (isRaiseError(parsed, ERROR_CODES.FundingGoalExceeded)) {
|
|
229
|
+
console.error('Project is fully funded');
|
|
230
|
+
} else {
|
|
231
|
+
console.error(getErrorMessage(parsed));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Utility Functions
|
|
237
|
+
|
|
238
|
+
### Time Helpers
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import {
|
|
242
|
+
timeRemaining,
|
|
243
|
+
formatDuration,
|
|
244
|
+
hasTimestampPassed,
|
|
245
|
+
timestampToDate
|
|
246
|
+
} from '@raise/sdk';
|
|
247
|
+
|
|
248
|
+
// Check voting deadline
|
|
249
|
+
const milestone = await client.fetchMilestone(projectId, 0);
|
|
250
|
+
if (milestone?.votingEndsAt) {
|
|
251
|
+
const remaining = timeRemaining(milestone.votingEndsAt);
|
|
252
|
+
console.log(`Time remaining: ${formatDuration(remaining)}`);
|
|
253
|
+
// Output: "Time remaining: 2d 5h 30m"
|
|
254
|
+
|
|
255
|
+
if (hasTimestampPassed(milestone.votingEndsAt)) {
|
|
256
|
+
console.log('Voting period ended');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### USDC Conversions
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { USDC } from '@raise/sdk';
|
|
265
|
+
|
|
266
|
+
// Convert USDC to lamports
|
|
267
|
+
const lamports = USDC.toAmount(100); // 100_000_000n
|
|
268
|
+
|
|
269
|
+
// Convert lamports to USDC
|
|
270
|
+
const usdc = USDC.fromAmount(100_000_000n); // 100
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Validation
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import {
|
|
277
|
+
validateMilestonePercentages,
|
|
278
|
+
validateMetadataUri
|
|
279
|
+
} from '@raise/sdk';
|
|
280
|
+
|
|
281
|
+
// Validate milestone percentages sum to 100
|
|
282
|
+
const isValid = validateMilestonePercentages([30, 40, 30]); // true
|
|
283
|
+
|
|
284
|
+
// Validate metadata URI
|
|
285
|
+
const isValidUri = validateMetadataUri('https://example.com/project.json');
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## React Integration
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { useMemo } from 'react';
|
|
292
|
+
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
|
|
293
|
+
import { Program, AnchorProvider } from '@coral-xyz/anchor';
|
|
294
|
+
import { RaiseClient } from '@raise/sdk';
|
|
295
|
+
import idl from './idl/raise.json';
|
|
296
|
+
|
|
297
|
+
export function useRaise(): RaiseClient | null {
|
|
298
|
+
const { connection } = useConnection();
|
|
299
|
+
const wallet = useWallet();
|
|
300
|
+
|
|
301
|
+
return useMemo(() => {
|
|
302
|
+
if (!wallet.publicKey || !wallet.signTransaction) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const provider = new AnchorProvider(
|
|
307
|
+
connection,
|
|
308
|
+
wallet as any,
|
|
309
|
+
AnchorProvider.defaultOptions()
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const program = new Program(idl as any, provider);
|
|
313
|
+
return RaiseClient.fromProgram(program);
|
|
314
|
+
}, [connection, wallet]);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Usage in component
|
|
318
|
+
function InvestButton({ projectId }) {
|
|
319
|
+
const client = useRaise();
|
|
320
|
+
|
|
321
|
+
const handleInvest = async () => {
|
|
322
|
+
if (!client) return;
|
|
323
|
+
|
|
324
|
+
const tx = await client.invest({
|
|
325
|
+
projectId: new BN(projectId),
|
|
326
|
+
amount: new BN(100_000_000),
|
|
327
|
+
investorTokenAccount: myUsdcAta,
|
|
328
|
+
escrowTokenAccount: projectEscrow,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
console.log('Investment tx:', tx);
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
return (
|
|
335
|
+
<button onClick={handleInvest} disabled={!client}>
|
|
336
|
+
Invest
|
|
337
|
+
</button>
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## API Reference
|
|
343
|
+
|
|
344
|
+
### RaiseClient Methods
|
|
345
|
+
|
|
346
|
+
#### Admin Operations
|
|
347
|
+
- `initializeAdmin(admin)` - Initialize admin config
|
|
348
|
+
- `transferAdmin(newAdmin)` - Propose admin transfer
|
|
349
|
+
- `acceptAdmin()` - Accept admin transfer
|
|
350
|
+
|
|
351
|
+
#### Project Operations
|
|
352
|
+
- `initializeProject(args)` - Create new project
|
|
353
|
+
- `submitForApproval(projectId)` - Submit for admin approval
|
|
354
|
+
- `approveProject(projectId, adminKeypair)` - Approve project
|
|
355
|
+
|
|
356
|
+
#### Milestone Operations
|
|
357
|
+
- `createMilestone(args)` - Add milestone to project
|
|
358
|
+
- `submitMilestone(projectId, index)` - Submit for voting
|
|
359
|
+
- `voteOnMilestone(args)` - Cast vote
|
|
360
|
+
- `finalizeVoting(projectId, index)` - End voting period
|
|
361
|
+
- `claimMilestoneFunds(args)` - Claim funds after passing
|
|
362
|
+
|
|
363
|
+
#### Investment Operations
|
|
364
|
+
- `invest(args)` - Invest USDC, receive NFT
|
|
365
|
+
- `cancelInvestment(args)` - Cancel within 24h cooling-off
|
|
366
|
+
|
|
367
|
+
#### TGE Operations
|
|
368
|
+
- `setTgeDate(args)` - Set token generation date
|
|
369
|
+
- `depositTokens(args)` - Deposit tokens for distribution
|
|
370
|
+
- `claimTokens(args)` - Claim allocated tokens
|
|
371
|
+
- `releaseHoldback(args)` - Release 10% founder holdback
|
|
372
|
+
|
|
373
|
+
#### Governance Operations
|
|
374
|
+
- `initiateShutdownVote(args)` - Start shutdown vote
|
|
375
|
+
- `voteOnShutdown(args)` - Vote on shutdown
|
|
376
|
+
- `finalizeShutdownVote(args)` - Finalize shutdown vote
|
|
377
|
+
- `claimShutdownRefund(args)` - Claim refund after shutdown
|
|
378
|
+
|
|
379
|
+
#### Pivot Operations
|
|
380
|
+
- `proposePivot(args)` - Propose project pivot
|
|
381
|
+
- `approvePivot(projectId, adminKeypair)` - Approve pivot
|
|
382
|
+
- `withdrawFromPivot(args)` - Withdraw during window
|
|
383
|
+
- `finalizePivot(args)` - Finalize after window
|
|
384
|
+
|
|
385
|
+
#### Account Fetchers
|
|
386
|
+
- `fetchProject(projectId)`
|
|
387
|
+
- `fetchMilestone(projectId, index)`
|
|
388
|
+
- `fetchAllMilestones(projectId)`
|
|
389
|
+
- `fetchInvestment(projectId, nftMint)`
|
|
390
|
+
- `fetchAllInvestments(projectId)`
|
|
391
|
+
- `fetchTopInvestors(projectId, count)`
|
|
392
|
+
- `fetchVote(projectId, milestoneIndex, voter)`
|
|
393
|
+
- `fetchWithdrawal(projectId, milestoneIndex)`
|
|
394
|
+
- `fetchPivotProposal(projectId)`
|
|
395
|
+
- `fetchShutdownVote(projectId)`
|
|
396
|
+
- `fetchAdminConfig()`
|
|
397
|
+
|
|
398
|
+
## Development
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# Install dependencies
|
|
402
|
+
npm install
|
|
403
|
+
|
|
404
|
+
# Build
|
|
405
|
+
npm run build
|
|
406
|
+
|
|
407
|
+
# Type check
|
|
408
|
+
npm run typecheck
|
|
409
|
+
|
|
410
|
+
# Watch mode
|
|
411
|
+
npm run dev
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## License
|
|
415
|
+
|
|
416
|
+
MIT
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var web3_js = require('@solana/web3.js');
|
|
4
|
+
var anchor = require('@coral-xyz/anchor');
|
|
5
|
+
|
|
6
|
+
// src/pdas/index.ts
|
|
7
|
+
|
|
8
|
+
// src/constants/index.ts
|
|
9
|
+
var SEEDS = {
|
|
10
|
+
PROJECT: "project",
|
|
11
|
+
MILESTONE: "milestone",
|
|
12
|
+
INVESTMENT: "investment",
|
|
13
|
+
VOTE: "vote",
|
|
14
|
+
PIVOT: "pivot",
|
|
15
|
+
TGE_ESCROW: "tge_escrow",
|
|
16
|
+
ADMIN_CONFIG: "admin-config"};
|
|
17
|
+
|
|
18
|
+
// src/pdas/index.ts
|
|
19
|
+
function ensureBN(value) {
|
|
20
|
+
if (value && typeof value.toArrayLike === "function") {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
return new anchor.BN(String(value));
|
|
24
|
+
}
|
|
25
|
+
function getProjectPDA(projectId, programId) {
|
|
26
|
+
const projectIdBN = ensureBN(projectId);
|
|
27
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
28
|
+
[Buffer.from(SEEDS.PROJECT), projectIdBN.toArrayLike(Buffer, "le", 8)],
|
|
29
|
+
programId
|
|
30
|
+
);
|
|
31
|
+
return pda;
|
|
32
|
+
}
|
|
33
|
+
function getMilestonePDA(projectPda, milestoneIndex, programId) {
|
|
34
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
35
|
+
[
|
|
36
|
+
Buffer.from(SEEDS.MILESTONE),
|
|
37
|
+
projectPda.toBuffer(),
|
|
38
|
+
Buffer.from([milestoneIndex])
|
|
39
|
+
],
|
|
40
|
+
programId
|
|
41
|
+
);
|
|
42
|
+
return pda;
|
|
43
|
+
}
|
|
44
|
+
function getInvestmentPDA(projectPda, nftMint, programId) {
|
|
45
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
46
|
+
[
|
|
47
|
+
Buffer.from(SEEDS.INVESTMENT),
|
|
48
|
+
projectPda.toBuffer(),
|
|
49
|
+
nftMint.toBuffer()
|
|
50
|
+
],
|
|
51
|
+
programId
|
|
52
|
+
);
|
|
53
|
+
return pda;
|
|
54
|
+
}
|
|
55
|
+
function getVotePDA(milestonePda, voterKey, votingRound, programId) {
|
|
56
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
57
|
+
[Buffer.from(SEEDS.VOTE), milestonePda.toBuffer(), voterKey.toBuffer(), Buffer.from([votingRound])],
|
|
58
|
+
programId
|
|
59
|
+
);
|
|
60
|
+
return pda;
|
|
61
|
+
}
|
|
62
|
+
function getPivotProposalPDA(projectPda, pivotCount, programId) {
|
|
63
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
64
|
+
[
|
|
65
|
+
Buffer.from(SEEDS.PIVOT),
|
|
66
|
+
// Use PIVOT seed, not PIVOT_PROPOSAL
|
|
67
|
+
projectPda.toBuffer(),
|
|
68
|
+
Buffer.from([pivotCount])
|
|
69
|
+
// pivot_count is u8 (1 byte) on-chain
|
|
70
|
+
],
|
|
71
|
+
programId
|
|
72
|
+
);
|
|
73
|
+
return pda;
|
|
74
|
+
}
|
|
75
|
+
function getTgeEscrowPDA(projectPda, programId) {
|
|
76
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
77
|
+
[Buffer.from(SEEDS.TGE_ESCROW), projectPda.toBuffer()],
|
|
78
|
+
programId
|
|
79
|
+
);
|
|
80
|
+
return pda;
|
|
81
|
+
}
|
|
82
|
+
function getAdminConfigPDA(programId) {
|
|
83
|
+
const [pda] = web3_js.PublicKey.findProgramAddressSync(
|
|
84
|
+
[Buffer.from(SEEDS.ADMIN_CONFIG)],
|
|
85
|
+
programId
|
|
86
|
+
);
|
|
87
|
+
return pda;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/accounts/index.ts
|
|
91
|
+
function getAccountNamespace(program) {
|
|
92
|
+
return program.account;
|
|
93
|
+
}
|
|
94
|
+
async function fetchProject(program, projectId) {
|
|
95
|
+
try {
|
|
96
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
97
|
+
return await getAccountNamespace(program).project.fetch(projectPda);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function fetchProjectByPda(program, projectPda) {
|
|
106
|
+
try {
|
|
107
|
+
return await getAccountNamespace(program).project.fetch(projectPda);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function fetchMilestone(program, projectId, milestoneIndex) {
|
|
116
|
+
try {
|
|
117
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
118
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
119
|
+
return await getAccountNamespace(program).milestone.fetch(milestonePda);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function fetchAllMilestones(program, projectId) {
|
|
128
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
129
|
+
const milestones = await getAccountNamespace(program).milestone.all([
|
|
130
|
+
{
|
|
131
|
+
memcmp: {
|
|
132
|
+
offset: 8,
|
|
133
|
+
// Skip discriminator
|
|
134
|
+
bytes: projectPda.toBase58()
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
]);
|
|
138
|
+
return milestones.map((m) => ({
|
|
139
|
+
publicKey: m.publicKey,
|
|
140
|
+
account: m.account
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
async function fetchInvestment(program, projectId, nftMint) {
|
|
144
|
+
try {
|
|
145
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
146
|
+
const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
|
|
147
|
+
return await getAccountNamespace(program).investment.fetch(investmentPda);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async function fetchAllInvestments(program, projectId) {
|
|
156
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
157
|
+
const investments = await getAccountNamespace(program).investment.all([
|
|
158
|
+
{
|
|
159
|
+
memcmp: {
|
|
160
|
+
offset: 8,
|
|
161
|
+
// Skip discriminator
|
|
162
|
+
bytes: projectPda.toBase58()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
]);
|
|
166
|
+
return investments.map((inv) => ({
|
|
167
|
+
publicKey: inv.publicKey,
|
|
168
|
+
account: inv.account
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
async function fetchVote(program, projectId, milestoneIndex, voterKey, votingRound) {
|
|
172
|
+
try {
|
|
173
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
174
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
175
|
+
const votePda = getVotePDA(milestonePda, voterKey, votingRound, program.programId);
|
|
176
|
+
return await getAccountNamespace(program).vote.fetch(votePda);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function fetchAllVotes(program, projectId, milestoneIndex) {
|
|
185
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
186
|
+
const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
|
|
187
|
+
const votes = await getAccountNamespace(program).vote.all([
|
|
188
|
+
{
|
|
189
|
+
memcmp: {
|
|
190
|
+
offset: 8,
|
|
191
|
+
// Skip discriminator
|
|
192
|
+
bytes: milestonePda.toBase58()
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
]);
|
|
196
|
+
return votes.map((v) => ({
|
|
197
|
+
publicKey: v.publicKey,
|
|
198
|
+
account: v.account
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
async function fetchPivotProposal(program, projectId) {
|
|
202
|
+
try {
|
|
203
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
204
|
+
const projectAccount = await getAccountNamespace(program).project.fetch(projectPda);
|
|
205
|
+
let pivotPda;
|
|
206
|
+
if (projectAccount.activePivot) {
|
|
207
|
+
pivotPda = projectAccount.activePivot;
|
|
208
|
+
} else {
|
|
209
|
+
const pivotCount = projectAccount.pivotCount || 0;
|
|
210
|
+
pivotPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
|
|
211
|
+
}
|
|
212
|
+
return await getAccountNamespace(program).pivotProposal.fetch(pivotPda);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function fetchTgeEscrow(program, projectId) {
|
|
221
|
+
try {
|
|
222
|
+
const projectPda = getProjectPDA(projectId, program.programId);
|
|
223
|
+
const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
|
|
224
|
+
return await getAccountNamespace(program).tgeEscrow.fetch(tgeEscrowPda);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
if (error instanceof Error && error.message?.includes("Account does not exist")) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function fetchAdminConfig(program) {
|
|
233
|
+
const adminConfigPda = getAdminConfigPDA(program.programId);
|
|
234
|
+
return await getAccountNamespace(program).adminConfig.fetch(adminConfigPda);
|
|
235
|
+
}
|
|
236
|
+
async function accountExists(program, accountType, pda) {
|
|
237
|
+
try {
|
|
238
|
+
await program.account[accountType].fetch(pda);
|
|
239
|
+
return true;
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
exports.accountExists = accountExists;
|
|
246
|
+
exports.fetchAdminConfig = fetchAdminConfig;
|
|
247
|
+
exports.fetchAllInvestments = fetchAllInvestments;
|
|
248
|
+
exports.fetchAllMilestones = fetchAllMilestones;
|
|
249
|
+
exports.fetchAllVotes = fetchAllVotes;
|
|
250
|
+
exports.fetchInvestment = fetchInvestment;
|
|
251
|
+
exports.fetchMilestone = fetchMilestone;
|
|
252
|
+
exports.fetchPivotProposal = fetchPivotProposal;
|
|
253
|
+
exports.fetchProject = fetchProject;
|
|
254
|
+
exports.fetchProjectByPda = fetchProjectByPda;
|
|
255
|
+
exports.fetchTgeEscrow = fetchTgeEscrow;
|
|
256
|
+
exports.fetchVote = fetchVote;
|
|
257
|
+
//# sourceMappingURL=index.cjs.map
|
|
258
|
+
//# sourceMappingURL=index.cjs.map
|