├── .gitignore
├── .idea
├── TokenAirdrop.iml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── Airdrop
├── .gitignore
├── config
│ └── config.js
├── contract
│ ├── JDCoin.sol
│ └── airdrop.sol
├── filemanger
│ ├── airdropListManager.js
│ ├── awards.js
│ ├── errorAirdropList.js
│ ├── excelHandleManager.js
│ └── xlsx
│ │ └── withdraw_sequence_1_20180705.xlsx
├── function
│ ├── airdrop.js
│ ├── approve.js
│ ├── base
│ │ ├── delpoy.js
│ │ ├── execute.js
│ │ ├── listen.js
│ │ └── transaction.js
│ ├── deployAirdropContract.js
│ ├── example
│ │ ├── converterProperty.js
│ │ ├── deployConverter.js
│ │ └── executeConverterFunction.js
│ ├── transferETH.js
│ └── transferToken.js
├── package.json
└── start.js
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /.idea
3 | .xml
4 |
--------------------------------------------------------------------------------
/.idea/TokenAirdrop.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 |
112 |
113 |
114 |
115 | readFile
116 | listenAirdropStatus
117 | intervalNumber
118 | startRinkebyListen
119 | tokenContractAddress
120 | maxLength
121 | !=
122 | ==
123 | awardsAirdrop
124 | getErrorAddressList
125 | config
126 | file
127 | writeData
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | true
157 | DEFINITION_ORDER
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 | project
283 |
284 |
285 | true
286 |
287 |
288 |
289 | DIRECTORY
290 |
291 | false
292 |
293 |
294 |
295 | project
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 | 1517654955133
324 |
325 |
326 | 1517654955133
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
--------------------------------------------------------------------------------
/Airdrop/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /.idea
3 | package-lock.json
4 | .xml
5 |
--------------------------------------------------------------------------------
/Airdrop/config/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/2/3.
3 | */
4 | require('web3');
5 | require('ethereumjs-tx');
6 | require('solc');
7 | require('ethjs-account');
8 | require('node-xlsx');
9 | require('silly-datetime');
10 | require('ws');
11 |
12 | console.log('require librarys');
13 |
14 | //itc 主空投账户
15 | const userConfig_main = {
16 | userPrivateKey:'',
17 | userAddress:'0xf5D0318dbb21755B4866CF10bA7f8843F0BD11bf',
18 | airdropContractAddress:'0xc3695ff043d9ad015dd3b6141ee4de0a7051204c'
19 |
20 | };
21 |
22 | //Ethereum Rinkeby 测试账户
23 | const userConfig_rinkeby = {
24 | userPrivateKey:'1311795de329cf9e8debd6441eae1437122e0bddf28911f8b6d770dc46a3b0e8',
25 | userAddress:'0xfdbc38257a9507d9329c2e203bce7a9b0b63f871',
26 | airdropContractAddress:'0x7a8cBfaA4bE827c834DFefae367c9535634f9B9D'
27 | };
28 |
29 | let userConfig = userConfig_rinkeby;
30 | // let userConfig = userConfig_main;
31 |
32 | //主网
33 | mainnetConfig = {
34 | internetType:'main',
35 | userModule:{
36 | userPrivateKey:userConfig.userPrivateKey,
37 | },
38 | tokenholderStartBlock:userConfig.startBlock,
39 | transaction:{
40 | url:'https://mainnet.infura.io',
41 | gasPrice:20000000000,
42 | gasLimit:6000000
43 | },
44 | airdropModule: {
45 | ercAirDropAmount:'1', //amount of normal airdrop
46 | airdropContractAddress:userConfig.airdropContractAddress, //
47 | tokenContractAddress:'0x5e6b6d9abad9093fdc861ea1600eba1b355cd940', //erc20 token contract address
48 | },
49 | approveModule:{
50 | amount : '5000', //The amount of contract transferable accounts
51 | approveAddress : userConfig.airdropContractAddress, //airdrop contract address
52 | tokenContractAddress : '0x5e6b6d9abad9093fdc861ea1600eba1b355cd940', //erc20 token contract address
53 | },
54 | };
55 |
56 | //rinkeby网络
57 | rinkebyConfig = {
58 | internetType:'rinkeby',
59 | userModule:{
60 | userPrivateKey:userConfig.userPrivateKey,
61 | },
62 | tokenholderStartBlock:userConfig.startBlock,
63 | transaction:{
64 | url:'https://rinkeby.infura.io/0x585a40461ff12c6734e8549a7fb527120d4b8d0d',
65 | gasPrice:50000000000,
66 | gasLimit:6000000
67 | },
68 | airdropModule: {
69 | ercAirDropAmount:'1', //amount of normal airdrop
70 | airdropContractAddress:userConfig.contractAddress, //
71 | tokenContractAddress:'0xc0eE6Df91C455c64928F1F179C2B84eb61E58870', //erc20 token contract address
72 | },
73 | approveModule:{
74 | amount : '5000', //The amount of contract transferable accounts
75 | approveAddress : userConfig.contractAddress, //airdrop contract address
76 | tokenContractAddress : '0xc0eE6Df91C455c64928F1F179C2B84eb61E58870', //erc20 token contract address
77 | },
78 | };
79 |
80 | module.exports = rinkebyConfig;
81 | // module.exports = mainnetConfig;
82 |
83 |
--------------------------------------------------------------------------------
/Airdrop/contract/JDCoin.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.16;
2 |
3 | interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
4 |
5 | contract JDToken {
6 | // Public variables of the token
7 | string public name = "JiDong Coin";
8 | string public symbol = "JDC";
9 | uint256 public decimals = 18;
10 | // 18 decimals is the strongly suggested default, avoid changing it
11 | uint256 public totalSupply = 100*1000*1000*10**decimals;
12 |
13 | // This creates an array with all balances
14 | mapping (address => uint256) public balanceOf;
15 | mapping (address => mapping (address => uint256)) public allowance;
16 |
17 | // This generates a public event on the blockchain that will notify clients
18 | event Transfer(address indexed from, address indexed to, uint256 value);
19 |
20 | // This notifies clients about the amount burnt
21 | event Burn(address indexed from, uint256 value);
22 |
23 | /**
24 | * Constrctor function
25 | *
26 | * Initializes contract with initial supply tokens to the creator of the contract
27 | */
28 | function JDToken(
29 | ) public {
30 | balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens
31 | }
32 |
33 | /**
34 | * Internal transfer, only can be called by this contract
35 | */
36 | function _transfer(address _from, address _to, uint _value) internal {
37 | // Prevent transfer to 0x0 address. Use burn() instead
38 | require(_to != 0x0);
39 | // Check if the sender has enough
40 | require(balanceOf[_from] >= _value);
41 | // Check for overflows
42 | require(balanceOf[_to] + _value > balanceOf[_to]);
43 | // Save this for an assertion in the future
44 | uint previousBalances = balanceOf[_from] + balanceOf[_to];
45 | // Subtract from the sender
46 | balanceOf[_from] -= _value;
47 | // Add the same to the recipient
48 | balanceOf[_to] += _value;
49 | Transfer(_from, _to, _value);
50 | // Asserts are used to use static analysis to find bugs in your code. They should never fail
51 | assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
52 | }
53 |
54 | /**
55 | * Transfer tokens
56 | *
57 | * Send `_value` tokens to `_to` from your account
58 | *
59 | * @param _to The address of the recipient
60 | * @param _value the amount to send
61 | */
62 | function transfer(address _to, uint256 _value) public {
63 | _transfer(msg.sender, _to, _value);
64 | }
65 |
66 | /**
67 | * Transfer tokens from other address
68 | *
69 | * Send `_value` tokens to `_to` in behalf of `_from`
70 | *
71 | * @param _from The address of the sender
72 | * @param _to The address of the recipient
73 | * @param _value the amount to send
74 | */
75 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
76 | require(_value <= allowance[_from][msg.sender]); // Check allowance
77 | allowance[_from][msg.sender] -= _value;
78 | _transfer(_from, _to, _value);
79 | return true;
80 | }
81 |
82 | /**
83 | * Set allowance for other address
84 | *
85 | * Allows `_spender` to spend no more than `_value` tokens in your behalf
86 | *
87 | * @param _spender The address authorized to spend
88 | * @param _value the max amount they can spend
89 | */
90 | function approve(address _spender, uint256 _value) public
91 | returns (bool success) {
92 | allowance[msg.sender][_spender] = _value;
93 | return true;
94 | }
95 |
96 | /**
97 | * Set allowance for other address and notify
98 | *
99 | * Allows `_spender` to spend no more than `_value` tokens in your behalf, and then ping the contract about it
100 | *
101 | * @param _spender The address authorized to spend
102 | * @param _value the max amount they can spend
103 | * @param _extraData some extra information to send to the approved contract
104 | */
105 | function approveAndCall(address _spender, uint256 _value, bytes _extraData)
106 | public
107 | returns (bool success) {
108 | tokenRecipient spender = tokenRecipient(_spender);
109 | if (approve(_spender, _value)) {
110 | spender.receiveApproval(msg.sender, _value, this, _extraData);
111 | return true;
112 | }
113 | }
114 |
115 | /**
116 | * Destroy tokens
117 | *
118 | * Remove `_value` tokens from the system irreversibly
119 | *
120 | * @param _value the amount of money to burn
121 | */
122 | function burn(uint256 _value) public returns (bool success) {
123 | require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
124 | balanceOf[msg.sender] -= _value; // Subtract from the sender
125 | totalSupply -= _value; // Updates totalSupply
126 | Burn(msg.sender, _value);
127 | return true;
128 | }
129 |
130 | /**
131 | * Destroy tokens from other account
132 | *
133 | * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
134 | *
135 | * @param _from the address of the sender
136 | * @param _value the amount of money to burn
137 | */
138 | function burnFrom(address _from, uint256 _value) public returns (bool success) {
139 | require(balanceOf[_from] >= _value); // Check if the targeted balance is enough
140 | require(_value <= allowance[_from][msg.sender]); // Check allowance
141 | balanceOf[_from] -= _value; // Subtract from the targeted balance
142 | allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance
143 | totalSupply -= _value; // Update totalSupply
144 | Burn(_from, _value);
145 | return true;
146 | }
147 | }
--------------------------------------------------------------------------------
/Airdrop/contract/airdrop.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | contract ERC20Interface {
4 | function transferFrom(address _from, address _to, uint _value) public returns (bool){}
5 | }
6 | contract Ownable {
7 | address public owner;
8 |
9 | function Ownable() public {
10 | owner = msg.sender;
11 | }
12 |
13 | modifier onlyOwner() {
14 | require(msg.sender == owner);
15 | _;
16 | }
17 |
18 | function transferOwnership(address newOwner) public onlyOwner {
19 |
20 | if (newOwner != address(0)) {
21 | owner = newOwner;
22 | }
23 | }
24 | }
25 |
26 |
27 | contract TokenAirDrop is Ownable {
28 |
29 | function airDrop ( address contractObj,
30 | address tokenRepo,
31 | address[] airDropDesinationAddress,
32 | uint[] amounts) public onlyOwner{
33 |
34 | for( uint i = 0 ; i < airDropDesinationAddress.length ; i++ ) {
35 |
36 | ERC20Interface(contractObj).transferFrom( tokenRepo, airDropDesinationAddress[i],amounts[i]);
37 | }
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/Airdrop/filemanger/airdropListManager.js:
--------------------------------------------------------------------------------
1 | let excelManager = require('./excelHandleManager');
2 |
3 | /*
4 | * filepath 文档路径
5 | * addressIndex 地址的序列
6 | * amountIndex 数量的序列
7 | * needJudgeRepeat 是否需要判断去重
8 | * result 结果回调
9 | * */
10 | function getAirdrop(filepath,addressIndex,amountIndex,needJudgeRepeat,result) {
11 |
12 |
13 | let listData = excelManager.readExcelContent(filepath);
14 |
15 | let repeatAirdropAddressIndexs = [];
16 |
17 | if (needJudgeRepeat){
18 |
19 | repeatAirdropAddressIndexs = getRepeatAccount(listData,addressIndex);
20 | }
21 |
22 | console.log('repeatAirdropAddressIndexs:\n'+repeatAirdropAddressIndexs);
23 |
24 | let airdropList = [];
25 | let amountArr = [];
26 | let invalidAirdropList = [];
27 | let repeatList = [];
28 |
29 | //start index
30 | let destinationStartIndex = 0;
31 | //max amount
32 | const maxLength = 10000;
33 |
34 | for (let i in listData){
35 |
36 | //第一行为标题
37 | if(i === 0){
38 | continue;
39 | }
40 |
41 | if(i < destinationStartIndex){
42 | continue;
43 | }
44 |
45 | if(i === destinationStartIndex + maxLength){
46 | break;
47 | }
48 |
49 | //repeat token Address
50 | if(repeatAirdropAddressIndexs.indexOf(i) !== -1){
51 |
52 | let arr = listData[i];
53 | repeatList.push(arr);
54 | continue;
55 | }
56 |
57 | let arr = listData[i];
58 | let addressObj = arr[addressIndex];
59 | let amount = arr[amountIndex];
60 |
61 | if(addressObj.length === 42){
62 | airdropList.push(addressObj);
63 | amountArr.push(amount);
64 | }
65 | else {
66 | invalidAirdropList.push(arr);
67 | }
68 | }
69 |
70 | console.log('airdropListAccount:'+airdropList.length);
71 | console.log('repeatAccountAmount:'+repeatList.length);
72 | console.log('invalidAccountAmount:'+invalidAirdropList.length+'\n');
73 |
74 | result(airdropList,amountArr);
75 | }
76 |
77 | function getRepeatAccount(dataArr,addressIndex) {
78 |
79 | let airdropList = [];
80 | let repeatAirdropAddressIndexs = [];
81 |
82 | //return repeatAirdropAddressIndexs;
83 | for (let i in dataArr){
84 |
85 | let arr = dataArr[i];
86 | let obj = arr[addressIndex];
87 |
88 | if (airdropList.indexOf(obj) === -1){
89 |
90 | airdropList.push(obj);
91 | }
92 | else {
93 | repeatAirdropAddressIndexs.push(i);
94 | }
95 | }
96 |
97 | return repeatAirdropAddressIndexs;
98 | }
99 |
100 | module.exports = {
101 |
102 | getAirdropList:getAirdrop
103 | };
--------------------------------------------------------------------------------
/Airdrop/filemanger/awards.js:
--------------------------------------------------------------------------------
1 |
2 | let excelManager = require('./excelHandleManager');
3 | let fs = require('fs');
4 |
5 |
6 | function createRandomAwardsList(originalListPath,addressIndex,result){
7 |
8 |
9 | fs.exists(awardsAirdropListPath,function (didExists) {
10 |
11 | console.log(didExists);
12 | if (didExists === false){
13 |
14 | createRandomAward();
15 | console.log('Generated awards list has been generated!');
16 | }
17 |
18 | console.log('did create awards list , if you want to create a new awards list ,please delete the old one');
19 | });
20 | }
21 |
22 |
23 | function createRandomAward(originalListPath,addressIndex){
24 |
25 | //read xlsx data
26 | let data = excelManager.readExcelContent(originalListPath);
27 |
28 | let airdropList = [];
29 | let nameList = [];
30 |
31 | let totolaName = [];
32 |
33 | for (let i in data){
34 |
35 | let arr = data[i];
36 | let obj = arr[addressIndex];
37 | if (airdropList.indexOf(obj) === -1 && obj.length === 42) {
38 |
39 | airdropList.push(obj);
40 | nameList.push(arr[1]);
41 | }
42 |
43 | totolaName.push(arr[1]);
44 | }
45 |
46 | let amountsArr = [];
47 | let accountsArr = [];
48 |
49 | //recoderArr
50 | let writeFileContent = [['Name','Rwards','Amount','sequence','Token Address']];
51 |
52 | //500个一等奖 20个二等奖 1个一等奖
53 | for (let i = 0; i < 500 + 20 + 1 ; i ++) {
54 |
55 | let content = [];
56 |
57 | while (1){
58 | let j = GetRandomNum(0, airdropList.length - 1);
59 | //console.log('random' + j);
60 |
61 | let obj = airdropList[j];
62 |
63 | if (accountsArr.indexOf(obj) === -1) {
64 |
65 | let name = nameList[j];
66 | content.push(name);
67 |
68 | let amount = '4';
69 | let awardName = 'Third prize';
70 | if (i === 0) {
71 | amount = '499';
72 | awardName = 'First prize';
73 | }
74 | else if (i < 21) {
75 | amount = '49';
76 | awardName = 'Second prize';
77 | }
78 |
79 | amountsArr.push(amount);
80 | content.push(awardName);
81 | content.push(amount);
82 |
83 | let index = totolaName.indexOf(name);
84 |
85 | content.push(index);
86 |
87 | accountsArr.push(obj);
88 | content.push(obj);
89 | break;
90 | }
91 | }
92 |
93 |
94 | writeFileContent.push(content);
95 | }
96 |
97 | //记录
98 | excelManager.writeDataToExcel(writeFileContent,awardsAirdropListPath);
99 | };
100 |
101 |
102 | function GetRandomNum(Min,Max)
103 | {
104 | let Range = Max - Min;
105 | let Rand = Math.random();
106 | return(Min + Math.round(Rand * Range));
107 | }
108 |
109 |
110 | module.exports = {
111 |
112 | createRandomAwardsList
113 | };
--------------------------------------------------------------------------------
/Airdrop/filemanger/errorAirdropList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/2/13.
3 | */
4 |
5 | var excelManager = require('./excelHandleManager');
6 |
7 | function getErrorAddressList(airdropListFilePath,errorAddressListPath,addressIndex) {
8 |
9 | var data = excelManager.readExcelContent(airdropListFilePath);
10 | var writeFileContent = [];
11 |
12 | for (var i in data){
13 |
14 | var arr = data[i];
15 | var obj = arr[addressIndex];
16 | if (obj.length !== 42 && writeFileContent.indexOf(arr) === -1) {
17 | writeFileContent.push(arr);
18 | }
19 | }
20 |
21 | excelManager.writeDataToExcel(writeFileContent,errorAddressListPath);
22 | }
23 |
24 | var Config = require('./../config/config.js');
25 |
26 | var errorAirdropListPath = Config.filePath.errorAirdropListPath;
27 | var totalAirdropListPath = './itc_airdrop_total.xlsx';
28 | var addressIndex = 3;
29 |
30 |
31 | getErrorAddressList(totalAirdropListPath,errorAirdropListPath,addressIndex);
--------------------------------------------------------------------------------
/Airdrop/filemanger/excelHandleManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/3/28.
3 | */
4 |
5 | var xlsx = require('node-xlsx');
6 | var fs = require('fs');
7 |
8 | function readFile(path){
9 |
10 | //parse
11 | var obj = xlsx.parse(path);
12 | var excelObj=obj[0].data;
13 | //console.log(excelObj);
14 |
15 | var data = [];
16 | for(var i in excelObj){
17 | var arr=[];
18 | var value=excelObj[i];
19 | for(var j in value){
20 | arr.push(value[j]);
21 | }
22 | data.push(arr);
23 | }
24 |
25 | return data;
26 | }
27 |
28 |
29 | function writeDataSync(data,path) {
30 |
31 | var buffer = xlsx.build([
32 | {
33 | name:'sheet1',
34 | data:data
35 | }
36 | ]);
37 |
38 | fs.writeFileSync(path,buffer,{'flag':'w'});
39 | }
40 |
41 | function appendData(data,path){
42 | var fs = require('fs');
43 |
44 | fs.exists(path,function (didExists) {
45 |
46 | if (didExists === false){
47 |
48 | console.log("need init recoder");
49 |
50 | var titleArr = [["Address","Amount"]];
51 | writeDataSync(titleArr,path)
52 | }
53 |
54 |
55 | var originalData = readFile(path);
56 | var appendData = originalData.concat(data);
57 |
58 | writeDataSync(appendData,path)
59 | });
60 |
61 | }
62 |
63 | module.exports = {
64 |
65 | readExcelContent:readFile,
66 | writeDataToExcel:writeDataSync,
67 | recoderAirdrop:appendData
68 | };
--------------------------------------------------------------------------------
/Airdrop/filemanger/xlsx/withdraw_sequence_1_20180705.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IoTChainCode/tokenAirdrop/1ebf5cf1c3e582c17f8a7bfa00a1d5eeebbd049a/Airdrop/filemanger/xlsx/withdraw_sequence_1_20180705.xlsx
--------------------------------------------------------------------------------
/Airdrop/function/airdrop.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/1/17.
3 | */
4 |
5 | const Config = require('./../config/config.js');
6 |
7 | Web3 = require('web3');
8 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
9 |
10 | //init
11 | const Tx = require('ethereumjs-tx');
12 | const ethjsaccount = require('ethjs-account');
13 | const fs = require('fs');
14 | const solc = require('solc');
15 |
16 | // compile the code
17 | const input = fs.readFileSync('./contract/airdrop.sol');
18 | const output = solc.compile(input.toString());
19 | const abi = JSON.parse(output.contracts[':TokenAirDrop'].interface);
20 |
21 |
22 | const tokenInput = fs.readFileSync('./contract/erc20Token.sol');
23 | const tokenOutput = solc.compile(tokenInput.toString());
24 | const tokenAbi = JSON.parse(tokenOutput.contracts[':TokenERC20'].interface);
25 |
26 |
27 | function privateKeyToAddress(privateKey) {
28 |
29 | return ethjsaccount.privateToAccount(privateKey).address;
30 | }
31 |
32 | //------------------------------ init property ----------------------------
33 |
34 | //airdrop contract address
35 | const airContractAddress = Config.airdropModule.airdropContractAddress;
36 | //user privateKey
37 | const userPrivateKey = Config.userModule.userPrivateKey;
38 | //erc20 token contract address
39 | const tokenContractAddress = Config.airdropModule.tokenContractAddress;
40 | //transfer from address
41 | const fromAddress = privateKeyToAddress(userPrivateKey);
42 | //network type
43 | const networkType = Config.internetType;
44 |
45 | //-------------------------------- function --------------------------------
46 |
47 | const execute = require('./base/execute');
48 |
49 | function transfer(erc20TokenContractAddress , airDropOriginalAddress ,airdropDestinationAddresses, airdropAmounts,hashIdCallBack,successCall, errorCall) {
50 |
51 | let airdropContract = new web3.eth.Contract(abi, airContractAddress);
52 |
53 | let dataAbi = airdropContract.methods.airDrop(erc20TokenContractAddress,
54 | airDropOriginalAddress,
55 | airdropDestinationAddresses,
56 | airdropAmounts).encodeABI();
57 |
58 | execute.executeFunction(airContractAddress,dataAbi,hashIdCallBack,successCall,errorCall);
59 | }
60 |
61 |
62 | let totalAirdropAdress = [];
63 | let totalAmounts = [];
64 | let airdropResultCall;
65 |
66 | let listen = require('./base/listen');
67 |
68 | //总共需要空投的数量
69 | let totalAmountOfAirdropList = 0;
70 | //每次空投数量
71 | const onceAmountOfAirdropList = 100;
72 |
73 | //标志位
74 | let didSendLastAirdropList;
75 | //是否需要将剩下的全部发出
76 | let needSendLastList = false;
77 |
78 | //上一波交易是否完成
79 | let perTranscationDidComplete = true;
80 |
81 | function transferWithAddressAndAmounts(addresses,amounts,resultCall) {
82 |
83 | for (let i in amounts){
84 |
85 | let amount = amounts[i].toString();
86 | let obj = web3.utils.toWei(amount, 'ether');
87 | totalAmounts.push(obj);
88 | }
89 |
90 | totalAirdropAdress = addresses;
91 |
92 | airdropResultCall = resultCall;
93 |
94 | //初始化数据
95 | totalAmountOfAirdropList = addresses.length;
96 | needSendLastList = false;
97 |
98 |
99 | //每5秒查询一次上一波是否发生成功
100 | let interval = setInterval(function(){
101 |
102 | if (perTranscationDidComplete){
103 |
104 | clearInterval(interval);
105 | startHandleAirdrop(0);
106 | }
107 | },5*1000);
108 | }
109 |
110 |
111 | function startHandleAirdrop(index) {
112 |
113 | console.log('\n');
114 |
115 | let currentAddresses = [];
116 | let currentAmounts = [];
117 |
118 | didSendLastAirdropList = false;
119 | perTranscationDidComplete = false;
120 |
121 | let i = index * onceAmountOfAirdropList;
122 |
123 | let topIndex = (index +1) * onceAmountOfAirdropList;
124 |
125 | if (needSendLastList){
126 | topIndex = totalAmountOfAirdropList;
127 | }
128 |
129 | for(i; i < topIndex ; i ++ ){
130 |
131 | let address = totalAirdropAdress[i];
132 | let amount = totalAmounts[i];
133 |
134 | currentAddresses.push(address);
135 | currentAmounts.push(amount);
136 |
137 | //判断是否为最后一部分
138 | if (i == totalAirdropAdress.length - 1){
139 | didSendLastAirdropList = true;
140 | break;
141 | }
142 | }
143 |
144 | console.log(currentAddresses +'\n'+currentAmounts);
145 |
146 | transfer(tokenContractAddress,fromAddress,currentAddresses,currentAmounts,function (hashId) {
147 |
148 | let parameter = {'hashId':hashId,'tokenAbi':tokenAbi,'tokenAddress':tokenContractAddress,'fromAddress':fromAddress};
149 |
150 | listen.startListenAirdropResult(parameter,function (result) {
151 |
152 | console.log('\n\n第'+(index+1)+'波已发送完毕\n');
153 |
154 | perTranscationDidComplete = true;
155 |
156 | //判断是否已经发送完最后一批
157 | if(didSendLastAirdropList){
158 | console.log("\n全部发送完毕!!!\n\n");
159 |
160 | //回调空投结果
161 | airdropResultCall(true);
162 |
163 | listen.stopListen();
164 | }
165 | else {
166 | console.log('\n开始第' + (index+2) + '波空投地址\n\n');
167 | startHandleAirdrop(index+1);
168 | }
169 | });
170 | },function (success) {
171 |
172 | perTranscationDidComplete = true;
173 |
174 | console.log("Transaction Success:\n"+success);
175 | },function (error) {
176 |
177 | console.log("Failure to send a signature transaction:\n"+error);
178 |
179 |
180 | let judgeStr = error.toString();
181 |
182 | let notMind = 'not mined';
183 |
184 | if (judgeStr.indexOf(notMind) == -1){
185 |
186 | perTranscationDidComplete = true;
187 | }
188 |
189 | let underpriced = 'underpriced';
190 | if (judgeStr.indexOf(underpriced) != -1) {
191 |
192 | console.log('重新发送此次交易');
193 |
194 | startHandleAirdrop(index);
195 | }else{
196 |
197 | airdropResultCall(false);
198 | }
199 |
200 | //回调空投结果
201 | listen.stopListen();
202 | });
203 | }
204 |
205 | const airdropListManager = require('../filemanger/airdropListManager');
206 |
207 | function startAirdrop(filePath,addressIndex,amountIndex,addressNeedJudgeRepeat,resultCall){
208 |
209 | // get list
210 | airdropListManager.getAirdropList(filePath,addressIndex,amountIndex,addressNeedJudgeRepeat,function (addresses,amounts) {
211 |
212 | if (addresses.length === 0 || amounts.length === 0){
213 |
214 | console.log('空投列表数据读取错误');
215 |
216 | resultCall(false);
217 |
218 | return;
219 | }
220 |
221 | console.log('此次空投:'+addresses+'\n共计:'+addresses.length);
222 |
223 | transferWithAddressAndAmounts(addresses,amounts,resultCall);
224 | });
225 | }
226 |
227 | function sendLastPartAirdrop(){
228 |
229 | needSendLastList = true;
230 | }
231 |
232 | module.exports = {
233 | startAirdrop,
234 | sendLastPartAirdrop
235 | };
236 |
--------------------------------------------------------------------------------
/Airdrop/function/approve.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/1/29.
3 | */
4 |
5 | const Config = require('./../config/config.js');
6 |
7 | Web3 = require('web3');
8 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
9 |
10 | //init
11 | const Tx = require('ethereumjs-tx');
12 | const ethjsaccount = require('ethjs-account');
13 | const fs = require('fs');
14 | const solc = require('solc');
15 |
16 | // compile the code
17 | const input = fs.readFileSync('./../contract/erc20Token.sol');
18 | const output = solc.compile(input.toString());
19 | const abi = JSON.parse(output.contracts[':TokenERC20'].interface);
20 |
21 | //------------------------------ init property ----------------------------
22 |
23 | //amount of airdrop
24 | let amount = web3.utils.toWei(Config.approveModule.amount, 'ether');
25 | //airdrop contract address
26 | let airdropApproveAddress = Config.approveModule.approveAddress;
27 | //erc20 token contract address
28 | let tokenContractAddress = Config.approveModule.tokenContractAddress;
29 |
30 | //-------------------------------- contract --------------------------------
31 | let token = new web3.eth.Contract(abi, tokenContractAddress);
32 |
33 | let execute = require('./base/execute');
34 |
35 | function approveTransfer(approveAddress,amount,hashIdCall,successCall, errorCall) {
36 |
37 | let functionABI = token.methods.approve(approveAddress,amount).encodeABI();
38 |
39 | execute.executeFunction(tokenContractAddress,functionABI,hashIdCall,successCall,errorCall);
40 | }
41 |
42 | approveTransfer(airdropApproveAddress,amount,function (hashId) {
43 |
44 | console.log('approve HashId',hashId);
45 | },function (success) {
46 |
47 | console.log('execute approveTransfer success');
48 | },function (error) {
49 |
50 | console.log('execute approveTransfer error');
51 | });
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Airdrop/function/base/delpoy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/1/30.
3 | */
4 | const fs = require('fs');
5 | const solc = require('solc');
6 |
7 | const Config = require('../../config/config');
8 | Web3 = require('web3');
9 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
10 |
11 | const transaction = require('./transaction');
12 |
13 | function startDeployContract(contractPath,contractName,extraParameter,success,error) {
14 |
15 | // compile the code
16 | const input = fs.readFileSync(contractPath);
17 | const output = solc.compile(input.toString());
18 |
19 | const name = ':'+contractName;
20 |
21 | let bytecode = output.contracts[name].bytecode;
22 |
23 | if (extraParameter != null){
24 |
25 | const abi = JSON.parse(output.contracts[name].interface);
26 | let contract = new web3.eth.Contract(abi,'0x0000000000000000000000000000000000000000');
27 |
28 | let parameter = {
29 | data:bytecode,
30 | arguments:extraParameter
31 | };
32 |
33 | bytecode = contract.deploy(parameter).encodeABI();
34 | }
35 |
36 | let t = {
37 | value: '0x00',
38 | data: ('0x'+bytecode),
39 | };
40 |
41 | transaction.startTransaction(t,null,success,error);
42 | }
43 |
44 |
45 | module.exports = {
46 | deployContract:startDeployContract
47 | };
--------------------------------------------------------------------------------
/Airdrop/function/base/execute.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/1/30.
3 | */
4 |
5 | const transaction = require('./transaction');
6 |
7 | function executeFunction(toAddress,functionABI,getHashIdCall,success,error) {
8 |
9 | let t = {
10 | to:toAddress,
11 | value: '0x00',
12 | data: functionABI
13 | };
14 |
15 | transaction.startTransaction(t,getHashIdCall,success,error);
16 | }
17 |
18 | function executeFunctionWithExtraEth(toAddress,functionABI,value,getHashIdCall,success,error) {
19 |
20 | let t = {
21 | to:toAddress,
22 | value: value,
23 | data: functionABI
24 | };
25 |
26 | transaction.startTransaction(t,getHashIdCall,success,error);
27 | }
28 |
29 | module.exports = {
30 | executeFunction,
31 | executeFunctionWithExtraEth
32 | };
--------------------------------------------------------------------------------
/Airdrop/function/base/listen.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/3/22.
3 | */
4 |
5 | const sd = require('silly-datetime');
6 |
7 | let ws ;
8 | const Config = require('../../config/config.js');
9 |
10 | Web3 = require('web3');
11 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
12 |
13 | //airdrop contract address
14 | const airContractAddress = Config.airdropModule.airdropContractAddress;
15 | const networkType = Config.internetType;
16 |
17 | //heartbeat Number
18 | var intervalNumber ;
19 |
20 | //transcation result callback
21 | var hashSuccessBlock ;
22 |
23 | //judge hashId
24 | var listenHashId = '';
25 |
26 | //------------------------------ Websocket function --------------------------
27 |
28 | function startRinkebyListen(tokenAbi,tokenAddress,fromAddress) {
29 |
30 | var tokenContract = new web3.eth.Contract(tokenAbi, tokenAddress);
31 |
32 | console.log('start transaction listen');
33 |
34 | clearInterval(intervalNumber);
35 | //五秒轮询一次
36 | intervalNumber = setInterval(function () {
37 |
38 | web3.eth.getBlockNumber().then(function (fromBlockNumber ) {
39 |
40 | var time=sd.format(new Date(),'YYYY-MM-DD HH:mm:ss');
41 | console.log(time+':current search blockNumber->'+fromBlockNumber);
42 |
43 | tokenContract.getPastEvents('Transfer', {
44 | fromBlock: fromBlockNumber,
45 | filter: {from:fromAddress}
46 | }, function(error, events){
47 |
48 | if (judgeObjCalss(events,'array') === false){
49 |
50 | return;
51 | }
52 |
53 | //console.log(events);
54 | var event = events[0];
55 | console.log('\nevent:'+event);
56 |
57 | if (event != null){
58 |
59 | if (event.transactionHash == listenHashId){
60 |
61 | console.log('监听到hashId相符合的交易:',listenHashId);
62 | listenHashId = null;
63 |
64 | //stop heartbeat
65 | clearInterval(intervalNumber);
66 |
67 | //5分钟后回调
68 | setTimeout(function () {
69 | hashSuccessBlock();
70 | },1000 * 60 * 1);
71 | }
72 | }
73 | });
74 | });
75 |
76 | },1000 * 2);
77 | }
78 |
79 |
80 | function judgeObjCalss(obj,className) {
81 |
82 | if (className.indexOf('arr') !== -1 ){
83 |
84 | return Object.prototype.toString.call(obj) === '[object Array]';
85 | }
86 | }
87 |
88 | //------------------------------ API --------------------------
89 | let listenAirdropStatus = function(parameter,result) {
90 |
91 | listenHashId = parameter.hashId;
92 | hashSuccessBlock = result;
93 |
94 | startRinkebyListen(parameter.tokenAbi,parameter.tokenAddress,parameter.fromAddress);
95 | };
96 |
97 |
98 | let stopListen = function () {
99 |
100 | clearInterval(intervalNumber);
101 | };
102 |
103 | module.exports = {
104 | startListenAirdropResult:listenAirdropStatus,
105 | stopListen:stopListen
106 | };
107 |
--------------------------------------------------------------------------------
/Airdrop/function/base/transaction.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/1/30.
3 | */
4 |
5 | const Tx = require('ethereumjs-tx');
6 | const ethjsaccount = require('ethjs-account');
7 |
8 | const Config = require('../../config/config');
9 | Web3 = require('web3');
10 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
11 | //------------------------------ init property ----------------------------
12 |
13 | const userPrivateKey = Config.userModule.userPrivateKey;
14 |
15 | //------------------------------ api ----------------------------
16 | function blockTransaction(t,hashIdCall,success,error){
17 |
18 | let fromAddress = privateKeyToAddress(userPrivateKey);
19 |
20 | console.log('fromAddress',fromAddress);
21 |
22 | //get current gasPrice, you can use default gasPrice or custom gasPrice!
23 | web3.eth.getGasPrice().then(function(p) {
24 | //t.gasPrice = web3.utils.toHex(p);
25 | //1 Gwei
26 | t.gasPrice = web3.utils.toHex(Config.transaction.gasPrice);
27 | //get nonce
28 | web3.eth.getTransactionCount(fromAddress,
29 | function(err, r) {
30 | t.nonce = web3.utils.toHex(r);
31 | t.from = fromAddress;
32 |
33 | //get gasLimit value , you can use estimateGas or custom gasLimit!
34 | web3.eth.estimateGas(t,
35 | function(err, gas) {
36 | //web3.utils.toHex(gas);
37 | t.gasLimit = web3.utils.toHex(Config.transaction.gasLimit);
38 |
39 | //初始化transaction
40 | let tx = new Tx(t);
41 | let privateKey = new Buffer(userPrivateKey, 'hex');
42 |
43 | //sign
44 | tx.sign(privateKey);
45 | let serializedTx = '0x' + tx.serialize().toString('hex');
46 | //console.log("serializedTx----"+serializedTx);
47 |
48 | console.log("send signed transaction");
49 |
50 | //sendSignedTransaction
51 | web3.eth.sendSignedTransaction(serializedTx)
52 | .on('transactionHash',function(hash){
53 |
54 | console.log('hashId:'+ hash+'\n');
55 | hashIdCall(hash);
56 |
57 | }).on('receipt',function(receipt){
58 | //console.log('receipt:'+ JSON.stringify(receipt));
59 |
60 | let s = receipt.status;
61 | console.log("resultStatus:"+s);
62 |
63 | if(s == 1){
64 | success(receipt);
65 | }
66 | else {
67 | error(receipt);
68 | }
69 |
70 | }).on('confirmation',function(confirmationNumber, receipt){
71 |
72 | /*web3.eth.getBlockNumber(function (number) {
73 | console.log("number--"+number+"\n");
74 | });*/
75 | // console.log('entrance'+ JSON.stringify(confirmationNumber)+'--------------'+ JSON.stringify(receipt));
76 | }).on('error',function(error){
77 |
78 | console.log('Failure to send a signature transaction:'+error);
79 | });
80 | });
81 | });
82 | });
83 | };
84 |
85 |
86 | function privateKeyToAddress(privateKey) {
87 |
88 | let address = ethjsaccount.privateToAccount(privateKey).address;
89 | return address;
90 | }
91 |
92 | function startBlockTransaction(t,getHashIdCall,successCall,errorCall) {
93 |
94 | console.log('startBlockTransaction');
95 |
96 | blockTransaction(t,function (hashId) {
97 |
98 | if (getHashIdCall != null){
99 |
100 | getHashIdCall(hashId);
101 | }
102 |
103 | },function (success) {
104 |
105 | console.log("Transaction Success:\n"+JSON.stringify(success));
106 | if (successCall != null){
107 |
108 | successCall(success);
109 | }
110 |
111 | },function (error) {
112 |
113 | console.log("Failure to send a signature transaction:\n"+error);
114 |
115 | if (errorCall != null){
116 |
117 | errorCall(error);
118 | }
119 | });
120 | }
121 |
122 | module.exports = {
123 |
124 | startTransaction:startBlockTransaction
125 | };
--------------------------------------------------------------------------------
/Airdrop/function/deployAirdropContract.js:
--------------------------------------------------------------------------------
1 | const deploy = require('./base/delpoy');
2 |
3 | const contractPath = '../contract/airdrop.sol';
4 |
5 | const contractName = 'TokenAirDrop';
6 |
7 | deploy.deployContract(contractPath,contractName,null,function (success) {
8 |
9 | console.log('\ndeployConverterSuccess!!! \nblockHash:'+ success.transactionHash +' \ncontractAddress:'+success.contractAddress);
10 |
11 | },function (error) {
12 |
13 | console.log("error:"+JSON.stringify(error));
14 | });
--------------------------------------------------------------------------------
/Airdrop/function/example/converterProperty.js:
--------------------------------------------------------------------------------
1 |
2 | const Config = require('../../config/config.js');
3 |
4 | Web3 = require('web3');
5 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
6 |
7 | //contract address
8 | const contractPath = './../../contract/converter.sol';
9 |
10 | //-------------------------------- contract --------------------------------
11 |
12 | const fs = require('fs');
13 | const solc = require('solc');
14 | const input = fs.readFileSync(contractPath);
15 | const output = solc.compile(input.toString());
16 | const abi = JSON.parse(output.contracts[':BancorConverter'].interface);
17 |
18 | var token = new web3.eth.Contract(abi, '0x5e04821d5Af7616f37Bf13bcD920571635d4989B');
19 |
20 | token.methods.extensions().call(null,function(error,result){
21 | console.log("extensions -> "+result);
22 | });
23 | token.methods.manager().call(null,function(error,result){
24 | console.log("manager -> "+result);
25 | });
26 | token.methods.maxConversionFee().call(null,function(error,result){
27 | console.log("maxConversionFee -> "+result);
28 | });
29 | token.methods.conversionFee().call(null,function(error,result){
30 | console.log("conversionFee -> "+result);
31 | });
32 | token.methods.getQuickBuyPathLength().call(null,function(error,result){
33 | console.log("getQuickBuyPathLength -> "+result);
34 | });
--------------------------------------------------------------------------------
/Airdrop/function/example/deployConverter.js:
--------------------------------------------------------------------------------
1 | const deploy = require('../base/delpoy');
2 |
3 | const contractPath = '../../contract/converter.sol';
4 |
5 | const parameter = ['0xcf3774e690544a0741Ad31C89Bd4BD490faaE3B1','0xF46002C37af6fb078aE1833Fd447698A0C9012F7','30000','0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C',500000];
6 |
7 | const contractName = 'BancorConverter';
8 |
9 | deploy.deployContract(contractPath,contractName,parameter,function (success) {
10 |
11 | console.log('\ndeployConverterSuccess!!! \nblockHash:'+ success.transactionHash +' \ncontractAddress:'+success.contractAddress);
12 |
13 | },function (error) {
14 |
15 | console.log("error:"+JSON.stringify(error));
16 | });
17 |
18 | /*
19 | deploySmartTokenSuccess!!!
20 | blockHash:0x6beb8c85bc9ee7c08ac9c01c4d5a29b2f2de3dcf5e8a873740da38c6fac71c60
21 | contractAddress:0x5e04821d5Af7616f37Bf13bcD920571635d4989B
22 | * */
--------------------------------------------------------------------------------
/Airdrop/function/example/executeConverterFunction.js:
--------------------------------------------------------------------------------
1 |
2 | const fs = require('fs');
3 | const solc = require('solc');
4 |
5 | const Config = require('../../config/config');
6 |
7 | const contractPath = '../../contract/converter.sol';
8 | const contractName = 'BancorConverter';
9 |
10 | Web3 = require('web3');
11 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
12 |
13 | const input = fs.readFileSync(contractPath);
14 | const output = solc.compile(input.toString());
15 | const name = ':'+contractName;
16 |
17 | const abi = JSON.parse(output.contracts[name].interface);
18 |
19 | const tokenContractAddress = '0x5e04821d5Af7616f37Bf13bcD920571635d4989B';
20 |
21 | let token = new web3.eth.Contract(abi, tokenContractAddress);
22 |
23 | let execute = require('../base/execute');
24 |
25 | // executeAddConnector();
26 | // executeSetConversionFee();
27 | //executeSetQuickBuyPath();
28 | executeWithdrawTokens();
29 |
30 | function executeAddConnector(){
31 |
32 | let functionABI = token.methods.addConnector('0x5E6b6d9aBAd9093fdc861Ea1600eBa1b355Cd940',
33 | 500000,false).encodeABI();
34 |
35 | execute.executeFunction(tokenContractAddress,functionABI,function (hashId) {
36 |
37 | console.log('execute addConnector hashId->',hashId);
38 | },function (success) {
39 |
40 | console.log('execute addConnector success');
41 | },function (error) {
42 |
43 | console.log('execute addConnector error');
44 | });
45 | }
46 |
47 | function executeSetConversionFee(){
48 |
49 | let functionABI = token.methods.setConversionFee(1420).encodeABI();
50 |
51 | execute.executeFunction(tokenContractAddress,functionABI,function (success) {
52 |
53 | console.log('execute setConversionFee success');
54 | },function (error) {
55 |
56 | console.log('execute setConversionFee error');
57 | });
58 | }
59 |
60 |
61 | function executeSetQuickBuyPath(){
62 |
63 | const parmeter = [
64 | '0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315',
65 | '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C',
66 | '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C',
67 | '0xcf3774e690544a0741Ad31C89Bd4BD490faaE3B1',
68 | '0x5E6b6d9aBAd9093fdc861Ea1600eBa1b355Cd940'
69 | ];
70 |
71 | let functionABI = token.methods.setQuickBuyPath(parmeter).encodeABI();
72 |
73 | execute.executeFunction(tokenContractAddress,functionABI,function (success) {
74 |
75 | console.log('execute setQuickBuyPath success');
76 | },function (error) {
77 |
78 | console.log('execute setQuickBuyPath error');
79 | });
80 | }
81 |
82 | function executeWithdrawTokens(){
83 |
84 | let functionABI = token.methods.withdrawTokens('0xc0eE6Df91C455c64928F1F179C2B84eb61E58870','0x5E6b6d9aBAd9093fdc861Ea1600eBa1b355Cd940',33 * 100000 * 100000 * 100000 * 1000).encodeABI();
85 |
86 | execute.executeFunction(tokenContractAddress,functionABI,function (success) {
87 |
88 | console.log('execute withdrawTokens success');
89 | },function (error) {
90 |
91 | console.log('execute withdrawTokens error');
92 | });
93 | }
--------------------------------------------------------------------------------
/Airdrop/function/transferETH.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/3/27.
3 | */
4 |
5 | const Config = require('./../config/config.js');
6 |
7 | Web3 = require('web3');
8 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
9 |
10 | const execute = require('./base/execute');
11 |
12 | //-------------------------------- api --------------------------------
13 | function transferEth(toAddress,amount,hashIdCallBack,successCall, errorCall) {
14 |
15 | let valueHex = web3.utils.toHex(amount);
16 | execute.executeFunctionWithExtraEth(toAddress,'0x00',valueHex,hashIdCallBack,successCall,errorCall);
17 | }
18 |
19 |
20 | function startTransferETH() {
21 |
22 | let ethAmount = '0.1';
23 | ethAmount = web3.utils.toWei(ethAmount, 'ether');
24 |
25 | transferEth('your address',ethAmount,function (hashId) {
26 | console.log('start TransferETH transcation!');
27 | },function (success) {
28 | console.log('TransferETH success!');
29 | },function (error) {
30 | console.log('TransferETH falid!');
31 | });
32 | }
33 |
34 | startTransferETH();
--------------------------------------------------------------------------------
/Airdrop/function/transferToken.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhaoyiyu on 2018/3/27.
3 | */
4 |
5 | const Config = require('./../config/config.js');
6 |
7 | Web3 = require('web3');
8 | const web3 = new Web3(new Web3.providers.HttpProvider(Config.transaction.url));
9 |
10 | //init
11 | const Tx = require('ethereumjs-tx');
12 | const ethjsaccount = require('ethjs-account');
13 | const fs = require('fs');
14 | const solc = require('solc');
15 |
16 | // compile the code
17 | const tokenInput = fs.readFileSync('./../contract/erc20Token.sol');
18 | const tokenOutput = solc.compile(tokenInput.toString());
19 | const tokenAbi = JSON.parse(tokenOutput.contracts[':TokenERC20'].interface);
20 |
21 |
22 | //-------------------------------- api --------------------------------
23 | let execute = require('./base/execute');
24 |
25 | let transferToken = function(tokenContractAddress,toAddress,amount,hashIdCallBack,successCall, errorCall) {
26 |
27 | let tokenContract = new web3.eth.Contract(tokenAbi, tokenContractAddress);
28 | let functionABI = tokenContract.methods.transfer(toAddress,amount).encodeABI();
29 |
30 | execute.executeFunction(tokenContractAddress,functionABI,hashIdCallBack,successCall,errorCall);
31 | };
32 |
33 | function startTransferToken() {
34 |
35 | let amount = '0.01';
36 | let obj = web3.utils.toWei(amount, 'ether');
37 |
38 | let tokenAddress = 'your token address';
39 |
40 | transferToken(tokenAddress,'your destination address',obj,function (hashId) {
41 | console.log('start transfer Token!,hashId->',hashId);
42 | },function (success) {
43 |
44 | console.log('transferToken success!');
45 | },function (error) {
46 |
47 | console.log('transferToken falid!');
48 | });
49 | }
50 |
51 | startTransferToken();
--------------------------------------------------------------------------------
/Airdrop/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "airdrop",
3 | "version": "1.0.0",
4 | "main": "airdrop.js",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1"
7 | },
8 | "author": "",
9 | "license": "ISC",
10 | "dependencies": {
11 | "ethereumjs-tx": "^1.3.3",
12 | "ethjs-account": "^0.1.4",
13 | "node-schedule": "^1.3.0",
14 | "node-xlsx": "^0.11.2",
15 | "silly-datetime": "^0.1.2",
16 | "solc": "^0.4.20",
17 | "web3": "^1.0.0-beta.30"
18 | },
19 | "description": ""
20 | }
21 |
--------------------------------------------------------------------------------
/Airdrop/start.js:
--------------------------------------------------------------------------------
1 |
2 | const airdrop = require('./function/airdrop');
3 |
4 | function withdraw(){
5 |
6 | excelPath = './filemanger/xlsx/withdraw_sequence_1_20180705.xlsx';
7 | //开始进行空投
8 |
9 | airdrop.startAirdrop(excelPath,0,1,false,function (status) {
10 |
11 | console.log('airdrop result => '+status);
12 | console.log('等待系统重置');
13 | });
14 | }
15 |
16 | withdraw()
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 IoTChain Project(ITC)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ERC20TokenAridrop
2 | This project can be used for all ERC20 based tokens for airdrop distribution!
3 | 1. A single transmission can support up to two hundred transfers.
4 | 2. Realize the monitoring transaction status and automatically send the next one.
5 | 3. The implementation fee is reduced to 0.000045--0.00007 eth/transcation.
6 |
7 | --------------------------------------------------------------------
8 | Airdrop
9 | ——config
10 | config.js
11 | ——contract
12 | *.sol
13 | ——filemanger
14 | airdropListManager.js
15 | awards.js
16 | errorAirdropList.js
17 | excelHandleManager.js
18 | ——function
19 | ——base
20 | deploy.js
21 | execute.js
22 | listen.js
23 | transaction.js
24 | airdrop.js
25 | approve.js
26 | deployAirdropContract.js
27 | transferETH.js
28 | transferToken.js
29 | start.js
30 |
31 | --------------------------------------------------------------------
32 | # Dependency library
33 | web3 solc ethereumjs-tx ethjs-account node-xlsx node-schedule silly-datetime
34 |
35 | # Description of some key files
36 | ## --- deploy.js
37 | This deploy.js can help you deploy the contract,you need set the'userPrivateKey' in config.js and run the func .
38 |
39 | parameters:
40 | 'contractPath' is mean that path of your contract.sol file,
41 | 'contractName' is the contract name which you want to deploy,
42 | 'extraParameter' is the parameters of what you need to init your contract.
43 |
44 | The contract address will be printed on the console and save the contract address in your file!
45 |
46 | ## --- approve.js
47 | This approve.js can help you authorize the airdrop contract address to use your specified number of tokens from your account;
48 | you need set 'amount','airdropApproveAddress','userPrivateKey' and 'tokenContractAddress'
49 | then run approve.js , it will print the txHash and transfer result;
50 |
51 | ## --- airdrop.js
52 | This airdrop.js is an executive document of the airdrop contract.
53 |
54 | parameters:
55 | 'filePath':your airdrop address file,and i am using the *.xlsx
56 | 'addressIndex': this means the index of eth address in your *.xlsx,
57 | 'amountIndex': this means the index of token amount in your *.xlsx,
58 | 'addressNeedJudgeRepeat': this parameter represents whether you want to filter duplicate addresses.
59 |
60 | ## --- execute.js
61 | This execute.js can execute the function of your contract.
62 |
63 | parameters:
64 | 'functionABI' is the data of your want to send in this transaction.
65 |
66 | ## --- config.js
67 | This config.js is the config file, contain 'userModule','airdropModule','approveModule'
68 |
69 |
70 | The airdrop sequence is as follows:
71 | 1. Deploy ERC20Token contract and airdrop contract.
72 | 2. Approve enough ERC20 tokens to the airdrop contract.
73 | 3. Compile a list of reciepient addresses and store them in 'airdropList.txt' file.
74 | 4. Run 'start.js' script.
75 | 5. You can look the airdrop result on the console or check the txHash in 'https://etherscan.io';
76 |
77 | If you are not familiar with the smart contract, then follow the steps below!
78 | 1. run npm install
79 | 2. Config your userPrivateKey and other info in config.js
80 | 3. Run deploy.js , then you will get the result on console
81 | 4. copy the contractAddress on the console, and paste it in config.js ->approveModule->airdropApproveAddress
82 | 5. Config your tokenContractAddress and userPrivateKey in config.js ->approveModule. this userPrivateKey is the private key of the account which you want to use for transfer token;
83 | 6. Run approve.js, then your will get the result on console .
84 | 7. The address and number of airdrop will be required to be listed in xlsx.
85 | 8. Run 'start.js' script.
86 | 9. You can check the airdrop result on the console or check the txHash in 'https://etherscan.io'.
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------