-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrunAirdrop.ts
More file actions
145 lines (121 loc) · 4.78 KB
/
runAirdrop.ts
File metadata and controls
145 lines (121 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import * as fs from 'fs';
import { AeSdk, MemoryAccount, Node, CompilerHttp, Contract, getFileSystem } from '@aeternity/aepp-sdk';
import { calculateAirdropAmounts } from './airdropCalculator';
import { phases } from './index';
// Path to the contract source file
const AIRDROP_TOKEN_MINTER_SOURCE = "./airdrop-contract/contracts/AirdropTokenMinter.aes";
// Read configuration from deploy-config.json
const loadConfig = () => {
try {
const configData = fs.readFileSync('./deploy-config.json', 'utf8');
return JSON.parse(configData);
} catch (error) {
console.error('Error reading config file:', error);
process.exit(1);
}
};
// Read contract address from contract-address.json
const loadContractAddress = () => {
try {
const addressData = fs.readFileSync('./contract-address.json', 'utf8');
return JSON.parse(addressData).address;
} catch (error) {
console.error('Error reading contract address file:', error);
console.error('Make sure you have deployed the contract using runInitialDeploy.ts first');
process.exit(1);
}
};
// Get airdrop amounts using the calculateAirdropAmounts function
const getAirdropAmounts = async (phaseIndex = 0) => {
try {
const selectedPhase = phases[phaseIndex];
console.log(`Calculating airdrop amounts for ${selectedPhase.name}...`);
return await calculateAirdropAmounts(selectedPhase);
} catch (error) {
console.error('Error calculating airdrop amounts:', error);
process.exit(1);
}
};
const runAirdrop = async () => {
// Parse command line arguments
const args = process.argv.slice(2);
let phaseIndex = 0; // Default to phase 1
// Check if a phase is specified
if (args.length > 0) {
const phaseArg = parseInt(args[0]);
if (isNaN(phaseArg) || phaseArg < 1 || phaseArg > phases.length) {
console.error(`Invalid phase number. Please specify a number between 1 and ${phases.length}.`);
process.exit(1);
}
phaseIndex = phaseArg - 1; // Convert from 1-based to 0-based indexing
}
console.log(`Using phase ${phaseIndex + 1}: ${phases[phaseIndex].name}`);
// Load configuration
const config = loadConfig();
const { privateKey } = config;
if (!privateKey || privateKey === 'YOUR_PRIVATE_KEY_HERE') {
console.error('Please provide a valid private key in deploy-config.json');
process.exit(1);
}
// Load contract address
const contractAddress = loadContractAddress();
console.log(`Using contract at address: ${contractAddress}`);
try {
// Initialize SDK with the provided private key
const account = new MemoryAccount(privateKey);
const node = new Node('https://mainnet.aeternity.io');
const compiler = new CompilerHttp('https://compiler.aeternity.io');
const aeSdk = new AeSdk({
nodes: [{ name: 'mainnet', instance: node }],
accounts: [account],
compiler,
});
// Set the account as default
await aeSdk.addAccount(account, { select: true });
// Get the contract source code
const sourceCode = fs.readFileSync(AIRDROP_TOKEN_MINTER_SOURCE, 'utf8');
// A filesystem object must be passed to the compiler if the contract uses custom includes
const fileSystem = await getFileSystem(AIRDROP_TOKEN_MINTER_SOURCE);
// Initialize the contract instance
const contract = await Contract.initialize({
client: aeSdk,
sourceCode,
fileSystem,
address: contractAddress,
});
// Get airdrop amounts from index.ts
const airdropAmounts = await getAirdropAmounts(phaseIndex);
console.log(`Found ${airdropAmounts.length} addresses eligible for airdrop`);
// Format the airdrop amounts for the batch_mint function
const batchMintArgs = airdropAmounts.map(({ address, airdropAmount }) => [
address,
BigInt(airdropAmount)
]);
// Split into batches of 100 to avoid transaction size limits
const batchSize = 100;
const batches = [];
for (let i = 0; i < batchMintArgs.length; i += batchSize) {
batches.push(batchMintArgs.slice(i, i + batchSize));
}
console.log(`Splitting airdrop into ${batches.length} batches`);
// Process each batch
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
console.log(`Processing batch ${i + 1}/${batches.length} with ${batch.length} addresses...`);
try {
const result = await contract.batch_mint(batch);
console.log(`Batch ${i + 1} processed successfully!`);
console.log(`Transaction hash: ${result.transaction}`);
} catch (error) {
console.error(`Error processing batch ${i + 1}:`, error);
// Continue with next batch
}
}
console.log('Airdrop completed successfully!');
} catch (error) {
console.error('Error running airdrop:', error);
process.exit(1);
}
};
// Execute the airdrop
runAirdrop().catch(console.error);