@aastar/enduser 0.16.14 → 0.16.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CommunityClient.d.ts +16 -0
- package/dist/CommunityClient.js +44 -0
- package/dist/UserClient.d.ts +4 -0
- package/dist/UserClient.js +17 -53
- package/dist/UserLifecycle.d.ts +85 -0
- package/dist/UserLifecycle.js +180 -0
- package/dist/enduser/src/CommunityClient.d.ts +81 -0
- package/dist/enduser/src/CommunityClient.js +244 -0
- package/dist/enduser/src/UserClient.d.ts +73 -0
- package/dist/enduser/src/UserClient.js +375 -0
- package/dist/enduser/src/UserLifecycle.d.ts +74 -0
- package/dist/enduser/src/UserLifecycle.js +179 -0
- package/dist/enduser/src/index.d.ts +3 -0
- package/dist/enduser/src/index.js +3 -0
- package/dist/enduser/src/testAccountManager.d.ts +149 -0
- package/dist/enduser/src/testAccountManager.js +271 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/paymaster/src/V4/BundlerCompat.d.ts +28 -0
- package/dist/paymaster/src/V4/BundlerCompat.js +37 -0
- package/dist/paymaster/src/V4/PaymasterClient.d.ts +89 -0
- package/dist/paymaster/src/V4/PaymasterClient.js +413 -0
- package/dist/paymaster/src/V4/PaymasterUtils.d.ts +66 -0
- package/dist/paymaster/src/V4/PaymasterUtils.js +141 -0
- package/package.json +4 -3
|
@@ -49,6 +49,22 @@ export declare class CommunityClient extends BaseClient {
|
|
|
49
49
|
logoURI?: string;
|
|
50
50
|
stakeAmount?: bigint;
|
|
51
51
|
}, options?: TransactionOptions): Promise<Hash>;
|
|
52
|
+
/**
|
|
53
|
+
* One-click Setup: Register Community + Deploy Token
|
|
54
|
+
* Orchestrates the complete community initialization flow.
|
|
55
|
+
*/
|
|
56
|
+
setupCommunity(params: {
|
|
57
|
+
name: string;
|
|
58
|
+
tokenName: string;
|
|
59
|
+
tokenSymbol: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
logoURI?: string;
|
|
62
|
+
website?: string;
|
|
63
|
+
stakeAmount?: bigint;
|
|
64
|
+
}, options?: TransactionOptions): Promise<{
|
|
65
|
+
tokenAddress: Address;
|
|
66
|
+
hashes: Hash[];
|
|
67
|
+
}>;
|
|
52
68
|
/**
|
|
53
69
|
* Airdrop SBTs to users to make them members
|
|
54
70
|
*/
|
package/dist/CommunityClient.js
CHANGED
|
@@ -103,6 +103,50 @@ export class CommunityClient extends BaseClient {
|
|
|
103
103
|
throw error;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* One-click Setup: Register Community + Deploy Token
|
|
108
|
+
* Orchestrates the complete community initialization flow.
|
|
109
|
+
*/
|
|
110
|
+
async setupCommunity(params, options) {
|
|
111
|
+
const hashes = [];
|
|
112
|
+
let tokenAddress = '0x0000000000000000000000000000000000000000';
|
|
113
|
+
// 1. Register as Community (Idempotent check handled inside or by registry)
|
|
114
|
+
// We should check hasRole first to avoid errors if already registered
|
|
115
|
+
const registry = registryActions(this.requireRegistry())(this.getStartPublicClient());
|
|
116
|
+
const ROLE_COMMUNITY = await registry.ROLE_COMMUNITY();
|
|
117
|
+
const hasRole = await registry.hasRole({ roleId: ROLE_COMMUNITY, user: this.getAddress() });
|
|
118
|
+
if (!hasRole) {
|
|
119
|
+
const hReg = await this.registerAsCommunity({
|
|
120
|
+
name: params.name,
|
|
121
|
+
ensName: params.website, // Mapping website to ENS param for now as per legacy behavior
|
|
122
|
+
website: params.website,
|
|
123
|
+
description: params.description,
|
|
124
|
+
logoURI: params.logoURI,
|
|
125
|
+
stakeAmount: params.stakeAmount
|
|
126
|
+
}, options);
|
|
127
|
+
hashes.push(hReg);
|
|
128
|
+
}
|
|
129
|
+
// 2. Deploy Token (Idempotent check via Factory)
|
|
130
|
+
if (this.factoryAddress) {
|
|
131
|
+
const factoryReader = xPNTsFactoryActions(this.factoryAddress)(this.getStartPublicClient());
|
|
132
|
+
const existingToken = await factoryReader.getTokenAddress({ community: this.getAddress() });
|
|
133
|
+
if (existingToken && existingToken !== '0x0000000000000000000000000000000000000000') {
|
|
134
|
+
tokenAddress = existingToken;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const hToken = await this.createCommunityToken({
|
|
138
|
+
name: params.tokenName,
|
|
139
|
+
tokenSymbol: params.tokenSymbol,
|
|
140
|
+
description: params.description
|
|
141
|
+
}, options);
|
|
142
|
+
hashes.push(hToken);
|
|
143
|
+
// Note: We can't get the address synchronously without waiting.
|
|
144
|
+
// In L3 pattern, we usually return hashes.
|
|
145
|
+
// The user can fetch token address later using factory.getTokenAddress(community)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { tokenAddress, hashes };
|
|
149
|
+
}
|
|
106
150
|
// ========================================
|
|
107
151
|
// 2. 成员管理
|
|
108
152
|
// ========================================
|
package/dist/UserClient.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface UserClientConfig extends ClientConfig {
|
|
|
8
8
|
gTokenStakingAddress?: Address;
|
|
9
9
|
registryAddress?: Address;
|
|
10
10
|
gTokenAddress?: Address;
|
|
11
|
+
bundlerClient?: any;
|
|
11
12
|
}
|
|
12
13
|
export declare class UserClient extends BaseClient {
|
|
13
14
|
accountAddress: Address;
|
|
@@ -16,6 +17,7 @@ export declare class UserClient extends BaseClient {
|
|
|
16
17
|
gTokenStakingAddress?: Address;
|
|
17
18
|
registryAddress?: Address;
|
|
18
19
|
gTokenAddress?: Address;
|
|
20
|
+
bundlerClient?: any;
|
|
19
21
|
constructor(config: UserClientConfig);
|
|
20
22
|
/**
|
|
21
23
|
* Get the nonce of the account from EntryPoint (more reliable for 4337)
|
|
@@ -83,5 +85,7 @@ export declare class UserClient extends BaseClient {
|
|
|
83
85
|
data: Hex;
|
|
84
86
|
paymaster: Address;
|
|
85
87
|
paymasterType: 'V4' | 'Super';
|
|
88
|
+
operator?: Address;
|
|
89
|
+
maxRate?: bigint;
|
|
86
90
|
}, options?: TransactionOptions): Promise<Hash>;
|
|
87
91
|
}
|
package/dist/UserClient.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { encodeFunctionData } from 'viem';
|
|
1
2
|
import { BaseClient } from '@aastar/core';
|
|
2
3
|
import { accountActions, sbtActions, tokenActions, entryPointActions, stakingActions, registryActions } from '@aastar/core';
|
|
3
|
-
import { bundlerActions
|
|
4
|
-
import { encodeFunctionData } from 'viem';
|
|
4
|
+
import { bundlerActions } from 'viem/account-abstraction';
|
|
5
5
|
export class UserClient extends BaseClient {
|
|
6
6
|
accountAddress;
|
|
7
7
|
sbtAddress;
|
|
@@ -9,8 +9,10 @@ export class UserClient extends BaseClient {
|
|
|
9
9
|
gTokenStakingAddress;
|
|
10
10
|
registryAddress;
|
|
11
11
|
gTokenAddress;
|
|
12
|
+
bundlerClient;
|
|
12
13
|
constructor(config) {
|
|
13
14
|
super(config);
|
|
15
|
+
this.bundlerClient = config.bundlerClient;
|
|
14
16
|
this.accountAddress = config.accountAddress;
|
|
15
17
|
this.sbtAddress = config.sbtAddress;
|
|
16
18
|
this.entryPointAddress = config.entryPointAddress;
|
|
@@ -328,67 +330,29 @@ export class UserClient extends BaseClient {
|
|
|
328
330
|
*/
|
|
329
331
|
async executeGasless(params, options) {
|
|
330
332
|
try {
|
|
331
|
-
const client = this.client.extend(bundlerActions);
|
|
333
|
+
const client = this.bundlerClient ? this.bundlerClient.extend(bundlerActions) : this.client.extend(bundlerActions);
|
|
332
334
|
const ep = this.requireEntryPoint();
|
|
333
|
-
const publicClient = this.getStartPublicClient();
|
|
334
335
|
// 1. Prepare Call Data
|
|
335
336
|
const callData = encodeFunctionData({
|
|
336
337
|
abi: [{ name: 'execute', type: 'function', inputs: [{ name: 'dest', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'func', type: 'bytes' }], outputs: [] }],
|
|
337
338
|
functionName: 'execute',
|
|
338
339
|
args: [params.target, params.value, params.data]
|
|
339
340
|
});
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
initCode: '0x',
|
|
351
|
-
callData,
|
|
352
|
-
paymasterAndData,
|
|
353
|
-
signature: '0x'
|
|
354
|
-
};
|
|
355
|
-
const gasEstimate = await client.estimateUserOperationGas({
|
|
356
|
-
userOperation: userOpPartial,
|
|
357
|
-
entryPoint: ep
|
|
358
|
-
});
|
|
359
|
-
// 4. Construct Final UserOp
|
|
360
|
-
const fees = await publicClient.estimateFeesPerGas();
|
|
361
|
-
const userOp = {
|
|
362
|
-
...userOpPartial,
|
|
363
|
-
callGasLimit: gasEstimate.callGasLimit,
|
|
364
|
-
verificationGasLimit: gasEstimate.verificationGasLimit + 50000n,
|
|
365
|
-
preVerificationGas: gasEstimate.preVerificationGas,
|
|
366
|
-
maxFeePerGas: fees.maxFeePerGas || fees.gasPrice || 1000000000n,
|
|
367
|
-
maxPriorityFeePerGas: fees.maxPriorityFeePerGas || 1000000000n
|
|
368
|
-
};
|
|
369
|
-
// 5. Sign
|
|
370
|
-
const chainId = this.client.chain?.id || 31337;
|
|
371
|
-
const hash = getUserOperationHash({
|
|
372
|
-
userOperation: userOp,
|
|
373
|
-
entryPointAddress: ep,
|
|
374
|
-
entryPointVersion: '0.7',
|
|
375
|
-
chainId
|
|
376
|
-
});
|
|
377
|
-
const signature = await this.client.signMessage({
|
|
378
|
-
message: { raw: hash },
|
|
379
|
-
account: this.client.account
|
|
380
|
-
});
|
|
381
|
-
const signedUserOp = {
|
|
382
|
-
...userOp,
|
|
383
|
-
signature
|
|
384
|
-
};
|
|
385
|
-
// 6. Send
|
|
386
|
-
return await client.sendUserOperation({
|
|
387
|
-
userOperation: signedUserOp,
|
|
388
|
-
entryPoint: ep
|
|
341
|
+
// 3. Delegate to PaymasterClient for v0.7 Gasless Submission
|
|
342
|
+
// This ensures we follow the exact same logic as successful demo scripts
|
|
343
|
+
// We dynamic import to avoid circular dependencies if any
|
|
344
|
+
const { PaymasterClient: SDKPaymasterClient } = await import('../../paymaster/src/V4/PaymasterClient.js');
|
|
345
|
+
const txHash = await SDKPaymasterClient.submitGaslessUserOperation(this.client, this.client, // WalletClient acts as signer
|
|
346
|
+
this.accountAddress, ep, params.paymaster, params.target, // placeholder for token if V4
|
|
347
|
+
this.bundlerClient?.transport?.url || this.client.transport.url || '', callData, {
|
|
348
|
+
operator: params.operator,
|
|
349
|
+
autoEstimate: true, // Let SDK handle estimation & tuning
|
|
350
|
+
paymasterPostOpGasLimit: 100000n // conservative default
|
|
389
351
|
});
|
|
352
|
+
return txHash;
|
|
390
353
|
}
|
|
391
354
|
catch (error) {
|
|
355
|
+
console.error(" ❌ executeGasless Error:", error.message);
|
|
392
356
|
throw error;
|
|
393
357
|
}
|
|
394
358
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type Address, type Hash, type Hex } from 'viem';
|
|
2
|
+
import { BaseClient, type ClientConfig } from '@aastar/core';
|
|
3
|
+
export interface GaslessConfig {
|
|
4
|
+
paymasterUrl: string;
|
|
5
|
+
policy?: 'CREDIT' | 'TOKEN' | 'SPONSORED';
|
|
6
|
+
}
|
|
7
|
+
export interface UserLifecycleConfig extends ClientConfig {
|
|
8
|
+
accountAddress: Address;
|
|
9
|
+
registryAddress: Address;
|
|
10
|
+
sbtAddress: Address;
|
|
11
|
+
gTokenAddress: Address;
|
|
12
|
+
gTokenStakingAddress: Address;
|
|
13
|
+
entryPointAddress: Address;
|
|
14
|
+
gasless?: GaslessConfig;
|
|
15
|
+
}
|
|
16
|
+
export interface OnboardResult {
|
|
17
|
+
success: boolean;
|
|
18
|
+
sbtId?: bigint;
|
|
19
|
+
txHash?: Hash;
|
|
20
|
+
}
|
|
21
|
+
export interface ReputationData {
|
|
22
|
+
score: bigint;
|
|
23
|
+
level: bigint;
|
|
24
|
+
creditLimit: bigint;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* UserLifecycle - L3 Pattern
|
|
28
|
+
*
|
|
29
|
+
* Responsibilities:
|
|
30
|
+
* 1. Managing the complete lifecycle of an End User (Onboard -> Operate -> Exit)
|
|
31
|
+
* 2. Providing a unified interface for Gasless operations
|
|
32
|
+
* 3. Abstracting underlying contract interactions via L2 Actions
|
|
33
|
+
*/
|
|
34
|
+
export declare class UserLifecycle extends BaseClient {
|
|
35
|
+
accountAddress: Address;
|
|
36
|
+
registryAddress: Address;
|
|
37
|
+
sbtAddress: Address;
|
|
38
|
+
gTokenAddress: Address;
|
|
39
|
+
gTokenStakingAddress: Address;
|
|
40
|
+
entryPointAddress: Address;
|
|
41
|
+
gaslessConfig?: GaslessConfig;
|
|
42
|
+
constructor(config: UserLifecycleConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Check if user is eligible to join a community
|
|
45
|
+
* @param community Address of the community
|
|
46
|
+
*/
|
|
47
|
+
checkEligibility(community: Address): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* One-click Onboarding: Approve -> Stake -> Register -> Mint SBT
|
|
50
|
+
* @param community Address of the community to join
|
|
51
|
+
* @param stakeAmount Amount of GToken to stake (default 0.4 GT)
|
|
52
|
+
*/
|
|
53
|
+
onboard(community: Address, stakeAmount?: bigint): Promise<OnboardResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Enable or update Gasless configuration
|
|
56
|
+
*/
|
|
57
|
+
enableGasless(config: GaslessConfig): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Execute a transaction effectively using Gasless configuration if available
|
|
60
|
+
*/
|
|
61
|
+
executeGaslessTx(params: {
|
|
62
|
+
target: Address;
|
|
63
|
+
value: bigint;
|
|
64
|
+
data: Hex;
|
|
65
|
+
operator?: Address;
|
|
66
|
+
}): Promise<Hash>;
|
|
67
|
+
/**
|
|
68
|
+
* Claim a specific SBT Role
|
|
69
|
+
*/
|
|
70
|
+
claimSBT(roleId: Hex): Promise<Hash>;
|
|
71
|
+
getMyReputation(): Promise<ReputationData>;
|
|
72
|
+
getCreditLimit(): Promise<bigint>;
|
|
73
|
+
/**
|
|
74
|
+
* Leave community: Unbind assets, Burn SBT, Remove Role
|
|
75
|
+
*/
|
|
76
|
+
leaveCommunity(community: Address): Promise<Hash>;
|
|
77
|
+
/**
|
|
78
|
+
* Exit a specific role in Registry
|
|
79
|
+
*/
|
|
80
|
+
exitRole(roleId: Hex): Promise<Hash>;
|
|
81
|
+
/**
|
|
82
|
+
* Unstake all GTokens from Staking contract
|
|
83
|
+
*/
|
|
84
|
+
unstakeAll(roleId: Hex): Promise<Hash>;
|
|
85
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { parseEther } from 'viem';
|
|
2
|
+
import { BaseClient } from '@aastar/core';
|
|
3
|
+
import { registryActions, sbtActions, stakingActions } from '@aastar/core'; // L2/L1 Actions
|
|
4
|
+
/**
|
|
5
|
+
* UserLifecycle - L3 Pattern
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* 1. Managing the complete lifecycle of an End User (Onboard -> Operate -> Exit)
|
|
9
|
+
* 2. Providing a unified interface for Gasless operations
|
|
10
|
+
* 3. Abstracting underlying contract interactions via L2 Actions
|
|
11
|
+
*/
|
|
12
|
+
export class UserLifecycle extends BaseClient {
|
|
13
|
+
accountAddress;
|
|
14
|
+
registryAddress;
|
|
15
|
+
sbtAddress;
|
|
16
|
+
gTokenAddress;
|
|
17
|
+
gTokenStakingAddress;
|
|
18
|
+
entryPointAddress;
|
|
19
|
+
gaslessConfig;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
super(config);
|
|
22
|
+
this.accountAddress = config.accountAddress;
|
|
23
|
+
this.registryAddress = config.registryAddress;
|
|
24
|
+
this.sbtAddress = config.sbtAddress;
|
|
25
|
+
this.gTokenAddress = config.gTokenAddress;
|
|
26
|
+
this.gTokenStakingAddress = config.gTokenStakingAddress;
|
|
27
|
+
this.entryPointAddress = config.entryPointAddress;
|
|
28
|
+
this.gaslessConfig = config.gasless;
|
|
29
|
+
}
|
|
30
|
+
// ===========================================
|
|
31
|
+
// 1. Onboarding Phase (Registration)
|
|
32
|
+
// ===========================================
|
|
33
|
+
/**
|
|
34
|
+
* Check if user is eligible to join a community
|
|
35
|
+
* @param community Address of the community
|
|
36
|
+
*/
|
|
37
|
+
async checkEligibility(community) {
|
|
38
|
+
// Validation logic (e.g., check blacklist or whitelist via Registry)
|
|
39
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
40
|
+
// Placeholder: simplistic check, real logic might involve community specific rules
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One-click Onboarding: Approve -> Stake -> Register -> Mint SBT
|
|
45
|
+
* @param community Address of the community to join
|
|
46
|
+
* @param stakeAmount Amount of GToken to stake (default 0.4 GT)
|
|
47
|
+
*/
|
|
48
|
+
async onboard(community, stakeAmount = parseEther('0.4')) {
|
|
49
|
+
try {
|
|
50
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
51
|
+
const userClient = await import('./UserClient.js').then(m => new m.UserClient({
|
|
52
|
+
...this.config,
|
|
53
|
+
accountAddress: this.accountAddress,
|
|
54
|
+
registryAddress: this.registryAddress,
|
|
55
|
+
gTokenStakingAddress: this.gTokenStakingAddress,
|
|
56
|
+
gTokenAddress: this.gTokenAddress,
|
|
57
|
+
sbtAddress: this.sbtAddress
|
|
58
|
+
}));
|
|
59
|
+
// Use UserClient's batch execution capability for atomic onboarding
|
|
60
|
+
const txHash = await userClient.registerAsEndUser(community, stakeAmount);
|
|
61
|
+
// Post-check: Verify role
|
|
62
|
+
const hasRole = await registry.hasRole({
|
|
63
|
+
roleId: await registry.ROLE_ENDUSER(),
|
|
64
|
+
user: this.accountAddress
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
success: hasRole,
|
|
68
|
+
txHash
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error("Onboarding failed:", error);
|
|
73
|
+
return { success: false };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Enable or update Gasless configuration
|
|
78
|
+
*/
|
|
79
|
+
async enableGasless(config) {
|
|
80
|
+
this.gaslessConfig = config;
|
|
81
|
+
// In future: verify paymaster connection here
|
|
82
|
+
}
|
|
83
|
+
// ===========================================
|
|
84
|
+
// 2. Operational Phase (Execute & Interact)
|
|
85
|
+
// ===========================================
|
|
86
|
+
/**
|
|
87
|
+
* Execute a transaction effectively using Gasless configuration if available
|
|
88
|
+
*/
|
|
89
|
+
async executeGaslessTx(params) {
|
|
90
|
+
if (!this.gaslessConfig) {
|
|
91
|
+
throw new Error("Gasless configuration not enabled. Call enableGasless() first.");
|
|
92
|
+
}
|
|
93
|
+
const userClient = await import('./UserClient.js').then(m => new m.UserClient({
|
|
94
|
+
...this.config,
|
|
95
|
+
accountAddress: this.accountAddress,
|
|
96
|
+
// Pass minimal config needed for execution
|
|
97
|
+
entryPointAddress: this.entryPointAddress,
|
|
98
|
+
bundlerClient: this.config.bundlerClient
|
|
99
|
+
}));
|
|
100
|
+
// Determine Paymaster Type based on policy
|
|
101
|
+
const paymasterType = this.gaslessConfig.policy === 'CREDIT' ? 'Super' : 'V4';
|
|
102
|
+
// Note: Real implementation needs to resolve actual Paymaster Address from Registry/Config
|
|
103
|
+
// This is a placeholder address resolution
|
|
104
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
105
|
+
const paymasterAddress = await registry.SUPER_PAYMASTER();
|
|
106
|
+
return await userClient.executeGasless({
|
|
107
|
+
target: params.target,
|
|
108
|
+
value: params.value,
|
|
109
|
+
data: params.data,
|
|
110
|
+
paymaster: paymasterAddress,
|
|
111
|
+
paymasterType,
|
|
112
|
+
operator: params.operator
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Claim a specific SBT Role
|
|
117
|
+
*/
|
|
118
|
+
async claimSBT(roleId) {
|
|
119
|
+
const userClient = await import('./UserClient.js').then(m => new m.UserClient({
|
|
120
|
+
...this.config,
|
|
121
|
+
accountAddress: this.accountAddress,
|
|
122
|
+
sbtAddress: this.sbtAddress
|
|
123
|
+
}));
|
|
124
|
+
return await userClient.mintSBT(roleId);
|
|
125
|
+
}
|
|
126
|
+
// ===========================================
|
|
127
|
+
// 3. Query Phase (Info & Stats)
|
|
128
|
+
// ===========================================
|
|
129
|
+
async getMyReputation() {
|
|
130
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
131
|
+
const [score, creditLimit] = await Promise.all([
|
|
132
|
+
registry.globalReputation({ user: this.accountAddress }),
|
|
133
|
+
registry.getCreditLimit({ user: this.accountAddress })
|
|
134
|
+
]);
|
|
135
|
+
return {
|
|
136
|
+
score,
|
|
137
|
+
level: 0n, // TODO: Add level calculation logic
|
|
138
|
+
creditLimit
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async getCreditLimit() {
|
|
142
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
143
|
+
return await registry.getCreditLimit({ user: this.accountAddress });
|
|
144
|
+
}
|
|
145
|
+
// ===========================================
|
|
146
|
+
// 4. Exit Phase (Cleanup)
|
|
147
|
+
// ===========================================
|
|
148
|
+
/**
|
|
149
|
+
* Leave community: Unbind assets, Burn SBT, Remove Role
|
|
150
|
+
*/
|
|
151
|
+
async leaveCommunity(community) {
|
|
152
|
+
const sbt = sbtActions(this.sbtAddress)(this.client);
|
|
153
|
+
// 1. Leave Logic (contracts usually handle burn)
|
|
154
|
+
return await sbt.leaveCommunity({
|
|
155
|
+
community,
|
|
156
|
+
account: this.accountAddress // Self-exit
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Exit a specific role in Registry
|
|
161
|
+
*/
|
|
162
|
+
async exitRole(roleId) {
|
|
163
|
+
const registry = registryActions(this.registryAddress)(this.client);
|
|
164
|
+
return await registry.exitRole({
|
|
165
|
+
roleId,
|
|
166
|
+
account: this.accountAddress
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Unstake all GTokens from Staking contract
|
|
171
|
+
*/
|
|
172
|
+
async unstakeAll(roleId) {
|
|
173
|
+
const staking = stakingActions(this.gTokenStakingAddress)(this.client);
|
|
174
|
+
return await staking.unlockAndTransfer({
|
|
175
|
+
user: this.accountAddress,
|
|
176
|
+
roleId,
|
|
177
|
+
account: this.accountAddress
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type Address, type Hash } from 'viem';
|
|
2
|
+
import { BaseClient, type ClientConfig, type TransactionOptions } from '@aastar/core';
|
|
3
|
+
export interface CommunityClientConfig extends ClientConfig {
|
|
4
|
+
sbtAddress?: Address;
|
|
5
|
+
factoryAddress?: Address;
|
|
6
|
+
reputationAddress?: Address;
|
|
7
|
+
}
|
|
8
|
+
export interface CreateCommunityParams {
|
|
9
|
+
name: string;
|
|
10
|
+
tokenSymbol: string;
|
|
11
|
+
ensName?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CommunityInfo {
|
|
15
|
+
address: Address;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Client for Community Managers (`ROLE_COMMUNITY`)
|
|
19
|
+
*/
|
|
20
|
+
export declare class CommunityClient extends BaseClient {
|
|
21
|
+
sbtAddress?: Address;
|
|
22
|
+
factoryAddress?: Address;
|
|
23
|
+
reputationAddress?: Address;
|
|
24
|
+
constructor(config: CommunityClientConfig);
|
|
25
|
+
/**
|
|
26
|
+
* Create a new Community Token (xPNTs) and register it.
|
|
27
|
+
* Note: In the current architecture, creating a community often involves:
|
|
28
|
+
* 1. Registering the ROLE_COMMUNITY on Registry (if not exists) -> usually manual or self-register
|
|
29
|
+
* 2. Deploying a Token (xPNTs) via Factory
|
|
30
|
+
* 3. Linking the Token to the Community in Registry
|
|
31
|
+
*/
|
|
32
|
+
createCommunityToken(params: CreateCommunityParams, options?: TransactionOptions): Promise<Hash>;
|
|
33
|
+
/**
|
|
34
|
+
* Register self as a Community Manager.
|
|
35
|
+
* This method handles all necessary steps:
|
|
36
|
+
* 1. Checks and approves GToken to GTokenStaking
|
|
37
|
+
* 2. Encodes CommunityRoleData with provided parameters
|
|
38
|
+
* 3. Calls registerRoleSelf on Registry
|
|
39
|
+
*
|
|
40
|
+
* @param params Community registration parameters
|
|
41
|
+
* @param options Transaction options
|
|
42
|
+
* @returns Transaction hash
|
|
43
|
+
*/
|
|
44
|
+
registerAsCommunity(params: {
|
|
45
|
+
name: string;
|
|
46
|
+
ensName?: string;
|
|
47
|
+
website?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
logoURI?: string;
|
|
50
|
+
stakeAmount?: bigint;
|
|
51
|
+
}, options?: TransactionOptions): Promise<Hash>;
|
|
52
|
+
/**
|
|
53
|
+
* One-click Setup: Register Community + Deploy Token
|
|
54
|
+
* Orchestrates the complete community initialization flow.
|
|
55
|
+
*/
|
|
56
|
+
setupCommunity(params: {
|
|
57
|
+
name: string;
|
|
58
|
+
tokenName: string;
|
|
59
|
+
tokenSymbol: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
logoURI?: string;
|
|
62
|
+
website?: string;
|
|
63
|
+
stakeAmount?: bigint;
|
|
64
|
+
}, options?: TransactionOptions): Promise<{
|
|
65
|
+
tokenAddress: Address;
|
|
66
|
+
hashes: Hash[];
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Airdrop SBTs to users to make them members
|
|
70
|
+
*/
|
|
71
|
+
airdropSBT(users: Address[], roleId: bigint, options?: TransactionOptions): Promise<Hash>;
|
|
72
|
+
setReputationRule(ruleId: bigint, ruleConfig: any, options?: TransactionOptions): Promise<Hash>;
|
|
73
|
+
/**
|
|
74
|
+
* Revoke membership (Burn SBT)
|
|
75
|
+
*/
|
|
76
|
+
revokeMembership(userAddr: Address, options?: TransactionOptions): Promise<Hash>;
|
|
77
|
+
/**
|
|
78
|
+
* Transfer ownership of the Community Token
|
|
79
|
+
*/
|
|
80
|
+
transferCommunityTokenOwnership(tokenAddress: Address, newOwner: Address, options?: TransactionOptions): Promise<Hash>;
|
|
81
|
+
}
|