Skip to content

Commit

Permalink
feat: publish config
Browse files Browse the repository at this point in the history
  • Loading branch information
LI-YONG-QI committed May 14, 2024
1 parent 811831a commit ca7adaa
Show file tree
Hide file tree
Showing 32 changed files with 2,284 additions and 89 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "publish package to npm"

on: push

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: node
uses: actions/setup-node@v2
with:
node-version: 16
registry-url: https://registry.npmjs.org
- name: publish
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}
52 changes: 18 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,39 @@ This is a script for automatic interaction with the onchain protocol by setting
# Supported protocols

1. Base AAVE
- deposit 0.001 ETH -> approve -> withdraw
- Deposit ETH -> approve -> withdraw
2. Base Uniswap
- swap DAI <-> 0.0001 ETH
- Swap DAI <-> ETH

# How to start ?
# Getting started

Two options for starting the bot

1. Node.js
2. Docker

## Prerequisites

Create `.env` file with `.env.example`

You can change default value of variables in `.env.example` to `.env` if you need

## Docker

1. Build image
1. Install CLI globally

```bash
npm run docker:build
npm install -g airdrop-bot
```

2. Run container
2. Check version

```bash
npm run docker:run
airdrop-bot -v
# 0.0.1
```

3. Check docker logs
3. Interact protocols (AAVE / Uniswap)

```bash
npm run docker:logs
```

## Node.js

1. Install packages
For example, interact aave by 0.01 ETH and setup delay 10 minutes

```bash
yarn
```
# set your private key to environment variables
export PK=<your-private-key>

2. Run app
# check private key
echo $PK
```

```bash
npm run app
airdrop-bot aave -p $PK --delay 10 --amount 0.01
```

---
Expand All @@ -72,8 +56,8 @@ Account <Public address from $PK>

Print below information when starting a new round

- Trigger start/end time (yime zone: Asia/Taipei)
- Random delay seconds (limit base on `$DELAY` variable in `.env`)
- Trigger start / end time (time zone: Asia/Taipei)
- Random delay seconds (limit base on `--delay` command option)
- Each txs hash and status (retry sent tx if status is `reverted`)

```bash
Expand Down
18 changes: 18 additions & 0 deletions dist/commands/aave.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.aave = void 0;
const viem_1 = require("viem");
const commander_1 = require("commander");
const protocol_1 = require("../types/protocol");
const aave_1 = require("../utils/aave");
exports.aave = new commander_1.Command("aave");
exports.aave
.description("Start the aave protocol")
.option("-p, --pk <private key>", "private key of signer")
.option(" --amount <amount>", "amount of ETH")
.option("-d, --delay <delay time>", "delay in minutes")
.action((options) => {
const cronTab = process.env.CRONJOB || "* * * * * *";
const aaveProtocol = new protocol_1.Protocol(aave_1.aave, options.pk, (0, viem_1.parseEther)(options.amount), cronTab, Number(options.delay));
aaveProtocol.execute();
});
18 changes: 18 additions & 0 deletions dist/commands/uniswap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniswap = void 0;
const viem_1 = require("viem");
const commander_1 = require("commander");
const protocol_1 = require("../types/protocol");
const uniswap_1 = require("../utils/uniswap");
exports.uniswap = new commander_1.Command("uniswap");
exports.uniswap
.description("Start the uniswap protocol")
.option("-p, --pk <private key>", "private key of signer")
.option(" --amount <amount>", "amount of ETH")
.option("-d, --delay <delay time>", "delay in minutes")
.action((options) => {
const cronTab = process.env.CRONJOB || "* * * * * *";
const uniswapProtocol = new protocol_1.Protocol(uniswap_1.uniswap, options.pk, (0, viem_1.parseEther)(options.amount), cronTab, Number(options.delay));
uniswapProtocol.execute();
});
18 changes: 18 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.program = void 0;
const commander_1 = require("commander");
const figlet_1 = require("figlet");
const aave_1 = require("./commands/aave");
const uniswap_1 = require("./commands/uniswap");
console.log((0, figlet_1.textSync)("BOT"));
exports.program = new commander_1.Command();
// Main
exports.program
.version("0.0.1", "-v, --versions", "output the current version")
.description("A simple airdrop bot")
.addCommand(uniswap_1.uniswap)
.addCommand(aave_1.aave)
.showHelpAfterError("(add --help for additional information)");
exports.program.parse();
30 changes: 30 additions & 0 deletions dist/libs/cron.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createConfig = void 0;
const time_1 = require("./time");
function createConfig(interaction, cronTime, delay) {
return {
cronTime: cronTime,
onTick: function () {
return __awaiter(this, void 0, void 0, function* () {
console.log("Start new round");
yield (0, time_1.randomDelay)(delay);
yield interaction();
console.log(`End time ${(0, time_1.getTime)()}`);
console.log("=============================");
});
},
start: true,
timeZone: "Asia/Taipei",
};
}
exports.createConfig = createConfig;
38 changes: 38 additions & 0 deletions dist/libs/time.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.delay = exports.randomDelay = exports.getTime = void 0;
function getTime() {
const date = new Date(Date.now());
const formatStakeTime = date.toLocaleString("zh-TW", {
timeZone: "Asia/Taipei",
});
return formatStakeTime;
}
exports.getTime = getTime;
function randomDelay() {
return __awaiter(this, arguments, void 0, function* (delay_ = 0) {
const MINUTES = 60; // 60 seconds
const LIMIT = Number(delay_) * MINUTES; // 最多不超過延遲 $DELAY 分鐘
const rand = Math.floor(Math.random() * LIMIT);
console.log(`Start time: ${getTime()} | Delay ${rand} seconds`);
yield delay(rand * 1000);
});
}
exports.randomDelay = randomDelay;
function delay(ms) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
});
}
exports.delay = delay;
30 changes: 30 additions & 0 deletions dist/libs/transaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendTransaction = void 0;
const public_1 = require("../utils/clients/public");
function sendTransaction(request, signer) {
return __awaiter(this, void 0, void 0, function* () {
while (1) {
const hash = yield signer.writeContract(request);
const transaction = yield public_1.PUBLIC_CLIENT.waitForTransactionReceipt({
confirmations: 5,
hash,
pollingInterval: 12000,
});
console.log(`Tx Hash: ${transaction.transactionHash} - ${transaction.status}`);
if (transaction.status === "success")
break;
console.log("Reverted !! Retrying...");
}
});
}
exports.sendTransaction = sendTransaction;
37 changes: 37 additions & 0 deletions dist/types/protocol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Protocol = void 0;
const cron_1 = require("cron");
const viem_1 = require("viem");
const accounts_1 = require("viem/accounts");
const cron_2 = require("../libs/cron");
const config_1 = require("../utils/clients/config");
class Protocol {
constructor(interaction, privateKey, amount, cronTime = "* * * * * *", delay = 0) {
this.amount = amount;
this.cronTime = cronTime;
this.delay = delay;
const _signer = this.setSigner(privateKey);
const _interaction = interaction.bind(null, _signer, amount);
const config = (0, cron_2.createConfig)(_interaction, cronTime, delay);
this.cron = new cron_1.CronJob(config.cronTime, config.onTick, null, config.start, config.timeZone);
}
execute() {
var _a;
console.log(`Starting app ...`);
console.log(`Mode ${process.env.MODE}`);
console.log(`Time ${this.cronTime} | Delay ${this.delay} minutes`);
console.log(`Account ${(_a = this.signer.account) === null || _a === void 0 ? void 0 : _a.address}`);
this.cron.start();
}
getSigner() {
return this.signer;
}
setSigner(privateKey) {
const account = (0, accounts_1.privateKeyToAccount)(privateKey);
const _signer = (0, viem_1.createWalletClient)(Object.assign({ account }, config_1.CONFIG));
this.signer = _signer;
return _signer;
}
}
exports.Protocol = Protocol;
42 changes: 42 additions & 0 deletions dist/utils/aave.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.aave = void 0;
const viem_1 = require("viem");
const transaction_1 = require("../libs/transaction");
const aave_1 = require("./contracts/aave");
function deposit(signer, amount) {
return __awaiter(this, void 0, void 0, function* () {
const { account } = signer;
const { request } = yield aave_1.AAVE.simulate.depositETH([viem_1.zeroAddress, account.address, 0], {
value: amount,
account,
});
console.log("Deposit...");
yield (0, transaction_1.sendTransaction)(request, signer);
});
}
function withdraw(signer, amount) {
return __awaiter(this, void 0, void 0, function* () {
const { account } = signer;
const { request: approveReq } = yield aave_1.WETH.simulate.approve([aave_1.AAVE.address, amount], { account: account });
console.log("Approving...");
yield (0, transaction_1.sendTransaction)(approveReq, signer);
const { request: withdrawReq } = yield aave_1.AAVE.simulate.withdrawETH([viem_1.zeroAddress, amount, account.address], { account: account });
console.log("Withdraw...");
yield (0, transaction_1.sendTransaction)(withdrawReq, signer);
});
}
const aave = (_signer, amount) => __awaiter(void 0, void 0, void 0, function* () {
yield deposit(_signer, amount);
yield withdraw(_signer, amount);
});
exports.aave = aave;
36 changes: 36 additions & 0 deletions dist/utils/clients/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CONFIG = void 0;
const chains_1 = require("viem/chains");
const viem_1 = require("viem");
const dotenv = __importStar(require("dotenv"));
dotenv.config({
path: `.env${process.env.NODE_ENV ? `.${process.env.NODE_ENV}` : ""}`,
});
exports.CONFIG = {
chain: process.env.MODE === "dev" ? chains_1.sepolia : chains_1.base,
transport: (0, viem_1.http)(process.env.RPC),
};
6 changes: 6 additions & 0 deletions dist/utils/clients/public.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PUBLIC_CLIENT = void 0;
const viem_1 = require("viem");
const config_1 = require("./config");
exports.PUBLIC_CLIENT = (0, viem_1.createPublicClient)(config_1.CONFIG);
Loading

0 comments on commit ca7adaa

Please sign in to comment.