@viwoapp/sdk 2.0.0 → 2.0.1
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 +88 -2
- package/dist/index.d.mts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +85 -0
- package/dist/index.mjs +85 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,85 @@
|
|
|
5
5
|
|
|
6
6
|
TypeScript SDK for VCoin Protocol Integration on Solana.
|
|
7
7
|
|
|
8
|
-
**Version:** 2.0.
|
|
8
|
+
**Version:** 2.0.1 (Delegation Balance Validation & 100% Audit Completion)
|
|
9
|
+
|
|
10
|
+
## What's New in v2.0.1
|
|
11
|
+
|
|
12
|
+
This release completes the security audit with **100% of all 68 findings resolved** and adds delegation balance validation.
|
|
13
|
+
|
|
14
|
+
### H-NEW-03: Delegation Balance Validation
|
|
15
|
+
|
|
16
|
+
The `delegateVotes` instruction now validates the delegation amount against the delegator's actual veVCoin balance from the staking protocol:
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// Build delegation transaction (validates balance on-chain)
|
|
20
|
+
const delegateTx = await client.governance.buildDelegateVotesTransaction({
|
|
21
|
+
delegate: delegatePubkey,
|
|
22
|
+
delegationType: 0, // Full delegation
|
|
23
|
+
categories: 0xFF, // All categories
|
|
24
|
+
amount: new BN(5000),
|
|
25
|
+
expiresAt: new BN(0),
|
|
26
|
+
revocable: true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Revoke delegation
|
|
30
|
+
const revokeTx = await client.governance.buildRevokeDelegationTransaction();
|
|
31
|
+
|
|
32
|
+
// Check existing delegation
|
|
33
|
+
const delegation = await client.governance.getDelegation();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**On-chain changes:**
|
|
37
|
+
- `DelegateVotes` context now requires `config` and `userStake` accounts
|
|
38
|
+
- Handler validates `vevcoin_amount <= delegator's actual veVCoin balance`
|
|
39
|
+
- Cross-program PDA verification from staking protocol
|
|
40
|
+
- Empty staking accounts correctly return balance of 0
|
|
41
|
+
|
|
42
|
+
### New SDK Features (v2.0.1)
|
|
43
|
+
|
|
44
|
+
- **`buildDelegateVotesTransaction()`**: Build delegation with on-chain balance validation
|
|
45
|
+
- **`buildRevokeDelegationTransaction()`**: Revoke existing delegation
|
|
46
|
+
- **`getDelegation()`**: Query delegation state for a user
|
|
47
|
+
- **`getDelegation()` PDA helper**: Derives delegation PDA from delegator pubkey
|
|
48
|
+
- **`getDelegateStats()` PDA helper**: Derives delegate stats PDA from delegate pubkey
|
|
49
|
+
- **`DelegateVotesParams`**: New type for delegation parameters
|
|
50
|
+
|
|
51
|
+
### Audit Completion
|
|
52
|
+
|
|
53
|
+
All 68 security findings now resolved:
|
|
54
|
+
|
|
55
|
+
| Severity | Count | Status |
|
|
56
|
+
|----------|-------|--------|
|
|
57
|
+
| Critical | 12 | ✅ 100% Fixed |
|
|
58
|
+
| High | 8 | ✅ 100% Fixed |
|
|
59
|
+
| Medium | 40 | ✅ 100% Fixed |
|
|
60
|
+
| Low | 8 | ✅ 100% Fixed |
|
|
61
|
+
|
|
62
|
+
Key fixes in this release:
|
|
63
|
+
- **H-NEW-03**: Delegation amount validated against veVCoin balance
|
|
64
|
+
- **M-01**: Voting power precision loss fixed (scale before divide)
|
|
65
|
+
- **M-04**: Tier update spam prevention (TierUnchanged check)
|
|
66
|
+
|
|
67
|
+
### Migration from v2.0.0
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Old: delegateVotes only needed 5 accounts
|
|
71
|
+
await program.methods.delegateVotes(0, 0, amount, expiresAt, true)
|
|
72
|
+
.accounts({
|
|
73
|
+
delegation, delegateStats, delegator, delegate, systemProgram,
|
|
74
|
+
}).rpc();
|
|
75
|
+
|
|
76
|
+
// New: delegateVotes requires config and userStake for balance validation
|
|
77
|
+
await program.methods.delegateVotes(0, 0, amount, expiresAt, true)
|
|
78
|
+
.accounts({
|
|
79
|
+
delegation, delegateStats, delegator, delegate,
|
|
80
|
+
config: govConfigPda, // NEW: governance config
|
|
81
|
+
userStake: userStakePda, // NEW: delegator's staking account
|
|
82
|
+
systemProgram,
|
|
83
|
+
}).rpc();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
9
87
|
|
|
10
88
|
## What's New in v2.0.0 (Major Release)
|
|
11
89
|
|
|
@@ -146,7 +224,7 @@ Run migration scripts to add new fields to existing state accounts (contact team
|
|
|
146
224
|
|
|
147
225
|
**Step 3: Update SDK**
|
|
148
226
|
```bash
|
|
149
|
-
npm install @viwoapp/sdk@2.0.
|
|
227
|
+
npm install @viwoapp/sdk@2.0.1
|
|
150
228
|
```
|
|
151
229
|
|
|
152
230
|
**Step 4: Update Code**
|
|
@@ -321,6 +399,13 @@ const votingPower = await client.governance.getVotingPower();
|
|
|
321
399
|
|
|
322
400
|
// Build transactions
|
|
323
401
|
const voteTx = await client.governance.buildVoteTransaction(proposalId, true);
|
|
402
|
+
|
|
403
|
+
// Delegation (v2.0.1)
|
|
404
|
+
const delegateTx = await client.governance.buildDelegateVotesTransaction({
|
|
405
|
+
delegate: delegatePubkey, delegationType: 0, categories: 0xFF,
|
|
406
|
+
amount: new BN(1000), expiresAt: new BN(0), revocable: true,
|
|
407
|
+
});
|
|
408
|
+
const revokeTx = await client.governance.buildRevokeDelegationTransaction();
|
|
324
409
|
```
|
|
325
410
|
|
|
326
411
|
### Rewards (`client.rewards`)
|
|
@@ -504,6 +589,7 @@ import type {
|
|
|
504
589
|
VoteChoice, // v0.1.4: Against, For, Abstain
|
|
505
590
|
GovernanceConfig,
|
|
506
591
|
Delegation,
|
|
592
|
+
DelegateVotesParams, // v2.0.1: Delegation parameters
|
|
507
593
|
PrivateVotingConfig,
|
|
508
594
|
DecryptionShare, // v0.1.1: ZK voting
|
|
509
595
|
|
package/dist/index.d.mts
CHANGED
|
@@ -272,6 +272,10 @@ declare class PDAs {
|
|
|
272
272
|
getGovernanceConfig(): PublicKey;
|
|
273
273
|
getProposal(proposalId: BN): PublicKey;
|
|
274
274
|
getVoteRecord(user: PublicKey, proposal: PublicKey): PublicKey;
|
|
275
|
+
/** H-NEW-03: Delegation PDA (one per delegator) */
|
|
276
|
+
getDelegation(delegator: PublicKey): PublicKey;
|
|
277
|
+
/** H-NEW-03: Delegate stats PDA (one per delegate) */
|
|
278
|
+
getDelegateStats(delegate: PublicKey): PublicKey;
|
|
275
279
|
getRewardsPoolConfig(): PublicKey;
|
|
276
280
|
getEpochDistribution(epoch: BN): PublicKey;
|
|
277
281
|
getUserClaim(user: PublicKey): PublicKey;
|
|
@@ -735,8 +739,25 @@ interface Delegation {
|
|
|
735
739
|
delegator: PublicKey;
|
|
736
740
|
delegate: PublicKey;
|
|
737
741
|
delegationType: number;
|
|
742
|
+
categories: number;
|
|
738
743
|
delegatedAmount: BN;
|
|
739
|
-
|
|
744
|
+
delegatedAt: BN;
|
|
745
|
+
expiresAt: BN;
|
|
746
|
+
revocable: boolean;
|
|
747
|
+
}
|
|
748
|
+
/** H-NEW-03: Parameters for creating a delegation */
|
|
749
|
+
interface DelegateVotesParams {
|
|
750
|
+
/** Address to delegate voting power to */
|
|
751
|
+
delegate: PublicKey;
|
|
752
|
+
/** Delegation type (0=Full, 1=PerCategory, 2=TimeScoped) */
|
|
753
|
+
delegationType: number;
|
|
754
|
+
/** Category bitmap (0xFF for all) */
|
|
755
|
+
categories: number;
|
|
756
|
+
/** Amount of veVCoin to delegate (must be <= actual balance) */
|
|
757
|
+
amount: BN;
|
|
758
|
+
/** Expiration timestamp (0 = never expires) */
|
|
759
|
+
expiresAt: BN;
|
|
760
|
+
/** Whether the delegation can be revoked mid-vote */
|
|
740
761
|
revocable: boolean;
|
|
741
762
|
}
|
|
742
763
|
/** Pending score update for oracle consensus */
|
|
@@ -932,6 +953,23 @@ declare class GovernanceClient {
|
|
|
932
953
|
* Build execute proposal transaction
|
|
933
954
|
*/
|
|
934
955
|
buildExecuteTransaction(proposalId: BN): Promise<Transaction>;
|
|
956
|
+
/**
|
|
957
|
+
* Get delegation for a user
|
|
958
|
+
*/
|
|
959
|
+
getDelegation(delegator?: PublicKey): Promise<Delegation | null>;
|
|
960
|
+
/**
|
|
961
|
+
* Build delegate votes transaction
|
|
962
|
+
*
|
|
963
|
+
* H-NEW-03: Validates delegation amount against actual veVCoin balance on-chain.
|
|
964
|
+
* The delegated amount must be <= the delegator's veVCoin balance from the staking protocol.
|
|
965
|
+
*
|
|
966
|
+
* @param params - Delegation parameters
|
|
967
|
+
*/
|
|
968
|
+
buildDelegateVotesTransaction(params: DelegateVotesParams): Promise<Transaction>;
|
|
969
|
+
/**
|
|
970
|
+
* Build revoke delegation transaction
|
|
971
|
+
*/
|
|
972
|
+
buildRevokeDelegationTransaction(): Promise<Transaction>;
|
|
935
973
|
/**
|
|
936
974
|
* Build cast private vote transaction
|
|
937
975
|
*
|
|
@@ -1709,4 +1747,4 @@ declare class StakingClient {
|
|
|
1709
1747
|
buildExtendLockTransaction(newDuration: number): Promise<Transaction>;
|
|
1710
1748
|
}
|
|
1711
1749
|
|
|
1712
|
-
export { ACTION_SCOPES, ActionType, type AggregateRevealedVotesParams, CONTENT_CONSTANTS, type CastPrivateVoteParams, type ClaimRewardsParams, type ConnectionConfig, ContentClient, type ContentRecord, ContentState, type CreateActionParams, type CreateProposalParams, type CreateSessionParams, type DecryptionShare, type Delegation, type EnablePrivateVotingParams, type EpochDistribution, FIVE_A_CONSTANTS, FeeMethod, FiveAClient, type FiveAConfig, type FiveAScore, GASLESS_CONSTANTS, GOVERNANCE_CONSTANTS, GaslessClient, type GaslessConfig, GovernanceClient, type GovernanceConfig, type HookConfig, type Identity, IdentityClient, type IdentityConfig, LEGACY_SLASH_DEPRECATED, LOCK_DURATIONS, MAX_EPOCH_BITMAP, MAX_URI_LENGTH, MERKLE_CONSTANTS, MERKLE_PROOF_MAX_SIZE, PDAs, PROGRAM_IDS, type PairTracking, type PendingAuthorityFields, type PendingScoreUpdate, type PrivateVotingConfig, type Proposal, ProposalStatus, type RegistryConfig, RewardsClient, type RewardsPoolConfig, SECURITY_CONSTANTS, SEEDS, SSCRE_CONSTANTS, STAKING_TIERS, type SessionKey, type SlashRequest, SlashStatus, type StakeParams, StakingClient, type StakingPool, StakingTier, type SubmitDecryptionShareParams, TransactionBuilder, type UserActionStatsExtended, type UserClaim, type UserEnergy, type UserGaslessStats, type UserStake, VALID_URI_PREFIXES, VCOIN_DECIMALS, VCOIN_INITIAL_CIRCULATING, VCOIN_TOTAL_SUPPLY, type VCoinConfig, VEVCOIN_DECIMALS, VILINK_CONSTANTS, type VeVCoinConfig, VerificationLevel, type ViLinkAction, ViLinkClient, type ViLinkConfig, ViWoClient, ViWoConnection, VoteChoice, type VoteRecord, type VouchRecord, type WalletAdapter, dateToTimestamp, formatVCoin, getCurrentTimestamp, parseVCoin, timestampToDate };
|
|
1750
|
+
export { ACTION_SCOPES, ActionType, type AggregateRevealedVotesParams, CONTENT_CONSTANTS, type CastPrivateVoteParams, type ClaimRewardsParams, type ConnectionConfig, ContentClient, type ContentRecord, ContentState, type CreateActionParams, type CreateProposalParams, type CreateSessionParams, type DecryptionShare, type DelegateVotesParams, type Delegation, type EnablePrivateVotingParams, type EpochDistribution, FIVE_A_CONSTANTS, FeeMethod, FiveAClient, type FiveAConfig, type FiveAScore, GASLESS_CONSTANTS, GOVERNANCE_CONSTANTS, GaslessClient, type GaslessConfig, GovernanceClient, type GovernanceConfig, type HookConfig, type Identity, IdentityClient, type IdentityConfig, LEGACY_SLASH_DEPRECATED, LOCK_DURATIONS, MAX_EPOCH_BITMAP, MAX_URI_LENGTH, MERKLE_CONSTANTS, MERKLE_PROOF_MAX_SIZE, PDAs, PROGRAM_IDS, type PairTracking, type PendingAuthorityFields, type PendingScoreUpdate, type PrivateVotingConfig, type Proposal, ProposalStatus, type RegistryConfig, RewardsClient, type RewardsPoolConfig, SECURITY_CONSTANTS, SEEDS, SSCRE_CONSTANTS, STAKING_TIERS, type SessionKey, type SlashRequest, SlashStatus, type StakeParams, StakingClient, type StakingPool, StakingTier, type SubmitDecryptionShareParams, TransactionBuilder, type UserActionStatsExtended, type UserClaim, type UserEnergy, type UserGaslessStats, type UserStake, VALID_URI_PREFIXES, VCOIN_DECIMALS, VCOIN_INITIAL_CIRCULATING, VCOIN_TOTAL_SUPPLY, type VCoinConfig, VEVCOIN_DECIMALS, VILINK_CONSTANTS, type VeVCoinConfig, VerificationLevel, type ViLinkAction, ViLinkClient, type ViLinkConfig, ViWoClient, ViWoConnection, VoteChoice, type VoteRecord, type VouchRecord, type WalletAdapter, dateToTimestamp, formatVCoin, getCurrentTimestamp, parseVCoin, timestampToDate };
|
package/dist/index.d.ts
CHANGED
|
@@ -272,6 +272,10 @@ declare class PDAs {
|
|
|
272
272
|
getGovernanceConfig(): PublicKey;
|
|
273
273
|
getProposal(proposalId: BN): PublicKey;
|
|
274
274
|
getVoteRecord(user: PublicKey, proposal: PublicKey): PublicKey;
|
|
275
|
+
/** H-NEW-03: Delegation PDA (one per delegator) */
|
|
276
|
+
getDelegation(delegator: PublicKey): PublicKey;
|
|
277
|
+
/** H-NEW-03: Delegate stats PDA (one per delegate) */
|
|
278
|
+
getDelegateStats(delegate: PublicKey): PublicKey;
|
|
275
279
|
getRewardsPoolConfig(): PublicKey;
|
|
276
280
|
getEpochDistribution(epoch: BN): PublicKey;
|
|
277
281
|
getUserClaim(user: PublicKey): PublicKey;
|
|
@@ -735,8 +739,25 @@ interface Delegation {
|
|
|
735
739
|
delegator: PublicKey;
|
|
736
740
|
delegate: PublicKey;
|
|
737
741
|
delegationType: number;
|
|
742
|
+
categories: number;
|
|
738
743
|
delegatedAmount: BN;
|
|
739
|
-
|
|
744
|
+
delegatedAt: BN;
|
|
745
|
+
expiresAt: BN;
|
|
746
|
+
revocable: boolean;
|
|
747
|
+
}
|
|
748
|
+
/** H-NEW-03: Parameters for creating a delegation */
|
|
749
|
+
interface DelegateVotesParams {
|
|
750
|
+
/** Address to delegate voting power to */
|
|
751
|
+
delegate: PublicKey;
|
|
752
|
+
/** Delegation type (0=Full, 1=PerCategory, 2=TimeScoped) */
|
|
753
|
+
delegationType: number;
|
|
754
|
+
/** Category bitmap (0xFF for all) */
|
|
755
|
+
categories: number;
|
|
756
|
+
/** Amount of veVCoin to delegate (must be <= actual balance) */
|
|
757
|
+
amount: BN;
|
|
758
|
+
/** Expiration timestamp (0 = never expires) */
|
|
759
|
+
expiresAt: BN;
|
|
760
|
+
/** Whether the delegation can be revoked mid-vote */
|
|
740
761
|
revocable: boolean;
|
|
741
762
|
}
|
|
742
763
|
/** Pending score update for oracle consensus */
|
|
@@ -932,6 +953,23 @@ declare class GovernanceClient {
|
|
|
932
953
|
* Build execute proposal transaction
|
|
933
954
|
*/
|
|
934
955
|
buildExecuteTransaction(proposalId: BN): Promise<Transaction>;
|
|
956
|
+
/**
|
|
957
|
+
* Get delegation for a user
|
|
958
|
+
*/
|
|
959
|
+
getDelegation(delegator?: PublicKey): Promise<Delegation | null>;
|
|
960
|
+
/**
|
|
961
|
+
* Build delegate votes transaction
|
|
962
|
+
*
|
|
963
|
+
* H-NEW-03: Validates delegation amount against actual veVCoin balance on-chain.
|
|
964
|
+
* The delegated amount must be <= the delegator's veVCoin balance from the staking protocol.
|
|
965
|
+
*
|
|
966
|
+
* @param params - Delegation parameters
|
|
967
|
+
*/
|
|
968
|
+
buildDelegateVotesTransaction(params: DelegateVotesParams): Promise<Transaction>;
|
|
969
|
+
/**
|
|
970
|
+
* Build revoke delegation transaction
|
|
971
|
+
*/
|
|
972
|
+
buildRevokeDelegationTransaction(): Promise<Transaction>;
|
|
935
973
|
/**
|
|
936
974
|
* Build cast private vote transaction
|
|
937
975
|
*
|
|
@@ -1709,4 +1747,4 @@ declare class StakingClient {
|
|
|
1709
1747
|
buildExtendLockTransaction(newDuration: number): Promise<Transaction>;
|
|
1710
1748
|
}
|
|
1711
1749
|
|
|
1712
|
-
export { ACTION_SCOPES, ActionType, type AggregateRevealedVotesParams, CONTENT_CONSTANTS, type CastPrivateVoteParams, type ClaimRewardsParams, type ConnectionConfig, ContentClient, type ContentRecord, ContentState, type CreateActionParams, type CreateProposalParams, type CreateSessionParams, type DecryptionShare, type Delegation, type EnablePrivateVotingParams, type EpochDistribution, FIVE_A_CONSTANTS, FeeMethod, FiveAClient, type FiveAConfig, type FiveAScore, GASLESS_CONSTANTS, GOVERNANCE_CONSTANTS, GaslessClient, type GaslessConfig, GovernanceClient, type GovernanceConfig, type HookConfig, type Identity, IdentityClient, type IdentityConfig, LEGACY_SLASH_DEPRECATED, LOCK_DURATIONS, MAX_EPOCH_BITMAP, MAX_URI_LENGTH, MERKLE_CONSTANTS, MERKLE_PROOF_MAX_SIZE, PDAs, PROGRAM_IDS, type PairTracking, type PendingAuthorityFields, type PendingScoreUpdate, type PrivateVotingConfig, type Proposal, ProposalStatus, type RegistryConfig, RewardsClient, type RewardsPoolConfig, SECURITY_CONSTANTS, SEEDS, SSCRE_CONSTANTS, STAKING_TIERS, type SessionKey, type SlashRequest, SlashStatus, type StakeParams, StakingClient, type StakingPool, StakingTier, type SubmitDecryptionShareParams, TransactionBuilder, type UserActionStatsExtended, type UserClaim, type UserEnergy, type UserGaslessStats, type UserStake, VALID_URI_PREFIXES, VCOIN_DECIMALS, VCOIN_INITIAL_CIRCULATING, VCOIN_TOTAL_SUPPLY, type VCoinConfig, VEVCOIN_DECIMALS, VILINK_CONSTANTS, type VeVCoinConfig, VerificationLevel, type ViLinkAction, ViLinkClient, type ViLinkConfig, ViWoClient, ViWoConnection, VoteChoice, type VoteRecord, type VouchRecord, type WalletAdapter, dateToTimestamp, formatVCoin, getCurrentTimestamp, parseVCoin, timestampToDate };
|
|
1750
|
+
export { ACTION_SCOPES, ActionType, type AggregateRevealedVotesParams, CONTENT_CONSTANTS, type CastPrivateVoteParams, type ClaimRewardsParams, type ConnectionConfig, ContentClient, type ContentRecord, ContentState, type CreateActionParams, type CreateProposalParams, type CreateSessionParams, type DecryptionShare, type DelegateVotesParams, type Delegation, type EnablePrivateVotingParams, type EpochDistribution, FIVE_A_CONSTANTS, FeeMethod, FiveAClient, type FiveAConfig, type FiveAScore, GASLESS_CONSTANTS, GOVERNANCE_CONSTANTS, GaslessClient, type GaslessConfig, GovernanceClient, type GovernanceConfig, type HookConfig, type Identity, IdentityClient, type IdentityConfig, LEGACY_SLASH_DEPRECATED, LOCK_DURATIONS, MAX_EPOCH_BITMAP, MAX_URI_LENGTH, MERKLE_CONSTANTS, MERKLE_PROOF_MAX_SIZE, PDAs, PROGRAM_IDS, type PairTracking, type PendingAuthorityFields, type PendingScoreUpdate, type PrivateVotingConfig, type Proposal, ProposalStatus, type RegistryConfig, RewardsClient, type RewardsPoolConfig, SECURITY_CONSTANTS, SEEDS, SSCRE_CONSTANTS, STAKING_TIERS, type SessionKey, type SlashRequest, SlashStatus, type StakeParams, StakingClient, type StakingPool, StakingTier, type SubmitDecryptionShareParams, TransactionBuilder, type UserActionStatsExtended, type UserClaim, type UserEnergy, type UserGaslessStats, type UserStake, VALID_URI_PREFIXES, VCOIN_DECIMALS, VCOIN_INITIAL_CIRCULATING, VCOIN_TOTAL_SUPPLY, type VCoinConfig, VEVCOIN_DECIMALS, VILINK_CONSTANTS, type VeVCoinConfig, VerificationLevel, type ViLinkAction, ViLinkClient, type ViLinkConfig, ViWoClient, ViWoConnection, VoteChoice, type VoteRecord, type VouchRecord, type WalletAdapter, dateToTimestamp, formatVCoin, getCurrentTimestamp, parseVCoin, timestampToDate };
|
package/dist/index.js
CHANGED
|
@@ -435,6 +435,22 @@ var PDAs = class {
|
|
|
435
435
|
);
|
|
436
436
|
return pda;
|
|
437
437
|
}
|
|
438
|
+
/** H-NEW-03: Delegation PDA (one per delegator) */
|
|
439
|
+
getDelegation(delegator) {
|
|
440
|
+
const [pda] = import_web32.PublicKey.findProgramAddressSync(
|
|
441
|
+
[Buffer.from(SEEDS.delegation), delegator.toBuffer()],
|
|
442
|
+
this.programIds.governanceProtocol
|
|
443
|
+
);
|
|
444
|
+
return pda;
|
|
445
|
+
}
|
|
446
|
+
/** H-NEW-03: Delegate stats PDA (one per delegate) */
|
|
447
|
+
getDelegateStats(delegate) {
|
|
448
|
+
const [pda] = import_web32.PublicKey.findProgramAddressSync(
|
|
449
|
+
[Buffer.from("delegate-stats"), delegate.toBuffer()],
|
|
450
|
+
this.programIds.governanceProtocol
|
|
451
|
+
);
|
|
452
|
+
return pda;
|
|
453
|
+
}
|
|
438
454
|
// SSCRE PDAs
|
|
439
455
|
getRewardsPoolConfig() {
|
|
440
456
|
const [pda] = import_web32.PublicKey.findProgramAddressSync(
|
|
@@ -1110,6 +1126,75 @@ var GovernanceClient = class {
|
|
|
1110
1126
|
const tx = new import_web34.Transaction();
|
|
1111
1127
|
return tx;
|
|
1112
1128
|
}
|
|
1129
|
+
// ============ Vote Delegation (H-NEW-03) ============
|
|
1130
|
+
/**
|
|
1131
|
+
* Get delegation for a user
|
|
1132
|
+
*/
|
|
1133
|
+
async getDelegation(delegator) {
|
|
1134
|
+
const target = delegator || this.client.publicKey;
|
|
1135
|
+
if (!target) {
|
|
1136
|
+
throw new Error("No user specified and wallet not connected");
|
|
1137
|
+
}
|
|
1138
|
+
try {
|
|
1139
|
+
const delegationPda = this.client.pdas.getDelegation(target);
|
|
1140
|
+
const accountInfo = await this.client.connection.connection.getAccountInfo(delegationPda);
|
|
1141
|
+
if (!accountInfo) {
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
const data = accountInfo.data;
|
|
1145
|
+
return {
|
|
1146
|
+
delegator: new import_web34.PublicKey(data.slice(8, 40)),
|
|
1147
|
+
delegate: new import_web34.PublicKey(data.slice(40, 72)),
|
|
1148
|
+
delegationType: data[72],
|
|
1149
|
+
categories: data[73],
|
|
1150
|
+
delegatedAmount: new import_anchor3.BN(data.slice(74, 82), "le"),
|
|
1151
|
+
delegatedAt: new import_anchor3.BN(data.slice(82, 90), "le"),
|
|
1152
|
+
expiresAt: new import_anchor3.BN(data.slice(90, 98), "le"),
|
|
1153
|
+
revocable: data[98] !== 0
|
|
1154
|
+
};
|
|
1155
|
+
} catch {
|
|
1156
|
+
return null;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Build delegate votes transaction
|
|
1161
|
+
*
|
|
1162
|
+
* H-NEW-03: Validates delegation amount against actual veVCoin balance on-chain.
|
|
1163
|
+
* The delegated amount must be <= the delegator's veVCoin balance from the staking protocol.
|
|
1164
|
+
*
|
|
1165
|
+
* @param params - Delegation parameters
|
|
1166
|
+
*/
|
|
1167
|
+
async buildDelegateVotesTransaction(params) {
|
|
1168
|
+
if (!this.client.publicKey) {
|
|
1169
|
+
throw new Error("Wallet not connected");
|
|
1170
|
+
}
|
|
1171
|
+
const delegationPda = this.client.pdas.getDelegation(this.client.publicKey);
|
|
1172
|
+
const delegateStatsPda = this.client.pdas.getDelegateStats(params.delegate);
|
|
1173
|
+
const configPda = this.client.pdas.getGovernanceConfig();
|
|
1174
|
+
const userStakePda = this.client.pdas.getUserStake(this.client.publicKey);
|
|
1175
|
+
const existing = await this.getDelegation();
|
|
1176
|
+
if (existing) {
|
|
1177
|
+
throw new Error("Active delegation already exists. Revoke it first.");
|
|
1178
|
+
}
|
|
1179
|
+
const tx = new import_web34.Transaction();
|
|
1180
|
+
return tx;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Build revoke delegation transaction
|
|
1184
|
+
*/
|
|
1185
|
+
async buildRevokeDelegationTransaction() {
|
|
1186
|
+
if (!this.client.publicKey) {
|
|
1187
|
+
throw new Error("Wallet not connected");
|
|
1188
|
+
}
|
|
1189
|
+
const existing = await this.getDelegation();
|
|
1190
|
+
if (!existing) {
|
|
1191
|
+
throw new Error("No active delegation to revoke");
|
|
1192
|
+
}
|
|
1193
|
+
const delegationPda = this.client.pdas.getDelegation(this.client.publicKey);
|
|
1194
|
+
const delegateStatsPda = this.client.pdas.getDelegateStats(existing.delegate);
|
|
1195
|
+
const tx = new import_web34.Transaction();
|
|
1196
|
+
return tx;
|
|
1197
|
+
}
|
|
1113
1198
|
// ============ ZK Private Voting ============
|
|
1114
1199
|
/**
|
|
1115
1200
|
* Build cast private vote transaction
|
package/dist/index.mjs
CHANGED
|
@@ -366,6 +366,22 @@ var PDAs = class {
|
|
|
366
366
|
);
|
|
367
367
|
return pda;
|
|
368
368
|
}
|
|
369
|
+
/** H-NEW-03: Delegation PDA (one per delegator) */
|
|
370
|
+
getDelegation(delegator) {
|
|
371
|
+
const [pda] = PublicKey2.findProgramAddressSync(
|
|
372
|
+
[Buffer.from(SEEDS.delegation), delegator.toBuffer()],
|
|
373
|
+
this.programIds.governanceProtocol
|
|
374
|
+
);
|
|
375
|
+
return pda;
|
|
376
|
+
}
|
|
377
|
+
/** H-NEW-03: Delegate stats PDA (one per delegate) */
|
|
378
|
+
getDelegateStats(delegate) {
|
|
379
|
+
const [pda] = PublicKey2.findProgramAddressSync(
|
|
380
|
+
[Buffer.from("delegate-stats"), delegate.toBuffer()],
|
|
381
|
+
this.programIds.governanceProtocol
|
|
382
|
+
);
|
|
383
|
+
return pda;
|
|
384
|
+
}
|
|
369
385
|
// SSCRE PDAs
|
|
370
386
|
getRewardsPoolConfig() {
|
|
371
387
|
const [pda] = PublicKey2.findProgramAddressSync(
|
|
@@ -1041,6 +1057,75 @@ var GovernanceClient = class {
|
|
|
1041
1057
|
const tx = new Transaction3();
|
|
1042
1058
|
return tx;
|
|
1043
1059
|
}
|
|
1060
|
+
// ============ Vote Delegation (H-NEW-03) ============
|
|
1061
|
+
/**
|
|
1062
|
+
* Get delegation for a user
|
|
1063
|
+
*/
|
|
1064
|
+
async getDelegation(delegator) {
|
|
1065
|
+
const target = delegator || this.client.publicKey;
|
|
1066
|
+
if (!target) {
|
|
1067
|
+
throw new Error("No user specified and wallet not connected");
|
|
1068
|
+
}
|
|
1069
|
+
try {
|
|
1070
|
+
const delegationPda = this.client.pdas.getDelegation(target);
|
|
1071
|
+
const accountInfo = await this.client.connection.connection.getAccountInfo(delegationPda);
|
|
1072
|
+
if (!accountInfo) {
|
|
1073
|
+
return null;
|
|
1074
|
+
}
|
|
1075
|
+
const data = accountInfo.data;
|
|
1076
|
+
return {
|
|
1077
|
+
delegator: new PublicKey4(data.slice(8, 40)),
|
|
1078
|
+
delegate: new PublicKey4(data.slice(40, 72)),
|
|
1079
|
+
delegationType: data[72],
|
|
1080
|
+
categories: data[73],
|
|
1081
|
+
delegatedAmount: new BN3(data.slice(74, 82), "le"),
|
|
1082
|
+
delegatedAt: new BN3(data.slice(82, 90), "le"),
|
|
1083
|
+
expiresAt: new BN3(data.slice(90, 98), "le"),
|
|
1084
|
+
revocable: data[98] !== 0
|
|
1085
|
+
};
|
|
1086
|
+
} catch {
|
|
1087
|
+
return null;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Build delegate votes transaction
|
|
1092
|
+
*
|
|
1093
|
+
* H-NEW-03: Validates delegation amount against actual veVCoin balance on-chain.
|
|
1094
|
+
* The delegated amount must be <= the delegator's veVCoin balance from the staking protocol.
|
|
1095
|
+
*
|
|
1096
|
+
* @param params - Delegation parameters
|
|
1097
|
+
*/
|
|
1098
|
+
async buildDelegateVotesTransaction(params) {
|
|
1099
|
+
if (!this.client.publicKey) {
|
|
1100
|
+
throw new Error("Wallet not connected");
|
|
1101
|
+
}
|
|
1102
|
+
const delegationPda = this.client.pdas.getDelegation(this.client.publicKey);
|
|
1103
|
+
const delegateStatsPda = this.client.pdas.getDelegateStats(params.delegate);
|
|
1104
|
+
const configPda = this.client.pdas.getGovernanceConfig();
|
|
1105
|
+
const userStakePda = this.client.pdas.getUserStake(this.client.publicKey);
|
|
1106
|
+
const existing = await this.getDelegation();
|
|
1107
|
+
if (existing) {
|
|
1108
|
+
throw new Error("Active delegation already exists. Revoke it first.");
|
|
1109
|
+
}
|
|
1110
|
+
const tx = new Transaction3();
|
|
1111
|
+
return tx;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Build revoke delegation transaction
|
|
1115
|
+
*/
|
|
1116
|
+
async buildRevokeDelegationTransaction() {
|
|
1117
|
+
if (!this.client.publicKey) {
|
|
1118
|
+
throw new Error("Wallet not connected");
|
|
1119
|
+
}
|
|
1120
|
+
const existing = await this.getDelegation();
|
|
1121
|
+
if (!existing) {
|
|
1122
|
+
throw new Error("No active delegation to revoke");
|
|
1123
|
+
}
|
|
1124
|
+
const delegationPda = this.client.pdas.getDelegation(this.client.publicKey);
|
|
1125
|
+
const delegateStatsPda = this.client.pdas.getDelegateStats(existing.delegate);
|
|
1126
|
+
const tx = new Transaction3();
|
|
1127
|
+
return tx;
|
|
1128
|
+
}
|
|
1044
1129
|
// ============ ZK Private Voting ============
|
|
1045
1130
|
/**
|
|
1046
1131
|
* Build cast private vote transaction
|