@claritydao/midnight-agora-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/.prettierrc +1 -0
- package/LICENSE +0 -0
- package/README.md +1134 -0
- package/dist/browser-providers.d.ts +21 -0
- package/dist/browser-providers.d.ts.map +1 -0
- package/dist/browser-providers.js +147 -0
- package/dist/browser-providers.js.map +1 -0
- package/dist/common-types.d.ts +29 -0
- package/dist/common-types.d.ts.map +1 -0
- package/dist/common-types.js +2 -0
- package/dist/common-types.js.map +1 -0
- package/dist/errors.d.ts +67 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +108 -0
- package/dist/errors.js.map +1 -0
- package/dist/governor-api.d.ts +348 -0
- package/dist/governor-api.d.ts.map +1 -0
- package/dist/governor-api.js +716 -0
- package/dist/governor-api.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +87 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +93 -0
- package/dist/manager.js.map +1 -0
- package/dist/types.d.ts +307 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +77 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/index.d.ts +34 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +57 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validators.d.ts +52 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +160 -0
- package/dist/validators.js.map +1 -0
- package/eslint.config.mjs +48 -0
- package/package.json +39 -0
- package/src/browser-providers.ts +274 -0
- package/src/common-types.ts +51 -0
- package/src/errors.ts +124 -0
- package/src/governor-api.ts +948 -0
- package/src/index.ts +51 -0
- package/src/manager.ts +203 -0
- package/src/types.ts +403 -0
- package/src/utils/index.ts +60 -0
- package/src/validators.ts +245 -0
- package/test/README.md +409 -0
- package/test/errors.test.ts +179 -0
- package/test/integration/governor-api.test.ts +370 -0
- package/test/mocks/providers.ts +130 -0
- package/test/types.test.ts +112 -0
- package/test/utils.test.ts +111 -0
- package/test/validators.test.ts +368 -0
- package/test/wasm-init.test.ts +132 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +9 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export { GovernorAPI, type DeployedGovernorAPI } from "./governor-api";
|
|
2
|
+
export { initializeProviders } from "./browser-providers";
|
|
3
|
+
export {
|
|
4
|
+
GovernorManager,
|
|
5
|
+
type DeployedGovernorAPIProvider,
|
|
6
|
+
type GovernorDeployment,
|
|
7
|
+
type InProgressGovernorDeployment,
|
|
8
|
+
type DeployedGovernorDeployment,
|
|
9
|
+
type FailedGovernorDeployment
|
|
10
|
+
} from "./manager";
|
|
11
|
+
export * from "./common-types";
|
|
12
|
+
export * as utils from "./utils/index";
|
|
13
|
+
|
|
14
|
+
// Export comprehensive type definitions
|
|
15
|
+
export type {
|
|
16
|
+
DeploymentConfig,
|
|
17
|
+
GovernanceConfig,
|
|
18
|
+
GovernorConfig,
|
|
19
|
+
TokenConfig,
|
|
20
|
+
ProposalAction,
|
|
21
|
+
StakeInfo,
|
|
22
|
+
ProposalDetails,
|
|
23
|
+
EffectDetails,
|
|
24
|
+
VoteCount,
|
|
25
|
+
GovernorStatus,
|
|
26
|
+
GovernorValue,
|
|
27
|
+
StakeRecord
|
|
28
|
+
} from "./types";
|
|
29
|
+
|
|
30
|
+
// Export enums
|
|
31
|
+
export { VoteChoice, ProposalStatus } from "./types";
|
|
32
|
+
|
|
33
|
+
// Export configuration presets
|
|
34
|
+
export { ConfigPresets } from "./types";
|
|
35
|
+
|
|
36
|
+
// Export all error classes
|
|
37
|
+
export {
|
|
38
|
+
GovernorSDKError,
|
|
39
|
+
WalletNotConnectedError,
|
|
40
|
+
InsufficientStakeError,
|
|
41
|
+
InvalidParameterError,
|
|
42
|
+
ContractNotFoundError,
|
|
43
|
+
ProposalNotFoundError,
|
|
44
|
+
TransactionError,
|
|
45
|
+
DeploymentError,
|
|
46
|
+
InvalidConfigurationError,
|
|
47
|
+
NetworkNotConfiguredError
|
|
48
|
+
} from "./errors";
|
|
49
|
+
|
|
50
|
+
// Export validators for advanced usage
|
|
51
|
+
export * as validators from "./validators";
|
package/src/manager.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DeployedGovernorAPI,
|
|
3
|
+
GovernorAPI,
|
|
4
|
+
type GovernorProviders
|
|
5
|
+
} from "./governor-api";
|
|
6
|
+
import { initializeProviders } from "./browser-providers";
|
|
7
|
+
import { type ContractAddress } from "@midnight-ntwrk/compact-runtime";
|
|
8
|
+
import { BehaviorSubject, type Observable } from "rxjs";
|
|
9
|
+
import { type Logger } from "pino";
|
|
10
|
+
import type { DeploymentConfig } from "./types";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* An in-progress governor deployment.
|
|
14
|
+
*/
|
|
15
|
+
export interface InProgressGovernorDeployment {
|
|
16
|
+
readonly status: "in-progress";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A deployed governor deployment.
|
|
21
|
+
*/
|
|
22
|
+
export interface DeployedGovernorDeployment {
|
|
23
|
+
readonly status: "deployed";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The {@link DeployedGovernorAPI} instance when connected to an on network governor contract.
|
|
27
|
+
*/
|
|
28
|
+
readonly api: DeployedGovernorAPI;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A failed governor deployment.
|
|
33
|
+
*/
|
|
34
|
+
export interface FailedGovernorDeployment {
|
|
35
|
+
readonly status: "failed";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The error that caused the deployment to fail.
|
|
39
|
+
*/
|
|
40
|
+
readonly error: Error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A governor deployment.
|
|
45
|
+
*/
|
|
46
|
+
export type GovernorDeployment =
|
|
47
|
+
| InProgressGovernorDeployment
|
|
48
|
+
| DeployedGovernorDeployment
|
|
49
|
+
| FailedGovernorDeployment;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Provides access to governor deployments.
|
|
53
|
+
*/
|
|
54
|
+
export interface DeployedGovernorAPIProvider {
|
|
55
|
+
/**
|
|
56
|
+
* Gets the observable set of governor deployments.
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* This property represents an observable array of {@link GovernorDeployment}, each also an
|
|
60
|
+
* observable. Changes to the array will be emitted as governors are resolved (deployed or joined),
|
|
61
|
+
* while changes to each underlying governor can be observed via each item in the array.
|
|
62
|
+
*/
|
|
63
|
+
readonly governorDeployments$: Observable<
|
|
64
|
+
Array<Observable<GovernorDeployment>>
|
|
65
|
+
>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Joins or deploys a governor contract.
|
|
69
|
+
*
|
|
70
|
+
* @param contractAddress An optional contract address to use when resolving.
|
|
71
|
+
* @returns An observable governor deployment.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* For a given `contractAddress`, the method will attempt to find and join the identified governor
|
|
75
|
+
* contract; otherwise it will attempt to deploy a new one.
|
|
76
|
+
*/
|
|
77
|
+
readonly resolve: (
|
|
78
|
+
contractAddress?: ContractAddress
|
|
79
|
+
) => Observable<GovernorDeployment>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A {@link DeployedGovernorAPIProvider} that manages governor deployments in a browser setting.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* {@link GovernorManager} configures and manages a connection to the Midnight Lace
|
|
87
|
+
* wallet, along with a collection of additional providers that work in a web-browser setting.
|
|
88
|
+
*/
|
|
89
|
+
export class GovernorManager implements DeployedGovernorAPIProvider {
|
|
90
|
+
readonly #governorDeploymentsSubject: BehaviorSubject<
|
|
91
|
+
Array<BehaviorSubject<GovernorDeployment>>
|
|
92
|
+
>;
|
|
93
|
+
#initializedProviders: Promise<GovernorProviders> | undefined;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Initializes a new {@link GovernorManager} instance.
|
|
97
|
+
*
|
|
98
|
+
* @param deploymentConfig The deployment configuration for the governor contract.
|
|
99
|
+
* @param logger The `pino` logger to for logging.
|
|
100
|
+
*/
|
|
101
|
+
constructor(
|
|
102
|
+
private readonly deploymentConfig: DeploymentConfig,
|
|
103
|
+
private readonly logger: Logger
|
|
104
|
+
) {
|
|
105
|
+
this.#governorDeploymentsSubject = new BehaviorSubject<
|
|
106
|
+
Array<BehaviorSubject<GovernorDeployment>>
|
|
107
|
+
>([]);
|
|
108
|
+
this.governorDeployments$ = this.#governorDeploymentsSubject;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** @inheritdoc */
|
|
112
|
+
readonly governorDeployments$: Observable<
|
|
113
|
+
Array<Observable<GovernorDeployment>>
|
|
114
|
+
>;
|
|
115
|
+
|
|
116
|
+
/** @inheritdoc */
|
|
117
|
+
resolve(contractAddress?: ContractAddress): Observable<GovernorDeployment> {
|
|
118
|
+
const deployments = this.#governorDeploymentsSubject.value;
|
|
119
|
+
let deployment = deployments.find(
|
|
120
|
+
(deployment) =>
|
|
121
|
+
deployment.value.status === "deployed" &&
|
|
122
|
+
deployment.value.api.deployedContractAddress === contractAddress
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (deployment) {
|
|
126
|
+
return deployment;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
deployment = new BehaviorSubject<GovernorDeployment>({
|
|
130
|
+
status: "in-progress"
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (contractAddress) {
|
|
134
|
+
void this.joinDeployment(deployment, contractAddress);
|
|
135
|
+
} else {
|
|
136
|
+
void this.deployDeployment(deployment);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.#governorDeploymentsSubject.next([...deployments, deployment]);
|
|
140
|
+
|
|
141
|
+
return deployment;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private getProviders(): Promise<GovernorProviders> {
|
|
145
|
+
// We use a cached `Promise` to hold the providers. This will:
|
|
146
|
+
//
|
|
147
|
+
// 1. Cache and re-use the providers (including the configured connector API), and
|
|
148
|
+
// 2. Act as a synchronization point if multiple contract deploys or joins run concurrently.
|
|
149
|
+
// Concurrent calls to `getProviders()` will receive, and ultimately await, the same
|
|
150
|
+
// `Promise`.
|
|
151
|
+
return (
|
|
152
|
+
this.#initializedProviders ??
|
|
153
|
+
(this.#initializedProviders = initializeProviders(this.logger))
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private async deployDeployment(
|
|
158
|
+
deployment: BehaviorSubject<GovernorDeployment>
|
|
159
|
+
): Promise<void> {
|
|
160
|
+
try {
|
|
161
|
+
const providers = await this.getProviders();
|
|
162
|
+
const api = await GovernorAPI.deploy(
|
|
163
|
+
providers,
|
|
164
|
+
this.deploymentConfig,
|
|
165
|
+
this.logger
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
deployment.next({
|
|
169
|
+
status: "deployed",
|
|
170
|
+
api
|
|
171
|
+
});
|
|
172
|
+
} catch (error: unknown) {
|
|
173
|
+
deployment.next({
|
|
174
|
+
status: "failed",
|
|
175
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private async joinDeployment(
|
|
181
|
+
deployment: BehaviorSubject<GovernorDeployment>,
|
|
182
|
+
contractAddress: ContractAddress
|
|
183
|
+
): Promise<void> {
|
|
184
|
+
try {
|
|
185
|
+
const providers = await this.getProviders();
|
|
186
|
+
const api = await GovernorAPI.join(
|
|
187
|
+
providers,
|
|
188
|
+
contractAddress,
|
|
189
|
+
this.logger
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
deployment.next({
|
|
193
|
+
status: "deployed",
|
|
194
|
+
api
|
|
195
|
+
});
|
|
196
|
+
} catch (error: unknown) {
|
|
197
|
+
deployment.next({
|
|
198
|
+
status: "failed",
|
|
199
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Agora DAO Governor SDK.
|
|
3
|
+
*
|
|
4
|
+
* @module types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Governance configuration parameters.
|
|
9
|
+
*/
|
|
10
|
+
export interface GovernanceConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Duration of the voting period in seconds.
|
|
13
|
+
* @example BigInt(604800) // 7 days for production
|
|
14
|
+
* @example BigInt(300) // 5 minutes for testing
|
|
15
|
+
*/
|
|
16
|
+
votingPeriod: bigint;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Minimum number of votes required for a proposal to pass (quorum).
|
|
20
|
+
* @example BigInt(100000) // 100K tokens for production
|
|
21
|
+
* @example BigInt(100) // 100 tokens for testing
|
|
22
|
+
*/
|
|
23
|
+
quorumThreshold: bigint;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Minimum stake required to create a proposal.
|
|
27
|
+
* @example BigInt(50000) // 50K tokens for production
|
|
28
|
+
* @example BigInt(100) // 100 tokens for testing
|
|
29
|
+
*/
|
|
30
|
+
proposalThreshold: bigint;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Maximum lifetime of a proposal in seconds.
|
|
34
|
+
* @example BigInt(2592000) // 30 days for production
|
|
35
|
+
* @example BigInt(86400) // 1 day for testing
|
|
36
|
+
*/
|
|
37
|
+
proposalLifetime: bigint;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Delay before a passed proposal can be executed, in seconds.
|
|
41
|
+
* @example BigInt(172800) // 2 days for production
|
|
42
|
+
* @example BigInt(60) // 1 minute for testing
|
|
43
|
+
*/
|
|
44
|
+
executionDelay: bigint;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Grace period after execution delay before proposal expires, in seconds.
|
|
48
|
+
* @example BigInt(604800) // 7 days for production
|
|
49
|
+
* @example BigInt(300) // 5 minutes for testing
|
|
50
|
+
*/
|
|
51
|
+
gracePeriod: bigint;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Minimum amount that can be staked.
|
|
55
|
+
* @example BigInt(1000) // 1K tokens for production
|
|
56
|
+
* @example BigInt(10) // 10 tokens for testing
|
|
57
|
+
*/
|
|
58
|
+
minStakeAmount: bigint;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Minimum staking period in seconds before tokens can be unstaked.
|
|
62
|
+
* @example BigInt(604800) // 7 days for production
|
|
63
|
+
* @example BigInt(60) // 1 minute for testing
|
|
64
|
+
*/
|
|
65
|
+
stakingPeriod: bigint;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Complete governor contract configuration.
|
|
70
|
+
*/
|
|
71
|
+
export interface GovernorConfig {
|
|
72
|
+
/** Governance-specific parameters */
|
|
73
|
+
governance: GovernanceConfig;
|
|
74
|
+
|
|
75
|
+
/** Delay before execution (should match governance.executionDelay) */
|
|
76
|
+
executionDelay: bigint;
|
|
77
|
+
|
|
78
|
+
/** Grace period for execution (should match governance.gracePeriod) */
|
|
79
|
+
gracePeriod: bigint;
|
|
80
|
+
|
|
81
|
+
/** Maximum number of active proposals allowed */
|
|
82
|
+
maxActiveProposals: bigint;
|
|
83
|
+
|
|
84
|
+
/** Proposal lifetime (should match governance.proposalLifetime) */
|
|
85
|
+
proposalLifetime: bigint;
|
|
86
|
+
|
|
87
|
+
/** Whether emergency veto is enabled */
|
|
88
|
+
emergencyVetoEnabled: boolean;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Stake threshold required for emergency veto.
|
|
92
|
+
* @example BigInt(75000) // 75K tokens for production
|
|
93
|
+
* @example BigInt(500) // 500 tokens for testing
|
|
94
|
+
*/
|
|
95
|
+
emergencyVetoThreshold: bigint;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Token configuration for governor deployment.
|
|
100
|
+
*/
|
|
101
|
+
export interface TokenConfig {
|
|
102
|
+
/**
|
|
103
|
+
* Token name.
|
|
104
|
+
* @example "Agora DAO Token"
|
|
105
|
+
*/
|
|
106
|
+
name: string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Token symbol.
|
|
110
|
+
* @example "AGORA"
|
|
111
|
+
*/
|
|
112
|
+
symbol: string;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Number of decimal places for token.
|
|
116
|
+
* @example BigInt(18) // Standard ERC20
|
|
117
|
+
* @example BigInt(6) // USDC-like
|
|
118
|
+
*/
|
|
119
|
+
decimals: bigint;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Complete deployment configuration for governor contract.
|
|
124
|
+
*/
|
|
125
|
+
export interface DeploymentConfig {
|
|
126
|
+
/** Governor configuration */
|
|
127
|
+
governor: GovernorConfig;
|
|
128
|
+
|
|
129
|
+
/** Token configuration */
|
|
130
|
+
token: TokenConfig;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Admin key for the contract (32 bytes).
|
|
134
|
+
*
|
|
135
|
+
* @remarks
|
|
136
|
+
* SECURITY: This should be generated securely and stored safely.
|
|
137
|
+
* Never use predictable or hardcoded admin keys in production.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* import { randomBytes } from '@midnight-ntwrk/midnight-js-utils';
|
|
142
|
+
* const adminKey = randomBytes(32);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
adminKey: Uint8Array;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Vote choice enumeration.
|
|
150
|
+
*/
|
|
151
|
+
export enum VoteChoice {
|
|
152
|
+
/** Vote in favor of the proposal */
|
|
153
|
+
For = 0,
|
|
154
|
+
|
|
155
|
+
/** Vote against the proposal */
|
|
156
|
+
Against = 1,
|
|
157
|
+
|
|
158
|
+
/** Abstain from voting */
|
|
159
|
+
Abstain = 2
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Proposal action type.
|
|
164
|
+
*/
|
|
165
|
+
export interface ProposalAction {
|
|
166
|
+
/** Action type identifier */
|
|
167
|
+
typ: number;
|
|
168
|
+
|
|
169
|
+
/** Token address for transfer actions */
|
|
170
|
+
token: Uint8Array;
|
|
171
|
+
|
|
172
|
+
/** Amount for transfer actions */
|
|
173
|
+
amount: bigint;
|
|
174
|
+
|
|
175
|
+
/** Recipient address for transfer actions */
|
|
176
|
+
to: Uint8Array;
|
|
177
|
+
|
|
178
|
+
/** Configuration key for config update actions */
|
|
179
|
+
configKey: Uint8Array;
|
|
180
|
+
|
|
181
|
+
/** Configuration value for config update actions */
|
|
182
|
+
configValue: Uint8Array;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Stake information for a user.
|
|
187
|
+
*/
|
|
188
|
+
export interface StakeInfo {
|
|
189
|
+
/** Amount of tokens staked */
|
|
190
|
+
stakedAmount: bigint;
|
|
191
|
+
|
|
192
|
+
/** Address to which stake is delegated */
|
|
193
|
+
delegatedTo: Uint8Array;
|
|
194
|
+
|
|
195
|
+
/** Timestamp when stake was registered */
|
|
196
|
+
stakedAt: bigint;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Proposal status enumeration.
|
|
201
|
+
*/
|
|
202
|
+
export enum ProposalStatus {
|
|
203
|
+
/** Proposal is pending and not yet active */
|
|
204
|
+
Pending = 0,
|
|
205
|
+
|
|
206
|
+
/** Proposal is active and accepting votes */
|
|
207
|
+
Active = 1,
|
|
208
|
+
|
|
209
|
+
/** Proposal voting period has ended, needs finalization */
|
|
210
|
+
Succeeded = 2,
|
|
211
|
+
|
|
212
|
+
/** Proposal was defeated */
|
|
213
|
+
Defeated = 3,
|
|
214
|
+
|
|
215
|
+
/** Proposal is queued for execution */
|
|
216
|
+
Queued = 4,
|
|
217
|
+
|
|
218
|
+
/** Proposal has been executed */
|
|
219
|
+
Executed = 5,
|
|
220
|
+
|
|
221
|
+
/** Proposal has expired */
|
|
222
|
+
Expired = 6,
|
|
223
|
+
|
|
224
|
+
/** Proposal was canceled */
|
|
225
|
+
Canceled = 7
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Detailed proposal information.
|
|
230
|
+
*/
|
|
231
|
+
export interface ProposalDetails {
|
|
232
|
+
/** Unique proposal identifier */
|
|
233
|
+
id: bigint;
|
|
234
|
+
|
|
235
|
+
/** Current proposal status */
|
|
236
|
+
status: ProposalStatus;
|
|
237
|
+
|
|
238
|
+
/** Timestamp when voting started */
|
|
239
|
+
votingStartTime: bigint;
|
|
240
|
+
|
|
241
|
+
/** Timestamp when voting ends */
|
|
242
|
+
votingEndTime: bigint;
|
|
243
|
+
|
|
244
|
+
/** Address of proposal creator */
|
|
245
|
+
creator: Uint8Array;
|
|
246
|
+
|
|
247
|
+
/** Number of votes in favor */
|
|
248
|
+
votesFor: bigint;
|
|
249
|
+
|
|
250
|
+
/** Number of votes against */
|
|
251
|
+
votesAgainst: bigint;
|
|
252
|
+
|
|
253
|
+
/** Number of abstain votes */
|
|
254
|
+
votesAbstain: bigint;
|
|
255
|
+
|
|
256
|
+
/** Associated effect ID */
|
|
257
|
+
effectId: bigint;
|
|
258
|
+
|
|
259
|
+
/** Proposal title */
|
|
260
|
+
title: string;
|
|
261
|
+
|
|
262
|
+
/** Proposal description */
|
|
263
|
+
description: string;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Effect details for a proposal.
|
|
268
|
+
*/
|
|
269
|
+
export interface EffectDetails {
|
|
270
|
+
/** Effect identifier */
|
|
271
|
+
id: bigint;
|
|
272
|
+
|
|
273
|
+
/** Associated proposal ID */
|
|
274
|
+
proposalId: bigint;
|
|
275
|
+
|
|
276
|
+
/** Effect status */
|
|
277
|
+
status: number;
|
|
278
|
+
|
|
279
|
+
/** Actions to be executed */
|
|
280
|
+
actions: ProposalAction[];
|
|
281
|
+
|
|
282
|
+
/** Timestamp when effect was created */
|
|
283
|
+
createdAt: bigint;
|
|
284
|
+
|
|
285
|
+
/** Timestamp when effect can be executed */
|
|
286
|
+
executableAt: bigint;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Vote count information for a proposal.
|
|
291
|
+
*/
|
|
292
|
+
export interface VoteCount {
|
|
293
|
+
/** Number of votes in favor */
|
|
294
|
+
votesFor: bigint;
|
|
295
|
+
|
|
296
|
+
/** Number of votes against */
|
|
297
|
+
votesAgainst: bigint;
|
|
298
|
+
|
|
299
|
+
/** Number of abstain votes */
|
|
300
|
+
votesAbstain: bigint;
|
|
301
|
+
|
|
302
|
+
/** Total number of votes cast */
|
|
303
|
+
totalVotes: bigint;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Governor contract status.
|
|
308
|
+
*/
|
|
309
|
+
export interface GovernorStatus {
|
|
310
|
+
/** Whether the governor is active */
|
|
311
|
+
isActive: boolean;
|
|
312
|
+
|
|
313
|
+
/** Number of active proposals */
|
|
314
|
+
activeProposalCount: bigint;
|
|
315
|
+
|
|
316
|
+
/** Number of queued proposals */
|
|
317
|
+
queuedProposalCount: bigint;
|
|
318
|
+
|
|
319
|
+
/** Current contract time */
|
|
320
|
+
currentTime: bigint;
|
|
321
|
+
|
|
322
|
+
/** Treasury balance */
|
|
323
|
+
treasuryBalance: bigint;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Governor value display information.
|
|
328
|
+
*/
|
|
329
|
+
export interface GovernorValue {
|
|
330
|
+
/** Contract address */
|
|
331
|
+
contractAddress: string;
|
|
332
|
+
|
|
333
|
+
/** Number of active proposals */
|
|
334
|
+
activeProposals: bigint;
|
|
335
|
+
|
|
336
|
+
/** Number of queued proposals */
|
|
337
|
+
queuedProposals: bigint;
|
|
338
|
+
|
|
339
|
+
/** Treasury balance */
|
|
340
|
+
treasuryBalance: bigint;
|
|
341
|
+
|
|
342
|
+
/** Whether governor is active */
|
|
343
|
+
isActive: boolean;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Stake record information.
|
|
348
|
+
*/
|
|
349
|
+
export interface StakeRecord {
|
|
350
|
+
/** User address */
|
|
351
|
+
userId: Uint8Array;
|
|
352
|
+
|
|
353
|
+
/** Staked amount */
|
|
354
|
+
amount: bigint;
|
|
355
|
+
|
|
356
|
+
/** Delegated to address */
|
|
357
|
+
delegatedTo: Uint8Array;
|
|
358
|
+
|
|
359
|
+
/** Stake timestamp */
|
|
360
|
+
stakedAt: bigint;
|
|
361
|
+
|
|
362
|
+
/** Whether stake is locked */
|
|
363
|
+
isLocked: boolean;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Helper functions for creating production and testing configurations.
|
|
368
|
+
*/
|
|
369
|
+
export const ConfigPresets = {
|
|
370
|
+
/**
|
|
371
|
+
* Creates a production-ready governance configuration.
|
|
372
|
+
*
|
|
373
|
+
* @remarks
|
|
374
|
+
* Suitable for mainnet deployment with secure parameters.
|
|
375
|
+
*/
|
|
376
|
+
production: (): GovernanceConfig => ({
|
|
377
|
+
votingPeriod: BigInt(604800), // 7 days
|
|
378
|
+
quorumThreshold: BigInt(100000), // 100K tokens
|
|
379
|
+
proposalThreshold: BigInt(50000), // 50K tokens
|
|
380
|
+
proposalLifetime: BigInt(2592000), // 30 days
|
|
381
|
+
executionDelay: BigInt(172800), // 2 days
|
|
382
|
+
gracePeriod: BigInt(604800), // 7 days
|
|
383
|
+
minStakeAmount: BigInt(1000), // 1K tokens
|
|
384
|
+
stakingPeriod: BigInt(604800) // 7 days
|
|
385
|
+
}),
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Creates a testing governance configuration.
|
|
389
|
+
*
|
|
390
|
+
* @remarks
|
|
391
|
+
* Suitable for testnet/development with shorter periods.
|
|
392
|
+
*/
|
|
393
|
+
testing: (): GovernanceConfig => ({
|
|
394
|
+
votingPeriod: BigInt(300), // 5 minutes
|
|
395
|
+
quorumThreshold: BigInt(100), // 100 tokens
|
|
396
|
+
proposalThreshold: BigInt(100), // 100 tokens
|
|
397
|
+
proposalLifetime: BigInt(86400), // 1 day
|
|
398
|
+
executionDelay: BigInt(60), // 1 minute
|
|
399
|
+
gracePeriod: BigInt(300), // 5 minutes
|
|
400
|
+
minStakeAmount: BigInt(10), // 10 tokens
|
|
401
|
+
stakingPeriod: BigInt(60) // 1 minute
|
|
402
|
+
})
|
|
403
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides utility functions.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a buffer containing a series of randomly generated bytes.
|
|
9
|
+
*
|
|
10
|
+
* @param length The number of bytes to generate.
|
|
11
|
+
* @returns A `Uint8Array` representing `length` randomly generated bytes.
|
|
12
|
+
*/
|
|
13
|
+
export const randomBytes = (length: number): Uint8Array => {
|
|
14
|
+
const bytes = new Uint8Array(length);
|
|
15
|
+
crypto.getRandomValues(bytes);
|
|
16
|
+
return bytes;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Converts a wallet address string to a Uint8Array (32 bytes).
|
|
21
|
+
*
|
|
22
|
+
* @param address The wallet address string.
|
|
23
|
+
* @returns A 32-byte Uint8Array representation of the address.
|
|
24
|
+
*/
|
|
25
|
+
export const addressToBytes = (address: string): Uint8Array => {
|
|
26
|
+
const addressBytes = new Uint8Array(32);
|
|
27
|
+
const addressStr = address.replace(/[^0-9a-f]/gi, "");
|
|
28
|
+
const addressHex = addressStr.slice(-64);
|
|
29
|
+
for (let i = 0; i < Math.min(32, addressHex.length / 2); i++) {
|
|
30
|
+
addressBytes[i] = parseInt(addressHex.substr(i * 2, 2), 16);
|
|
31
|
+
}
|
|
32
|
+
return addressBytes;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Converts a Uint8Array to a hex string.
|
|
37
|
+
*
|
|
38
|
+
* @param bytes The bytes to convert.
|
|
39
|
+
* @returns Hex string representation.
|
|
40
|
+
*/
|
|
41
|
+
export const bytesToHex = (bytes: Uint8Array): string => {
|
|
42
|
+
return Array.from(bytes)
|
|
43
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
44
|
+
.join("");
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Converts a hex string to a Uint8Array.
|
|
49
|
+
*
|
|
50
|
+
* @param hex The hex string to convert.
|
|
51
|
+
* @returns Uint8Array representation.
|
|
52
|
+
*/
|
|
53
|
+
export const hexToBytes = (hex: string): Uint8Array => {
|
|
54
|
+
const cleanHex = hex.replace(/^0x/, "");
|
|
55
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
56
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
57
|
+
bytes[i] = parseInt(cleanHex.substr(i * 2, 2), 16);
|
|
58
|
+
}
|
|
59
|
+
return bytes;
|
|
60
|
+
};
|