qvtx-developer-kit 1.0.0 → 1.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.
Files changed (45) hide show
  1. package/.env.example +108 -0
  2. package/README.md +0 -0
  3. package/abis/QVTXBridge.json +273 -0
  4. package/abis/QVTXGovernance.json +267 -0
  5. package/abis/QVTXNFT.json +370 -0
  6. package/abis/QVTXRewards.json +155 -0
  7. package/abis/QVTXToken.json +311 -0
  8. package/abis/QVTXVesting.json +216 -0
  9. package/abis/index.js +15 -0
  10. package/bin/qvtx-developer-cli.js +99 -0
  11. package/config/index.js +108 -0
  12. package/config/networks.js +247 -0
  13. package/examples/basic-usage.js +39 -0
  14. package/examples/bridge-example.js +123 -0
  15. package/examples/governance-example.js +140 -0
  16. package/examples/nft-example.js +141 -0
  17. package/examples/staking-example.js +96 -0
  18. package/index.js +145 -0
  19. package/languages/blockchain_ai_sdk.js +0 -0
  20. package/languages/node_sdk.js +0 -0
  21. package/languages/solana_sdk.js +383 -0
  22. package/package.json +28 -3
  23. package/rewards/index.js +71 -0
  24. package/smart-contracts/QVTXBridge.sol +305 -0
  25. package/smart-contracts/QVTXGovernance.sol +325 -0
  26. package/smart-contracts/QVTXNFT.sol +338 -0
  27. package/smart-contracts/QVTXRewards.sol +102 -0
  28. package/smart-contracts/QVTXToken.sol +227 -0
  29. package/smart-contracts/QVTXVesting.sol +411 -0
  30. package/smart-contracts/interfaces/IERC20.sol +14 -0
  31. package/smart-contracts/interfaces/IERC20Metadata.sol +8 -0
  32. package/smart-contracts/interfaces/IERC721.sol +18 -0
  33. package/smart-contracts/interfaces/IERC721Metadata.sol +8 -0
  34. package/smart-contracts/interfaces/IERC721Receiver.sol +11 -0
  35. package/storage/index.js +112 -0
  36. package/templates/contract/ERC20Token.sol +116 -0
  37. package/templates/dapp/index.html +93 -0
  38. package/test/index.js +182 -0
  39. package/tools/build-tool.js +63 -0
  40. package/tools/create-template.js +116 -0
  41. package/tools/deploy-tool.js +55 -0
  42. package/tools/generate-docs.js +149 -0
  43. package/tools/init-project.js +138 -0
  44. package/tools/run-tests.js +64 -0
  45. package/types/index.d.ts +264 -0
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Configuration Module
5
+ * Central configuration management
6
+ */
7
+
8
+ const networks = require('./networks');
9
+ const path = require('path');
10
+ const fs = require('fs');
11
+
12
+ // Load environment variables from .env if exists
13
+ function loadEnv(envPath) {
14
+ const dotenvPath = envPath || path.join(process.cwd(), '.env');
15
+
16
+ if (fs.existsSync(dotenvPath)) {
17
+ const content = fs.readFileSync(dotenvPath, 'utf8');
18
+ const lines = content.split('\n');
19
+
20
+ for (const line of lines) {
21
+ const trimmed = line.trim();
22
+ if (trimmed && !trimmed.startsWith('#')) {
23
+ const [key, ...valueParts] = trimmed.split('=');
24
+ const value = valueParts.join('=').trim();
25
+ if (key && !process.env[key]) {
26
+ process.env[key] = value;
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ // Default configuration
34
+ const DEFAULT_CONFIG = {
35
+ network: 'ethereum',
36
+ environment: 'mainnet',
37
+ debug: false,
38
+ timeout: 30000,
39
+ retries: 3,
40
+ gasMultiplier: 1.2
41
+ };
42
+
43
+ // Get configuration value
44
+ function get(key, defaultValue) {
45
+ const envKey = `QVTX_${key.toUpperCase()}`;
46
+ return process.env[envKey] || defaultValue;
47
+ }
48
+
49
+ // Get private key (with validation)
50
+ function getPrivateKey() {
51
+ const key = process.env.PRIVATE_KEY;
52
+ if (!key) {
53
+ throw new Error('PRIVATE_KEY environment variable not set');
54
+ }
55
+ if (!key.startsWith('0x')) {
56
+ return '0x' + key;
57
+ }
58
+ return key;
59
+ }
60
+
61
+ // Get RPC URL for network
62
+ function getRpcUrl(network, environment) {
63
+ const envKey = `${network.toUpperCase()}_RPC`;
64
+ if (process.env[envKey]) {
65
+ return process.env[envKey];
66
+ }
67
+
68
+ const networkConfig = networks.getNetwork(network, environment);
69
+ let rpc = networkConfig.rpc;
70
+
71
+ // Replace API key placeholders
72
+ if (rpc.includes('${INFURA_API_KEY}') && process.env.INFURA_API_KEY) {
73
+ rpc = rpc.replace('${INFURA_API_KEY}', process.env.INFURA_API_KEY);
74
+ }
75
+ if (rpc.includes('${ALCHEMY_API_KEY}') && process.env.ALCHEMY_API_KEY) {
76
+ rpc = rpc.replace('${ALCHEMY_API_KEY}', process.env.ALCHEMY_API_KEY);
77
+ }
78
+
79
+ return rpc;
80
+ }
81
+
82
+ // Get contract address
83
+ function getContractAddress(contractName, network = 'ethereum') {
84
+ const envKey = `QVTX_${contractName.toUpperCase()}_${network.toUpperCase()}`;
85
+ return process.env[envKey] || null;
86
+ }
87
+
88
+ // Create configuration object
89
+ function createConfig(options = {}) {
90
+ return {
91
+ ...DEFAULT_CONFIG,
92
+ ...options,
93
+ getPrivateKey,
94
+ getRpcUrl: (net, env) => getRpcUrl(net || options.network, env || options.environment),
95
+ getContractAddress
96
+ };
97
+ }
98
+
99
+ module.exports = {
100
+ loadEnv,
101
+ get,
102
+ getPrivateKey,
103
+ getRpcUrl,
104
+ getContractAddress,
105
+ createConfig,
106
+ DEFAULT_CONFIG,
107
+ ...networks
108
+ };
@@ -0,0 +1,247 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Network Configurations
5
+ * Supported blockchain networks and their settings
6
+ */
7
+
8
+ const NETWORKS = {
9
+ // Ethereum
10
+ ethereum: {
11
+ mainnet: {
12
+ chainId: 1,
13
+ name: 'Ethereum Mainnet',
14
+ rpc: 'https://eth.llamarpc.com',
15
+ rpcAlternatives: [
16
+ 'https://mainnet.infura.io/v3/${INFURA_API_KEY}',
17
+ 'https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}',
18
+ 'https://cloudflare-eth.com'
19
+ ],
20
+ nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
21
+ blockExplorer: 'https://etherscan.io',
22
+ avgBlockTime: 12
23
+ },
24
+ goerli: {
25
+ chainId: 5,
26
+ name: 'Goerli Testnet',
27
+ rpc: 'https://goerli.infura.io/v3/${INFURA_API_KEY}',
28
+ nativeCurrency: { name: 'Goerli Ether', symbol: 'ETH', decimals: 18 },
29
+ blockExplorer: 'https://goerli.etherscan.io',
30
+ faucet: 'https://goerlifaucet.com',
31
+ avgBlockTime: 12
32
+ },
33
+ sepolia: {
34
+ chainId: 11155111,
35
+ name: 'Sepolia Testnet',
36
+ rpc: 'https://sepolia.infura.io/v3/${INFURA_API_KEY}',
37
+ nativeCurrency: { name: 'Sepolia Ether', symbol: 'ETH', decimals: 18 },
38
+ blockExplorer: 'https://sepolia.etherscan.io',
39
+ faucet: 'https://sepoliafaucet.com',
40
+ avgBlockTime: 12
41
+ }
42
+ },
43
+
44
+ // BNB Smart Chain
45
+ bsc: {
46
+ mainnet: {
47
+ chainId: 56,
48
+ name: 'BNB Smart Chain',
49
+ rpc: 'https://bsc-dataseed.binance.org/',
50
+ rpcAlternatives: [
51
+ 'https://bsc-dataseed1.defibit.io/',
52
+ 'https://bsc-dataseed1.ninicoin.io/'
53
+ ],
54
+ nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 },
55
+ blockExplorer: 'https://bscscan.com',
56
+ avgBlockTime: 3
57
+ },
58
+ testnet: {
59
+ chainId: 97,
60
+ name: 'BSC Testnet',
61
+ rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545/',
62
+ nativeCurrency: { name: 'Test BNB', symbol: 'tBNB', decimals: 18 },
63
+ blockExplorer: 'https://testnet.bscscan.com',
64
+ faucet: 'https://testnet.binance.org/faucet-smart',
65
+ avgBlockTime: 3
66
+ }
67
+ },
68
+
69
+ // Polygon
70
+ polygon: {
71
+ mainnet: {
72
+ chainId: 137,
73
+ name: 'Polygon Mainnet',
74
+ rpc: 'https://polygon-rpc.com/',
75
+ rpcAlternatives: [
76
+ 'https://rpc-mainnet.maticvigil.com/',
77
+ 'https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}'
78
+ ],
79
+ nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
80
+ blockExplorer: 'https://polygonscan.com',
81
+ avgBlockTime: 2
82
+ },
83
+ mumbai: {
84
+ chainId: 80001,
85
+ name: 'Mumbai Testnet',
86
+ rpc: 'https://rpc-mumbai.maticvigil.com/',
87
+ nativeCurrency: { name: 'Test MATIC', symbol: 'MATIC', decimals: 18 },
88
+ blockExplorer: 'https://mumbai.polygonscan.com',
89
+ faucet: 'https://faucet.polygon.technology/',
90
+ avgBlockTime: 2
91
+ }
92
+ },
93
+
94
+ // Arbitrum
95
+ arbitrum: {
96
+ mainnet: {
97
+ chainId: 42161,
98
+ name: 'Arbitrum One',
99
+ rpc: 'https://arb1.arbitrum.io/rpc',
100
+ rpcAlternatives: [
101
+ 'https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}'
102
+ ],
103
+ nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
104
+ blockExplorer: 'https://arbiscan.io',
105
+ avgBlockTime: 0.25
106
+ },
107
+ goerli: {
108
+ chainId: 421613,
109
+ name: 'Arbitrum Goerli',
110
+ rpc: 'https://goerli-rollup.arbitrum.io/rpc',
111
+ nativeCurrency: { name: 'Goerli Ether', symbol: 'ETH', decimals: 18 },
112
+ blockExplorer: 'https://goerli.arbiscan.io',
113
+ faucet: 'https://faucet.arbitrum.io/',
114
+ avgBlockTime: 0.25
115
+ }
116
+ },
117
+
118
+ // Avalanche
119
+ avalanche: {
120
+ mainnet: {
121
+ chainId: 43114,
122
+ name: 'Avalanche C-Chain',
123
+ rpc: 'https://api.avax.network/ext/bc/C/rpc',
124
+ rpcAlternatives: [
125
+ 'https://avalanche-mainnet.infura.io/v3/${INFURA_API_KEY}'
126
+ ],
127
+ nativeCurrency: { name: 'AVAX', symbol: 'AVAX', decimals: 18 },
128
+ blockExplorer: 'https://snowtrace.io',
129
+ avgBlockTime: 2
130
+ },
131
+ fuji: {
132
+ chainId: 43113,
133
+ name: 'Avalanche Fuji',
134
+ rpc: 'https://api.avax-test.network/ext/bc/C/rpc',
135
+ nativeCurrency: { name: 'Test AVAX', symbol: 'AVAX', decimals: 18 },
136
+ blockExplorer: 'https://testnet.snowtrace.io',
137
+ faucet: 'https://faucet.avax.network/',
138
+ avgBlockTime: 2
139
+ }
140
+ },
141
+
142
+ // Optimism
143
+ optimism: {
144
+ mainnet: {
145
+ chainId: 10,
146
+ name: 'Optimism',
147
+ rpc: 'https://mainnet.optimism.io',
148
+ rpcAlternatives: [
149
+ 'https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}'
150
+ ],
151
+ nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
152
+ blockExplorer: 'https://optimistic.etherscan.io',
153
+ avgBlockTime: 2
154
+ },
155
+ goerli: {
156
+ chainId: 420,
157
+ name: 'Optimism Goerli',
158
+ rpc: 'https://goerli.optimism.io',
159
+ nativeCurrency: { name: 'Goerli Ether', symbol: 'ETH', decimals: 18 },
160
+ blockExplorer: 'https://goerli-optimism.etherscan.io',
161
+ avgBlockTime: 2
162
+ }
163
+ },
164
+
165
+ // Solana (different structure)
166
+ solana: {
167
+ 'mainnet-beta': {
168
+ name: 'Solana Mainnet',
169
+ rpc: 'https://api.mainnet-beta.solana.com',
170
+ rpcAlternatives: [
171
+ 'https://solana-api.projectserum.com'
172
+ ],
173
+ blockExplorer: 'https://explorer.solana.com'
174
+ },
175
+ devnet: {
176
+ name: 'Solana Devnet',
177
+ rpc: 'https://api.devnet.solana.com',
178
+ blockExplorer: 'https://explorer.solana.com?cluster=devnet',
179
+ faucet: 'https://solfaucet.com/'
180
+ },
181
+ testnet: {
182
+ name: 'Solana Testnet',
183
+ rpc: 'https://api.testnet.solana.com',
184
+ blockExplorer: 'https://explorer.solana.com?cluster=testnet'
185
+ }
186
+ }
187
+ };
188
+
189
+ // Helper functions
190
+ function getNetwork(name, environment = 'mainnet') {
191
+ const network = NETWORKS[name.toLowerCase()];
192
+ if (!network) {
193
+ throw new Error(`Unknown network: ${name}`);
194
+ }
195
+ const env = network[environment];
196
+ if (!env) {
197
+ throw new Error(`Unknown environment: ${environment} for network ${name}`);
198
+ }
199
+ return env;
200
+ }
201
+
202
+ function getChainById(chainId) {
203
+ for (const [networkName, envs] of Object.entries(NETWORKS)) {
204
+ for (const [envName, config] of Object.entries(envs)) {
205
+ if (config.chainId === chainId) {
206
+ return { network: networkName, environment: envName, ...config };
207
+ }
208
+ }
209
+ }
210
+ return null;
211
+ }
212
+
213
+ function getAllNetworks() {
214
+ return NETWORKS;
215
+ }
216
+
217
+ function getMainnets() {
218
+ const mainnets = {};
219
+ for (const [name, envs] of Object.entries(NETWORKS)) {
220
+ if (envs.mainnet || envs['mainnet-beta']) {
221
+ mainnets[name] = envs.mainnet || envs['mainnet-beta'];
222
+ }
223
+ }
224
+ return mainnets;
225
+ }
226
+
227
+ function getTestnets() {
228
+ const testnets = {};
229
+ for (const [name, envs] of Object.entries(NETWORKS)) {
230
+ for (const [envName, config] of Object.entries(envs)) {
231
+ if (envName !== 'mainnet' && envName !== 'mainnet-beta') {
232
+ if (!testnets[name]) testnets[name] = {};
233
+ testnets[name][envName] = config;
234
+ }
235
+ }
236
+ }
237
+ return testnets;
238
+ }
239
+
240
+ module.exports = {
241
+ NETWORKS,
242
+ getNetwork,
243
+ getChainById,
244
+ getAllNetworks,
245
+ getMainnets,
246
+ getTestnets
247
+ };
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Developer Kit - Basic Usage Example
5
+ */
6
+
7
+ const QVTX = require('qvtx-developer-kit');
8
+
9
+ async function main() {
10
+ // Initialize the SDK
11
+ const kit = new QVTX({
12
+ network: 'ethereum',
13
+ environment: 'mainnet'
14
+ });
15
+
16
+ console.log('QVTX Developer Kit v' + kit.getVersion());
17
+ console.log('Validator ID:', kit.validatorId);
18
+
19
+ // Display supported networks
20
+ console.log('\nSupported Networks:');
21
+ const networks = kit.getNetworks();
22
+ Object.entries(networks).forEach(([name, envs]) => {
23
+ console.log(` ${name}: ${Object.keys(envs).join(', ')}`);
24
+ });
25
+
26
+ // Display token info
27
+ console.log('\nQVTX Token Info:');
28
+ const tokenInfo = kit.getTokenInfo();
29
+ console.log(` Name: ${tokenInfo.name}`);
30
+ console.log(` Symbol: ${tokenInfo.symbol}`);
31
+ console.log(` Decimals: ${tokenInfo.decimals}`);
32
+
33
+ // Initialize Web3 (requires Infura API key)
34
+ // const web3 = await kit.initWeb3('https://mainnet.infura.io/v3/YOUR_API_KEY');
35
+ // const blockNumber = await web3.eth.getBlockNumber();
36
+ // console.log('\nCurrent block:', blockNumber);
37
+ }
38
+
39
+ main().catch(console.error);
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Cross-Chain Bridge Example
5
+ * Demonstrates how to bridge QVTX tokens between chains
6
+ */
7
+
8
+ const QVTX = require('qvtx-developer-kit');
9
+ const { QVTXBridge: BridgeABI, QVTXToken: TokenABI } = require('qvtx-developer-kit/abis');
10
+
11
+ // Configuration
12
+ const CONFIG = {
13
+ PRIVATE_KEY: process.env.PRIVATE_KEY || 'your-private-key-here',
14
+
15
+ // Source chain (Ethereum)
16
+ SOURCE_RPC: process.env.SOURCE_RPC || 'https://mainnet.infura.io/v3/YOUR_KEY',
17
+ SOURCE_BRIDGE: process.env.SOURCE_BRIDGE || '0x...', // Bridge contract on Ethereum
18
+ SOURCE_TOKEN: process.env.SOURCE_TOKEN || '0x...', // QVTX token on Ethereum
19
+
20
+ // Target chain (BSC)
21
+ TARGET_CHAIN_ID: 56,
22
+ TARGET_RPC: process.env.TARGET_RPC || 'https://bsc-dataseed.binance.org/',
23
+ TARGET_BRIDGE: process.env.TARGET_BRIDGE || '0x...', // Bridge contract on BSC
24
+ };
25
+
26
+ async function main() {
27
+ console.log('QVTX Cross-Chain Bridge Example\n');
28
+ console.log('================================\n');
29
+
30
+ // Initialize SDK
31
+ const kit = new QVTX({
32
+ network: 'ethereum',
33
+ environment: 'mainnet'
34
+ });
35
+
36
+ // Initialize Web3 for source chain
37
+ const web3 = await kit.initWeb3(CONFIG.SOURCE_RPC);
38
+ const account = web3.eth.accounts.privateKeyToAccount(CONFIG.PRIVATE_KEY);
39
+ web3.eth.accounts.wallet.add(account);
40
+
41
+ console.log('Wallet Address:', account.address);
42
+ console.log('Source Chain: Ethereum');
43
+ console.log('Target Chain: BSC (Chain ID:', CONFIG.TARGET_CHAIN_ID, ')');
44
+
45
+ // Initialize contracts
46
+ const bridgeContract = new web3.eth.Contract(BridgeABI.abi, CONFIG.SOURCE_BRIDGE);
47
+ const tokenContract = new web3.eth.Contract(TokenABI.abi, CONFIG.SOURCE_TOKEN);
48
+
49
+ // Check token balance
50
+ const balance = await tokenContract.methods.balanceOf(account.address).call();
51
+ console.log('\nQVTX Balance:', web3.utils.fromWei(balance, 'ether'), 'QVTX');
52
+
53
+ // Check bridge configuration
54
+ const bridgeFee = await bridgeContract.methods.bridgeFee().call();
55
+ const minAmount = await bridgeContract.methods.minBridgeAmount().call();
56
+ const maxAmount = await bridgeContract.methods.maxBridgeAmount().call();
57
+ const isTargetSupported = await bridgeContract.methods.isChainSupported(CONFIG.TARGET_CHAIN_ID).call();
58
+
59
+ console.log('\n--- Bridge Configuration ---');
60
+ console.log('Bridge Fee:', web3.utils.fromWei(bridgeFee, 'ether'), 'ETH');
61
+ console.log('Min Bridge Amount:', web3.utils.fromWei(minAmount, 'ether'), 'QVTX');
62
+ console.log('Max Bridge Amount:', web3.utils.fromWei(maxAmount, 'ether'), 'QVTX');
63
+ console.log('Target Chain Supported:', isTargetSupported);
64
+
65
+ // Check if bridge is paused
66
+ const isPaused = await bridgeContract.methods.paused().call();
67
+ if (isPaused) {
68
+ console.log('\nWARNING: Bridge is currently paused!');
69
+ return;
70
+ }
71
+
72
+ console.log('\n--- Bridge Operations ---\n');
73
+
74
+ // Example: Bridge tokens (uncomment to use)
75
+ /*
76
+ const bridgeAmount = web3.utils.toWei('100', 'ether'); // 100 QVTX
77
+ const recipient = account.address; // Same address on target chain
78
+
79
+ console.log('Bridging', web3.utils.fromWei(bridgeAmount, 'ether'), 'QVTX to BSC...');
80
+
81
+ // Step 1: Approve bridge contract to spend tokens
82
+ console.log('Step 1: Approving tokens...');
83
+ const approveTx = await tokenContract.methods.approve(CONFIG.SOURCE_BRIDGE, bridgeAmount)
84
+ .send({ from: account.address, gas: 100000 });
85
+ console.log('Approve TX:', approveTx.transactionHash);
86
+
87
+ // Step 2: Initiate bridge
88
+ console.log('Step 2: Initiating bridge transfer...');
89
+ const bridgeTx = await bridgeContract.methods.bridge(
90
+ recipient,
91
+ bridgeAmount,
92
+ CONFIG.TARGET_CHAIN_ID
93
+ ).send({
94
+ from: account.address,
95
+ value: bridgeFee,
96
+ gas: 200000
97
+ });
98
+
99
+ console.log('Bridge TX:', bridgeTx.transactionHash);
100
+
101
+ // Get request ID from event
102
+ const requestId = bridgeTx.events.BridgeInitiated.returnValues.requestId;
103
+ console.log('Bridge Request ID:', requestId);
104
+ console.log('\nTokens are being bridged. They will appear on BSC within 5-15 minutes.');
105
+ */
106
+
107
+ // Check bridge history
108
+ const userRequests = await bridgeContract.methods.getUserBridgeRequests(account.address).call();
109
+ console.log('Your Bridge Requests:', userRequests.length);
110
+
111
+ if (userRequests.length > 0) {
112
+ console.log('\nRecent Bridge Requests:');
113
+ for (const requestId of userRequests.slice(-5)) {
114
+ const request = await bridgeContract.methods.getBridgeRequest(requestId).call();
115
+ const statusMap = ['Pending', 'Completed', 'Refunded', 'Failed'];
116
+ console.log(` #${requestId}: ${web3.utils.fromWei(request.amount, 'ether')} QVTX - ${statusMap[request.status]}`);
117
+ }
118
+ }
119
+
120
+ console.log('\nBridge example completed!');
121
+ }
122
+
123
+ main().catch(console.error);
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Governance Example
5
+ * Demonstrates how to create proposals and vote
6
+ */
7
+
8
+ const QVTX = require('qvtx-developer-kit');
9
+ const { QVTXGovernance: GovernanceABI, QVTXToken: TokenABI } = require('qvtx-developer-kit/abis');
10
+
11
+ // Configuration
12
+ const CONFIG = {
13
+ PRIVATE_KEY: process.env.PRIVATE_KEY || 'your-private-key-here',
14
+ RPC_URL: process.env.RPC_URL || 'https://mainnet.infura.io/v3/YOUR_KEY',
15
+ GOVERNANCE_CONTRACT: process.env.GOVERNANCE_CONTRACT || '0x...',
16
+ TOKEN_CONTRACT: process.env.TOKEN_CONTRACT || '0x...'
17
+ };
18
+
19
+ async function main() {
20
+ console.log('QVTX Governance Example\n');
21
+ console.log('=======================\n');
22
+
23
+ // Initialize SDK
24
+ const kit = new QVTX({
25
+ network: 'ethereum',
26
+ environment: 'mainnet'
27
+ });
28
+
29
+ // Initialize Web3
30
+ const web3 = await kit.initWeb3(CONFIG.RPC_URL);
31
+ const account = web3.eth.accounts.privateKeyToAccount(CONFIG.PRIVATE_KEY);
32
+ web3.eth.accounts.wallet.add(account);
33
+
34
+ console.log('Wallet Address:', account.address);
35
+
36
+ // Initialize contracts
37
+ const governance = new web3.eth.Contract(GovernanceABI.abi, CONFIG.GOVERNANCE_CONTRACT);
38
+ const token = new web3.eth.Contract(TokenABI.abi, CONFIG.TOKEN_CONTRACT);
39
+
40
+ // Check voting power (token balance)
41
+ const balance = await token.methods.balanceOf(account.address).call();
42
+ console.log('QVTX Balance (Voting Power):', web3.utils.fromWei(balance, 'ether'), 'QVTX');
43
+
44
+ // Get governance parameters
45
+ const proposalThreshold = await governance.methods.proposalThreshold().call();
46
+ const quorumVotes = await governance.methods.quorumVotes().call();
47
+ const votingPeriod = await governance.methods.votingPeriod().call();
48
+ const timelockDelay = await governance.methods.timelockDelay().call();
49
+ const proposalCount = await governance.methods.proposalCount().call();
50
+
51
+ console.log('\n--- Governance Parameters ---');
52
+ console.log('Proposal Threshold:', web3.utils.fromWei(proposalThreshold, 'ether'), 'QVTX');
53
+ console.log('Quorum Required:', web3.utils.fromWei(quorumVotes, 'ether'), 'QVTX');
54
+ console.log('Voting Period:', votingPeriod, 'blocks (~', Math.round(votingPeriod * 15 / 86400), 'days)');
55
+ console.log('Timelock Delay:', timelockDelay, 'seconds (~', Math.round(timelockDelay / 86400), 'days)');
56
+ console.log('Total Proposals:', proposalCount);
57
+
58
+ // Check if user can propose
59
+ const canPropose = BigInt(balance) >= BigInt(proposalThreshold);
60
+ console.log('\nCan Create Proposals:', canPropose ? 'Yes' : 'No (need more QVTX)');
61
+
62
+ console.log('\n--- Governance Operations ---\n');
63
+
64
+ // Example: Create proposal (uncomment to use)
65
+ /*
66
+ if (!canPropose) {
67
+ console.log('Insufficient QVTX to create proposal');
68
+ return;
69
+ }
70
+
71
+ const proposalTitle = 'Increase Staking Rewards';
72
+ const proposalDescription = 'This proposal increases the staking reward rate from 100 to 150 tokens per block to incentivize more participation.';
73
+ const targetContract = CONFIG.GOVERNANCE_CONTRACT; // Or any contract to call
74
+ const value = 0; // ETH to send
75
+ const callData = '0x'; // Encoded function call
76
+
77
+ console.log('Creating proposal:', proposalTitle);
78
+
79
+ const proposeTx = await governance.methods.propose(
80
+ proposalTitle,
81
+ proposalDescription,
82
+ targetContract,
83
+ value,
84
+ callData
85
+ ).send({
86
+ from: account.address,
87
+ gas: 500000
88
+ });
89
+
90
+ const proposalId = proposeTx.events.ProposalCreated.returnValues.id;
91
+ console.log('Proposal Created! ID:', proposalId);
92
+ console.log('TX:', proposeTx.transactionHash);
93
+ */
94
+
95
+ // Example: Vote on proposal (uncomment to use)
96
+ /*
97
+ const proposalIdToVote = 1; // Replace with actual proposal ID
98
+ const support = 1; // 0 = Against, 1 = For, 2 = Abstain
99
+ const reason = 'I support increasing rewards to grow the ecosystem.';
100
+
101
+ // Check proposal state first
102
+ const state = await governance.methods.getProposalState(proposalIdToVote).call();
103
+ const stateNames = ['Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'];
104
+ console.log('Proposal State:', stateNames[state]);
105
+
106
+ if (state == 1) { // Active
107
+ console.log('Voting on proposal', proposalIdToVote, '...');
108
+
109
+ const voteTx = await governance.methods.castVoteWithReason(
110
+ proposalIdToVote,
111
+ support,
112
+ reason
113
+ ).send({
114
+ from: account.address,
115
+ gas: 200000
116
+ });
117
+
118
+ console.log('Vote Cast! TX:', voteTx.transactionHash);
119
+ }
120
+ */
121
+
122
+ // View recent proposals
123
+ if (proposalCount > 0) {
124
+ console.log('Recent Proposals:\n');
125
+ const stateNames = ['Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'];
126
+
127
+ const startId = Math.max(1, proposalCount - 4);
128
+ for (let i = startId; i <= proposalCount; i++) {
129
+ const proposal = await governance.methods.getProposal(i).call();
130
+ console.log(` #${proposal.id}: ${proposal.title}`);
131
+ console.log(` State: ${stateNames[proposal.state]}`);
132
+ console.log(` For: ${web3.utils.fromWei(proposal.forVotes, 'ether')} | Against: ${web3.utils.fromWei(proposal.againstVotes, 'ether')} | Abstain: ${web3.utils.fromWei(proposal.abstainVotes, 'ether')}`);
133
+ console.log('');
134
+ }
135
+ }
136
+
137
+ console.log('Governance example completed!');
138
+ }
139
+
140
+ main().catch(console.error);