@aastar/community 0.16.11 → 0.16.12
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/package.json +6 -3
- package/__tests__/index.test.ts +0 -9
- package/src/index.ts +0 -326
- package/tsconfig.json +0 -8
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aastar/community",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.12",
|
|
4
4
|
"description": "Community management client for AAstar SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
7
10
|
"keywords": [
|
|
8
11
|
"aastar",
|
|
9
12
|
"community",
|
|
@@ -14,8 +17,8 @@
|
|
|
14
17
|
"license": "MIT",
|
|
15
18
|
"dependencies": {
|
|
16
19
|
"viem": "2.43.3",
|
|
17
|
-
"@aastar/core": "0.16.
|
|
18
|
-
"@aastar/tokens": "0.16.
|
|
20
|
+
"@aastar/core": "0.16.12",
|
|
21
|
+
"@aastar/tokens": "0.16.12"
|
|
19
22
|
},
|
|
20
23
|
"devDependencies": {
|
|
21
24
|
"typescript": "5.7.2"
|
package/__tests__/index.test.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import { Address, Hash, PublicClient, WalletClient, parseEther, parseAbi } from 'viem';
|
|
2
|
-
import { ROLE_COMMUNITY, RequirementChecker, type RoleRequirement } from '@aastar/core';
|
|
3
|
-
|
|
4
|
-
// Import contract addresses dynamically to avoid circular dependency
|
|
5
|
-
let CONTRACTS: any;
|
|
6
|
-
import('@aastar/core').then(m => { CONTRACTS = m.CONTRACTS; });
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Community configuration for launch
|
|
10
|
-
*/
|
|
11
|
-
export interface CommunityLaunchConfig {
|
|
12
|
-
name: string;
|
|
13
|
-
ensName?: string;
|
|
14
|
-
website?: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
logoURI?: string;
|
|
17
|
-
stakeAmount: bigint;
|
|
18
|
-
entryBurn?: bigint;
|
|
19
|
-
sbtRules?: SBTRuleConfig;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* SBT minting rules configuration
|
|
24
|
-
*/
|
|
25
|
-
export interface SBTRuleConfig {
|
|
26
|
-
minStake: bigint;
|
|
27
|
-
maxSupply: bigint;
|
|
28
|
-
mintPrice: bigint;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* xPNTs issuance parameters
|
|
33
|
-
*/
|
|
34
|
-
export interface XPNTsIssuanceParams {
|
|
35
|
-
symbol: string;
|
|
36
|
-
initialSupply: bigint;
|
|
37
|
-
exchangeRate: bigint;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Community statistics
|
|
42
|
-
*/
|
|
43
|
-
export interface CommunityStats {
|
|
44
|
-
totalMembers: number;
|
|
45
|
-
totalStaked: bigint;
|
|
46
|
-
xpntsSupply: bigint;
|
|
47
|
-
reputationAvg: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Community management client
|
|
52
|
-
*
|
|
53
|
-
* @roleRequired ROLE_COMMUNITY (for most operations after launch)
|
|
54
|
-
* @description Provides high-level APIs for community lifecycle operations
|
|
55
|
-
*
|
|
56
|
-
* ## Permission Requirements:
|
|
57
|
-
* - **Launch Community**: Requires GToken balance >= stakeAmount + entryBurn
|
|
58
|
-
* - **Issue xPNTs**: Requires COMMUNITY role
|
|
59
|
-
* - **Configure SBT**: Requires COMMUNITY role + community ownership
|
|
60
|
-
*
|
|
61
|
-
* ## Typical Users:
|
|
62
|
-
* - Community Administrators
|
|
63
|
-
* - DAO Operators
|
|
64
|
-
* - Protocol Partners
|
|
65
|
-
*/
|
|
66
|
-
export class CommunityClient {
|
|
67
|
-
private publicClient: PublicClient;
|
|
68
|
-
private walletClient: WalletClient;
|
|
69
|
-
private requirementChecker: RequirementChecker;
|
|
70
|
-
private registryAddress?: Address;
|
|
71
|
-
private gtokenAddress?: Address;
|
|
72
|
-
private stakingAddress?: Address;
|
|
73
|
-
|
|
74
|
-
constructor(
|
|
75
|
-
publicClient: PublicClient,
|
|
76
|
-
walletClient: WalletClient,
|
|
77
|
-
addresses?: {
|
|
78
|
-
registry?: Address;
|
|
79
|
-
gtoken?: Address;
|
|
80
|
-
staking?: Address;
|
|
81
|
-
}
|
|
82
|
-
) {
|
|
83
|
-
this.publicClient = publicClient;
|
|
84
|
-
this.walletClient = walletClient;
|
|
85
|
-
this.requirementChecker = new RequirementChecker(publicClient as any, addresses);
|
|
86
|
-
|
|
87
|
-
this.registryAddress = addresses?.registry;
|
|
88
|
-
this.gtokenAddress = addresses?.gtoken;
|
|
89
|
-
this.stakingAddress = addresses?.staking;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Check if user meets requirements to launch a community
|
|
94
|
-
*
|
|
95
|
-
* @roleRequired None (pre-check before registration)
|
|
96
|
-
* @param address User address to check (optional, defaults to wallet account)
|
|
97
|
-
* @param requiredAmount Total GToken required (stake + burn)
|
|
98
|
-
* @returns Requirement check result
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const check = await communityClient.checkLaunchRequirements(
|
|
103
|
-
* myAddress,
|
|
104
|
-
* parseEther("33") // 30 stake + 3 burn
|
|
105
|
-
* );
|
|
106
|
-
* if (!check.hasEnoughGToken) {
|
|
107
|
-
* console.error(`❌ ${check.missingRequirements.join('\n')}`);
|
|
108
|
-
* return;
|
|
109
|
-
* }
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
|
-
async checkLaunchRequirements(
|
|
113
|
-
address?: Address,
|
|
114
|
-
requiredAmount?: bigint
|
|
115
|
-
): Promise<RoleRequirement> {
|
|
116
|
-
const userAddress = address || this.walletClient.account?.address;
|
|
117
|
-
if (!userAddress) throw new Error('No wallet account found');
|
|
118
|
-
|
|
119
|
-
const amount = requiredAmount || parseEther("33"); // Default: 30+3
|
|
120
|
-
|
|
121
|
-
return await this.requirementChecker.checkRequirements({
|
|
122
|
-
address: userAddress,
|
|
123
|
-
requiredGToken: amount,
|
|
124
|
-
requireSBT: false
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Launch a community with one-click operation
|
|
130
|
-
*
|
|
131
|
-
* @roleRequired None (will register ROLE_COMMUNITY)
|
|
132
|
-
* @permission Requires GToken balance >= stakeAmount + entryBurn
|
|
133
|
-
*
|
|
134
|
-
* @description Combines: approve → stake → register → configure
|
|
135
|
-
* - Auto-approves GToken for staking contract
|
|
136
|
-
* - Registers caller as COMMUNITY role
|
|
137
|
-
* - Stakes required amount
|
|
138
|
-
* - **Pre-checks requirements before execution**
|
|
139
|
-
*
|
|
140
|
-
* @param config Community configuration
|
|
141
|
-
* @returns Community ID and transaction hash
|
|
142
|
-
*
|
|
143
|
-
* @throws Error if requirements not met
|
|
144
|
-
*
|
|
145
|
-
* @example
|
|
146
|
-
* ```typescript
|
|
147
|
-
* const communityClient = new CommunityClient(publicClient, walletClient);
|
|
148
|
-
*
|
|
149
|
-
* try {
|
|
150
|
-
* const { communityId, txHash } = await communityClient.launchCommunity({
|
|
151
|
-
* name: "MyDAO",
|
|
152
|
-
* stakeAmount: parseEther("30"),
|
|
153
|
-
* entryBurn: parseEther("3"),
|
|
154
|
-
* logoURI: "ipfs://..."
|
|
155
|
-
* });
|
|
156
|
-
* console.log(`✅ Community launched: ${communityId}`);
|
|
157
|
-
* } catch (error) {
|
|
158
|
-
* console.error(`❌ Failed: ${error.message}`);
|
|
159
|
-
* }
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
162
|
-
async launchCommunity(config: CommunityLaunchConfig): Promise<{
|
|
163
|
-
communityId: Address;
|
|
164
|
-
txHash: Hash;
|
|
165
|
-
}> {
|
|
166
|
-
const account = this.walletClient.account;
|
|
167
|
-
if (!account) throw new Error('Wallet account not found');
|
|
168
|
-
|
|
169
|
-
// PRE-CHECK: Verify requirements
|
|
170
|
-
const totalRequired = config.stakeAmount + (config.entryBurn || 0n);
|
|
171
|
-
const check = await this.checkLaunchRequirements(account.address, totalRequired);
|
|
172
|
-
|
|
173
|
-
if (!check.hasEnoughGToken) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
`Insufficient funds to launch community:\n` +
|
|
176
|
-
check.missingRequirements.join('\n')
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Load contract addresses
|
|
181
|
-
const { CONTRACTS } = await import('@aastar/core');
|
|
182
|
-
const registryAddress = this.registryAddress || CONTRACTS.sepolia.core.registry;
|
|
183
|
-
const gtokenAddress = this.gtokenAddress || CONTRACTS.sepolia.core.gToken;
|
|
184
|
-
const stakingAddress = this.stakingAddress || CONTRACTS.sepolia.core.gTokenStaking;
|
|
185
|
-
|
|
186
|
-
// Step 1: Approve GToken
|
|
187
|
-
const approveTx = await this.walletClient.writeContract({
|
|
188
|
-
address: gtokenAddress,
|
|
189
|
-
abi: [{
|
|
190
|
-
name: 'approve',
|
|
191
|
-
type: 'function',
|
|
192
|
-
stateMutability: 'nonpayable',
|
|
193
|
-
inputs: [
|
|
194
|
-
{ name: 'spender', type: 'address' },
|
|
195
|
-
{ name: 'amount', type: 'uint256' }
|
|
196
|
-
],
|
|
197
|
-
outputs: [{ type: 'bool' }]
|
|
198
|
-
}],
|
|
199
|
-
functionName: 'approve',
|
|
200
|
-
args: [stakingAddress, totalRequired],
|
|
201
|
-
chain: this.walletClient.chain
|
|
202
|
-
} as any);
|
|
203
|
-
|
|
204
|
-
await this.publicClient.waitForTransactionReceipt({ hash: approveTx });
|
|
205
|
-
|
|
206
|
-
// Step 2: Register role
|
|
207
|
-
const roleData = '0x'; // Simplified - needs proper encoding
|
|
208
|
-
const registerTx = await this.walletClient.writeContract({
|
|
209
|
-
address: registryAddress,
|
|
210
|
-
abi: [{
|
|
211
|
-
name: 'registerRole',
|
|
212
|
-
type: 'function',
|
|
213
|
-
stateMutability: 'nonpayable',
|
|
214
|
-
inputs: [
|
|
215
|
-
{ name: 'roleId', type: 'bytes32' },
|
|
216
|
-
{ name: 'user', type: 'address' },
|
|
217
|
-
{ name: 'roleData', type: 'bytes' }
|
|
218
|
-
],
|
|
219
|
-
outputs: []
|
|
220
|
-
}],
|
|
221
|
-
functionName: 'registerRole',
|
|
222
|
-
args: [ROLE_COMMUNITY, account.address, roleData],
|
|
223
|
-
chain: this.walletClient.chain
|
|
224
|
-
} as any);
|
|
225
|
-
|
|
226
|
-
await this.publicClient.waitForTransactionReceipt({ hash: registerTx });
|
|
227
|
-
|
|
228
|
-
return {
|
|
229
|
-
communityId: account.address,
|
|
230
|
-
txHash: registerTx
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Issue community-specific xPNTs token
|
|
236
|
-
*
|
|
237
|
-
* @roleRequired ROLE_COMMUNITY
|
|
238
|
-
* @permission Must be registered community admin
|
|
239
|
-
*
|
|
240
|
-
* @param params xPNTs issuance parameters
|
|
241
|
-
* @returns xPNTs contract address and transaction hash
|
|
242
|
-
*/
|
|
243
|
-
async issueXPNTs(params: XPNTsIssuanceParams): Promise<{
|
|
244
|
-
xpntsAddress: Address;
|
|
245
|
-
txHash: Hash;
|
|
246
|
-
}> {
|
|
247
|
-
const account = this.walletClient.account;
|
|
248
|
-
if (!account) throw new Error('Wallet account not found');
|
|
249
|
-
|
|
250
|
-
// PRE-CHECK: Verify COMMUNITY role
|
|
251
|
-
const hasRole = await this.requirementChecker.checkHasRole(
|
|
252
|
-
ROLE_COMMUNITY,
|
|
253
|
-
account.address
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
if (!hasRole) {
|
|
257
|
-
throw new Error(
|
|
258
|
-
`Missing ROLE_COMMUNITY. Please register as a community first.`
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Load contract addresses
|
|
263
|
-
const { CORE_ADDRESSES } = await import('@aastar/core');
|
|
264
|
-
const factoryAddress = CORE_ADDRESSES.xPNTsFactory;
|
|
265
|
-
|
|
266
|
-
if (!factoryAddress) throw new Error('xPNTsFactory address not found');
|
|
267
|
-
|
|
268
|
-
// Deploy xPNTs via Factory
|
|
269
|
-
// Assuming ABI: createXPNTs(string symbol, uint256 supply, uint256 rate)
|
|
270
|
-
const deployTx = await this.walletClient.writeContract({
|
|
271
|
-
address: factoryAddress,
|
|
272
|
-
abi: parseAbi(['function createXPNTs(string,uint256,uint256) returns (address)']),
|
|
273
|
-
functionName: 'createXPNTs',
|
|
274
|
-
args: [params.symbol, params.initialSupply, params.exchangeRate],
|
|
275
|
-
chain: this.walletClient.chain,
|
|
276
|
-
account
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// We can't easily get the address without parsing logs, so we return zero address for now or simulate
|
|
280
|
-
return {
|
|
281
|
-
xpntsAddress: '0x0000000000000000000000000000000000000000',
|
|
282
|
-
txHash: deployTx
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Configure SBT minting rules for the community
|
|
288
|
-
*
|
|
289
|
-
* @roleRequired ROLE_COMMUNITY
|
|
290
|
-
* @permission Must be registered community admin + community ownership
|
|
291
|
-
*
|
|
292
|
-
* @param rules SBT rule configuration
|
|
293
|
-
* @returns Transaction hash
|
|
294
|
-
*/
|
|
295
|
-
async configureSBTRules(rules: SBTRuleConfig): Promise<Hash> {
|
|
296
|
-
const account = this.walletClient.account;
|
|
297
|
-
if (!account) throw new Error('Wallet account not found');
|
|
298
|
-
|
|
299
|
-
// PRE-CHECK: Verify COMMUNITY role
|
|
300
|
-
const hasRole = await this.requirementChecker.checkHasRole(
|
|
301
|
-
ROLE_COMMUNITY,
|
|
302
|
-
account.address
|
|
303
|
-
);
|
|
304
|
-
|
|
305
|
-
if (!hasRole) {
|
|
306
|
-
throw new Error(
|
|
307
|
-
`Missing ROLE_COMMUNITY. Please register as a community first.`
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// TODO: Implement MySBT configuration
|
|
312
|
-
throw new Error('Not implemented yet - requires MySBT rule configuration');
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Get community statistics
|
|
317
|
-
*
|
|
318
|
-
* @roleRequired None (public query)
|
|
319
|
-
* @param communityId Community address
|
|
320
|
-
* @returns Community statistics
|
|
321
|
-
*/
|
|
322
|
-
async getCommunityStats(communityId: Address): Promise<CommunityStats> {
|
|
323
|
-
// TODO: Implement by querying Registry, Staking, and Reputation contracts
|
|
324
|
-
throw new Error('Not implemented yet - requires multi-contract aggregation');
|
|
325
|
-
}
|
|
326
|
-
}
|