Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcb11204

Browse files
committed
🚀 initial commit
0 parents  commitcb11204

File tree

17 files changed

+1391
-0
lines changed

17 files changed

+1391
-0
lines changed

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.env

‎config.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
if(!process.env.PUBLIC_KEY&&!process.env.PRIVATE_KEY&&!process.env.ETH_IN_AMOUNT&&!process.env.DB_URL){
2+
3+
thrownewError("PUBLIC_KEY && PRIVATE_KEY && ETH_IN_AMOUNT && DB_URL, Must be defined in your .env file");
4+
}
5+
exportconstconfig={
6+
WALLET:{
7+
PUBLIC_KEY:process.env.PUBLIC_KEY!,
8+
PRIVATE_KEY:process.env.PRIVATE_KEY!
9+
},
10+
PROVIDERS:{
11+
INFURA_API_KEY:''
12+
},
13+
NETWORK:{
14+
ID:1// 1 eth, 56 is bsc, 137 polygon, 10 optimism, 42161 arbitrum
15+
},
16+
PRICE_CHECK_INTERVAL_IN_SECONDS:process.env.PRICE_CHECK_INTERVAL_IN_SECONDS||45,
17+
ETH_IN_AMOUNT:parseFloat(process.env.ETH_IN_AMOUNT!),
18+
DB_URL:process.env.DB_URL!
19+
20+
}

‎example.env‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Wallet
2+
PRIVATE_KEY=''
3+
PUBLIC_KEY=''
4+
5+
PRICE_CHECK_INTERVAL_IN_SECONDS=45
6+
7+
# Trading Preference
8+
ETH_IN_AMOUNT='1'
9+
10+
# Database
11+
DB_URL=''

‎package.json‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name":"multidexarbbot",
3+
"version":"1.0.0",
4+
"description":"",
5+
"main":"src/index.ts",
6+
"scripts": {
7+
"test":"echo\"Error: no test specified\" && exit 1",
8+
"start":"ts-node-dev -r dotenv/config src/index.ts"
9+
},
10+
"author": {
11+
"name":"Dennoh Peter",
12+
"email":"dennoh@coredevs.co"
13+
},
14+
"keywords": [
15+
"Arbitrage",
16+
"MultiDex",
17+
"Trading"
18+
],
19+
"license":"MIT",
20+
"dependencies": {
21+
"@types/node-cron":"^3.0.0",
22+
"axios":"^0.22.0",
23+
"bignumber.js":"^9.0.1",
24+
"chalk":"^4.1.2",
25+
"chalk-table":"^1.0.2",
26+
"dotenv":"^10.0.0",
27+
"ethers":"^5.4.7",
28+
"mongoose":"^6.0.9",
29+
"node-cron":"^3.0.0",
30+
"telegraf":"^4.4.2"
31+
}
32+
}

‎src/data/token.ts‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
exportconstMONITORED_TOKENS=[
2+
3+
// { address: "0xdac17f958d2ee523a2206206994597c13d831ec7", symbol: "USDT", name: "USD Tether" },
4+
{address:"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",symbol:"USDC",name:"USD Coin"},
5+
// { address: "0x6b175474e89094c44da98b954eedeac495271d0f", symbol: "DAI", name: "MakerDao StableCoin" },
6+
// // { address: "0x3845badade8e6dff049820680d1f14bd3903a5d0", symbol: "SAND", name: "Sandbox" },
7+
// { address: "0xd46ba6d942050d489dbd938a2c909a5d5039a161", symbol: "AMPL", name: "Ampleforth" },
8+
// // { address: "0x956f47f50a910163d8bf957cf5846d573e7f87ca", symbol: "FEI", name: "Fei Protocol StableCoin" },
9+
// { address: "0xbc396689893d065f41bc2c6ecbee5e0085233447", symbol: "PERP", name: "Defi Trading Platform with AMMs" },
10+
// // { address: "0x1453dbb8a29551ade11d89825ca812e05317eaeb", symbol: "TEND", name: "Tendies" },
11+
// // { address: "0x2b591e99afe9f32eaa6214f7b7629768c40eeb39", symbol: "HEX", name: "Staking" },
12+
// { address: "0xe53ec727dbdeb9e2d5456c3be40cff031ab40a55", symbol: "SUPER", name: "SuperFarm" },
13+
// { address: "0xa47c8bf37f92abed4a126bda807a7b7498661acd", symbol: "UST", name: "Mirror StableCoin" },
14+
// // { address: "0x853d955acef822db058eb8505911ed77f175b99e", symbol: "FRAX", name: "Frax" },
15+
// { address: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", symbol: "WBTC", name: "Wrapped Bitcoin" },
16+
// // { address: "0x72e364f2abdc788b7e918bc238b21f109cd634d7", symbol: "MVI", name: "Metaverse Virtual Reality" },
17+
// // { address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", symbol: "SHIB", name: "Shiba Inu" },
18+
// { address: "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", symbol: "UNI", name: "Uniswap" },
19+
// // { address: "0x1c9922314ed1415c95b9fd453c3818fd41867d0b", symbol: "TOWER", name: "Crazy Defense Heroes" },
20+
// // { address: "0x990f341946a3fdb507ae7e52d17851b87168017c", symbol: "STRONG", name: "StrongBlock Eth MasterNodes as a service" },
21+
// // { address: "0x07150e919b4de5fd6a63de1f9384828396f25fdc", symbol: "BASE", name: "Base Protocol" },
22+
// // { address: "0xc770eefad204b5180df6a14ee197d99d808ee52d", symbol: "FOX", name: "Fox" },
23+
// // { address: "0xfb7b4564402e5500db5bb6d63ae671302777c75a", symbol: "DEXT", name: "Dex Tools " },
24+
// // { address: "0x514910771af9ca656af840dff83e8264ecf986ca", symbol: "LINK", name: "Chainlink Oracle" },
25+
// { address: "0x557b933a7c2c45672b610f8954a3deb39a51a8ca", symbol: "REVV", name: "REv Motorsport" },
26+
// { address: "0x09a3ecafa817268f77be1283176b946c4ff2e608", symbol: "MIR", name: "Mirror Protocol" },
27+
{address:"0x8e870d67f660d95d5be530380d0ec0bd388289e1",symbol:"PAX",name:"Paxos Standard"},
28+
{address:"0x111111111117dc0aa78b770fa6a738034120c302",symbol:"1INCH",name:"1Inch Token"},
29+
{address:"0x0f5d2fb29fb7d3cfee444a200298f468908cc942",symbol:"MANA",name:"Decentralland"},
30+
{address:"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",symbol:"MATIC",name:"Polygon Network"},
31+
{address:"0xde30da39c46104798bb5aa3fe8b9e0e1f348163f",symbol:"GTC",name:"GitCoin"},
32+
{address:"0xa0246c9032bc3a600820415ae600c6388619a14d",symbol:"FARM",name:"Harvest Finance Staking"},
33+
{address:"0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f",symbol:"SNX",name:"Synthetix"},
34+
{address:"0xd2877702675e6ceb975b4a1dff9fb7baf4c91ea9",symbol:"LUNA",name:"Mirror synthetics protocol token"},
35+
{address:"0x35a532d376ffd9a705d0bb319532837337a398e7",symbol:"WDOGE",name:"Wrapped DogeCoin"},
36+
]

‎src/index.ts‎

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
importchalkfrom"chalk";
2+
import{connect}from"mongoose";
3+
import{schedule}from"node-cron";
4+
import{config}from"../config";
5+
import{OneInch}from"./lib/1inch.io";
6+
import{Quote,Token}from"./types/1inch";
7+
constchalkTable=require('chalk-table');
8+
importBigNumberfrom"bignumber.js";
9+
import{flat}from"./utils";
10+
import{MONITORED_TOKENS}from"./data/token";
11+
12+
constMain=async()=>{
13+
constoneInch=newOneInch()
14+
console.log('Starting...');
15+
console.log(`---`.repeat(10));
16+
17+
// try {
18+
// bot.stop()
19+
// }
20+
// catch (err) {
21+
// }
22+
23+
// console.log('Connecting to telegram bot...\n---');
24+
// await bot.launch().then((result) => {
25+
// console.log('Connected to telegram bot!');
26+
27+
// }).catch(async (err) => {
28+
// let error = JSON.parse(JSON.stringify(err))
29+
// console.log('Telegram Error:', error?.message);
30+
31+
// }).catch((error: any) => {
32+
// console.log('Telegram error:', error);
33+
// })
34+
35+
// console.log(`---`.repeat(10));
36+
console.log('Connecting to MongoDb...\n---');
37+
constoptions={
38+
useNewUrlParser:true,
39+
useUnifiedTopology:true,
40+
useCreateIndex:true,
41+
keepAlive:true,
42+
connectTimeoutMS:60000,
43+
socketTimeoutMS:60000,
44+
}
45+
46+
awaitconnect(config.DB_URL,options).then((result)=>{
47+
console.log("Connected to MongoDb :)");
48+
}).catch(async(err)=>{
49+
leterror=JSON.parse(JSON.stringify(err))
50+
console.log('Mongo Error:',error?.name);
51+
});
52+
console.log(`---`.repeat(10));
53+
54+
awaitoneInch.getProtocols()
55+
.then((protocols:string[])=>{
56+
console.log(`Finding the best route for trade on the following exchanges${protocols.join(', ')}...`);
57+
})
58+
.catch((err:any)=>{})
59+
60+
console.log(`---`.repeat(10));
61+
62+
letethAmount=newBigNumber(config.ETH_IN_AMOUNT).shiftedBy(18).toString()
63+
schedule(`*/${config.PRICE_CHECK_INTERVAL_IN_SECONDS} * * * * *`,asyncfunction(){
64+
console.log(`***`.repeat(10));
65+
MONITORED_TOKENS.forEach(async(token:any)=>{
66+
try{
67+
constbuy_quote:Quote=awaitoneInch.getQuote({
68+
srcToken:'0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
69+
toToken:token.address,
70+
srcAmount:ethAmount
71+
})
72+
lettoken_amount=buy_quote.toAmount
73+
constsell_quote:Quote=awaitoneInch.getQuote({
74+
srcToken:token.address,
75+
toToken:buy_quote.srcToken.address,
76+
srcAmount:token_amount
77+
})
78+
79+
constoptions={
80+
leftPad:0,
81+
columns:[
82+
{field:"eth_in",name:chalk.cyan("ETH IN")},
83+
{field:"buy_on_dex",name:chalk.green(`BEST BUY ROUTEs`)},
84+
{field:"sell_on_dex",name:chalk.yellow("BEST SELL ROUTEs")},
85+
{field:"token_amount",name:chalk.yellow("Token OUT")},
86+
{field:"eth_out",name:chalk.yellow("ETH OUT")},
87+
{field:"profit",name:chalk.yellow("PROFIT PCT")},
88+
{field:"time",name:chalk.magenta("Time 📅")},
89+
{field:"rate",name:chalk.blue("Fetch Rate 🕠")},
90+
]
91+
};
92+
consttimestamp=newDate()
93+
leteth_out=parseFloat(newBigNumber(sell_quote.toAmount).shiftedBy(-sell_quote.toToken.decimals).toFixed(6))
94+
constprofit_pct=((eth_out-config.ETH_IN_AMOUNT)/config.ETH_IN_AMOUNT)*100
95+
lettoken_out=parseFloat(newBigNumber(token_amount).shiftedBy(-buy_quote.toToken.decimals).toFixed(6))
96+
letbest_buy_protocols=(awaitflat(buy_quote.protocols)).map((quote:any)=>quote.name).join(',')
97+
letbest_sell_protocols=(awaitflat(sell_quote.protocols)).map((quote:any)=>quote.name).join(',')
98+
consttable=chalkTable(options,[
99+
{
100+
eth_in:config.ETH_IN_AMOUNT,
101+
buy_on_dex:best_buy_protocols,
102+
sell_on_dex:best_sell_protocols,
103+
token_amount:`${token_out}${buy_quote.toToken.symbol}`,
104+
eth_out:`${eth_out}${sell_quote.toToken.symbol}`,
105+
profit:`${profit_pct.toFixed(6)}%`,
106+
time:timestamp.toISOString().replace(/T/,' ').replace(/\..+/,''),
107+
rate:`${config.PRICE_CHECK_INTERVAL_IN_SECONDS}s`
108+
},
109+
]);
110+
if(!(JSON.stringify(best_buy_protocols)==JSON.stringify(best_sell_protocols))){
111+
console.log(table);
112+
}
113+
114+
}catch(error:any){
115+
console.error('Error:',JSON.parse(JSON.stringify(error)).code);
116+
}
117+
118+
});
119+
})
120+
121+
}
122+
123+
124+
Main()

‎src/lib/1inch.io.ts‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
importaxiosfrom"axios";
2+
import{config}from"../../config";
3+
import{Quote}from"../types/1inch";
4+
import{Aggr}from"./aggr";
5+
6+
exportclassOneInchextendsAggr{
7+
constructor(){
8+
super(`1Inch`,`https://api.1inch.exchange/v3.0/`);
9+
}
10+
getQuote=async(params:{srcToken:string,toToken:string,srcAmount:number|string,side?:string}):Promise<Quote>=>{
11+
const{ srcToken, toToken, srcAmount, side}=params
12+
try{
13+
const{ data}:any=awaitaxios({
14+
method:'GET',
15+
url:`${this.API_URL}${config.NETWORK.ID}/quote?fromTokenAddress=${srcToken}&toTokenAddress=${toToken}&amount=${srcAmount}`
16+
})
17+
return{
18+
srcToken:data.fromToken,
19+
srcAmount:data.fromTokenAmount,
20+
toToken:data.toToken,
21+
toAmount:data.toTokenAmount,
22+
protocols:data.protocols
23+
}
24+
}catch(error:any){
25+
thrownewError(JSON.stringify(error));
26+
27+
}
28+
}
29+
buildTx=async(srcToken:string,toToken:string,srcAmount:number,slippage?:number):Promise<string>=>{
30+
try{
31+
const{ data}=awaitaxios({
32+
method:"GET",
33+
url:`${this.API_URL}${config.NETWORK.ID}/swap?fromTokenAddress=${srcToken}&toTokenAddress=${toToken}&amount=${srcAmount}&fromAddress=${config.WALLET.PUBLIC_KEY}&disableEstimate=true${slippage ?`&slippage=${slippage}` :''}`
34+
})
35+
returndata
36+
}catch(error:any){
37+
thrownewError(JSON.stringify(error));
38+
}
39+
}
40+
41+
getProtocols=async():Promise<string[]>=>{
42+
try{
43+
const{ data}:any=awaitaxios({
44+
method:"GET",
45+
url:`${this.API_URL}${config.NETWORK.ID}/protocols`
46+
})
47+
returndata.protocols
48+
49+
}catch(error){
50+
thrownewError(JSON.stringify(error));
51+
}
52+
}
53+
54+
}

‎src/lib/aggr.ts‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import{ethers,Wallet}from"ethers";
2+
import{config}from"../../config";
3+
4+
exportabstractclassAggr{
5+
readonlyname:string;
6+
readonlyprovider:ethers.providers.JsonRpcProvider;
7+
readonlyaccount:Wallet
8+
readonlyAPI_URL:string
9+
10+
constructor(name:string,api_url:string){
11+
this.name=name;
12+
this.provider=newethers.providers.JsonRpcProvider(config.PROVIDERS.INFURA_API_KEY)
13+
this.account=newWallet(config.WALLET.PRIVATE_KEY,this.provider);
14+
this.API_URL=api_url
15+
}
16+
17+
sendTx=async(params:{data:any,nonce:number})=>{
18+
const{ data, nonce}=params
19+
try{
20+
21+
if(!isNaN(nonce)){
22+
data.nonce=nonce
23+
}
24+
25+
consttx=awaitthis.account.sendTransaction(data)
26+
returntx
27+
console.log("Tx success");
28+
}catch(e){
29+
thrownewError(`Tx failure${e}`);
30+
}
31+
}
32+
33+
/**
34+
* Gets balance of a token in a wallet address
35+
*@param tokenAddress token address to check to check balance
36+
*@returns balance of token in a wallet
37+
*/
38+
balanceOf=async(tokenAddress:string)=>{
39+
letcontract=newethers.Contract(
40+
tokenAddress,
41+
['function balanceOf(address account) external view returns (uint256)'],
42+
this.account
43+
)
44+
returnawaitcontract.balanceOf(config.WALLET.PUBLIC_KEY);
45+
46+
}
47+
48+
/**
49+
* Gets the current nonce of a wallet
50+
*@returns nonce
51+
*/
52+
getNonce=async():Promise<number>=>{
53+
returnawaitthis.provider.getTransactionCount(config.WALLET.PUBLIC_KEY)
54+
}
55+
}

‎src/lib/dex.ag.ts‎

Whitespace-only changes.

‎src/lib/index.ts‎

Whitespace-only changes.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp