qvtx-developer-kit 1.0.0 → 1.2.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/.env.example +108 -0
- package/README.md +0 -0
- package/abis/QVTXBridge.json +273 -0
- package/abis/QVTXDirectPurchase.json +621 -0
- package/abis/QVTXGovernance.json +267 -0
- package/abis/QVTXNFT.json +370 -0
- package/abis/QVTXRewards.json +155 -0
- package/abis/QVTXToken.json +311 -0
- package/abis/QVTXVesting.json +216 -0
- package/abis/index.js +16 -0
- package/bin/qvtx-developer-cli.js +99 -0
- package/config/index.js +108 -0
- package/config/networks.js +247 -0
- package/examples/basic-usage.js +39 -0
- package/examples/bridge-example.js +123 -0
- package/examples/direct-purchase.js +300 -0
- package/examples/governance-example.js +140 -0
- package/examples/nft-example.js +141 -0
- package/examples/staking-example.js +96 -0
- package/index.js +145 -0
- package/languages/blockchain_ai_sdk.js +0 -0
- package/languages/node_sdk.js +0 -0
- package/languages/solana_sdk.js +383 -0
- package/package.json +30 -3
- package/purchase/index.js +567 -0
- package/rewards/index.js +71 -0
- package/smart-contracts/QVTXBridge.sol +305 -0
- package/smart-contracts/QVTXDirectPurchase.sol +543 -0
- package/smart-contracts/QVTXGovernance.sol +325 -0
- package/smart-contracts/QVTXNFT.sol +338 -0
- package/smart-contracts/QVTXRewards.sol +102 -0
- package/smart-contracts/QVTXToken.sol +227 -0
- package/smart-contracts/QVTXVesting.sol +411 -0
- package/smart-contracts/interfaces/IERC20.sol +14 -0
- package/smart-contracts/interfaces/IERC20Metadata.sol +8 -0
- package/smart-contracts/interfaces/IERC721.sol +18 -0
- package/smart-contracts/interfaces/IERC721Metadata.sol +8 -0
- package/smart-contracts/interfaces/IERC721Receiver.sol +11 -0
- package/storage/index.js +112 -0
- package/templates/contract/ERC20Token.sol +116 -0
- package/templates/dapp/index.html +93 -0
- package/test/index.js +182 -0
- package/tools/build-tool.js +63 -0
- package/tools/create-template.js +116 -0
- package/tools/deploy-tool.js +55 -0
- package/tools/generate-docs.js +149 -0
- package/tools/init-project.js +138 -0
- package/tools/run-tests.js +64 -0
- package/types/index.d.ts +386 -0
|
@@ -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,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QVTX Direct Purchase Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to use the QVTXDirectPurchase SDK
|
|
5
|
+
* to buy QVTX tokens directly from the ecosystem.
|
|
6
|
+
*
|
|
7
|
+
* Features shown:
|
|
8
|
+
* - Getting pricing information
|
|
9
|
+
* - Calculating costs
|
|
10
|
+
* - Purchasing with native currency (ETH/BNB/MATIC)
|
|
11
|
+
* - Purchasing with stablecoins (USDT/USDC)
|
|
12
|
+
* - Using referral codes for discounts
|
|
13
|
+
* - Managing vested tokens
|
|
14
|
+
* - Generating referral links
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { createDirectPurchase, STABLECOINS } = require('qvtx-developer-kit/purchase');
|
|
18
|
+
require('dotenv').config();
|
|
19
|
+
|
|
20
|
+
// Configuration
|
|
21
|
+
const CONFIG = {
|
|
22
|
+
// Replace with actual deployed contract address
|
|
23
|
+
purchaseContract: process.env.QVTX_PURCHASE_CONTRACT || '0x...',
|
|
24
|
+
|
|
25
|
+
// BSC Mainnet RPC
|
|
26
|
+
rpcUrl: process.env.BSC_RPC || 'https://bsc-dataseed.binance.org/',
|
|
27
|
+
|
|
28
|
+
// Your private key (NEVER commit this!)
|
|
29
|
+
privateKey: process.env.PRIVATE_KEY,
|
|
30
|
+
|
|
31
|
+
// QVTX Token on BSC
|
|
32
|
+
qvtxToken: '0x5ad163056FC308C5ab88bf9295EAA2C16F3db400'
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
async function main() {
|
|
36
|
+
console.log('='.repeat(60));
|
|
37
|
+
console.log('QVTX Direct Purchase Example');
|
|
38
|
+
console.log('='.repeat(60));
|
|
39
|
+
|
|
40
|
+
// Initialize the SDK
|
|
41
|
+
const purchase = createDirectPurchase({
|
|
42
|
+
provider: CONFIG.rpcUrl,
|
|
43
|
+
contractAddress: CONFIG.purchaseContract,
|
|
44
|
+
privateKey: CONFIG.privateKey
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ============================================
|
|
48
|
+
// 1. GET SALE INFORMATION
|
|
49
|
+
// ============================================
|
|
50
|
+
console.log('\n--- Sale Information ---\n');
|
|
51
|
+
|
|
52
|
+
// Check if sale is active
|
|
53
|
+
const isPaused = await purchase.isPaused();
|
|
54
|
+
console.log(`Sale Status: ${isPaused ? 'PAUSED' : 'ACTIVE'}`);
|
|
55
|
+
|
|
56
|
+
// Get purchase limits
|
|
57
|
+
const limits = await purchase.getPurchaseLimits();
|
|
58
|
+
console.log(`Min Purchase: ${limits.minPurchase} QVTX`);
|
|
59
|
+
console.log(`Max Purchase: ${limits.maxPurchase} QVTX`);
|
|
60
|
+
console.log(`Max Per Wallet: ${limits.maxWalletPurchase} QVTX`);
|
|
61
|
+
console.log(`Total Sale Cap: ${limits.totalSaleCap} QVTX`);
|
|
62
|
+
console.log(`Already Sold: ${limits.totalSold} QVTX`);
|
|
63
|
+
console.log(`Remaining: ${limits.remainingSupply} QVTX`);
|
|
64
|
+
|
|
65
|
+
// Get current price
|
|
66
|
+
const priceInBNB = await purchase.getPriceInNative();
|
|
67
|
+
console.log(`\nPrice: ${priceInBNB} BNB per QVTX`);
|
|
68
|
+
|
|
69
|
+
// ============================================
|
|
70
|
+
// 2. CALCULATE PURCHASE COSTS
|
|
71
|
+
// ============================================
|
|
72
|
+
console.log('\n--- Calculate Costs ---\n');
|
|
73
|
+
|
|
74
|
+
const buyAmount = '10000'; // Buy 10,000 QVTX
|
|
75
|
+
|
|
76
|
+
// Calculate cost in native currency
|
|
77
|
+
const nativeCost = await purchase.calculateNativeCost(buyAmount);
|
|
78
|
+
console.log(`Cost for ${buyAmount} QVTX: ${nativeCost} BNB`);
|
|
79
|
+
|
|
80
|
+
// Calculate cost with referral discount
|
|
81
|
+
const referrer = '0x1234567890123456789012345678901234567890';
|
|
82
|
+
const discountedCost = await purchase.calculateNativeCost(buyAmount, referrer);
|
|
83
|
+
console.log(`Cost with referral: ${discountedCost} BNB`);
|
|
84
|
+
console.log(`Savings: ${(parseFloat(nativeCost) - parseFloat(discountedCost)).toFixed(6)} BNB`);
|
|
85
|
+
|
|
86
|
+
// Get QVTX amount for specific BNB amount
|
|
87
|
+
const bnbAmount = '1.0';
|
|
88
|
+
const qvtxForBNB = await purchase.getQVTXForNative(bnbAmount);
|
|
89
|
+
console.log(`\n${bnbAmount} BNB = ${qvtxForBNB} QVTX`);
|
|
90
|
+
|
|
91
|
+
// ============================================
|
|
92
|
+
// 3. CHECK IF PURCHASE IS VALID
|
|
93
|
+
// ============================================
|
|
94
|
+
console.log('\n--- Validate Purchase ---\n');
|
|
95
|
+
|
|
96
|
+
// Get connected wallet address
|
|
97
|
+
const walletAddress = CONFIG.privateKey
|
|
98
|
+
? new (require('ethers').Wallet)(CONFIG.privateKey).address
|
|
99
|
+
: '0x0000000000000000000000000000000000000000';
|
|
100
|
+
|
|
101
|
+
const validation = await purchase.canPurchase(walletAddress, buyAmount);
|
|
102
|
+
console.log(`Can purchase ${buyAmount} QVTX: ${validation.valid}`);
|
|
103
|
+
if (!validation.valid) {
|
|
104
|
+
console.log(`Reason: ${validation.reason}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ============================================
|
|
108
|
+
// 4. GET WALLET INFORMATION
|
|
109
|
+
// ============================================
|
|
110
|
+
console.log('\n--- Wallet Info ---\n');
|
|
111
|
+
|
|
112
|
+
const walletInfo = await purchase.getWalletInfo(walletAddress);
|
|
113
|
+
console.log(`Total Purchased: ${walletInfo.totalPurchased} QVTX`);
|
|
114
|
+
console.log(`Remaining Allocation: ${walletInfo.remainingAllocation} QVTX`);
|
|
115
|
+
console.log(`Purchase Count: ${walletInfo.purchaseCount}`);
|
|
116
|
+
|
|
117
|
+
if (walletInfo.purchases.length > 0) {
|
|
118
|
+
console.log('\nPurchase History:');
|
|
119
|
+
walletInfo.purchases.forEach((p, i) => {
|
|
120
|
+
console.log(` ${i + 1}. ${p.amount} QVTX on ${p.timestamp.toLocaleDateString()}`);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ============================================
|
|
125
|
+
// 5. GET REFERRAL INFORMATION
|
|
126
|
+
// ============================================
|
|
127
|
+
console.log('\n--- Referral Info ---\n');
|
|
128
|
+
|
|
129
|
+
const referralInfo = await purchase.getReferralInfo(walletAddress);
|
|
130
|
+
console.log(`Referral Reward: ${referralInfo.rewardPercent}%`);
|
|
131
|
+
console.log(`Buyer Discount: ${referralInfo.discountPercent}%`);
|
|
132
|
+
console.log(`Your Referrals: ${referralInfo.referralCount}`);
|
|
133
|
+
console.log(`Total Earnings: ${referralInfo.totalEarnings} QVTX`);
|
|
134
|
+
|
|
135
|
+
// Generate your referral link
|
|
136
|
+
const referralLink = purchase.generateReferralLink(walletAddress);
|
|
137
|
+
console.log(`\nYour Referral Link: ${referralLink}`);
|
|
138
|
+
|
|
139
|
+
// ============================================
|
|
140
|
+
// 6. PURCHASE WITH NATIVE CURRENCY (BNB)
|
|
141
|
+
// ============================================
|
|
142
|
+
console.log('\n--- Purchase with BNB ---\n');
|
|
143
|
+
|
|
144
|
+
// IMPORTANT: Only run this if you want to make a real purchase!
|
|
145
|
+
const EXECUTE_PURCHASE = false;
|
|
146
|
+
|
|
147
|
+
if (EXECUTE_PURCHASE && CONFIG.privateKey) {
|
|
148
|
+
try {
|
|
149
|
+
// Get purchase summary before buying
|
|
150
|
+
const summary = await purchase.getPurchaseSummary(buyAmount, referrer);
|
|
151
|
+
console.log('Purchase Summary:');
|
|
152
|
+
console.log(` Amount: ${summary.qvtxAmount} QVTX`);
|
|
153
|
+
console.log(` Cost: ${summary.nativeCost} BNB`);
|
|
154
|
+
console.log(` Referrer: ${summary.referrer}`);
|
|
155
|
+
console.log(` Discount: ${summary.discount}`);
|
|
156
|
+
|
|
157
|
+
// Execute purchase
|
|
158
|
+
console.log('\nExecuting purchase...');
|
|
159
|
+
const tx = await purchase.purchaseWithNative(buyAmount, {
|
|
160
|
+
referrer: referrer
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
console.log(`Transaction Hash: ${tx.hash}`);
|
|
164
|
+
console.log('Waiting for confirmation...');
|
|
165
|
+
|
|
166
|
+
const receipt = await tx.wait();
|
|
167
|
+
console.log(`Confirmed in block: ${receipt.blockNumber}`);
|
|
168
|
+
console.log(`Gas Used: ${receipt.gasUsed.toString()}`);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('Purchase failed:', error.message);
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
console.log('(Purchase execution disabled - set EXECUTE_PURCHASE = true to buy)');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ============================================
|
|
177
|
+
// 7. PURCHASE WITH STABLECOIN (USDT)
|
|
178
|
+
// ============================================
|
|
179
|
+
console.log('\n--- Purchase with USDT ---\n');
|
|
180
|
+
|
|
181
|
+
const usdtAddress = STABLECOINS.bsc.USDT;
|
|
182
|
+
console.log(`USDT Address: ${usdtAddress}`);
|
|
183
|
+
|
|
184
|
+
// Check if USDT is supported
|
|
185
|
+
const supportedTokens = await purchase.getSupportedTokens();
|
|
186
|
+
const usdtSupported = supportedTokens.includes(usdtAddress);
|
|
187
|
+
console.log(`USDT Supported: ${usdtSupported}`);
|
|
188
|
+
|
|
189
|
+
if (usdtSupported) {
|
|
190
|
+
const usdtCost = await purchase.calculateTokenCost(usdtAddress, buyAmount);
|
|
191
|
+
console.log(`Cost for ${buyAmount} QVTX: ${usdtCost} USDT`);
|
|
192
|
+
|
|
193
|
+
// IMPORTANT: Only run this if you want to make a real purchase!
|
|
194
|
+
if (EXECUTE_PURCHASE && CONFIG.privateKey) {
|
|
195
|
+
try {
|
|
196
|
+
console.log('\nExecuting USDT purchase...');
|
|
197
|
+
const tx = await purchase.purchaseWithToken(usdtAddress, buyAmount, {
|
|
198
|
+
referrer: referrer,
|
|
199
|
+
approve: true // Auto-approve USDT spending
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
console.log(`Transaction Hash: ${tx.hash}`);
|
|
203
|
+
const receipt = await tx.wait();
|
|
204
|
+
console.log(`Confirmed in block: ${receipt.blockNumber}`);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('USDT purchase failed:', error.message);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ============================================
|
|
212
|
+
// 8. VESTING SCHEDULE MANAGEMENT
|
|
213
|
+
// ============================================
|
|
214
|
+
console.log('\n--- Vesting Schedules ---\n');
|
|
215
|
+
|
|
216
|
+
const vestingSchedules = await purchase.getVestingSchedules(walletAddress);
|
|
217
|
+
|
|
218
|
+
if (vestingSchedules.length === 0) {
|
|
219
|
+
console.log('No vesting schedules found.');
|
|
220
|
+
console.log('(Large purchases over threshold will have vesting)');
|
|
221
|
+
} else {
|
|
222
|
+
console.log(`Found ${vestingSchedules.length} vesting schedule(s):\n`);
|
|
223
|
+
|
|
224
|
+
for (const schedule of vestingSchedules) {
|
|
225
|
+
console.log(`Schedule #${schedule.index}:`);
|
|
226
|
+
console.log(` Total: ${schedule.totalAmount} QVTX`);
|
|
227
|
+
console.log(` Released: ${schedule.released} QVTX`);
|
|
228
|
+
console.log(` Remaining: ${schedule.remaining} QVTX`);
|
|
229
|
+
console.log(` Start: ${schedule.startTime.toLocaleDateString()}`);
|
|
230
|
+
console.log(` End: ${schedule.endTime.toLocaleDateString()}`);
|
|
231
|
+
console.log(` Duration: ${schedule.duration} days`);
|
|
232
|
+
console.log(` Progress: ${schedule.percentVested.toFixed(2)}%\n`);
|
|
233
|
+
|
|
234
|
+
// Release vested tokens
|
|
235
|
+
if (EXECUTE_PURCHASE && parseFloat(schedule.remaining) > 0) {
|
|
236
|
+
try {
|
|
237
|
+
console.log(' Releasing vested tokens...');
|
|
238
|
+
const tx = await purchase.releaseVested(schedule.index);
|
|
239
|
+
await tx.wait();
|
|
240
|
+
console.log(' Released successfully!');
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error(` Release failed: ${error.message}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ============================================
|
|
249
|
+
// 9. WHITELIST CHECK (FOR PRIVATE SALES)
|
|
250
|
+
// ============================================
|
|
251
|
+
console.log('\n--- Whitelist Status ---\n');
|
|
252
|
+
|
|
253
|
+
const whitelistEnabled = await purchase.isWhitelistEnabled();
|
|
254
|
+
console.log(`Whitelist Mode: ${whitelistEnabled ? 'ENABLED (Private Sale)' : 'DISABLED (Public Sale)'}`);
|
|
255
|
+
|
|
256
|
+
if (whitelistEnabled) {
|
|
257
|
+
const isWhitelisted = await purchase.isWhitelisted(walletAddress);
|
|
258
|
+
console.log(`Your Status: ${isWhitelisted ? 'WHITELISTED' : 'NOT WHITELISTED'}`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ============================================
|
|
262
|
+
// DONE
|
|
263
|
+
// ============================================
|
|
264
|
+
console.log('\n' + '='.repeat(60));
|
|
265
|
+
console.log('Example complete!');
|
|
266
|
+
console.log('='.repeat(60));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Run the example
|
|
270
|
+
main().catch(console.error);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Quick Purchase Function
|
|
274
|
+
* Use this for simple purchases in your own code
|
|
275
|
+
*/
|
|
276
|
+
async function quickPurchase(amount, options = {}) {
|
|
277
|
+
const purchase = createDirectPurchase({
|
|
278
|
+
provider: options.rpcUrl || CONFIG.rpcUrl,
|
|
279
|
+
contractAddress: options.contractAddress || CONFIG.purchaseContract,
|
|
280
|
+
privateKey: options.privateKey || CONFIG.privateKey
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Validate first
|
|
284
|
+
const wallet = new (require('ethers').Wallet)(options.privateKey || CONFIG.privateKey);
|
|
285
|
+
const { valid, reason } = await purchase.canPurchase(wallet.address, amount);
|
|
286
|
+
|
|
287
|
+
if (!valid) {
|
|
288
|
+
throw new Error(`Cannot purchase: ${reason}`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Execute purchase
|
|
292
|
+
const tx = await purchase.purchaseWithNative(amount, {
|
|
293
|
+
referrer: options.referrer
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
return tx;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Export for use in other files
|
|
300
|
+
module.exports = { quickPurchase };
|
|
@@ -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);
|