From 26a20afe59838439db9476e17f8a2b8c37ed5640 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 20:23:05 +0100
Subject: [PATCH 01/16] Update LimitSwap.py
---
LimitSwap.py | 909 +++++++++++++++++++++++++++------------------------
1 file changed, 473 insertions(+), 436 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index ab783fe..ffc21a3 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from web3 import Web3
from time import sleep, time
import json
@@ -9,26 +10,11 @@
import sys
import requests
import cryptocode, re, pwinput
-import argparse
-import signal
-
-# DEVELOPER CONSIDERATIONS
-#
-# USER INTERACTION - Do not depend on user interaction. If you develop a setting that is going to require
-# user interaction while the bot is running, warn the user before hand. Accept a value before the check
-# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
-# entire process from buying all the way to selling multiple positions and multiple pairs with zero user
-# interaction.
-#
-# HANDLING NEW ENTRIES IN settings.json - When adding a new configuration item in settings.json be sure to
-# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file.
-# Do not assume a user has changed their settings.json file to work with the new version, your additions
-# should be backwards compatible and have safe default values if possible
-#
-# HANDLING NEW ENTRIES IN tokens.json - When adding a new configuration item in tokens.json be sure to
-# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file
-# Do not assume a user has changed their tokens.json file to work with the new version, your additions
-# should be backwards compatible and have safe default values if possible
+
+# global used to track if any settings need to be written to file
+settings_changed = False
+
+failedtransactionsamount = 0
# color styles
@@ -44,156 +30,20 @@ class style(): # Class of different text colours - default is white
UNDERLINE = '\033[4m'
RESET = '\033[0m'
-# Function to cleanly exit on SIGINT
-def signal_handler(sig, frame):
- sys.exit(0)
-signal.signal(signal.SIGINT, signal_handler)
def timestamp():
timestamp = time()
dt_object = datetime.fromtimestamp(timestamp)
return dt_object
-#
-# COMMAND LINE ARGUMENTS
-#
-
-parser = argparse.ArgumentParser()
-parser.add_argument("-p", "--password", type=str, help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
-parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)", default="./settings.json")
-parser.add_argument("-t", "--tokens" , type=str, help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
-parser.add_argument("-v", "--verbose" , action='store_true', help="Print detailed messages to stdout")
-command_line_args = parser.parse_args()
-
-def printt(*print_args):
- # Function: printt
- # ----------------------------
- # provides normal print() functionality but also prints our timestamp
- #
- # returns: nothing
-
- print(timestamp(),' '.join(map(str,print_args)))
-
-def printt_v(*print_args):
- # Function: printt
- # ----------------------------
- # provides normal print() functionality but also prints our timestamp and pays attention to user set verbosity.
- #
- # returns: nothing
-
- if command_line_args.verbose == True:
- print(timestamp(),' '.join(map(str,print_args)))
-
-def printt_err(*print_args):
- # Function: printt_err
- # --------------------
- # provides normal print() functionality but also prints our timestamp and the text highlighted to display an error
- #
- # returns: nothing
-
- print(timestamp(), " ", style.RED, ' '.join(map(str,print_args)), style.RESET, sep="")
-
-def load_settings_file(settings_path, load_message = True):
- # Function: load_settings_file
- # ----------------------------
- # loads the settings file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
- # exits with an error message if necessary variables are not found in the settings files
- #
- # settings_path = the path of the file to load settings from
- #
- # returns: a dictionary with the settings from the file loaded
-
- if load_message == True:
- print(timestamp(), "Loading settings from", command_line_args.settings)
-
- f = open(command_line_args.settings, )
- settings = json.load(f)[0]
- f.close()
-
- for default_false in ['UNLIMITEDSLIPPAGE', 'USECUSTOMNODE']:
- if default_false not in settings:
- printt_v (default_false, "not found in settings configuration file, settings a default value of false.")
- settings[default_false] = "false"
- else:
- settings[default_false] = settings[default_false].lower()
-
- for default_true in ['PREAPPROVE']:
- if default_true not in settings:
- printt_v (default_true, "not found in settings configuration file, settings a default value of true.")
- settings[default_true] = "true"
- else:
- settings[default_true] = settings[default_true].lower()
-
- # Keys that must be set
- for required_key in ['EXCHANGE']:
- if required_key not in settings:
- printt_err (required_key, "not found in settings configuration file.")
- exit (-1)
- else:
- settings[required_key] = settings[required_key].lower()
-
- return settings
-
-def load_tokens_file(tokens_path, load_message = True):
- # Function: load_tokens_File
- # ----------------------------
- # loads the token definition file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
- # exits with an error message if necessary variables are not found in the settings files
- #
- # tokens_path: the path of the file to load tokens from
- #
- # returns: a dictionary with the settings from the file loaded
-
- if load_message == True:
- print(timestamp(), "Loading tokens from", command_line_args.tokens)
-
- s = open(command_line_args.tokens, )
- tokens = json.load(s)
- s.close()
-
- # Make sure all values are lowercase
- for token in tokens:
-
- for default_false in ['ENABLED', 'LIQUIDITYCHECK', 'LIQUIDITYINNATIVETOKEN', 'USECUSTOMBASEPAIR', 'HASFEES']:
- if default_false not in token:
- printt_v (default_false, "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a default value of false")
- token[default_false] = "false"
- else:
- token[default_false] = token[default_false].lower()
-
-
- # Keys that must be set
- for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE' ]:
- if required_key not in token:
- printt_err (required_key, "not found in configuration file in configuration for to token", token['SYMBOL'])
- exit (-1)
-
- token_defaults = {
- 'SLIPPAGE' : 49,
- 'MAXTOKENS' : 0,
- 'MOONBAG' : 0,
- 'SELLAMOUNTINTOKENS' : 'all',
- 'GAS' : 20,
- 'BOOSTPERCENT' : 50,
- 'GASLIMIT' : 1000000
-
- }
-
- for default_key in token_defaults:
- if default_key not in token:
- printt_v (default_key , "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a value of", token_defaults['default_key'])
- token[default_key] = token_defaults[default_key]
- elif default_key == 'SELLAMOUNTINTOKENS':
- token_defaults[default_key] = token_defaults[default_key].lower()
-
- return tokens
-
"""""""""""""""""""""""""""
//PRELOAD
"""""""""""""""""""""""""""
print(timestamp(), "Preloading Data")
-settings = load_settings_file(command_line_args.settings)
+f = open('./settings.json', )
+settings = json.load(f)[0]
+f.close()
directory = './abi/'
filename = "standard.json"
@@ -240,14 +90,6 @@ def load_tokens_file(tokens_path, load_message = True):
"""""""""""""""""""""""""""
//ERROR LOGGING
"""""""""""""""""""""""""""
-os.makedirs('./logs', exist_ok=True)
-
-if not os.path.exists('./logs/errors.log'):
- open('./logs/errors.log', 'w').close()
-
-if not os.path.exists('./logs/exceptions.log'):
- open('./logs/exceptions.log', 'w').close()
-
log_format = '%(levelname)s: %(asctime)s %(message)s'
logging.basicConfig(filename='./logs/errors.log',
level=logging.INFO,
@@ -393,7 +235,7 @@ def load_tokens_file(tokens_path, load_message = True):
base_symbol = "BNB"
rugdocchain = '&chain=bsc'
modified = False
-
+
elif settings['EXCHANGE'].lower() == 'apeswap':
if settings['USECUSTOMNODE'].lower() == 'true':
my_provider = settings['CUSTOMNODE']
@@ -563,13 +405,7 @@ def load_tokens_file(tokens_path, load_message = True):
def get_password():
- # Function: get_password
- # ----------------------------
- # Handles the decision making logic concerning private key encryption and asking the user for their password.
- #
- # returns: the user's password
-
- settings_changed = False
+ global settings_changed
setnewpassword = False
# Check to see if the user has a version of the settings file before private key encryption existed
@@ -577,7 +413,7 @@ def get_password():
response = ""
settings_changed = True
while response != "y" and response != "n":
- print ("\nWould you like to use a password to encrypt your private keys?")
+ print("\nWould you like to use a password to encrypt your private keys?")
response = input("You will need to input this password each time LimitSwap is executed (y/n): ")
if response == "y":
@@ -588,7 +424,7 @@ def get_password():
# If the user wants to encrypt their private keys, but we don't have an encrypted private key recorded, we need to ask for a password
elif settings['ENCRYPTPRIVATEKEYS'] == "true" and not settings['PRIVATEKEY'].startswith('aes:'):
- print ("\nPlease create a password to encrypt your private keys.")
+ print("\nPlease create a password to encrypt your private keys.")
setnewpassword = True
# Set a new password when necessary
@@ -600,34 +436,28 @@ def get_password():
pwd2 = pwinput.pwinput(prompt="\nType your new password again: ")
if pwd != pwd2:
- print ("Error, password mismatch. Try again.")
+ print("Error, password mismatch. Try again.")
else:
passwords_differ = False
# The user already has encrypted private keys. Accept a password so we can unencrypt them
elif settings['ENCRYPTPRIVATEKEYS'] == "true":
- if command_line_args.password:
- pwd = command_line_args.password
- else:
- pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
+ pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
else:
pwd = ""
if not pwd.strip():
- print ()
- print ("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
- print ("X You are running LimitSwap without encrypting your private keys. X")
- print ("X Private keys are stored on disk unencrypted and can be accessed by X")
- print ("X anyone with access to the file system, including the Systems/VPS administrator X")
- print ("X and anyone with physical access to the machine or hard drives. X")
- print ("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
- print ()
+ print()
+ print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
+ print("X You are running LimitSwap without encrypting your private keys. X")
+ print("X Private keys are stored on disk unencrypted and can be accessed by X")
+ print("X anyone with access to the file system, including the Systems/VPS administrator X")
+ print("X and anyone with physical access to the machine or hard drives. X")
+ print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
+ print()
- if settings_changed == True:
- save_settings(settings, pwd)
-
return pwd
@@ -652,9 +482,12 @@ def get_password():
"APPROVE_FAILED": (style.RED + '\nRUGDOC API RESULT : APPROVE_FAILED \n'
'/!\ /!\ /!\ Failed to approve the token.\n This is very likely a honeypot.'),
"SWAP_FAILED": (style.RED + '\nRUGDOC API RESULT : SWAP_FAILED \n'
- '/!\ /!\ /!\ Failed to sell the token. \n This is very likely a honeypot.')
+ '/!\ /!\ /!\ Failed to sell the token. \n This is very likely a honeypot.'),
+ "chain not found": (style.RED + '\nRUGDOC API RESULT : chain not found \n'
+ '/!\ Sorry, rugdoc API does not work on this chain... (it does not work on ETH, mainly) \n')
}
+
# Function to check rugdoc API
def honeypot_check(address):
url = (honeypot_url + address + rugdocchain)
@@ -662,39 +495,35 @@ def honeypot_check(address):
return requests.get(url)
-def save_settings(settings, pwd):
+def save_settings(pwd):
+ global settings_changed
if len(pwd) > 0:
encrypted_settings = settings.copy()
- encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'], pwd)
+ encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
+ pwd)
encrypted_settings['PRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['PRIVATEKEY'], pwd)
- # TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
- # settings.json output so that it's reasable. This should probably be fixed by us importing
- # the entire json file, instead of just the [0] element.
-
- print (timestamp(), "Writing settings to file.")
+ # MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
+ # settings.json output so that it's reasable. This should probably be fixed by us importing
+ # the entire json file, instead of just the [0] element.
+ if settings_changed == True:
+ print(timestamp(), "Writing settings to file.")
- if settings['ENCRYPTPRIVATEKEYS'] == "true":
- output_settings = encrypted_settings
- else:
- output_settings = settings
+ if settings['ENCRYPTPRIVATEKEYS'] == "true":
+ output_settings = encrypted_settings
+ else:
+ output_settings = settings
- with open(command_line_args.settings, 'w') as f:
- f.write("[\n")
- f.write(json.dumps(output_settings, indent=4))
- f.write("\n]\n")
+ with open('settings.json', 'w') as f:
+ f.write("[\n")
+ f.write(json.dumps(output_settings, indent=4))
+ f.write("\n]\n")
-def parse_wallet_settings(settings, pwd):
- # Function: load_wallet_settings
- # ----------------------------
- # Handles the process of deciding whether or not the user's private key needs to be decrypted
- # Accepts user input for new private keys and wallet addresses
- #
- # returns: none (exits on incorrect password)
-
- settings_changed = False
+def load_wallet_settings(pwd):
+ global settings
+ global settings_changed
# Check for limit wallet information
if " " in settings['LIMITWALLETADDRESS'] or settings['LIMITWALLETADDRESS'] == "":
@@ -709,15 +538,15 @@ def parse_wallet_settings(settings, pwd):
# If the limit wallet private key is already set and encrypted, decrypt it
elif settings['LIMITWALLETPRIVATEKEY'].startswith('aes:'):
- printt("Decrypting limit wallet private key.")
+ print(timestamp(), "Decrypting limit wallet private key.")
settings['LIMITWALLETPRIVATEKEY'] = settings['LIMITWALLETPRIVATEKEY'].replace('aes:', "", 1)
settings['LIMITWALLETPRIVATEKEY'] = cryptocode.decrypt(settings['LIMITWALLETPRIVATEKEY'], pwd)
if settings['LIMITWALLETPRIVATEKEY'] == False:
- printt_err("ERROR: User provided an invalid password for private key decryption.")
- print(style.RED + "\nERROR: Your private key decryption password is incorrect")
- print(style.RESET + "Please re-launch the bot and try again\n")
- exit(-1)
+ print(style.RED + "ERROR: Your private key decryption password is incorrect")
+ print(style.RESET + "Please re-launch the bot and try again")
+ sleep(10)
+ sys.exit()
# Check for trading wallet information
if " " in settings['WALLETADDRESS'] or settings['WALLETADDRESS'] == "":
@@ -731,15 +560,10 @@ def parse_wallet_settings(settings, pwd):
# If the trading wallet private key is already set and encrypted, decrypt it
elif settings['PRIVATEKEY'].startswith('aes:'):
- print (timestamp(), "Decrypting limit wallet private key.")
+ print(timestamp(), "Decrypting limit wallet private key.")
settings['PRIVATEKEY'] = settings['PRIVATEKEY'].replace('aes:', "", 1)
settings['PRIVATEKEY'] = cryptocode.decrypt(settings['PRIVATEKEY'], pwd)
- if settings_changed == True:
- save_settings(settings, pwd)
-
-
-
def decimals(address):
try:
@@ -852,8 +676,7 @@ def approve(address, amount):
exit()
contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
- transaction = contract.functions.approve(routerAddress, amount
- ).buildTransaction({
+ transaction = contract.functions.approve(routerAddress, amount).buildTransaction({
'gasPrice': Web3.toWei(gas, 'gwei'),
'gas': 300000,
'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
@@ -878,7 +701,7 @@ def approve(address, amount):
return tx_hash
else:
print(timestamp(),
- style.RED + "You have less than 0.01 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet." + style.RESET)
+ "You have less than 0.01 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
logging.info(
"You have less than 0.01 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
@@ -890,16 +713,20 @@ def check_approval(address, balance):
contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
allowance = contract.functions.allowance(Web3.toChecksumAddress(settings['WALLETADDRESS']), routerAddress).call()
- if allowance < balance:
+ print("debut allowance:", allowance)
+ print("debut balance:", balance)
+ sleep(10)
+
+ if int(allowance) < int(balance):
if settings["EXCHANGE"].lower() == 'quickswap':
print("Revert to Zero To change approval")
tx = approve(address, 0)
wait_for_tx(tx, address, False)
- tx = approve(address, balance)
+ tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
wait_for_tx(tx, address, False)
else:
- tx = approve(address, balance)
+ tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
wait_for_tx(tx, address, False)
return
@@ -949,7 +776,7 @@ def check_pool(inToken, outToken, symbol):
return pooled
-def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase):
+def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase, sellpriceinbase):
# CHECK GET RATE OF THE TOKEn
DECIMALS = decimals(inToken)
@@ -965,26 +792,26 @@ def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth, outToken]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base)
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
else:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
else:
if outToken != weth:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, outToken]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base)
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
else:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
return tokenPrice
@@ -1017,7 +844,6 @@ def wait_for_tx(tx_hash, address, check):
sleep(5)
break
-
# loop to check for balance after purchase
if check == True:
timeout = time() + 30
@@ -1050,14 +876,14 @@ def preapprove(tokens):
115792089237316195423570985008687907853269984665640564039457584007913129639934)
-def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds, failedtransactionsnumber):
-
+def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds,
+ failedtransactionsnumber):
seconds = int(waitseconds)
if int(failedtransactionsamount) == int(failedtransactionsnumber):
- print(style.RED + "\n ---------------------------------------------------------------\n"
- " Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
- " ---------------------------------------------------------------\n\n")
-
+ print(
+ style.RED + "\n ---------------------------------------------------------------\n"
+ " Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
+ " ---------------------------------------------------------------\n\n")
logging.info("Bot has reached maximum FAILED TRANSACTIONS number: it stops")
sleep(10)
@@ -1071,7 +897,8 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
print(timestamp(), "Placing New Buy Order for " + symbol)
if int(gaslimit) < 250000:
- print("Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
+ print(
+ "Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
gaslimit = 300000
if custom.lower() == 'false':
@@ -1097,6 +924,7 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
amount = int(float(amount) * DECIMALS)
if custom.lower() == 'false':
+ # if USECUSTOMBASEPAIR = false
amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
min_tokens = 100
@@ -1105,7 +933,8 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
deadline = int(time() + + 60)
- # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
+ # THIS SECTION IS FOR MODIFIED CONTRACTS : EACH EXCHANGE NEEDS TO BE SPECIFIED
+ # USECUSTOMBASEPAIR = false
if modified == True:
if settings["EXCHANGE"].lower() == 'koffeeswap':
@@ -1138,38 +967,28 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
else:
- # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
- if modified == True:
+ # USECUSTOMBASEPAIR = false
+ # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
- if settings["EXCHANGE"].lower() == 'koffeeswap':
- transaction = routerContract.functions.swapExactKCSForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'value': amount,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
- transaction = routerContract.functions.swapExactAVAXForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'value': amount,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # Special condition on Uniswap, to implement EIP-1559
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ transaction = routerContract.functions.swapExactETHForTokens(
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
else:
+ # USECUSTOMBASEPAIR = false
+ # for all the rest of exchanges with Modified = false
transaction = routerContract.functions.swapExactETHForTokens(
min_tokens,
[weth, outToken],
@@ -1184,8 +1003,10 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
})
else:
-
+ # USECUSTOMBASEPAIR = true
if inToken == weth:
+ # USECUSTOMBASEPAIR = true
+ # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
min_tokens = 100
@@ -1193,53 +1014,28 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
min_tokens = int(amount_out * (1 - (slippage / 100)))
deadline = int(time() + + 60)
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
- else:
-
- if routing.lower() == 'true':
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[-1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
transaction = routerContract.functions.swapExactTokensForTokens(
amount,
min_tokens,
- [inToken, weth, outToken],
+ [weth, outToken],
Web3.toChecksumAddress(settings['WALLETADDRESS']),
deadline
).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
'gas': gaslimit,
'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
})
else:
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
transaction = routerContract.functions.swapExactTokensForTokens(
amount,
min_tokens,
- [inToken, outToken],
+ [weth, outToken],
Web3.toChecksumAddress(settings['WALLETADDRESS']),
deadline
).buildTransaction({
@@ -1249,6 +1045,111 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
})
+ else:
+ # LIQUIDITYINNATIVETOKEN = true
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ if routing.lower() == 'true':
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[
+ -1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # LIQUIDITYINNATIVETOKEN = true
+
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # LIQUIDITYINNATIVETOKEN = true
+ # Exchange different from Uniswap
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # Special condition on Uniswap, to implement EIP-1559
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # Exchange different from Uniswap
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
sync(inToken, outToken)
signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
@@ -1277,7 +1178,7 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, routing):
print(timestamp(), "Placing Sell Order " + symbol)
balance = Web3.fromWei(check_balance(inToken, symbol), 'ether')
- check_approval(inToken, balance)
+ check_approval(inToken, balance*1000000000)
if int(gaslimit) < 250000:
gaslimit = 300000
@@ -1304,12 +1205,10 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
balance = check_balance(inToken, symbol)
moonbag = int(Decimal(moonbag) * DECIMALS)
amount = int(Decimal(balance - moonbag))
- print("debug 1036 amount ALL:", amount)
else:
balance = check_balance(inToken, symbol)
amount = Decimal(amount) * DECIMALS
- print("debug 1040 amount:", amount)
moonbag = int(Decimal(moonbag) * DECIMALS)
if balance < amount:
@@ -1324,6 +1223,7 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
amount = 0
if custom.lower() == 'false':
+ # USECUSTOMBASEPAIR = false
sync(inToken, weth)
amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
@@ -1334,6 +1234,8 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
# THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
if modified == True:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = true
if settings["EXCHANGE"].lower() == 'koffeeswap':
transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
@@ -1364,6 +1266,9 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
})
else:
+ # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = true
transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
amount,
min_tokens,
@@ -1377,9 +1282,14 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
})
else:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
# THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
if modified == True:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
+ # Modified = true
if settings["EXCHANGE"].lower() == 'koffeeswap':
transaction = routerContract.functions.swapExactTokensForKCS(
@@ -1409,34 +1319,63 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
})
else:
- transaction = routerContract.functions.swapExactTokensForETH(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
+ # Modified = false --> uniswap / pancakeswap / apeswap, etc.
- else:
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForETH(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+ else:
+ # for all the rest of exchanges with Modified = false
+ transaction = routerContract.functions.swapExactTokensForETH(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
if outToken == weth:
+ # if user has set WETH or WBNB as Custom base pair
sync(inToken, outToken)
amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
min_tokens = int(amount_out * (1 - (slippage / 100)))
deadline = int(time() + + 60)
if fees.lower() == 'true':
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
if int(gaslimit) < 950000:
gaslimit = 950000
# THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
if modified == True:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ # Modified = true
if settings["EXCHANGE"].lower() == 'koffeeswap':
transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
@@ -1467,6 +1406,10 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
})
else:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ # Modified = false
+
transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
amount,
min_tokens,
@@ -1480,6 +1423,8 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
})
else:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = false
transaction = routerContract.functions.swapExactTokensForTokens(
amount,
min_tokens,
@@ -1498,38 +1443,88 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
sync(inToken, outToken)
if routing.lower() == 'false' and outToken != weth:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
min_tokens = int(amount_out * (1 - (slippage / 100)))
deadline = int(time() + + 60)
if fees.lower() == 'true':
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # for all the rest of exchanges
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
else:
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = false
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # for all the rest of exchanges
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
elif routing.lower() == 'false' and outToken == weth:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
print(
"ERROR IN YOUR TOKENS.JSON : YOU NEED TO CHOOSE THE PROPER BASE PAIR AS SYMBOL IF YOU ARE TRADING OUTSIDE OF NATIVE LIQUIDITY POOL")
@@ -1539,31 +1534,69 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
deadline = int(time() + + 60)
if fees.lower() == 'true':
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # HASFEES = true
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
else:
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
+ # HASFEES = false
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+ else:
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
sync(inToken, outToken)
signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
@@ -1588,20 +1621,22 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
def run():
-
global failedtransactionsamount
try:
-
- tokens = load_tokens_file(command_line_args.tokens, True)
+ s = open('./tokens.json', )
+ tokens = json.load(s)
+ s.close()
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
if eth_balance > 0.05:
pass
else:
- print(style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet" + style.RESET)
- logging.info("You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ print(
+ style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
+ logging.info(
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
sys.exit()
@@ -1610,15 +1645,7 @@ def run():
else:
pass
-
for token in tokens:
-
- if 'RUGDOC_CHECK' not in token:
- token['RUGDOC_CHECK'] = 'false'
- if 'BUYAFTER_XXX_SECONDS' not in token:
- token['BUYAFTER_XXX_SECONDS'] = 0
- if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
if token['RUGDOC_CHECK'].lower() == 'true':
@@ -1632,11 +1659,11 @@ def run():
decision = ""
while decision != "y" and decision != "n":
- print (style.RESET + "\nWhat is your decision?")
+ print(style.RESET + "\nWhat is your decision?")
decision = input("Would you like to snipe this token? (y/n): ")
if decision == "y":
- print (style.RESET + "\nOK let's go!!\n")
+ print(style.RESET + "\nOK let's go!!\n")
pass
else:
sys.exit()
@@ -1645,18 +1672,12 @@ def run():
pass
while True:
-
- tokens = load_tokens_file(command_line_args.tokens, False)
+ s = open('./tokens.json', )
+ tokens = json.load(s)
+ s.close()
for token in tokens:
- if 'RUGDOC_CHECK' not in token:
- token['RUGDOC_CHECK'] = 'false'
- if 'BUYAFTER_XXX_SECONDS' not in token:
- token['BUYAFTER_XXX_SECONDS'] = 0
- if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
-
if token['ENABLED'].lower() == 'true':
inToken = Web3.toChecksumAddress(token['ADDRESS'])
@@ -1668,7 +1689,7 @@ def run():
try:
quote = check_price(inToken, outToken, token['SYMBOL'], token['BASESYMBOL'],
token['USECUSTOMBASEPAIR'], token['LIQUIDITYINNATIVETOKEN'],
- token['BUYPRICEINBASE'])
+ token['BUYPRICEINBASE'], token['SELLPRICEINBASE'])
pool = check_pool(inToken, outToken, token['BASESYMBOL'])
# print("Debug Liquidity Reserves ligne 1267:", float(pool))
# print("Debug inToken : ", inToken, "outToken :", outToken)
@@ -1697,13 +1718,15 @@ def run():
tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
- token['BASESYMBOL'], token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+ token['BASESYMBOL'], token['LIQUIDITYINNATIVETOKEN'],
+ token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
if tx != False:
tx = wait_for_tx(tx, token['ADDRESS'], True)
- print(style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
print(style.RESET + "")
sleep(3)
check_balance(token['ADDRESS'], token['SYMBOL'])
@@ -1713,20 +1736,21 @@ def run():
if tx != 1:
# transaction is a FAILURE
print(
- style.RED + "\n -------------------------------------------------\n"
- " FAILURE ! Plese check your wallet. \n"
- " Cause of failure can be : \n"
- " - GASLIMIT too low\n"
- " - SLIPPAGE too low\n"
- " -------------------------------------------------\n\n")
+ style.RED + "\n -------------------------------------------------\n"
+ " FAILURE ! Plese check your wallet. \n"
+ " Cause of failure can be : \n"
+ " - GASLIMIT too low\n"
+ " - SLIPPAGE too low\n"
+ " -------------------------------------------------\n\n")
print(style.RESET + "")
failedtransactionsamount += 1
preapprove(tokens)
else:
# transaction is a SUCCESS
- print(style.GREEN + "\n ----------------------------------\n"
- " SUCCESS : your Tx is confirmed :)\n"
- " ----------------------------------\n")
+ print(
+ style.GREEN + "\n ----------------------------------\n"
+ " SUCCESS : your Tx is confirmed :)\n"
+ " ----------------------------------\n")
print(style.RESET + "")
pass
@@ -1744,13 +1768,15 @@ def run():
tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'], token['SLIPPAGE'],
token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['BASESYMBOL'],
- token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+ token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
if tx != False:
tx = wait_for_tx(tx, token['ADDRESS'], True)
- print(style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
print(style.RESET + "")
sleep(3)
check_balance(token['ADDRESS'], token['SYMBOL'])
@@ -1759,20 +1785,22 @@ def run():
if tx != 1:
# transaction is a FAILURE
- print(style.RED + "\n -------------------------------------------------\n"
- " FAILURE ! Please check your wallet. \n"
- " Cause of failure can be : \n"
- " - GASLIMIT too low\n"
- " - SLIPPAGE too low\n"
- " -------------------------------------------------\n\n")
+ print(
+ style.RED + "\n -------------------------------------------------\n"
+ " FAILURE ! Please check your wallet. \n"
+ " Cause of failure can be : \n"
+ " - GASLIMIT too low\n"
+ " - SLIPPAGE too low\n"
+ " -------------------------------------------------\n\n")
print(style.RESET + "")
failedtransactionsamount += 1
preapprove(tokens)
else:
# transaction is a SUCCESS
- print(style.GREEN + "\n ----------------------------------\n"
- " SUCCESS : your Tx is confirmed :)\n"
- " ----------------------------------\n")
+ print(
+ style.GREEN + "\n ----------------------------------\n"
+ " SUCCESS : your Tx is confirmed :)\n"
+ " ----------------------------------\n")
print(style.RESET + "")
pass
else:
@@ -1782,7 +1810,7 @@ def run():
else:
print(
- timestamp(), "You own more tokens than your MAXTOKENS parameter for ", token['SYMBOL'])
+ timestamp(), "You own more tokens than your MAXTOKENS parameter for ", token['SYMBOL'])
if quote > Decimal(token['SELLPRICEINBASE']):
DECIMALS = decimals(inToken)
@@ -1799,6 +1827,12 @@ def run():
token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
token['LIQUIDITYINNATIVETOKEN'])
wait_for_tx(tx, token['ADDRESS'], False)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ sleep(5)
+ print(style.RESET + "")
else:
pass
@@ -1817,6 +1851,13 @@ def run():
token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['LIQUIDITYINNATIVETOKEN'])
wait_for_tx(tx, token['ADDRESS'], False)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ sleep(5)
+ print(style.RESET + "")
+
else:
# Double Check For Buy if Sell Signal Triggers
if quote < Decimal(token['BUYPRICEINBASE']):
@@ -1828,7 +1869,8 @@ def run():
tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
- token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+ token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
wait_for_tx(tx, token['ADDRESS'], False)
else:
print(timestamp(), "Bot has reached MAXTOKENS Position Size for ", token['SYMBOL'])
@@ -1859,15 +1901,10 @@ def run():
try:
check_logs()
-
- # Get the user password on first run
userpassword = get_password()
-
- # Handle any proccessing that is necessary to load the private key for the wallet
- parse_wallet_settings(settings, userpassword)
-
- # The LIMIT balance of the user.
+ load_wallet_settings(userpassword)
true_balance = auth()
+ save_settings(userpassword)
version = 3.36
logging.info("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
From e505d98c2c3b0b58239f9319d8e0b170b27b38dc Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 21:35:56 +0100
Subject: [PATCH 02/16] Update LimitSwap.py
---
LimitSwap.py | 239 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 210 insertions(+), 29 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index ffc21a3..8c51ac2 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -10,10 +10,29 @@
import sys
import requests
import cryptocode, re, pwinput
-
-# global used to track if any settings need to be written to file
-settings_changed = False
-
+import argparse
+import signal
+
+# DEVELOPER CONSIDERATIONS
+#
+# USER INTERACTION - Do not depend on user interaction. If you develop a setting that is going to require
+# user interaction while the bot is running, warn the user before hand. Accept a value before the check
+# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
+# entire process from buying all the way to selling multiple positions and multiple pairs with zero user
+# interaction.
+#
+# HANDLING NEW ENTRIES IN settings.json - When adding a new configuration item in settings.json be sure to
+# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file.
+# Do not assume a user has changed their settings.json file to work with the new version, your additions
+# should be backwards compatible and have safe default values if possible
+#
+# HANDLING NEW ENTRIES IN tokens.json - When adding a new configuration item in tokens.json be sure to
+# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file
+# Do not assume a user has changed their tokens.json file to work with the new version, your additions
+# should be backwards compatible and have safe default values if possible
+
+
+# initialization of number of failed transactions
failedtransactionsamount = 0
@@ -29,21 +48,157 @@ class style(): # Class of different text colours - default is white
WHITE = '\033[37m'
UNDERLINE = '\033[4m'
RESET = '\033[0m'
-
+
+# Function to cleanly exit on SIGINT
+def signal_handler(sig, frame):
+ sys.exit(0)
+signal.signal(signal.SIGINT, signal_handler)
def timestamp():
timestamp = time()
dt_object = datetime.fromtimestamp(timestamp)
return dt_object
+#
+# COMMAND LINE ARGUMENTS
+#
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-p", "--password", type=str, help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
+parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)", default="./settings.json")
+parser.add_argument("-t", "--tokens" , type=str, help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
+parser.add_argument("-v", "--verbose" , action='store_true', help="Print detailed messages to stdout")
+command_line_args = parser.parse_args()
+
+def printt(*print_args):
+ # Function: printt
+ # ----------------------------
+ # provides normal print() functionality but also prints our timestamp
+ #
+ # returns: nothing
+
+ print(timestamp(),' '.join(map(str,print_args)))
+
+def printt_v(*print_args):
+ # Function: printt
+ # ----------------------------
+ # provides normal print() functionality but also prints our timestamp and pays attention to user set verbosity.
+ #
+ # returns: nothing
+
+ if command_line_args.verbose == True:
+ print(timestamp(),' '.join(map(str,print_args)))
+
+def printt_err(*print_args):
+ # Function: printt_err
+ # --------------------
+ # provides normal print() functionality but also prints our timestamp and the text highlighted to display an error
+ #
+ # returns: nothing
+
+ print(timestamp(), " ", style.RED, ' '.join(map(str,print_args)), style.RESET, sep="")
+
+def load_settings_file(settings_path, load_message = True):
+ # Function: load_settings_file
+ # ----------------------------
+ # loads the settings file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
+ # exits with an error message if necessary variables are not found in the settings files
+ #
+ # settings_path = the path of the file to load settings from
+ #
+ # returns: a dictionary with the settings from the file loaded
+
+ if load_message == True:
+ print(timestamp(), "Loading settings from", command_line_args.settings)
+
+ f = open(command_line_args.settings, )
+ settings = json.load(f)[0]
+ f.close()
+
+ for default_false in ['UNLIMITEDSLIPPAGE', 'USECUSTOMNODE']:
+ if default_false not in settings:
+ printt_v (default_false, "not found in settings configuration file, settings a default value of false.")
+ settings[default_false] = "false"
+ else:
+ settings[default_false] = settings[default_false].lower()
+
+ for default_true in ['PREAPPROVE']:
+ if default_true not in settings:
+ printt_v (default_true, "not found in settings configuration file, settings a default value of true.")
+ settings[default_true] = "true"
+ else:
+ settings[default_true] = settings[default_true].lower()
+
+ # Keys that must be set
+ for required_key in ['EXCHANGE']:
+ if required_key not in settings:
+ printt_err (required_key, "not found in settings configuration file.")
+ exit (-1)
+ else:
+ settings[required_key] = settings[required_key].lower()
+
+ return settings
+
+def load_tokens_file(tokens_path, load_message = True):
+ # Function: load_tokens_File
+ # ----------------------------
+ # loads the token definition file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
+ # exits with an error message if necessary variables are not found in the settings files
+ #
+ # tokens_path: the path of the file to load tokens from
+ #
+ # returns: a dictionary with the settings from the file loaded
+
+ if load_message == True:
+ print(timestamp(), "Loading tokens from", command_line_args.tokens)
+
+ s = open(command_line_args.tokens, )
+ tokens = json.load(s)
+ s.close()
+
+ # Make sure all values are lowercase
+ for token in tokens:
+
+ for default_false in ['ENABLED', 'LIQUIDITYCHECK', 'LIQUIDITYINNATIVETOKEN', 'USECUSTOMBASEPAIR', 'HASFEES']:
+ if default_false not in token:
+ printt_v (default_false, "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a default value of false")
+ token[default_false] = "false"
+ else:
+ token[default_false] = token[default_false].lower()
+
+
+ # Keys that must be set
+ for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE' ]:
+ if required_key not in token:
+ printt_err (required_key, "not found in configuration file in configuration for to token", token['SYMBOL'])
+ exit (-1)
+
+ token_defaults = {
+ 'SLIPPAGE' : 49,
+ 'MAXTOKENS' : 0,
+ 'MOONBAG' : 0,
+ 'SELLAMOUNTINTOKENS' : 'all',
+ 'GAS' : 20,
+ 'BOOSTPERCENT' : 50,
+ 'GASLIMIT' : 1000000
+
+ }
+
+ for default_key in token_defaults:
+ if default_key not in token:
+ printt_v (default_key , "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a value of", token_defaults['default_key'])
+ token[default_key] = token_defaults[default_key]
+ elif default_key == 'SELLAMOUNTINTOKENS':
+ token_defaults[default_key] = token_defaults[default_key].lower()
+
+ return tokens
+
"""""""""""""""""""""""""""
//PRELOAD
"""""""""""""""""""""""""""
print(timestamp(), "Preloading Data")
-f = open('./settings.json', )
-settings = json.load(f)[0]
-f.close()
+settings = load_settings_file(command_line_args.settings)
directory = './abi/'
filename = "standard.json"
@@ -90,6 +245,14 @@ def timestamp():
"""""""""""""""""""""""""""
//ERROR LOGGING
"""""""""""""""""""""""""""
+os.makedirs('./logs', exist_ok=True)
+
+if not os.path.exists('./logs/errors.log'):
+ open('./logs/errors.log', 'w').close()
+
+if not os.path.exists('./logs/exceptions.log'):
+ open('./logs/exceptions.log', 'w').close()
+
log_format = '%(levelname)s: %(asctime)s %(message)s'
logging.basicConfig(filename='./logs/errors.log',
level=logging.INFO,
@@ -405,7 +568,13 @@ def timestamp():
def get_password():
- global settings_changed
+ # Function: get_password
+ # ----------------------------
+ # Handles the decision making logic concerning private key encryption and asking the user for their password.
+ #
+ # returns: the user's password
+
+ settings_changed = False
setnewpassword = False
# Check to see if the user has a version of the settings file before private key encryption existed
@@ -443,8 +612,11 @@ def get_password():
# The user already has encrypted private keys. Accept a password so we can unencrypt them
elif settings['ENCRYPTPRIVATEKEYS'] == "true":
- pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
-
+ if command_line_args.password:
+ pwd = command_line_args.password
+ else:
+ pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
+
else:
pwd = ""
@@ -457,6 +629,9 @@ def get_password():
print("X and anyone with physical access to the machine or hard drives. X")
print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
print()
+
+ if settings_changed == True:
+ save_settings(settings, pwd)
return pwd
@@ -495,36 +670,40 @@ def honeypot_check(address):
return requests.get(url)
-def save_settings(pwd):
- global settings_changed
-
+def save_settings(settings, pwd):
+
if len(pwd) > 0:
encrypted_settings = settings.copy()
encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
pwd)
encrypted_settings['PRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['PRIVATEKEY'], pwd)
- # MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
+ # TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
# settings.json output so that it's reasable. This should probably be fixed by us importing
# the entire json file, instead of just the [0] element.
- if settings_changed == True:
- print(timestamp(), "Writing settings to file.")
+ print(timestamp(), "Writing settings to file.")
- if settings['ENCRYPTPRIVATEKEYS'] == "true":
- output_settings = encrypted_settings
- else:
- output_settings = settings
+ if settings['ENCRYPTPRIVATEKEYS'] == "true":
+ output_settings = encrypted_settings
+ else:
+ output_settings = settings
- with open('settings.json', 'w') as f:
- f.write("[\n")
- f.write(json.dumps(output_settings, indent=4))
- f.write("\n]\n")
+ with open(command_line_args.settings, 'w') as f:
+ f.write("[\n")
+ f.write(json.dumps(output_settings, indent=4))
+ f.write("\n]\n")
-def load_wallet_settings(pwd):
- global settings
- global settings_changed
+def parse_wallet_settings(settings, pwd):
+ # Function: load_wallet_settings
+ # ----------------------------
+ # Handles the process of deciding whether or not the user's private key needs to be decrypted
+ # Accepts user input for new private keys and wallet addresses
+ #
+ # returns: none (exits on incorrect password)
+ settings_changed = False
+
# Check for limit wallet information
if " " in settings['LIMITWALLETADDRESS'] or settings['LIMITWALLETADDRESS'] == "":
settings_changed = True
@@ -538,7 +717,7 @@ def load_wallet_settings(pwd):
# If the limit wallet private key is already set and encrypted, decrypt it
elif settings['LIMITWALLETPRIVATEKEY'].startswith('aes:'):
- print(timestamp(), "Decrypting limit wallet private key.")
+ printt("Decrypting limit wallet private key.")
settings['LIMITWALLETPRIVATEKEY'] = settings['LIMITWALLETPRIVATEKEY'].replace('aes:', "", 1)
settings['LIMITWALLETPRIVATEKEY'] = cryptocode.decrypt(settings['LIMITWALLETPRIVATEKEY'], pwd)
@@ -564,6 +743,8 @@ def load_wallet_settings(pwd):
settings['PRIVATEKEY'] = settings['PRIVATEKEY'].replace('aes:', "", 1)
settings['PRIVATEKEY'] = cryptocode.decrypt(settings['PRIVATEKEY'], pwd)
+ if settings_changed == True:
+ save_settings(settings, pwd)
def decimals(address):
try:
From 9290d81f1f96e758d2936039084093585a899acb Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 21:45:57 +0100
Subject: [PATCH 03/16] Update LimitSwap.py
---
LimitSwap.py | 45 ++++++++++++++++++++++++++++++---------------
1 file changed, 30 insertions(+), 15 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 8c51ac2..878904e 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -1805,17 +1805,14 @@ def run():
global failedtransactionsamount
try:
- s = open('./tokens.json', )
- tokens = json.load(s)
- s.close()
+ tokens = load_tokens_file(command_line_args.tokens, True)
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
if eth_balance > 0.05:
pass
else:
- print(
- style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
+ print(style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
logging.info(
"You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
@@ -1827,7 +1824,15 @@ def run():
pass
for token in tokens:
-
+ # Initialization of values, in case the user re-used some old tokens.json files
+ if 'RUGDOC_CHECK' not in token:
+ token['RUGDOC_CHECK'] = 'false'
+ if 'BUYAFTER_XXX_SECONDS' not in token:
+ token['BUYAFTER_XXX_SECONDS'] = 0
+ if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
+ # End of initialization of values
+
if token['RUGDOC_CHECK'].lower() == 'true':
honeypot = honeypot_check(address=token['ADDRESS'])
@@ -1853,12 +1858,18 @@ def run():
pass
while True:
- s = open('./tokens.json', )
- tokens = json.load(s)
- s.close()
-
+ tokens = load_tokens_file(command_line_args.tokens, False)
+
for token in tokens:
-
+ # Initialization of values, in case the user re-used some old tokens.json files
+ if 'RUGDOC_CHECK' not in token:
+ token['RUGDOC_CHECK'] = 'false'
+ if 'BUYAFTER_XXX_SECONDS' not in token:
+ token['BUYAFTER_XXX_SECONDS'] = 0
+ if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
+ # End of initialization of values
+
if token['ENABLED'].lower() == 'true':
inToken = Web3.toChecksumAddress(token['ADDRESS'])
@@ -1990,8 +2001,7 @@ def run():
else:
- print(
- timestamp(), "You own more tokens than your MAXTOKENS parameter for ", token['SYMBOL'])
+ print(timestamp(), "You own more tokens than your MAXTOKENS parameter for ", token['SYMBOL'])
if quote > Decimal(token['SELLPRICEINBASE']):
DECIMALS = decimals(inToken)
@@ -2082,10 +2092,15 @@ def run():
try:
check_logs()
+
+ # Get the user password on first run
userpassword = get_password()
- load_wallet_settings(userpassword)
+
+ # Handle any proccessing that is necessary to load the private key for the wallet
+ parse_wallet_settings(settings, userpassword)
+
+ # The LIMIT balance of the user.
true_balance = auth()
- save_settings(userpassword)
version = 3.36
logging.info("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
From a8424d76c45c38834d5e66adb4aba32b1e632b55 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 21:57:15 +0100
Subject: [PATCH 04/16] Update LimitSwap.py
---
LimitSwap.py | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 878904e..beae467 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -48,7 +48,7 @@ class style(): # Class of different text colours - default is white
WHITE = '\033[37m'
UNDERLINE = '\033[4m'
RESET = '\033[0m'
-
+
# Function to cleanly exit on SIGINT
def signal_handler(sig, frame):
sys.exit(0)
@@ -252,7 +252,7 @@ def load_tokens_file(tokens_path, load_message = True):
if not os.path.exists('./logs/exceptions.log'):
open('./logs/exceptions.log', 'w').close()
-
+
log_format = '%(levelname)s: %(asctime)s %(message)s'
logging.basicConfig(filename='./logs/errors.log',
level=logging.INFO,
@@ -616,7 +616,7 @@ def get_password():
pwd = command_line_args.password
else:
pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
-
+
else:
pwd = ""
@@ -671,7 +671,7 @@ def honeypot_check(address):
def save_settings(settings, pwd):
-
+
if len(pwd) > 0:
encrypted_settings = settings.copy()
encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
@@ -681,6 +681,7 @@ def save_settings(settings, pwd):
# TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
# settings.json output so that it's reasable. This should probably be fixed by us importing
# the entire json file, instead of just the [0] element.
+
print(timestamp(), "Writing settings to file.")
if settings['ENCRYPTPRIVATEKEYS'] == "true":
@@ -746,6 +747,7 @@ def parse_wallet_settings(settings, pwd):
if settings_changed == True:
save_settings(settings, pwd)
+
def decimals(address):
try:
balanceContract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
@@ -882,9 +884,9 @@ def approve(address, amount):
return tx_hash
else:
print(timestamp(),
- "You have less than 0.01 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
logging.info(
- "You have less than 0.01 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
sys.exit()
@@ -1057,12 +1059,10 @@ def preapprove(tokens):
115792089237316195423570985008687907853269984665640564039457584007913129639934)
-def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds,
- failedtransactionsnumber):
+def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds, failedtransactionsnumber):
seconds = int(waitseconds)
if int(failedtransactionsamount) == int(failedtransactionsnumber):
- print(
- style.RED + "\n ---------------------------------------------------------------\n"
+ print(style.RED + "\n ---------------------------------------------------------------\n"
" Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
" ---------------------------------------------------------------\n\n")
@@ -1078,8 +1078,7 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
print(timestamp(), "Placing New Buy Order for " + symbol)
if int(gaslimit) < 250000:
- print(
- "Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
+ print("Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
gaslimit = 300000
if custom.lower() == 'false':
@@ -1802,9 +1801,11 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
def run():
+
global failedtransactionsamount
try:
+
tokens = load_tokens_file(command_line_args.tokens, True)
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
@@ -1813,8 +1814,7 @@ def run():
pass
else:
print(style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
- logging.info(
- "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ logging.info("You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
sys.exit()
From af034368417e9265630176da0595ecc2e3badcc5 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:01:01 +0100
Subject: [PATCH 05/16] Update LimitSwap.py
---
LimitSwap.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index beae467..54c44b4 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -896,10 +896,6 @@ def check_approval(address, balance):
contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
allowance = contract.functions.allowance(Web3.toChecksumAddress(settings['WALLETADDRESS']), routerAddress).call()
- print("debut allowance:", allowance)
- print("debut balance:", balance)
- sleep(10)
-
if int(allowance) < int(balance):
if settings["EXCHANGE"].lower() == 'quickswap':
From ebe317bf524d6567b5d977640404c9443ee75c5b Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:12:28 +0100
Subject: [PATCH 06/16] Update LimitSwap.py
---
LimitSwap.py | 2306 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 2250 insertions(+), 56 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 54c44b4..c334a05 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -17,7 +17,7 @@
#
# USER INTERACTION - Do not depend on user interaction. If you develop a setting that is going to require
# user interaction while the bot is running, warn the user before hand. Accept a value before the check
-# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
+# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
# entire process from buying all the way to selling multiple positions and multiple pairs with zero user
# interaction.
#
@@ -49,27 +49,2209 @@ class style(): # Class of different text colours - default is white
UNDERLINE = '\033[4m'
RESET = '\033[0m'
+
+# Function to cleanly exit on SIGINT
+def signal_handler(sig, frame):
+ sys.exit(0)
+
+
+signal.signal(signal.SIGINT, signal_handler)
+
+
+def timestamp():
+ timestamp = time()
+ dt_object = datetime.fromtimestamp(timestamp)
+ return dt_object
+
+
+#
+# COMMAND LINE ARGUMENTS
+#
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-p", "--password", type=str,
+ help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
+parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)",
+ default="./settings.json")
+parser.add_argument("-t", "--tokens", type=str,
+ help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
+parser.add_argument("-v", "--verbose", action='store_true', help="Print detailed messages to stdout")
+command_line_args = parser.parse_args()
+
+
+def printt(*print_args):
+ # Function: printt
+ # ----------------------------
+ # provides normal print() functionality but also prints our timestamp
+ #
+ # returns: nothing
+
+ print(timestamp(), ' '.join(map(str, print_args)))
+
+
+def printt_v(*print_args):
+ # Function: printt
+ # ----------------------------
+ # provides normal print() functionality but also prints our timestamp and pays attention to user set verbosity.
+ #
+ # returns: nothing
+
+ if command_line_args.verbose == True:
+ print(timestamp(), ' '.join(map(str, print_args)))
+
+
+def printt_err(*print_args):
+ # Function: printt_err
+ # --------------------
+ # provides normal print() functionality but also prints our timestamp and the text highlighted to display an error
+ #
+ # returns: nothing
+
+ print(timestamp(), " ", style.RED, ' '.join(map(str, print_args)), style.RESET, sep="")
+
+
+def load_settings_file(settings_path, load_message=True):
+ # Function: load_settings_file
+ # ----------------------------
+ # loads the settings file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
+ # exits with an error message if necessary variables are not found in the settings files
+ #
+ # settings_path = the path of the file to load settings from
+ #
+ # returns: a dictionary with the settings from the file loaded
+
+ if load_message == True:
+ print(timestamp(), "Loading settings from", command_line_args.settings)
+
+ f = open(command_line_args.settings, )
+ settings = json.load(f)[0]
+ f.close()
+
+ for default_false in ['UNLIMITEDSLIPPAGE', 'USECUSTOMNODE']:
+ if default_false not in settings:
+ printt_v(default_false, "not found in settings configuration file, settings a default value of false.")
+ settings[default_false] = "false"
+ else:
+ settings[default_false] = settings[default_false].lower()
+
+ for default_true in ['PREAPPROVE']:
+ if default_true not in settings:
+ printt_v(default_true, "not found in settings configuration file, settings a default value of true.")
+ settings[default_true] = "true"
+ else:
+ settings[default_true] = settings[default_true].lower()
+
+ # Keys that must be set
+ for required_key in ['EXCHANGE']:
+ if required_key not in settings:
+ printt_err(required_key, "not found in settings configuration file.")
+ exit(-1)
+ else:
+ settings[required_key] = settings[required_key].lower()
+
+ return settings
+
+
+def load_tokens_file(tokens_path, load_message=True):
+ # Function: load_tokens_File
+ # ----------------------------
+ # loads the token definition file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
+ # exits with an error message if necessary variables are not found in the settings files
+ #
+ # tokens_path: the path of the file to load tokens from
+ #
+ # returns: a dictionary with the settings from the file loaded
+
+ if load_message == True:
+ print(timestamp(), "Loading tokens from", command_line_args.tokens)
+
+ s = open(command_line_args.tokens, )
+ tokens = json.load(s)
+ s.close()
+
+ # Make sure all values are lowercase
+ for token in tokens:
+
+ for default_false in ['ENABLED', 'LIQUIDITYCHECK', 'LIQUIDITYINNATIVETOKEN', 'USECUSTOMBASEPAIR', 'HASFEES']:
+ if default_false not in token:
+ printt_v(default_false, "not found in configuration file in configuration for to token",
+ token['SYMBOL'], "setting a default value of false")
+ token[default_false] = "false"
+ else:
+ token[default_false] = token[default_false].lower()
+
+ # Keys that must be set
+ for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE']:
+ if required_key not in token:
+ printt_err(required_key, "not found in configuration file in configuration for to token",
+ token['SYMBOL'])
+ exit(-1)
+
+ token_defaults = {
+ 'SLIPPAGE': 49,
+ 'MAXTOKENS': 0,
+ 'MOONBAG': 0,
+ 'SELLAMOUNTINTOKENS': 'all',
+ 'GAS': 20,
+ 'BOOSTPERCENT': 50,
+ 'GASLIMIT': 1000000
+
+ }
+
+ for default_key in token_defaults:
+ if default_key not in token:
+ printt_v(default_key, "not found in configuration file in configuration for to token", token['SYMBOL'],
+ "setting a value of", token_defaults['default_key'])
+ token[default_key] = token_defaults[default_key]
+ elif default_key == 'SELLAMOUNTINTOKENS':
+ token_defaults[default_key] = token_defaults[default_key].lower()
+
+ return tokens
+
+
+"""""""""""""""""""""""""""
+//PRELOAD
+"""""""""""""""""""""""""""
+print(timestamp(), "Preloading Data")
+settings = load_settings_file(command_line_args.settings)
+
+directory = './abi/'
+filename = "standard.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ standardAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "lp.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ lpAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "router.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ routerAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "factory2.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ factoryAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "koffee.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ koffeeAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "pangolin.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ pangolinAbi = json.load(json_file)
+
+directory = './abi/'
+filename = "joeRouter.json"
+file_path = os.path.join(directory, filename)
+with open(file_path) as json_file:
+ joeRouter = json.load(json_file)
+
+"""""""""""""""""""""""""""
+//ERROR LOGGING
+"""""""""""""""""""""""""""
+os.makedirs('./logs', exist_ok=True)
+
+if not os.path.exists('./logs/errors.log'):
+ open('./logs/errors.log', 'w').close()
+
+if not os.path.exists('./logs/exceptions.log'):
+ open('./logs/exceptions.log', 'w').close()
+
+log_format = '%(levelname)s: %(asctime)s %(message)s'
+logging.basicConfig(filename='./logs/errors.log',
+ level=logging.INFO,
+ format=log_format)
+
+logger1 = logging.getLogger('1')
+logger1.addHandler(logging.FileHandler('./logs/exceptions.log'))
+
+logging.info("*************************************************************************************")
+logging.info("For Help & To Learn More About how the bot works please visit our wiki here:")
+logging.info("https://cryptognome.gitbook.io/limitswap/")
+logging.info("*************************************************************************************")
+
+"""""""""""""""""""""""""""
+//NETWORKS SELECT
+"""""""""""""""""""""""""""
+
+if settings['EXCHANGE'].lower() == 'pancakeswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ print(timestamp(), 'Using custom node.')
+ else:
+ my_provider = "https://bsc-dataseed4.defibit.io"
+
+ if not my_provider:
+ print(timestamp(), 'Custom node empty. Exiting')
+ exit(1)
+
+ if my_provider[0].lower() == 'h':
+ print(timestamp(), 'Using HTTPProvider')
+ client = Web3(Web3.HTTPProvider(my_provider))
+ elif my_provider[0].lower() == 'w':
+ print(timestamp(), 'Using WebsocketProvider')
+ client = Web3(Web3.WebsocketProvider(my_provider))
+ else:
+ print(timestamp(), 'Using IPCProvider')
+ client = Web3(Web3.IPCProvider(my_provider))
+
+ print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+
+ if settings['EXCHANGEVERSION'] == "1":
+ routerAddress = Web3.toChecksumAddress("0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F")
+ factoryAddress = Web3.toChecksumAddress("0xbcfccbde45ce874adcb698cc183debcf17952812")
+ elif settings['EXCHANGEVERSION'] == "2":
+ routerAddress = Web3.toChecksumAddress("0x10ED43C718714eb63d5aA57B78B54704E256024E")
+ factoryAddress = Web3.toChecksumAddress("0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73")
+
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
+ base_symbol = "BNB"
+ rugdocchain = '&chain=bsc'
+ modified = False
+
+if settings['EXCHANGE'].lower() == 'traderjoe':
+
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://api.avax.network/ext/bc/C/rpc"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "AVAX Smart Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+
+ routerAddress = Web3.toChecksumAddress("0x60aE616a2155Ee3d9A68541Ba4544862310933d4")
+ factoryAddress = Web3.toChecksumAddress("0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10")
+
+ routerContract = client.eth.contract(address=routerAddress, abi=joeRouter)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7")
+ base_symbol = "AVAX"
+ rugdocchain = '&chain=avax'
+ modified = True
+
+elif settings['EXCHANGE'].lower() == 'pinkswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ print(timestamp(), 'Using custom node.')
+ else:
+ my_provider = "https://bsc-dataseed4.defibit.io"
+
+ if not my_provider:
+ print(timestamp(), 'Custom node empty. Exiting')
+ exit(1)
+
+ if my_provider[0].lower() == 'h':
+ print(timestamp(), 'Using HTTPProvider')
+ client = Web3(Web3.HTTPProvider(my_provider))
+ elif my_provider[0].lower() == 'w':
+ print(timestamp(), 'Using WebsocketProvider')
+ client = Web3(Web3.WebsocketProvider(my_provider))
+ else:
+ print(timestamp(), 'Using IPCProvider')
+ client = Web3(Web3.IPCProvider(my_provider))
+
+ print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading PinkSwap Smart Contracts...")
+
+ routerAddress = Web3.toChecksumAddress("0x319EF69a98c8E8aAB36Aea561Daba0Bf3D0fa3ac")
+ factoryAddress = Web3.toChecksumAddress("0x7d2ce25c28334e40f37b2a068ec8d5a59f11ea54")
+
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+
+ weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
+ base_symbol = "BNB"
+ rugdocchain = '&chain=bsc'
+ modified = False
+
+elif settings['EXCHANGE'].lower() == 'biswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ print(timestamp(), 'Using custom node.')
+ else:
+ my_provider = "https://bsc-dataseed4.defibit.io"
+
+ if not my_provider:
+ print(timestamp(), 'Custom node empty. Exiting')
+ exit(1)
+
+ if my_provider[0].lower() == 'h':
+ print(timestamp(), 'Using HTTPProvider')
+ client = Web3(Web3.HTTPProvider(my_provider))
+ elif my_provider[0].lower() == 'w':
+ print(timestamp(), 'Using WebsocketProvider')
+ client = Web3(Web3.WebsocketProvider(my_provider))
+ else:
+ print(timestamp(), 'Using IPCProvider')
+ client = Web3(Web3.IPCProvider(my_provider))
+
+ print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading PinkSwap Smart Contracts...")
+
+ routerAddress = Web3.toChecksumAddress("0x3a6d8cA21D1CF76F653A67577FA0D27453350dD8")
+ factoryAddress = Web3.toChecksumAddress("0x858E3312ed3A876947EA49d572A7C42DE08af7EE")
+
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+
+ weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
+ base_symbol = "BNB"
+ rugdocchain = '&chain=bsc'
+ modified = False
+
+elif settings['EXCHANGE'].lower() == 'apeswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://bsc-dataseed4.defibit.io"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+
+ print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading ApeSwap Smart Contracts...")
+
+ routerAddress = Web3.toChecksumAddress("0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7")
+ factoryAddress = Web3.toChecksumAddress("0x0841BD0B734E4F5853f0dD8d7Ea041c241fb0Da6")
+
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+
+ weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
+ busd = Web3.toChecksumAddress("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56")
+ base_symbol = "BNB"
+ rugdocchain = '&chain=bsc'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'uniswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://pedantic-montalcini:lair-essay-ranger-rigid-hardy-petted@nd-857-678-344.p2pify.com"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "Uniswap Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D")
+ factoryAddress = Web3.toChecksumAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
+ base_symbol = "ETH"
+ rugdocchain = '&chain=eth'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'kuswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://rpc-mainnet.kcc.network"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "Kucoin Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading KuSwap Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0xa58350d6dee8441aa42754346860e3545cc83cda")
+ factoryAddress = Web3.toChecksumAddress("0xAE46cBBCDFBa3bE0F02F463Ec5486eBB4e2e65Ae")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x4446Fc4eb47f2f6586f9fAAb68B3498F86C07521")
+ base_symbol = "KCS"
+ rugdocchain = '&chain=kcc'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'koffeeswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://rpc-mainnet.kcc.network"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "Kucoin Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading KoffeeSwap Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0xc0fFee0000C824D24E0F280f1e4D21152625742b")
+ factoryAddress = Web3.toChecksumAddress("0xC0fFeE00000e1439651C6aD025ea2A71ED7F3Eab")
+ routerContract = client.eth.contract(address=routerAddress, abi=koffeeAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x4446Fc4eb47f2f6586f9fAAb68B3498F86C07521")
+ base_symbol = "KCS"
+ rugdocchain = '&chain=kcc'
+ modified = True
+
+elif settings["EXCHANGE"].lower() == 'spookyswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://rpcapi.fantom.network"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "FANTOM Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0xF491e7B69E4244ad4002BC14e878a34207E38c29")
+ factoryAddress = Web3.toChecksumAddress("0x152eE697f2E276fA89E96742e9bB9aB1F2E61bE3")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83")
+ base_symbol = "FTM"
+ rugdocchain = '&chain=ftm'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'spiritswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://rpcapi.fantom.network"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "FANTOM Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52")
+ factoryAddress = Web3.toChecksumAddress("0xEF45d134b73241eDa7703fa787148D9C9F4950b0")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83")
+ base_symbol = "FTM"
+ rugdocchain = '&chain=ftm'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'quickswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://polygon-rpc.com"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "Matic Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff")
+ factoryAddress = Web3.toChecksumAddress("0x5757371414417b8c6caad45baef941abc7d3ab32")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270")
+ base_symbol = "MATIC"
+ rugdocchain = '&chain=poly'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'waultswap':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://rpc-waultfinance-mainnet.maticvigil.com/v1/0bc1bb1691429f1eeee66b2a4b919c279d83d6b0"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "Matic Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0x3a1D87f206D12415f5b0A33E786967680AAb4f6d")
+ factoryAddress = Web3.toChecksumAddress("0xa98ea6356A316b44Bf710D5f9b6b4eA0081409Ef")
+ routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270")
+ base_symbol = "MATIC"
+ rugdocchain = '&chain=poly'
+ modified = False
+
+elif settings["EXCHANGE"].lower() == 'pangolin':
+ if settings['USECUSTOMNODE'].lower() == 'true':
+ my_provider = settings['CUSTOMNODE']
+ else:
+ my_provider = "https://api.avax.network/ext/bc/C/rpc"
+
+ client = Web3(Web3.HTTPProvider(my_provider))
+ print(timestamp(), "AVAX Chain Connected =", client.isConnected())
+ print(timestamp(), "Loading Smart Contracts...")
+ routerAddress = Web3.toChecksumAddress("0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106")
+ factoryAddress = Web3.toChecksumAddress("0xefa94DE7a4656D787667C749f7E1223D71E9FD88")
+ routerContract = client.eth.contract(address=routerAddress, abi=pangolinAbi)
+ factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
+ weth = Web3.toChecksumAddress("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7")
+ base_symbol = "AVAX"
+ rugdocchain = '&chain=avax'
+ modified = True
+
+
+def get_password():
+ # Function: get_password
+ # ----------------------------
+ # Handles the decision making logic concerning private key encryption and asking the user for their password.
+ #
+ # returns: the user's password
+
+ settings_changed = False
+ setnewpassword = False
+
+ # Check to see if the user has a version of the settings file before private key encryption existed
+ if 'ENCRYPTPRIVATEKEYS' not in settings:
+ response = ""
+ settings_changed = True
+ while response != "y" and response != "n":
+ print("\nWould you like to use a password to encrypt your private keys?")
+ response = input("You will need to input this password each time LimitSwap is executed (y/n): ")
+
+ if response == "y":
+ settings['ENCRYPTPRIVATEKEYS'] = "true"
+ setnewpassword = True
+ else:
+ settings['ENCRYPTPRIVATEKEYS'] = "false"
+
+ # If the user wants to encrypt their private keys, but we don't have an encrypted private key recorded, we need to ask for a password
+ elif settings['ENCRYPTPRIVATEKEYS'] == "true" and not settings['PRIVATEKEY'].startswith('aes:'):
+ print("\nPlease create a password to encrypt your private keys.")
+ setnewpassword = True
+
+ # Set a new password when necessary
+ if setnewpassword == True:
+ settings_changed = True
+ passwords_differ = True
+ while passwords_differ:
+ pwd = pwinput.pwinput(prompt="\nType your new password: ")
+ pwd2 = pwinput.pwinput(prompt="\nType your new password again: ")
+
+ if pwd != pwd2:
+ print("Error, password mismatch. Try again.")
+ else:
+ passwords_differ = False
+
+ # The user already has encrypted private keys. Accept a password so we can unencrypt them
+ elif settings['ENCRYPTPRIVATEKEYS'] == "true":
+
+ if command_line_args.password:
+ pwd = command_line_args.password
+ else:
+ pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
+
+ else:
+ pwd = ""
+
+ if not pwd.strip():
+ print()
+ print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
+ print("X You are running LimitSwap without encrypting your private keys. X")
+ print("X Private keys are stored on disk unencrypted and can be accessed by X")
+ print("X anyone with access to the file system, including the Systems/VPS administrator X")
+ print("X and anyone with physical access to the machine or hard drives. X")
+ print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
+ print()
+
+ if settings_changed == True:
+ save_settings(settings, pwd)
+
+ return pwd
+
+
+# RUGDOC CONTROL IMPLEMENTATION
+# Honeypot API details
+honeypot_url = 'https://honeypot.api.rugdoc.io/api/honeypotStatus.js?address='
+
+# Rugdoc's answers interpretations
+interpretations = {
+ "UNKNOWN": (style.RED + '\nThe status of this token is unknown. '
+ 'This is usually a system error but could \n also be a bad sign for the token. Be careful.'),
+ "OK": (style.GREEN + '\nRUGDOC API RESULT : OK \n'
+ '√ Honeypot tests passed. RugDoc program was able to buy and sell it successfully. This however does not guarantee that it is not a honeypot.'),
+ "NO_PAIRS": (style.RED + '\nRUGDOC API RESULT : NO_PAIRS \n'
+ '⚠ Could not find any trading pair for this token on the default router and could thus not test it.'),
+ "SEVERE_FEE": (style.RED + '\nRUGDOC API RESULT : SEVERE_FEE \n'
+ '/!\ /!\ A severely high trading fee (over 50%) was detected when selling or buying this token.'),
+ "HIGH_FEE": (style.YELLOW + '\nRUGDOC API RESULT : HIGH_FEE \n'
+ '/!\ /!\ A high trading fee (Between 20% and 50%) was detected when selling or buying this token. Our system was however able to sell the token again.'),
+ "MEDIUM_FEE": (style.YELLOW + '\nRUGDOC API RESULT : MEDIUM_FEE \n'
+ '/!\ A trading fee of over 10% but less then 20% was detected when selling or buying this token. Our system was however able to sell the token again.'),
+ "APPROVE_FAILED": (style.RED + '\nRUGDOC API RESULT : APPROVE_FAILED \n'
+ '/!\ /!\ /!\ Failed to approve the token.\n This is very likely a honeypot.'),
+ "SWAP_FAILED": (style.RED + '\nRUGDOC API RESULT : SWAP_FAILED \n'
+ '/!\ /!\ /!\ Failed to sell the token. \n This is very likely a honeypot.'),
+ "chain not found": (style.RED + '\nRUGDOC API RESULT : chain not found \n'
+ '/!\ Sorry, rugdoc API does not work on this chain... (it does not work on ETH, mainly) \n')
+}
+
+
+# Function to check rugdoc API
+def honeypot_check(address):
+ url = (honeypot_url + address + rugdocchain)
+ # sending get request and saving the response as response object
+ return requests.get(url)
+
+
+def save_settings(settings, pwd):
+ if len(pwd) > 0:
+ encrypted_settings = settings.copy()
+ encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
+ pwd)
+ encrypted_settings['PRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['PRIVATEKEY'], pwd)
+
+ # TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
+ # settings.json output so that it's reasable. This should probably be fixed by us importing
+ # the entire json file, instead of just the [0] element.
+
+ print(timestamp(), "Writing settings to file.")
+
+ if settings['ENCRYPTPRIVATEKEYS'] == "true":
+ output_settings = encrypted_settings
+ else:
+ output_settings = settings
+
+ with open(command_line_args.settings, 'w') as f:
+ f.write("[\n")
+ f.write(json.dumps(output_settings, indent=4))
+ f.write("\n]\n")
+
+
+def parse_wallet_settings(settings, pwd):
+ # Function: load_wallet_settings
+ # ----------------------------
+ # Handles the process of deciding whether or not the user's private key needs to be decrypted
+ # Accepts user input for new private keys and wallet addresses
+ #
+ # returns: none (exits on incorrect password)
+
+ settings_changed = False
+
+ # Check for limit wallet information
+ if " " in settings['LIMITWALLETADDRESS'] or settings['LIMITWALLETADDRESS'] == "":
+ settings_changed = True
+ settings['LIMITWALLETADDRESS'] = input("Please provide the wallet address where you have your LIMIT: ")
+
+ # Check for limit wallet private key
+ if " " in settings['LIMITWALLETPRIVATEKEY'] or settings['LIMITWALLETPRIVATEKEY'] == "":
+ settings_changed = True
+ settings['LIMITWALLETPRIVATEKEY'] = input(
+ "Please provide the private key for the wallet where you have your LIMIT: ")
+
+ # If the limit wallet private key is already set and encrypted, decrypt it
+ elif settings['LIMITWALLETPRIVATEKEY'].startswith('aes:'):
+ printt("Decrypting limit wallet private key.")
+ settings['LIMITWALLETPRIVATEKEY'] = settings['LIMITWALLETPRIVATEKEY'].replace('aes:', "", 1)
+ settings['LIMITWALLETPRIVATEKEY'] = cryptocode.decrypt(settings['LIMITWALLETPRIVATEKEY'], pwd)
+
+ if settings['LIMITWALLETPRIVATEKEY'] == False:
+ print(style.RED + "ERROR: Your private key decryption password is incorrect")
+ print(style.RESET + "Please re-launch the bot and try again")
+ sleep(10)
+ sys.exit()
+
+ # Check for trading wallet information
+ if " " in settings['WALLETADDRESS'] or settings['WALLETADDRESS'] == "":
+ settings_changed = True
+ settings['WALLETADDRESS'] = input("Please provide the wallet address for your trading wallet: ")
+
+ # Check for trading wallet private key
+ if " " in settings['PRIVATEKEY'] or settings['PRIVATEKEY'] == "":
+ settings_changed = True
+ settings['PRIVATEKEY'] = input("Please provide the private key for the wallet you want to trade with: ")
+
+ # If the trading wallet private key is already set and encrypted, decrypt it
+ elif settings['PRIVATEKEY'].startswith('aes:'):
+ print(timestamp(), "Decrypting limit wallet private key.")
+ settings['PRIVATEKEY'] = settings['PRIVATEKEY'].replace('aes:', "", 1)
+ settings['PRIVATEKEY'] = cryptocode.decrypt(settings['PRIVATEKEY'], pwd)
+
+ if settings_changed == True:
+ save_settings(settings, pwd)
+
+
+def decimals(address):
+ try:
+ balanceContract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
+ decimals = balanceContract.functions.decimals().call()
+ DECIMALS = 10 ** decimals
+ except ABIFunctionNotFound:
+ DECIMALS = 10 ** 18
+ except ValueError as ve:
+ logging.exception(ve)
+ print("Please check your SELLPRICE values.")
+ return DECIMALS
+
+
+def check_logs():
+ print(timestamp(), "Quickly Checking Log Size")
+ with open('./logs/errors.log') as f:
+ line_count = 0
+ for line in f:
+ line_count += 1
+ if line_count > 100:
+ with open('./logs/errors.log', "r") as f:
+ lines = f.readlines()
+
+ with open('./logs/errors.log', "w") as f:
+ f.writelines(lines[20:])
+
+ f.close()
+
+
+def decode_key():
+ private_key = settings['LIMITWALLETPRIVATEKEY']
+ acct = client.eth.account.privateKeyToAccount(private_key)
+ addr = acct.address
+ return addr
+
+
+def check_release():
+ try:
+ url = 'https://api.github.com/repos/CryptoGnome/LimitSwap/releases/latest'
+ r = requests.get(url).json()['tag_name']
+ print("Checking Latest Release Version on Github, Please Make Sure You are Staying Updated = ", r)
+ logging.info("Checking Latest Release Version on Github, Please Make Sure You are Staying Updated = " + r)
+ except Exception:
+ r = "github api down, please ignore"
+
+ return r
+
+
+def auth():
+ my_provider2 = 'https://reverent-raman:photo-hamlet-ankle-saved-scared-bobbed@nd-539-402-515.p2pify.com'
+ client2 = Web3(Web3.HTTPProvider(my_provider2))
+ print(timestamp(), "Connected to Ethereum BlockChain =", client2.isConnected())
+ # Insert LIMITSWAP Token Contract Here To Calculate Staked Verification
+ address = Web3.toChecksumAddress("0xab95e915c123fded5bdfb6325e35ef5515f1ea69")
+ abi = standardAbi
+ balanceContract = client2.eth.contract(address=address, abi=abi)
+ decimals = balanceContract.functions.decimals().call()
+ DECIMALS = 10 ** decimals
+
+ # Exception for incorrect Key Input
+ try:
+ decode = decode_key()
+ except Exception:
+ print("There is a problem with your private key : please check if it's correct. Don't enter seed phrase !")
+ logging.info(
+ "There is a problem with your private key : please check if it's correct. Don't enter seed phrase !")
+
+ wallet_address = Web3.toChecksumAddress(decode)
+ balance = balanceContract.functions.balanceOf(wallet_address).call()
+ true_balance = balance / DECIMALS
+ print(timestamp(), "Current Tokens Staked =", true_balance)
+ logging.info("Current Tokens Staked = " + str(true_balance))
+ return true_balance
+
+
+def approve(address, amount):
+ print(timestamp(), "Approving", address)
+
+ eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
+
+ if eth_balance > 0.00005:
+ print("Estimating Gas Cost Using Web3")
+ if settings['EXCHANGE'].lower() == 'uniswap':
+ print("Estimating Gas Cost Using Web3")
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price =", gas)
+
+ elif settings['EXCHANGE'].lower() == 'pancakeswap':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ elif settings['EXCHANGE'].lower() == 'spiritswap':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ elif settings['EXCHANGE'].lower() == 'spookyswap':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ elif settings['EXCHANGE'].lower() == 'pangolin':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ elif settings['EXCHANGE'].lower() == 'quickswap':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ elif settings['EXCHANGE'].lower() == 'kuswap' or 'koffeeswap':
+ gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
+ print("Current Gas Price = ", gas)
+ else:
+ print("EXCHANGE NAME IN SETTINGS IS SPELLED INCORRECTLY OR NOT SUPPORTED YET CHECK WIKI!")
+ logging.info("EXCHANGE NAME IN SETTINGS IS SPELLED INCORRECTLY OR NOT SUPPORTED YET CHECK WIKI!")
+ exit()
+
+ contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
+ transaction = contract.functions.approve(routerAddress, amount).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': 300000,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+ signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
+
+ try:
+ return client.eth.sendRawTransaction(signed_txn.rawTransaction)
+ finally:
+ print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
+ # LOG TX TO JSON
+ with open('./transactions.json', 'r') as fp:
+ data = json.load(fp)
+ tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
+ tx_input = {"hash": tx_hash}
+ data.append(tx_input)
+ with open('./transactions.json', 'w') as fp:
+ json.dump(data, fp, indent=2)
+ fp.close()
+
+ return tx_hash
+ else:
+ print(timestamp(),
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ logging.info(
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ sleep(10)
+ sys.exit()
+
+
+def check_approval(address, balance):
+ print(timestamp(), "Checking Approval Status", address)
+ contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
+ allowance = contract.functions.allowance(Web3.toChecksumAddress(settings['WALLETADDRESS']), routerAddress).call()
+
+ if int(allowance) < int(balance):
+
+ if settings["EXCHANGE"].lower() == 'quickswap':
+ print("Revert to Zero To change approval")
+ tx = approve(address, 0)
+ wait_for_tx(tx, address, False)
+ tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
+ wait_for_tx(tx, address, False)
+ else:
+ print(style.YELLOW + "\n ---------------------------------------------------------------------------\n"
+ " You need to APPROVE this token before selling it : LimitSwap will do it now\n"
+ " ---------------------------------------------------------------------------\n")
+ print(style.RESET + "\n")
+
+ tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
+ wait_for_tx(tx, address, False)
+ print(style.GREEN + "\n ---------------------------------------------------------\n"
+ " Token is now approved : LimitSwap will make a BUY order\n"
+ " ---------------------------------------------------------\n")
+ print(style.RESET + "\n")
+
+ return
+
+ else:
+ pass
+
+
+def check_bnb_balance():
+ balance = client.eth.getBalance(settings['WALLETADDRESS'])
+ print(timestamp(), "Current Wallet Balance is :", Web3.fromWei(balance, 'ether'), base_symbol)
+ return balance
+
+
+def check_balance(address, symbol):
+ address = Web3.toChecksumAddress(address)
+ DECIMALS = decimals(address)
+ balanceContract = client.eth.contract(address=address, abi=standardAbi)
+ balance = balanceContract.functions.balanceOf(settings['WALLETADDRESS']).call()
+ print(timestamp(), "Current Wallet Balance is: " + str(balance / DECIMALS) + " " + symbol)
+
+ return balance
+
+
+def fetch_pair(inToken, outToken):
+ print(timestamp(), "Fetching Pair Address")
+ pair = factoryContract.functions.getPair(inToken, outToken).call()
+ print(timestamp(), "Pair Address = ", pair)
+ return pair
+
+
+def sync(inToken, outToken):
+ pair = factoryContract.functions.getPair(inToken, outToken).call()
+ syncContract = client.eth.contract(address=Web3.toChecksumAddress(pair), abi=lpAbi)
+ sync = syncContract.functions.sync().call()
+
+
+def check_pool(inToken, outToken, symbol):
+ # This function is made to calculate Liquidity of a token
+ pair_address = factoryContract.functions.getPair(inToken, outToken).call()
+ DECIMALS = decimals(outToken)
+ pair_contract = client.eth.contract(address=pair_address, abi=lpAbi)
+ reserves = pair_contract.functions.getReserves().call()
+ pooled = reserves[1] / DECIMALS
+ # print("Debug LIQUIDITYAMOUNT line 627 :", pooled, "in token:", outToken)
+
+ return pooled
+
+
+def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase, sellpriceinbase):
+ # CHECK GET RATE OF THE TOKEn
+
+ DECIMALS = decimals(inToken)
+ stamp = timestamp()
+
+ if custom.lower() == 'false':
+ base = base_symbol
+ else:
+ pass
+
+ if routing == 'true':
+ if outToken != weth:
+ price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth, outToken]).call()[-1]
+ DECIMALS = decimals(outToken)
+ tokenPrice = price_check / DECIMALS
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
+ else:
+ price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
+ DECIMALS = decimals(outToken)
+ tokenPrice = price_check / DECIMALS
+ price_output = "{:.18f}".format(tokenPrice)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
+
+ else:
+ if outToken != weth:
+ price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, outToken]).call()[-1]
+ DECIMALS = decimals(outToken)
+ tokenPrice = price_check / DECIMALS
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
+ else:
+ price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
+ DECIMALS = decimals(outToken)
+ tokenPrice = price_check / DECIMALS
+ price_output = "{:.18f}".format(tokenPrice)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
+
+ return tokenPrice
+
+
+def wait_for_tx(tx_hash, address, check):
+ print(timestamp(), "............Waiting 1 minute for TX to Confirm............")
+ timeout = time() + 60
+ while True:
+ print(timestamp(), "............Waiting 1 minute for TX to Confirm............")
+ sleep(1)
+ try:
+ txn_receipt = client.eth.getTransactionReceipt(tx_hash)
+ return txn_receipt['status']
+
+ except Exception as e:
+ txn_receipt = None
+
+ if txn_receipt is not None and txn_receipt['blockHash'] is not None:
+ return txn_receipt['status']
+
+ elif time() > timeout:
+ print(style.RED + "\n")
+ print(timestamp(), "Transaction was not confirmed after 1 minute : something wrong happened.\n"
+ "Please check if :\n"
+ "- your node is running correctly\n"
+ "- you have enough Gaslimit (check 'Gas Used by Transaction') if you have a failed Tx")
+ print(style.RESET + "\n")
+ failedtransactionsamount += 1
+ logging.info("Transaction was not confirmed after 1 minute, breaking Check Cycle....")
+ sleep(5)
+ break
+
+ # loop to check for balance after purchase
+ if check == True:
+ timeout = time() + 30
+ print(style.RESET + "\n")
+
+ while True:
+ print(timestamp(), ".........Waiting 30s to check tokens balance in your wallet after purchase............")
+ sleep(1)
+
+ balance = check_balance(address, address)
+
+ if balance > 0:
+ break
+ elif time() > timeout:
+ print(timestamp(),
+ "NO BUY FOUND, WE WILL CHECK A FEW TIMES TO SEE IF THERE IS BLOCKCHAIN DELAY, IF NOT WE WILL ASSUME THE TX HAS FAILED")
+ logging.info(
+ "NO BUY FOUND, WE WILL CHECK A FEW TIMES TO SEE IF THERE IS BLOCKCHAIN DELAY, IF NOT WE WILL ASSUME THE TX HAS FAILED")
+ break
+
+
+def preapprove(tokens):
+ for token in tokens:
+ check_approval(token['ADDRESS'], 115792089237316195423570985008687907853269984665640564039457584007913129639934)
+
+ if token['USECUSTOMBASEPAIR'].lower() == 'false':
+ check_approval(weth, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
+ else:
+ check_approval(token['BASEADDRESS'],
+ 115792089237316195423570985008687907853269984665640564039457584007913129639934)
+
+
+def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds,
+ failedtransactionsnumber):
+ seconds = int(waitseconds)
+ if int(failedtransactionsamount) == int(failedtransactionsnumber):
+ print(
+ style.RED + "\n ---------------------------------------------------------------\n"
+ " Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
+ " ---------------------------------------------------------------\n\n")
+
+ logging.info("Bot has reached maximum FAILED TRANSACTIONS number: it stops")
+ sleep(10)
+ sys.exit()
+ else:
+
+ if waitseconds != '0':
+ print("Bot will wait", waitseconds, " seconds before buy, as you entered in BUYAFTER_XXX_SECONDS parameter")
+ sleep(seconds)
+
+ print(timestamp(), "Placing New Buy Order for " + symbol)
+
+ if int(gaslimit) < 250000:
+ print(
+ "Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
+ gaslimit = 300000
+
+ if custom.lower() == 'false':
+ balance = Web3.fromWei(check_bnb_balance(), 'ether')
+ base = base_symbol
+ else:
+ address = Web3.toChecksumAddress(inToken)
+ DECIMALS = decimals(address)
+ balance_check = check_balance(inToken, base)
+ balance = balance_check / DECIMALS
+
+ if balance > Decimal(amount):
+ if gas.lower() == 'boost':
+ gas_check = client.eth.gasPrice
+ gas_price = gas_check / 1000000000
+ gas = (gas_price * ((int(boost)) / 100)) + gas_price
+ else:
+ gas = int(gas)
+
+ gaslimit = int(gaslimit)
+ slippage = int(slippage)
+ DECIMALS = decimals(inToken)
+ amount = int(float(amount) * DECIMALS)
+
+ if custom.lower() == 'false':
+ # if USECUSTOMBASEPAIR = false
+ amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+
+ deadline = int(time() + + 60)
+
+ # THIS SECTION IS FOR MODIFIED CONTRACTS : EACH EXCHANGE NEEDS TO BE SPECIFIED
+ # USECUSTOMBASEPAIR = false
+ if modified == True:
+
+ if settings["EXCHANGE"].lower() == 'koffeeswap':
+ transaction = routerContract.functions.swapExactKCSForTokens(
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'value': amount,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
+ transaction = routerContract.functions.swapExactAVAXForTokens(
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'value': amount,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+
+ else:
+ # USECUSTOMBASEPAIR = false
+ # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
+
+ # Special condition on Uniswap, to implement EIP-1559
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ transaction = routerContract.functions.swapExactETHForTokens(
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = false
+ # for all the rest of exchanges with Modified = false
+ transaction = routerContract.functions.swapExactETHForTokens(
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'value': amount,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
+ if inToken == weth:
+ # USECUSTOMBASEPAIR = true
+ # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
+ amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = true
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ if routing.lower() == 'true':
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[
+ -1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # LIQUIDITYINNATIVETOKEN = true
+
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # LIQUIDITYINNATIVETOKEN = true
+ # Exchange different from Uniswap
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
+ if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
+ min_tokens = 100
+ else:
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # Special condition on Uniswap, to implement EIP-1559
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # Base Pair different from weth
+ # Exchange different from Uniswap
+
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ sync(inToken, outToken)
+ signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
+
+ try:
+ return client.eth.sendRawTransaction(signed_txn.rawTransaction)
+ finally:
+ print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
+ # LOG TX TO JSON
+ with open('./transactions.json', 'r') as fp:
+ data = json.load(fp)
+ tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
+ tx_input = {"hash": tx_hash}
+ data.append(tx_input)
+ with open('./transactions.json', 'w') as fp:
+ json.dump(data, fp, indent=2)
+ fp.close()
+
+ return tx_hash
+
+ else:
+ print(timestamp(), "Not Enough " + base + " Balance to make buys")
+ logging.info("Not Enough " + base + " Balance to make buys")
+ return False
+
+
+def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, routing):
+ print(timestamp(), "Placing Sell Order " + symbol)
+ balance = Web3.fromWei(check_balance(inToken, symbol), 'ether')
+ check_approval(inToken, balance * 1000000000)
+
+ if int(gaslimit) < 250000:
+ gaslimit = 300000
+
+ if type(amount) == str:
+ amount_check = balance
+ else:
+ amount_check = Decimal(amount)
+
+ if balance >= Decimal(amount_check) and balance > 0.0000000000000001:
+
+ if gas.lower() == 'boost':
+ gas_check = client.eth.gasPrice
+ gas_price = gas_check / 1000000000
+ gas = (gas_price * ((int(boost) * 4) / 100)) + gas_price
+ else:
+ gas = int(gas)
+
+ slippage = int(slippage)
+ gaslimit = int(gaslimit)
+ DECIMALS = decimals(inToken)
+
+ if amount.lower() == 'all':
+ balance = check_balance(inToken, symbol)
+ moonbag = int(Decimal(moonbag) * DECIMALS)
+ amount = int(Decimal(balance - moonbag))
+
+ else:
+ balance = check_balance(inToken, symbol)
+ amount = Decimal(amount) * DECIMALS
+ moonbag = int(Decimal(moonbag) * DECIMALS)
+
+ if balance < amount:
+ print(timestamp(), "Selling Remaining ", symbol)
+ amount = int(Decimal(balance - moonbag))
+ else:
+ amount = int(Decimal(balance - moonbag))
+ if amount > 0:
+ print(timestamp(), "Selling", amount / DECIMALS, symbol)
+ else:
+ print("Not enough left to sell, would bust moonbag")
+ amount = 0
+
+ if custom.lower() == 'false':
+ # USECUSTOMBASEPAIR = false
+ sync(inToken, weth)
+
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if fees.lower() == 'true':
+
+ # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
+ if modified == True:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = true
+
+ if settings["EXCHANGE"].lower() == 'koffeeswap':
+ transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ if settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
+ transaction = routerContract.functions.swapExactTokensForAVAXSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = true
+ transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+ else:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
+
+ # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
+ if modified == True:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
+ # Modified = true
+
+ if settings["EXCHANGE"].lower() == 'koffeeswap':
+ transaction = routerContract.functions.swapExactTokensForKCS(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+ elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
+ transaction = routerContract.functions.swapExactTokensForAVAX(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = false
+ # HASFEES = false
+ # Modified = false --> uniswap / pancakeswap / apeswap, etc.
+
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForETH(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # for all the rest of exchanges with Modified = false
+ transaction = routerContract.functions.swapExactTokensForETH(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
+ if outToken == weth:
+ # if user has set WETH or WBNB as Custom base pair
+ sync(inToken, outToken)
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if fees.lower() == 'true':
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+
+ if int(gaslimit) < 950000:
+ gaslimit = 950000
+
+ # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
+ if modified == True:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ # Modified = true
+
+ if settings["EXCHANGE"].lower() == 'koffeeswap':
+ transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
+ transaction = routerContract.functions.swapExactTokensForAVAXSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ # Modified = false
+
+ transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+ else:
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = false
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+
+ else:
+ sync(inToken, outToken)
+
+ if routing.lower() == 'false' and outToken != weth:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if fees.lower() == 'true':
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = true
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # for all the rest of exchanges
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # HASFEES = false
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ # for all the rest of exchanges
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ elif routing.lower() == 'false' and outToken == weth:
+ # LIQUIDITYINNATIVETOKEN = false
+ # USECUSTOMBASEPAIR = true
+ # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
+ print(
+ "ERROR IN YOUR TOKENS.JSON : YOU NEED TO CHOOSE THE PROPER BASE PAIR AS SYMBOL IF YOU ARE TRADING OUTSIDE OF NATIVE LIQUIDITY POOL")
+
+ else:
+ amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[-1]
+ min_tokens = int(amount_out * (1 - (slippage / 100)))
+ deadline = int(time() + + 60)
+
+ if fees.lower() == 'true':
+ # HASFEES = true
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+
+ else:
+ transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ else:
+ # HASFEES = false
+ if settings["EXCHANGE"].lower() == 'uniswap':
+ # Special condition on Uniswap, to implement EIP-1559
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
+ 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
+ 'type': "0x02"
+ })
+ else:
+ transaction = routerContract.functions.swapExactTokensForTokens(
+ amount,
+ min_tokens,
+ [inToken, weth, outToken],
+ Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ deadline
+ ).buildTransaction({
+ 'gasPrice': Web3.toWei(gas, 'gwei'),
+ 'gas': gaslimit,
+ 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
+ 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
+ })
+
+ sync(inToken, outToken)
+ signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
+
+ try:
+ return client.eth.sendRawTransaction(signed_txn.rawTransaction)
+ finally:
+ print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
+ # LOG TX TO JSON
+ with open('./transactions.json', 'r') as fp:
+ data = json.load(fp)
+ tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
+ tx_input = {"hash": tx_hash}
+ data.append(tx_input)
+ with open('./transactions.json', 'w') as fp:
+ json.dump(data, fp, indent=2)
+ fp.close()
+
+ return tx_hash
+ else:
+ pass
+
+
+def run():
+ global failedtransactionsamount
+
+ try:
+
+ tokens = load_tokens_file(command_line_args.tokens, True)
+
+ eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
+
+ if eth_balance > 0.000005:
+ pass
+ else:
+ print(
+ style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
+ logging.info(
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ sleep(10)
+ sys.exit()
+
+ if settings['PREAPPROVE'].lower() == 'true':
+ preapprove(tokens)
+ else:
+ pass
+
+ for token in tokens:
+ # Initialization of values, in case the user re-used some old tokens.json files
+ if 'RUGDOC_CHECK' not in token:
+ token['RUGDOC_CHECK'] = 'false'
+ if 'BUYAFTER_XXX_SECONDS' not in token:
+ token['BUYAFTER_XXX_SECONDS'] = 0
+ if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
+ # End of initialization of values
+
+ if token['RUGDOC_CHECK'].lower() == 'true':
+
+ honeypot = honeypot_check(address=token['ADDRESS'])
+ d = json.loads(honeypot.content)
+ for key, value in interpretations.items():
+ if d["status"] in key:
+ honeypot_status = value
+ honeypot_code = key
+ print(honeypot_status)
+
+ decision = ""
+ while decision != "y" and decision != "n":
+ print(style.RESET + "\nWhat is your decision?")
+ decision = input("Would you like to snipe this token? (y/n): ")
+
+ if decision == "y":
+ print(style.RESET + "\nOK let's go!!\n")
+ pass
+ else:
+ sys.exit()
+
+ else:
+ pass
+
+ while True:
+ tokens = load_tokens_file(command_line_args.tokens, False)
+
+ for token in tokens:
+ # Initialization of values, in case the user re-used some old tokens.json files
+ if 'RUGDOC_CHECK' not in token:
+ token['RUGDOC_CHECK'] = 'false'
+ if 'BUYAFTER_XXX_SECONDS' not in token:
+ token['BUYAFTER_XXX_SECONDS'] = 0
+ if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
+ # End of initialization of values
+
+ if token['ENABLED'].lower() == 'true':
+ inToken = Web3.toChecksumAddress(token['ADDRESS'])
+
+ if token['USECUSTOMBASEPAIR'].lower() == 'true':
+ outToken = Web3.toChecksumAddress(token['BASEADDRESS'])
+ else:
+ outToken = weth
+
+ try:
+ quote = check_price(inToken, outToken, token['SYMBOL'], token['BASESYMBOL'],
+ token['USECUSTOMBASEPAIR'], token['LIQUIDITYINNATIVETOKEN'],
+ token['BUYPRICEINBASE'], token['SELLPRICEINBASE'])
+ pool = check_pool(inToken, outToken, token['BASESYMBOL'])
+ # print("Debug Liquidity Reserves ligne 1267:", float(pool))
+ # print("Debug inToken : ", inToken, "outToken :", outToken)
+
+ except Exception:
+ print(timestamp(), token['SYMBOL'],
+ " Not Listed For Trade Yet... waiting for liquidity to be added on exchange")
+ quote = 0
+
+ if quote < Decimal(token['BUYPRICEINBASE']) and quote != 0:
+ balance = check_balance(inToken, token['SYMBOL'])
+ DECIMALS = decimals(inToken)
+ if Decimal(balance / DECIMALS) < Decimal(token['MAXTOKENS']):
+
+ if token["LIQUIDITYCHECK"].lower() == 'true':
+ pool = check_pool(inToken, outToken, token['BASESYMBOL'])
+ print(timestamp(), "You have set LIQUIDITYCHECK = true.")
+ print(timestamp(), "Current", token['SYMBOL'], "Liquidity = ", int(pool), "in token:",
+ outToken)
+
+ if float(token['LIQUIDITYAMOUNT']) <= float(pool):
+ print(timestamp(), "LIQUIDITYAMOUNT parameter =", int(token['LIQUIDITYAMOUNT']),
+ " --> Enough liquidity detected : Buy Signal Found!")
+ log_price = "{:.18f}".format(quote)
+ logging.info("BuySignal Found @" + str(log_price))
+ tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
+ token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
+ token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
+ token['BASESYMBOL'], token['LIQUIDITYINNATIVETOKEN'],
+ token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+
+ if tx != False:
+ tx = wait_for_tx(tx, token['ADDRESS'], True)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ print(style.RESET + "")
+ sleep(3)
+ check_balance(token['ADDRESS'], token['SYMBOL'])
+ print(style.RESET + "\n")
+ sleep(3)
+
+ if tx != 1:
+ # transaction is a FAILURE
+ print(
+ style.RED + "\n -------------------------------------------------\n"
+ " FAILURE ! Plese check your wallet. \n"
+ " Cause of failure can be : \n"
+ " - GASLIMIT too low\n"
+ " - SLIPPAGE too low\n"
+ " -------------------------------------------------\n\n")
+ print(style.RESET + "")
+ failedtransactionsamount += 1
+ preapprove(tokens)
+ else:
+ # transaction is a SUCCESS
+ print(
+ style.GREEN + "\n ----------------------------------\n"
+ " SUCCESS : your Tx is confirmed :)\n"
+ " ----------------------------------\n")
+ print(style.RESET + "")
+ pass
+
+ else:
+ # print("debug 1450")
+ pass
+ else:
+ print(timestamp(), "LIQUIDITYAMOUNT parameter =", int(token['LIQUIDITYAMOUNT']),
+ " : not enough liquidity, bot will not buy")
+
+ else:
+ print(timestamp(), "Buy Signal Found!")
+ log_price = "{:.18f}".format(quote)
+ logging.info("BuySignal Found @" + str(log_price))
+ tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'], token['SLIPPAGE'],
+ token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
+ token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['BASESYMBOL'],
+ token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+
+ if tx != False:
+ tx = wait_for_tx(tx, token['ADDRESS'], True)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ print(style.RESET + "")
+ sleep(3)
+ check_balance(token['ADDRESS'], token['SYMBOL'])
+ print(style.RESET + "\n")
+ sleep(3)
+
+ if tx != 1:
+ # transaction is a FAILURE
+ print(
+ style.RED + "\n -------------------------------------------------\n"
+ " FAILURE ! Please check your wallet. \n"
+ " Cause of failure can be : \n"
+ " - GASLIMIT too low\n"
+ " - SLIPPAGE too low\n"
+ " -------------------------------------------------\n\n")
+ print(style.RESET + "")
+ failedtransactionsamount += 1
+ preapprove(tokens)
+ else:
+ # transaction is a SUCCESS
+ print(
+ style.GREEN + "\n ----------------------------------\n"
+ " SUCCESS : your Tx is confirmed :)\n"
+ " ----------------------------------\n")
+ print(style.RESET + "")
+ pass
+ else:
+ # print("debug 1497")
+ pass
+
+
+ else:
+ print(timestamp(), "You own more tokens than your MAXTOKENS parameter for ",
+ token['SYMBOL'])
+
+ if quote > Decimal(token['SELLPRICEINBASE']):
+ DECIMALS = decimals(inToken)
+ balance = check_balance(inToken, token['SYMBOL'])
+ moonbag = int(Decimal(token['MOONBAG']) * DECIMALS)
+ balance = int(Decimal(balance - moonbag))
+
+ if balance > 0:
+ print(timestamp(), "Sell Signal Found " + token['SYMBOL'])
+ log_price = "{:.18f}".format(quote)
+ logging.info("Sell Signal Found @" + str(log_price))
+ tx = sell(token['SELLAMOUNTINTOKENS'], token['MOONBAG'], inToken, outToken,
+ token['GAS'], token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
+ token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
+ token['LIQUIDITYINNATIVETOKEN'])
+ wait_for_tx(tx, token['ADDRESS'], False)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ sleep(5)
+ print(style.RESET + "")
+ else:
+ pass
+
+
+ elif quote > Decimal(token['SELLPRICEINBASE']) and quote != 0:
+ DECIMALS = decimals(inToken)
+ balance = check_balance(inToken, token['SYMBOL'])
+ moonbag = int(Decimal(token['MOONBAG']) * DECIMALS)
+ balance = int(Decimal(balance - moonbag))
+
+ if balance > 0:
+ print(timestamp(), "Sell Signal Found " + token['SYMBOL'])
+ log_price = "{:.18f}".format(quote)
+ logging.info("Sell Signal Found @" + str(log_price))
+ tx = sell(token['SELLAMOUNTINTOKENS'], token['MOONBAG'], inToken, outToken, token['GAS'],
+ token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
+ token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['LIQUIDITYINNATIVETOKEN'])
+ wait_for_tx(tx, token['ADDRESS'], False)
+ print(
+ style.RESET + "\n --------------------------------------\n"
+ " √ Tx done. Check your wallet \n"
+ " --------------------------------------")
+ sleep(5)
+ print(style.RESET + "")
+
+ else:
+ # Double Check For Buy if Sell Signal Triggers
+ if quote < Decimal(token['BUYPRICEINBASE']):
+ balance = check_balance(inToken, token['SYMBOL'])
+ if Web3.fromWei(balance, 'ether') < Decimal(token['MAXTOKENS']):
+ print(timestamp(), "Buy Signal Found!")
+ log_price = "{:.18f}".format(quote)
+ logging.info("Sell Signal Found @" + str(log_price))
+ tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
+ token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
+ token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
+ token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
+ token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
+ wait_for_tx(tx, token['ADDRESS'], False)
+ else:
+ print(timestamp(), "Bot has reached MAXTOKENS Position Size for ", token['SYMBOL'])
+ pass
+ else:
+ pass
+
+ sleep(cooldown)
+
+ except Exception as ee:
+ print(timestamp(), "ERROR. Please go to /log folder and open your error logs : you will find more details.")
+ logging.exception(ee)
+ logger1.exception(ee)
+ sleep(10)
+ print("Restarting LimitSwap")
+ logging.info("Restarting LimitSwap")
+ # Cooldown Logic
+ timeout = 10
+ nonce = 0
+ while True:
+ print(".........Restart Cooldown left " + str(timeout - nonce) + " seconds.............")
+ nonce += 1
+ sleep(1)
+ if nonce > timeout:
+ run()
+
+
+try:
+
+ check_logs()
+
+ # Get the user password on first run
+ userpassword = get_password()
+
+ # Handle any proccessing that is necessary to load the private key for the wallet
+ parse_wallet_settings(settings, userpassword)
+
+ # The LIMIT balance of the user.
+ true_balance = auth()
+
+ version = 3.36
+ logging.info("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
+ print("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
+ check_release()
+
+ if true_balance >= 50:
+ print(timestamp(), "Professional Subscriptions Active")
+ cooldown = 0.01
+ run()
+
+ elif true_balance >= 25 and true_balance < 50:
+ print(timestamp(), "Trader Subscriptions Active")
+ cooldown = 3
+ run()
+ elif true_balance >= 10 and true_balance < 25:
+ print(timestamp(), "Casual Subscriptions Active")
+ cooldown = 6
+ run()
+ else:
+ print(timestamp(),
+ "10 - 50 $LIMIT tokens needed to use this bot, please visit the LimitSwap.com for more info or buy more tokens on Uniswap to use!")
+ logging.exception(
+ "10 - 50 $LIMIT tokens needed to use this bot, please visit the LimitSwap.com for more info or buy more tokens on Uniswap to use!")
+
+
+except Exception as e:
+ print(timestamp(), "ERROR. Please go to /log folder and open your error logs : you will find more details.")
+ logging.exception(e)
+ logger1.exception(e)
+ print("Restarting LimitSwap")
+ logging.info("Restarting LimitSwap")
+ # Cooldown Logic
+ timeout = 10
+ nonce = 0
+ while True:
+ print(".........Restart Cooldown left " + str(timeout - nonce) + " seconds.............")
+ nonce += 1
+ sleep(1)
+ if nonce > timeout:
+ run()
+
+# -*- coding: utf-8 -*-
+from web3 import Web3
+from time import sleep, time
+import json
+from decimal import Decimal
+import os
+from web3.exceptions import ABIFunctionNotFound, TransactionNotFound, BadFunctionCallOutput
+import logging
+from datetime import datetime
+import sys
+import requests
+import cryptocode, re, pwinput
+import argparse
+import signal
+
+# DEVELOPER CONSIDERATIONS
+#
+# USER INTERACTION - Do not depend on user interaction. If you develop a setting that is going to require
+# user interaction while the bot is running, warn the user before hand. Accept a value before the check
+# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
+# entire process from buying all the way to selling multiple positions and multiple pairs with zero user
+# interaction.
+#
+# HANDLING NEW ENTRIES IN settings.json - When adding a new configuration item in settings.json be sure to
+# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file.
+# Do not assume a user has changed their settings.json file to work with the new version, your additions
+# should be backwards compatible and have safe default values if possible
+#
+# HANDLING NEW ENTRIES IN tokens.json - When adding a new configuration item in tokens.json be sure to
+# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file
+# Do not assume a user has changed their tokens.json file to work with the new version, your additions
+# should be backwards compatible and have safe default values if possible
+
+
+# initialization of number of failed transactions
+failedtransactionsamount = 0
+
+
+# color styles
+class style(): # Class of different text colours - default is white
+ BLACK = '\033[30m'
+ RED = '\033[31m'
+ GREEN = '\033[32m'
+ YELLOW = '\033[33m'
+ BLUE = '\033[34m'
+ MAGENTA = '\033[35m'
+ CYAN = '\033[36m'
+ WHITE = '\033[37m'
+ UNDERLINE = '\033[4m'
+ RESET = '\033[0m'
+
+
# Function to cleanly exit on SIGINT
def signal_handler(sig, frame):
sys.exit(0)
+
+
signal.signal(signal.SIGINT, signal_handler)
+
def timestamp():
timestamp = time()
dt_object = datetime.fromtimestamp(timestamp)
return dt_object
+
#
# COMMAND LINE ARGUMENTS
#
parser = argparse.ArgumentParser()
-parser.add_argument("-p", "--password", type=str, help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
-parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)", default="./settings.json")
-parser.add_argument("-t", "--tokens" , type=str, help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
-parser.add_argument("-v", "--verbose" , action='store_true', help="Print detailed messages to stdout")
+parser.add_argument("-p", "--password", type=str,
+ help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
+parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)",
+ default="./settings.json")
+parser.add_argument("-t", "--tokens", type=str,
+ help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
+parser.add_argument("-v", "--verbose", action='store_true', help="Print detailed messages to stdout")
command_line_args = parser.parse_args()
+
def printt(*print_args):
# Function: printt
# ----------------------------
@@ -77,7 +2259,8 @@ def printt(*print_args):
#
# returns: nothing
- print(timestamp(),' '.join(map(str,print_args)))
+ print(timestamp(), ' '.join(map(str, print_args)))
+
def printt_v(*print_args):
# Function: printt
@@ -87,7 +2270,8 @@ def printt_v(*print_args):
# returns: nothing
if command_line_args.verbose == True:
- print(timestamp(),' '.join(map(str,print_args)))
+ print(timestamp(), ' '.join(map(str, print_args)))
+
def printt_err(*print_args):
# Function: printt_err
@@ -96,9 +2280,10 @@ def printt_err(*print_args):
#
# returns: nothing
- print(timestamp(), " ", style.RED, ' '.join(map(str,print_args)), style.RESET, sep="")
+ print(timestamp(), " ", style.RED, ' '.join(map(str, print_args)), style.RESET, sep="")
+
-def load_settings_file(settings_path, load_message = True):
+def load_settings_file(settings_path, load_message=True):
# Function: load_settings_file
# ----------------------------
# loads the settings file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
@@ -116,15 +2301,15 @@ def load_settings_file(settings_path, load_message = True):
f.close()
for default_false in ['UNLIMITEDSLIPPAGE', 'USECUSTOMNODE']:
- if default_false not in settings:
- printt_v (default_false, "not found in settings configuration file, settings a default value of false.")
+ if default_false not in settings:
+ printt_v(default_false, "not found in settings configuration file, settings a default value of false.")
settings[default_false] = "false"
else:
settings[default_false] = settings[default_false].lower()
for default_true in ['PREAPPROVE']:
if default_true not in settings:
- printt_v (default_true, "not found in settings configuration file, settings a default value of true.")
+ printt_v(default_true, "not found in settings configuration file, settings a default value of true.")
settings[default_true] = "true"
else:
settings[default_true] = settings[default_true].lower()
@@ -132,14 +2317,15 @@ def load_settings_file(settings_path, load_message = True):
# Keys that must be set
for required_key in ['EXCHANGE']:
if required_key not in settings:
- printt_err (required_key, "not found in settings configuration file.")
- exit (-1)
+ printt_err(required_key, "not found in settings configuration file.")
+ exit(-1)
else:
settings[required_key] = settings[required_key].lower()
return settings
-def load_tokens_file(tokens_path, load_message = True):
+
+def load_tokens_file(tokens_path, load_message=True):
# Function: load_tokens_File
# ----------------------------
# loads the token definition file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
@@ -161,32 +2347,34 @@ def load_tokens_file(tokens_path, load_message = True):
for default_false in ['ENABLED', 'LIQUIDITYCHECK', 'LIQUIDITYINNATIVETOKEN', 'USECUSTOMBASEPAIR', 'HASFEES']:
if default_false not in token:
- printt_v (default_false, "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a default value of false")
+ printt_v(default_false, "not found in configuration file in configuration for to token",
+ token['SYMBOL'], "setting a default value of false")
token[default_false] = "false"
else:
token[default_false] = token[default_false].lower()
-
# Keys that must be set
- for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE' ]:
+ for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE']:
if required_key not in token:
- printt_err (required_key, "not found in configuration file in configuration for to token", token['SYMBOL'])
- exit (-1)
+ printt_err(required_key, "not found in configuration file in configuration for to token",
+ token['SYMBOL'])
+ exit(-1)
token_defaults = {
- 'SLIPPAGE' : 49,
- 'MAXTOKENS' : 0,
- 'MOONBAG' : 0,
- 'SELLAMOUNTINTOKENS' : 'all',
- 'GAS' : 20,
- 'BOOSTPERCENT' : 50,
- 'GASLIMIT' : 1000000
+ 'SLIPPAGE': 49,
+ 'MAXTOKENS': 0,
+ 'MOONBAG': 0,
+ 'SELLAMOUNTINTOKENS': 'all',
+ 'GAS': 20,
+ 'BOOSTPERCENT': 50,
+ 'GASLIMIT': 1000000
}
for default_key in token_defaults:
if default_key not in token:
- printt_v (default_key , "not found in configuration file in configuration for to token", token['SYMBOL'], "setting a value of", token_defaults['default_key'])
+ printt_v(default_key, "not found in configuration file in configuration for to token", token['SYMBOL'],
+ "setting a value of", token_defaults['default_key'])
token[default_key] = token_defaults[default_key]
elif default_key == 'SELLAMOUNTINTOKENS':
token_defaults[default_key] = token_defaults[default_key].lower()
@@ -629,7 +2817,7 @@ def get_password():
print("X and anyone with physical access to the machine or hard drives. X")
print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
print()
-
+
if settings_changed == True:
save_settings(settings, pwd)
@@ -659,7 +2847,7 @@ def get_password():
"SWAP_FAILED": (style.RED + '\nRUGDOC API RESULT : SWAP_FAILED \n'
'/!\ /!\ /!\ Failed to sell the token. \n This is very likely a honeypot.'),
"chain not found": (style.RED + '\nRUGDOC API RESULT : chain not found \n'
- '/!\ Sorry, rugdoc API does not work on this chain... (it does not work on ETH, mainly) \n')
+ '/!\ Sorry, rugdoc API does not work on this chain... (it does not work on ETH, mainly) \n')
}
@@ -671,7 +2859,6 @@ def honeypot_check(address):
def save_settings(settings, pwd):
-
if len(pwd) > 0:
encrypted_settings = settings.copy()
encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
@@ -681,7 +2868,7 @@ def save_settings(settings, pwd):
# TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
# settings.json output so that it's reasable. This should probably be fixed by us importing
# the entire json file, instead of just the [0] element.
-
+
print(timestamp(), "Writing settings to file.")
if settings['ENCRYPTPRIVATEKEYS'] == "true":
@@ -704,7 +2891,7 @@ def parse_wallet_settings(settings, pwd):
# returns: none (exits on incorrect password)
settings_changed = False
-
+
# Check for limit wallet information
if " " in settings['LIMITWALLETADDRESS'] or settings['LIMITWALLETADDRESS'] == "":
settings_changed = True
@@ -971,26 +3158,30 @@ def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth, outToken]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
else:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
else:
if outToken != weth:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, outToken]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
+ print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
else:
price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
DECIMALS = decimals(outToken)
tokenPrice = price_check / DECIMALS
price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base, "//// your sellprice =", sellpriceinbase, base)
+ print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
+ "//// your sellprice =", sellpriceinbase, base)
return tokenPrice
@@ -1055,10 +3246,12 @@ def preapprove(tokens):
115792089237316195423570985008687907853269984665640564039457584007913129639934)
-def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds, failedtransactionsnumber):
+def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds,
+ failedtransactionsnumber):
seconds = int(waitseconds)
if int(failedtransactionsamount) == int(failedtransactionsnumber):
- print(style.RED + "\n ---------------------------------------------------------------\n"
+ print(
+ style.RED + "\n ---------------------------------------------------------------\n"
" Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
" ---------------------------------------------------------------\n\n")
@@ -1074,7 +3267,8 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
print(timestamp(), "Placing New Buy Order for " + symbol)
if int(gaslimit) < 250000:
- print("Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
+ print(
+ "Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
gaslimit = 300000
if custom.lower() == 'false':
@@ -1100,7 +3294,7 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
amount = int(float(amount) * DECIMALS)
if custom.lower() == 'false':
- # if USECUSTOMBASEPAIR = false
+ # if USECUSTOMBASEPAIR = false
amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
min_tokens = 100
@@ -1354,7 +3548,7 @@ def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom,
def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, routing):
print(timestamp(), "Placing Sell Order " + symbol)
balance = Web3.fromWei(check_balance(inToken, symbol), 'ether')
- check_approval(inToken, balance*1000000000)
+ check_approval(inToken, balance * 1000000000)
if int(gaslimit) < 250000:
gaslimit = 300000
@@ -1630,7 +3824,7 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
# USECUSTOMBASEPAIR = true
# HASFEES = true
if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
+ # Special condition on Uniswap, to implement EIP-1559
transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
min_tokens,
@@ -1666,7 +3860,7 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
# USECUSTOMBASEPAIR = true
# HASFEES = false
if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
+ # Special condition on Uniswap, to implement EIP-1559
transaction = routerContract.functions.swapExactTokensForTokens(
amount,
min_tokens,
@@ -1712,7 +3906,7 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
if fees.lower() == 'true':
# HASFEES = true
if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
+ # Special condition on Uniswap, to implement EIP-1559
transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
min_tokens,
@@ -1745,7 +3939,7 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
else:
# HASFEES = false
if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
+ # Special condition on Uniswap, to implement EIP-1559
transaction = routerContract.functions.swapExactTokensForTokens(
amount,
min_tokens,
@@ -1797,11 +3991,10 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
def run():
-
global failedtransactionsamount
try:
-
+
tokens = load_tokens_file(command_line_args.tokens, True)
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
@@ -1809,8 +4002,10 @@ def run():
if eth_balance > 0.05:
pass
else:
- print(style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
- logging.info("You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
+ print(
+ style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
+ logging.info(
+ "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
sleep(10)
sys.exit()
@@ -1828,7 +4023,7 @@ def run():
if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
# End of initialization of values
-
+
if token['RUGDOC_CHECK'].lower() == 'true':
honeypot = honeypot_check(address=token['ADDRESS'])
@@ -1855,7 +4050,7 @@ def run():
while True:
tokens = load_tokens_file(command_line_args.tokens, False)
-
+
for token in tokens:
# Initialization of values, in case the user re-used some old tokens.json files
if 'RUGDOC_CHECK' not in token:
@@ -1865,7 +4060,7 @@ def run():
if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
# End of initialization of values
-
+
if token['ENABLED'].lower() == 'true':
inToken = Web3.toChecksumAddress(token['ADDRESS'])
@@ -1997,7 +4192,8 @@ def run():
else:
- print(timestamp(), "You own more tokens than your MAXTOKENS parameter for ", token['SYMBOL'])
+ print(timestamp(), "You own more tokens than your MAXTOKENS parameter for ",
+ token['SYMBOL'])
if quote > Decimal(token['SELLPRICEINBASE']):
DECIMALS = decimals(inToken)
@@ -2139,5 +4335,3 @@ def run():
if nonce > timeout:
run()
-
-
From 50df28ed25d2f10ed7547b19ecc94169e87436f9 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:13:13 +0100
Subject: [PATCH 07/16] Update LimitSwap.py
---
LimitSwap.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index c334a05..bd80d0d 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -815,7 +815,7 @@ def auth():
client2 = Web3(Web3.HTTPProvider(my_provider2))
print(timestamp(), "Connected to Ethereum BlockChain =", client2.isConnected())
# Insert LIMITSWAP Token Contract Here To Calculate Staked Verification
- address = Web3.toChecksumAddress("0xab95e915c123fded5bdfb6325e35ef5515f1ea69")
+ address = Web3.toChecksumAddress("0x1712aad2c773ee04bdc9114b32163c058321cd85")
abi = standardAbi
balanceContract = client2.eth.contract(address=address, abi=abi)
decimals = balanceContract.functions.decimals().call()
@@ -842,7 +842,7 @@ def approve(address, amount):
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
- if eth_balance > 0.00005:
+ if eth_balance > 0.05:
print("Estimating Gas Cost Using Web3")
if settings['EXCHANGE'].lower() == 'uniswap':
print("Estimating Gas Cost Using Web3")
@@ -1835,7 +1835,7 @@ def run():
eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
- if eth_balance > 0.000005:
+ if eth_balance > 0.05:
pass
else:
print(
From e944fe68e2e618eb6a4075ecf552ba3d8b6e3336 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:15:51 +0100
Subject: [PATCH 08/16] Update LimitSwap.py
---
LimitSwap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index bd80d0d..937611f 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -192,7 +192,7 @@ def load_tokens_file(tokens_path, load_message=True):
'MAXTOKENS': 0,
'MOONBAG': 0,
'SELLAMOUNTINTOKENS': 'all',
- 'GAS': 20,
+ 'GAS': 8,
'BOOSTPERCENT': 50,
'GASLIMIT': 1000000
From 7948cec528526c7830eb5994ca1a0d8ce18763d8 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:27:47 +0100
Subject: [PATCH 09/16] Update LimitSwap.py
---
LimitSwap.py | 2171 +-------------------------------------------------
1 file changed, 3 insertions(+), 2168 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 937611f..72b4b67 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -192,7 +192,7 @@ def load_tokens_file(tokens_path, load_message=True):
'MAXTOKENS': 0,
'MOONBAG': 0,
'SELLAMOUNTINTOKENS': 'all',
- 'GAS': 8,
+ 'GAS': 20,
'BOOSTPERCENT': 50,
'GASLIMIT': 1000000
@@ -921,14 +921,14 @@ def check_approval(address, balance):
else:
print(style.YELLOW + "\n ---------------------------------------------------------------------------\n"
" You need to APPROVE this token before selling it : LimitSwap will do it now\n"
- " ---------------------------------------------------------------------------\n")
+ " ---------------------------------------------------------------------------")
print(style.RESET + "\n")
tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
wait_for_tx(tx, address, False)
print(style.GREEN + "\n ---------------------------------------------------------\n"
" Token is now approved : LimitSwap will make a BUY order\n"
- " ---------------------------------------------------------\n")
+ " ---------------------------------------------------------")
print(style.RESET + "\n")
return
@@ -2170,2168 +2170,3 @@ def run():
sleep(1)
if nonce > timeout:
run()
-
-# -*- coding: utf-8 -*-
-from web3 import Web3
-from time import sleep, time
-import json
-from decimal import Decimal
-import os
-from web3.exceptions import ABIFunctionNotFound, TransactionNotFound, BadFunctionCallOutput
-import logging
-from datetime import datetime
-import sys
-import requests
-import cryptocode, re, pwinput
-import argparse
-import signal
-
-# DEVELOPER CONSIDERATIONS
-#
-# USER INTERACTION - Do not depend on user interaction. If you develop a setting that is going to require
-# user interaction while the bot is running, warn the user before hand. Accept a value before the check
-# for liquidity, and provide a command line flag. Basically, provide ways for the bot to continue it's
-# entire process from buying all the way to selling multiple positions and multiple pairs with zero user
-# interaction.
-#
-# HANDLING NEW ENTRIES IN settings.json - When adding a new configuration item in settings.json be sure to
-# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file.
-# Do not assume a user has changed their settings.json file to work with the new version, your additions
-# should be backwards compatible and have safe default values if possible
-#
-# HANDLING NEW ENTRIES IN tokens.json - When adding a new configuration item in tokens.json be sure to
-# review comment "COMMAND LINE ARGUMENTS" and the functions load_settings_file and save_settings_file
-# Do not assume a user has changed their tokens.json file to work with the new version, your additions
-# should be backwards compatible and have safe default values if possible
-
-
-# initialization of number of failed transactions
-failedtransactionsamount = 0
-
-
-# color styles
-class style(): # Class of different text colours - default is white
- BLACK = '\033[30m'
- RED = '\033[31m'
- GREEN = '\033[32m'
- YELLOW = '\033[33m'
- BLUE = '\033[34m'
- MAGENTA = '\033[35m'
- CYAN = '\033[36m'
- WHITE = '\033[37m'
- UNDERLINE = '\033[4m'
- RESET = '\033[0m'
-
-
-# Function to cleanly exit on SIGINT
-def signal_handler(sig, frame):
- sys.exit(0)
-
-
-signal.signal(signal.SIGINT, signal_handler)
-
-
-def timestamp():
- timestamp = time()
- dt_object = datetime.fromtimestamp(timestamp)
- return dt_object
-
-
-#
-# COMMAND LINE ARGUMENTS
-#
-
-parser = argparse.ArgumentParser()
-parser.add_argument("-p", "--password", type=str,
- help="Password to decrypt private keys (WARNING: your password could be saved in your command prompt history)")
-parser.add_argument("-s", "--settings", type=str, help="Specify the file to user for settings (default: settings.json)",
- default="./settings.json")
-parser.add_argument("-t", "--tokens", type=str,
- help="Specify the file to use for tokens to trade (default: tokens.json)", default="./tokens.json")
-parser.add_argument("-v", "--verbose", action='store_true', help="Print detailed messages to stdout")
-command_line_args = parser.parse_args()
-
-
-def printt(*print_args):
- # Function: printt
- # ----------------------------
- # provides normal print() functionality but also prints our timestamp
- #
- # returns: nothing
-
- print(timestamp(), ' '.join(map(str, print_args)))
-
-
-def printt_v(*print_args):
- # Function: printt
- # ----------------------------
- # provides normal print() functionality but also prints our timestamp and pays attention to user set verbosity.
- #
- # returns: nothing
-
- if command_line_args.verbose == True:
- print(timestamp(), ' '.join(map(str, print_args)))
-
-
-def printt_err(*print_args):
- # Function: printt_err
- # --------------------
- # provides normal print() functionality but also prints our timestamp and the text highlighted to display an error
- #
- # returns: nothing
-
- print(timestamp(), " ", style.RED, ' '.join(map(str, print_args)), style.RESET, sep="")
-
-
-def load_settings_file(settings_path, load_message=True):
- # Function: load_settings_file
- # ----------------------------
- # loads the settings file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
- # exits with an error message if necessary variables are not found in the settings files
- #
- # settings_path = the path of the file to load settings from
- #
- # returns: a dictionary with the settings from the file loaded
-
- if load_message == True:
- print(timestamp(), "Loading settings from", command_line_args.settings)
-
- f = open(command_line_args.settings, )
- settings = json.load(f)[0]
- f.close()
-
- for default_false in ['UNLIMITEDSLIPPAGE', 'USECUSTOMNODE']:
- if default_false not in settings:
- printt_v(default_false, "not found in settings configuration file, settings a default value of false.")
- settings[default_false] = "false"
- else:
- settings[default_false] = settings[default_false].lower()
-
- for default_true in ['PREAPPROVE']:
- if default_true not in settings:
- printt_v(default_true, "not found in settings configuration file, settings a default value of true.")
- settings[default_true] = "true"
- else:
- settings[default_true] = settings[default_true].lower()
-
- # Keys that must be set
- for required_key in ['EXCHANGE']:
- if required_key not in settings:
- printt_err(required_key, "not found in settings configuration file.")
- exit(-1)
- else:
- settings[required_key] = settings[required_key].lower()
-
- return settings
-
-
-def load_tokens_file(tokens_path, load_message=True):
- # Function: load_tokens_File
- # ----------------------------
- # loads the token definition file defined by command_line_args.settings, sets sane defaults if variables aren't found in settings file
- # exits with an error message if necessary variables are not found in the settings files
- #
- # tokens_path: the path of the file to load tokens from
- #
- # returns: a dictionary with the settings from the file loaded
-
- if load_message == True:
- print(timestamp(), "Loading tokens from", command_line_args.tokens)
-
- s = open(command_line_args.tokens, )
- tokens = json.load(s)
- s.close()
-
- # Make sure all values are lowercase
- for token in tokens:
-
- for default_false in ['ENABLED', 'LIQUIDITYCHECK', 'LIQUIDITYINNATIVETOKEN', 'USECUSTOMBASEPAIR', 'HASFEES']:
- if default_false not in token:
- printt_v(default_false, "not found in configuration file in configuration for to token",
- token['SYMBOL'], "setting a default value of false")
- token[default_false] = "false"
- else:
- token[default_false] = token[default_false].lower()
-
- # Keys that must be set
- for required_key in ['ADDRESS', 'BUYAMOUNTINBASE', 'BUYPRICEINBASE', 'SELLPRICEINBASE']:
- if required_key not in token:
- printt_err(required_key, "not found in configuration file in configuration for to token",
- token['SYMBOL'])
- exit(-1)
-
- token_defaults = {
- 'SLIPPAGE': 49,
- 'MAXTOKENS': 0,
- 'MOONBAG': 0,
- 'SELLAMOUNTINTOKENS': 'all',
- 'GAS': 20,
- 'BOOSTPERCENT': 50,
- 'GASLIMIT': 1000000
-
- }
-
- for default_key in token_defaults:
- if default_key not in token:
- printt_v(default_key, "not found in configuration file in configuration for to token", token['SYMBOL'],
- "setting a value of", token_defaults['default_key'])
- token[default_key] = token_defaults[default_key]
- elif default_key == 'SELLAMOUNTINTOKENS':
- token_defaults[default_key] = token_defaults[default_key].lower()
-
- return tokens
-
-
-"""""""""""""""""""""""""""
-//PRELOAD
-"""""""""""""""""""""""""""
-print(timestamp(), "Preloading Data")
-settings = load_settings_file(command_line_args.settings)
-
-directory = './abi/'
-filename = "standard.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- standardAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "lp.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- lpAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "router.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- routerAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "factory2.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- factoryAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "koffee.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- koffeeAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "pangolin.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- pangolinAbi = json.load(json_file)
-
-directory = './abi/'
-filename = "joeRouter.json"
-file_path = os.path.join(directory, filename)
-with open(file_path) as json_file:
- joeRouter = json.load(json_file)
-
-"""""""""""""""""""""""""""
-//ERROR LOGGING
-"""""""""""""""""""""""""""
-os.makedirs('./logs', exist_ok=True)
-
-if not os.path.exists('./logs/errors.log'):
- open('./logs/errors.log', 'w').close()
-
-if not os.path.exists('./logs/exceptions.log'):
- open('./logs/exceptions.log', 'w').close()
-
-log_format = '%(levelname)s: %(asctime)s %(message)s'
-logging.basicConfig(filename='./logs/errors.log',
- level=logging.INFO,
- format=log_format)
-
-logger1 = logging.getLogger('1')
-logger1.addHandler(logging.FileHandler('./logs/exceptions.log'))
-
-logging.info("*************************************************************************************")
-logging.info("For Help & To Learn More About how the bot works please visit our wiki here:")
-logging.info("https://cryptognome.gitbook.io/limitswap/")
-logging.info("*************************************************************************************")
-
-"""""""""""""""""""""""""""
-//NETWORKS SELECT
-"""""""""""""""""""""""""""
-
-if settings['EXCHANGE'].lower() == 'pancakeswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- print(timestamp(), 'Using custom node.')
- else:
- my_provider = "https://bsc-dataseed4.defibit.io"
-
- if not my_provider:
- print(timestamp(), 'Custom node empty. Exiting')
- exit(1)
-
- if my_provider[0].lower() == 'h':
- print(timestamp(), 'Using HTTPProvider')
- client = Web3(Web3.HTTPProvider(my_provider))
- elif my_provider[0].lower() == 'w':
- print(timestamp(), 'Using WebsocketProvider')
- client = Web3(Web3.WebsocketProvider(my_provider))
- else:
- print(timestamp(), 'Using IPCProvider')
- client = Web3(Web3.IPCProvider(my_provider))
-
- print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
-
- if settings['EXCHANGEVERSION'] == "1":
- routerAddress = Web3.toChecksumAddress("0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F")
- factoryAddress = Web3.toChecksumAddress("0xbcfccbde45ce874adcb698cc183debcf17952812")
- elif settings['EXCHANGEVERSION'] == "2":
- routerAddress = Web3.toChecksumAddress("0x10ED43C718714eb63d5aA57B78B54704E256024E")
- factoryAddress = Web3.toChecksumAddress("0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73")
-
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
- base_symbol = "BNB"
- rugdocchain = '&chain=bsc'
- modified = False
-
-if settings['EXCHANGE'].lower() == 'traderjoe':
-
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://api.avax.network/ext/bc/C/rpc"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "AVAX Smart Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
-
- routerAddress = Web3.toChecksumAddress("0x60aE616a2155Ee3d9A68541Ba4544862310933d4")
- factoryAddress = Web3.toChecksumAddress("0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10")
-
- routerContract = client.eth.contract(address=routerAddress, abi=joeRouter)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7")
- base_symbol = "AVAX"
- rugdocchain = '&chain=avax'
- modified = True
-
-elif settings['EXCHANGE'].lower() == 'pinkswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- print(timestamp(), 'Using custom node.')
- else:
- my_provider = "https://bsc-dataseed4.defibit.io"
-
- if not my_provider:
- print(timestamp(), 'Custom node empty. Exiting')
- exit(1)
-
- if my_provider[0].lower() == 'h':
- print(timestamp(), 'Using HTTPProvider')
- client = Web3(Web3.HTTPProvider(my_provider))
- elif my_provider[0].lower() == 'w':
- print(timestamp(), 'Using WebsocketProvider')
- client = Web3(Web3.WebsocketProvider(my_provider))
- else:
- print(timestamp(), 'Using IPCProvider')
- client = Web3(Web3.IPCProvider(my_provider))
-
- print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
- print(timestamp(), "Loading PinkSwap Smart Contracts...")
-
- routerAddress = Web3.toChecksumAddress("0x319EF69a98c8E8aAB36Aea561Daba0Bf3D0fa3ac")
- factoryAddress = Web3.toChecksumAddress("0x7d2ce25c28334e40f37b2a068ec8d5a59f11ea54")
-
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
-
- weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
- base_symbol = "BNB"
- rugdocchain = '&chain=bsc'
- modified = False
-
-elif settings['EXCHANGE'].lower() == 'biswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- print(timestamp(), 'Using custom node.')
- else:
- my_provider = "https://bsc-dataseed4.defibit.io"
-
- if not my_provider:
- print(timestamp(), 'Custom node empty. Exiting')
- exit(1)
-
- if my_provider[0].lower() == 'h':
- print(timestamp(), 'Using HTTPProvider')
- client = Web3(Web3.HTTPProvider(my_provider))
- elif my_provider[0].lower() == 'w':
- print(timestamp(), 'Using WebsocketProvider')
- client = Web3(Web3.WebsocketProvider(my_provider))
- else:
- print(timestamp(), 'Using IPCProvider')
- client = Web3(Web3.IPCProvider(my_provider))
-
- print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
- print(timestamp(), "Loading PinkSwap Smart Contracts...")
-
- routerAddress = Web3.toChecksumAddress("0x3a6d8cA21D1CF76F653A67577FA0D27453350dD8")
- factoryAddress = Web3.toChecksumAddress("0x858E3312ed3A876947EA49d572A7C42DE08af7EE")
-
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
-
- weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
- base_symbol = "BNB"
- rugdocchain = '&chain=bsc'
- modified = False
-
-elif settings['EXCHANGE'].lower() == 'apeswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://bsc-dataseed4.defibit.io"
-
- client = Web3(Web3.HTTPProvider(my_provider))
-
- print(timestamp(), "Binance Smart Chain Connected =", client.isConnected())
- print(timestamp(), "Loading ApeSwap Smart Contracts...")
-
- routerAddress = Web3.toChecksumAddress("0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7")
- factoryAddress = Web3.toChecksumAddress("0x0841BD0B734E4F5853f0dD8d7Ea041c241fb0Da6")
-
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
-
- weth = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
- busd = Web3.toChecksumAddress("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56")
- base_symbol = "BNB"
- rugdocchain = '&chain=bsc'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'uniswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://pedantic-montalcini:lair-essay-ranger-rigid-hardy-petted@nd-857-678-344.p2pify.com"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "Uniswap Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D")
- factoryAddress = Web3.toChecksumAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
- base_symbol = "ETH"
- rugdocchain = '&chain=eth'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'kuswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://rpc-mainnet.kcc.network"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "Kucoin Chain Connected =", client.isConnected())
- print(timestamp(), "Loading KuSwap Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0xa58350d6dee8441aa42754346860e3545cc83cda")
- factoryAddress = Web3.toChecksumAddress("0xAE46cBBCDFBa3bE0F02F463Ec5486eBB4e2e65Ae")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x4446Fc4eb47f2f6586f9fAAb68B3498F86C07521")
- base_symbol = "KCS"
- rugdocchain = '&chain=kcc'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'koffeeswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://rpc-mainnet.kcc.network"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "Kucoin Chain Connected =", client.isConnected())
- print(timestamp(), "Loading KoffeeSwap Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0xc0fFee0000C824D24E0F280f1e4D21152625742b")
- factoryAddress = Web3.toChecksumAddress("0xC0fFeE00000e1439651C6aD025ea2A71ED7F3Eab")
- routerContract = client.eth.contract(address=routerAddress, abi=koffeeAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x4446Fc4eb47f2f6586f9fAAb68B3498F86C07521")
- base_symbol = "KCS"
- rugdocchain = '&chain=kcc'
- modified = True
-
-elif settings["EXCHANGE"].lower() == 'spookyswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://rpcapi.fantom.network"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "FANTOM Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0xF491e7B69E4244ad4002BC14e878a34207E38c29")
- factoryAddress = Web3.toChecksumAddress("0x152eE697f2E276fA89E96742e9bB9aB1F2E61bE3")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83")
- base_symbol = "FTM"
- rugdocchain = '&chain=ftm'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'spiritswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://rpcapi.fantom.network"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "FANTOM Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52")
- factoryAddress = Web3.toChecksumAddress("0xEF45d134b73241eDa7703fa787148D9C9F4950b0")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83")
- base_symbol = "FTM"
- rugdocchain = '&chain=ftm'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'quickswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://polygon-rpc.com"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "Matic Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff")
- factoryAddress = Web3.toChecksumAddress("0x5757371414417b8c6caad45baef941abc7d3ab32")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270")
- base_symbol = "MATIC"
- rugdocchain = '&chain=poly'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'waultswap':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://rpc-waultfinance-mainnet.maticvigil.com/v1/0bc1bb1691429f1eeee66b2a4b919c279d83d6b0"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "Matic Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0x3a1D87f206D12415f5b0A33E786967680AAb4f6d")
- factoryAddress = Web3.toChecksumAddress("0xa98ea6356A316b44Bf710D5f9b6b4eA0081409Ef")
- routerContract = client.eth.contract(address=routerAddress, abi=routerAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270")
- base_symbol = "MATIC"
- rugdocchain = '&chain=poly'
- modified = False
-
-elif settings["EXCHANGE"].lower() == 'pangolin':
- if settings['USECUSTOMNODE'].lower() == 'true':
- my_provider = settings['CUSTOMNODE']
- else:
- my_provider = "https://api.avax.network/ext/bc/C/rpc"
-
- client = Web3(Web3.HTTPProvider(my_provider))
- print(timestamp(), "AVAX Chain Connected =", client.isConnected())
- print(timestamp(), "Loading Smart Contracts...")
- routerAddress = Web3.toChecksumAddress("0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106")
- factoryAddress = Web3.toChecksumAddress("0xefa94DE7a4656D787667C749f7E1223D71E9FD88")
- routerContract = client.eth.contract(address=routerAddress, abi=pangolinAbi)
- factoryContract = client.eth.contract(address=factoryAddress, abi=factoryAbi)
- weth = Web3.toChecksumAddress("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7")
- base_symbol = "AVAX"
- rugdocchain = '&chain=avax'
- modified = True
-
-
-def get_password():
- # Function: get_password
- # ----------------------------
- # Handles the decision making logic concerning private key encryption and asking the user for their password.
- #
- # returns: the user's password
-
- settings_changed = False
- setnewpassword = False
-
- # Check to see if the user has a version of the settings file before private key encryption existed
- if 'ENCRYPTPRIVATEKEYS' not in settings:
- response = ""
- settings_changed = True
- while response != "y" and response != "n":
- print("\nWould you like to use a password to encrypt your private keys?")
- response = input("You will need to input this password each time LimitSwap is executed (y/n): ")
-
- if response == "y":
- settings['ENCRYPTPRIVATEKEYS'] = "true"
- setnewpassword = True
- else:
- settings['ENCRYPTPRIVATEKEYS'] = "false"
-
- # If the user wants to encrypt their private keys, but we don't have an encrypted private key recorded, we need to ask for a password
- elif settings['ENCRYPTPRIVATEKEYS'] == "true" and not settings['PRIVATEKEY'].startswith('aes:'):
- print("\nPlease create a password to encrypt your private keys.")
- setnewpassword = True
-
- # Set a new password when necessary
- if setnewpassword == True:
- settings_changed = True
- passwords_differ = True
- while passwords_differ:
- pwd = pwinput.pwinput(prompt="\nType your new password: ")
- pwd2 = pwinput.pwinput(prompt="\nType your new password again: ")
-
- if pwd != pwd2:
- print("Error, password mismatch. Try again.")
- else:
- passwords_differ = False
-
- # The user already has encrypted private keys. Accept a password so we can unencrypt them
- elif settings['ENCRYPTPRIVATEKEYS'] == "true":
-
- if command_line_args.password:
- pwd = command_line_args.password
- else:
- pwd = pwinput.pwinput(prompt="\nPlease specify the password to decrypt your keys: ")
-
- else:
- pwd = ""
-
- if not pwd.strip():
- print()
- print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
- print("X You are running LimitSwap without encrypting your private keys. X")
- print("X Private keys are stored on disk unencrypted and can be accessed by X")
- print("X anyone with access to the file system, including the Systems/VPS administrator X")
- print("X and anyone with physical access to the machine or hard drives. X")
- print("X WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING =-= WARNING=-= WARNING X")
- print()
-
- if settings_changed == True:
- save_settings(settings, pwd)
-
- return pwd
-
-
-# RUGDOC CONTROL IMPLEMENTATION
-# Honeypot API details
-honeypot_url = 'https://honeypot.api.rugdoc.io/api/honeypotStatus.js?address='
-
-# Rugdoc's answers interpretations
-interpretations = {
- "UNKNOWN": (style.RED + '\nThe status of this token is unknown. '
- 'This is usually a system error but could \n also be a bad sign for the token. Be careful.'),
- "OK": (style.GREEN + '\nRUGDOC API RESULT : OK \n'
- '√ Honeypot tests passed. RugDoc program was able to buy and sell it successfully. This however does not guarantee that it is not a honeypot.'),
- "NO_PAIRS": (style.RED + '\nRUGDOC API RESULT : NO_PAIRS \n'
- '⚠ Could not find any trading pair for this token on the default router and could thus not test it.'),
- "SEVERE_FEE": (style.RED + '\nRUGDOC API RESULT : SEVERE_FEE \n'
- '/!\ /!\ A severely high trading fee (over 50%) was detected when selling or buying this token.'),
- "HIGH_FEE": (style.YELLOW + '\nRUGDOC API RESULT : HIGH_FEE \n'
- '/!\ /!\ A high trading fee (Between 20% and 50%) was detected when selling or buying this token. Our system was however able to sell the token again.'),
- "MEDIUM_FEE": (style.YELLOW + '\nRUGDOC API RESULT : MEDIUM_FEE \n'
- '/!\ A trading fee of over 10% but less then 20% was detected when selling or buying this token. Our system was however able to sell the token again.'),
- "APPROVE_FAILED": (style.RED + '\nRUGDOC API RESULT : APPROVE_FAILED \n'
- '/!\ /!\ /!\ Failed to approve the token.\n This is very likely a honeypot.'),
- "SWAP_FAILED": (style.RED + '\nRUGDOC API RESULT : SWAP_FAILED \n'
- '/!\ /!\ /!\ Failed to sell the token. \n This is very likely a honeypot.'),
- "chain not found": (style.RED + '\nRUGDOC API RESULT : chain not found \n'
- '/!\ Sorry, rugdoc API does not work on this chain... (it does not work on ETH, mainly) \n')
-}
-
-
-# Function to check rugdoc API
-def honeypot_check(address):
- url = (honeypot_url + address + rugdocchain)
- # sending get request and saving the response as response object
- return requests.get(url)
-
-
-def save_settings(settings, pwd):
- if len(pwd) > 0:
- encrypted_settings = settings.copy()
- encrypted_settings['LIMITWALLETPRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['LIMITWALLETPRIVATEKEY'],
- pwd)
- encrypted_settings['PRIVATEKEY'] = 'aes:' + cryptocode.encrypt(settings['PRIVATEKEY'], pwd)
-
- # TODO: MASSAGE OUTPUT - LimitSwap currently loads settings.json as a [0] element, so we need to massage our
- # settings.json output so that it's reasable. This should probably be fixed by us importing
- # the entire json file, instead of just the [0] element.
-
- print(timestamp(), "Writing settings to file.")
-
- if settings['ENCRYPTPRIVATEKEYS'] == "true":
- output_settings = encrypted_settings
- else:
- output_settings = settings
-
- with open(command_line_args.settings, 'w') as f:
- f.write("[\n")
- f.write(json.dumps(output_settings, indent=4))
- f.write("\n]\n")
-
-
-def parse_wallet_settings(settings, pwd):
- # Function: load_wallet_settings
- # ----------------------------
- # Handles the process of deciding whether or not the user's private key needs to be decrypted
- # Accepts user input for new private keys and wallet addresses
- #
- # returns: none (exits on incorrect password)
-
- settings_changed = False
-
- # Check for limit wallet information
- if " " in settings['LIMITWALLETADDRESS'] or settings['LIMITWALLETADDRESS'] == "":
- settings_changed = True
- settings['LIMITWALLETADDRESS'] = input("Please provide the wallet address where you have your LIMIT: ")
-
- # Check for limit wallet private key
- if " " in settings['LIMITWALLETPRIVATEKEY'] or settings['LIMITWALLETPRIVATEKEY'] == "":
- settings_changed = True
- settings['LIMITWALLETPRIVATEKEY'] = input(
- "Please provide the private key for the wallet where you have your LIMIT: ")
-
- # If the limit wallet private key is already set and encrypted, decrypt it
- elif settings['LIMITWALLETPRIVATEKEY'].startswith('aes:'):
- printt("Decrypting limit wallet private key.")
- settings['LIMITWALLETPRIVATEKEY'] = settings['LIMITWALLETPRIVATEKEY'].replace('aes:', "", 1)
- settings['LIMITWALLETPRIVATEKEY'] = cryptocode.decrypt(settings['LIMITWALLETPRIVATEKEY'], pwd)
-
- if settings['LIMITWALLETPRIVATEKEY'] == False:
- print(style.RED + "ERROR: Your private key decryption password is incorrect")
- print(style.RESET + "Please re-launch the bot and try again")
- sleep(10)
- sys.exit()
-
- # Check for trading wallet information
- if " " in settings['WALLETADDRESS'] or settings['WALLETADDRESS'] == "":
- settings_changed = True
- settings['WALLETADDRESS'] = input("Please provide the wallet address for your trading wallet: ")
-
- # Check for trading wallet private key
- if " " in settings['PRIVATEKEY'] or settings['PRIVATEKEY'] == "":
- settings_changed = True
- settings['PRIVATEKEY'] = input("Please provide the private key for the wallet you want to trade with: ")
-
- # If the trading wallet private key is already set and encrypted, decrypt it
- elif settings['PRIVATEKEY'].startswith('aes:'):
- print(timestamp(), "Decrypting limit wallet private key.")
- settings['PRIVATEKEY'] = settings['PRIVATEKEY'].replace('aes:', "", 1)
- settings['PRIVATEKEY'] = cryptocode.decrypt(settings['PRIVATEKEY'], pwd)
-
- if settings_changed == True:
- save_settings(settings, pwd)
-
-
-def decimals(address):
- try:
- balanceContract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
- decimals = balanceContract.functions.decimals().call()
- DECIMALS = 10 ** decimals
- except ABIFunctionNotFound:
- DECIMALS = 10 ** 18
- except ValueError as ve:
- logging.exception(ve)
- print("Please check your SELLPRICE values.")
- return DECIMALS
-
-
-def check_logs():
- print(timestamp(), "Quickly Checking Log Size")
- with open('./logs/errors.log') as f:
- line_count = 0
- for line in f:
- line_count += 1
- if line_count > 100:
- with open('./logs/errors.log', "r") as f:
- lines = f.readlines()
-
- with open('./logs/errors.log', "w") as f:
- f.writelines(lines[20:])
-
- f.close()
-
-
-def decode_key():
- private_key = settings['LIMITWALLETPRIVATEKEY']
- acct = client.eth.account.privateKeyToAccount(private_key)
- addr = acct.address
- return addr
-
-
-def check_release():
- try:
- url = 'https://api.github.com/repos/CryptoGnome/LimitSwap/releases/latest'
- r = requests.get(url).json()['tag_name']
- print("Checking Latest Release Version on Github, Please Make Sure You are Staying Updated = ", r)
- logging.info("Checking Latest Release Version on Github, Please Make Sure You are Staying Updated = " + r)
- except Exception:
- r = "github api down, please ignore"
-
- return r
-
-
-def auth():
- my_provider2 = 'https://reverent-raman:photo-hamlet-ankle-saved-scared-bobbed@nd-539-402-515.p2pify.com'
- client2 = Web3(Web3.HTTPProvider(my_provider2))
- print(timestamp(), "Connected to Ethereum BlockChain =", client2.isConnected())
- # Insert LIMITSWAP Token Contract Here To Calculate Staked Verification
- address = Web3.toChecksumAddress("0x1712aad2c773ee04bdc9114b32163c058321cd85")
- abi = standardAbi
- balanceContract = client2.eth.contract(address=address, abi=abi)
- decimals = balanceContract.functions.decimals().call()
- DECIMALS = 10 ** decimals
-
- # Exception for incorrect Key Input
- try:
- decode = decode_key()
- except Exception:
- print("There is a problem with your private key : please check if it's correct. Don't enter seed phrase !")
- logging.info(
- "There is a problem with your private key : please check if it's correct. Don't enter seed phrase !")
-
- wallet_address = Web3.toChecksumAddress(decode)
- balance = balanceContract.functions.balanceOf(wallet_address).call()
- true_balance = balance / DECIMALS
- print(timestamp(), "Current Tokens Staked =", true_balance)
- logging.info("Current Tokens Staked = " + str(true_balance))
- return true_balance
-
-
-def approve(address, amount):
- print(timestamp(), "Approving", address)
-
- eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
-
- if eth_balance > 0.05:
- print("Estimating Gas Cost Using Web3")
- if settings['EXCHANGE'].lower() == 'uniswap':
- print("Estimating Gas Cost Using Web3")
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price =", gas)
-
- elif settings['EXCHANGE'].lower() == 'pancakeswap':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- elif settings['EXCHANGE'].lower() == 'spiritswap':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- elif settings['EXCHANGE'].lower() == 'spookyswap':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- elif settings['EXCHANGE'].lower() == 'pangolin':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- elif settings['EXCHANGE'].lower() == 'quickswap':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- elif settings['EXCHANGE'].lower() == 'kuswap' or 'koffeeswap':
- gas = (((client.eth.gasPrice) / 1000000000)) + ((client.eth.gasPrice) / 1000000000) * (int(20) / 100)
- print("Current Gas Price = ", gas)
- else:
- print("EXCHANGE NAME IN SETTINGS IS SPELLED INCORRECTLY OR NOT SUPPORTED YET CHECK WIKI!")
- logging.info("EXCHANGE NAME IN SETTINGS IS SPELLED INCORRECTLY OR NOT SUPPORTED YET CHECK WIKI!")
- exit()
-
- contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
- transaction = contract.functions.approve(routerAddress, amount).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': 300000,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
- signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
-
- try:
- return client.eth.sendRawTransaction(signed_txn.rawTransaction)
- finally:
- print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
- # LOG TX TO JSON
- with open('./transactions.json', 'r') as fp:
- data = json.load(fp)
- tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
- tx_input = {"hash": tx_hash}
- data.append(tx_input)
- with open('./transactions.json', 'w') as fp:
- json.dump(data, fp, indent=2)
- fp.close()
-
- return tx_hash
- else:
- print(timestamp(),
- "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
- logging.info(
- "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
- sleep(10)
- sys.exit()
-
-
-def check_approval(address, balance):
- print(timestamp(), "Checking Approval Status", address)
- contract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
- allowance = contract.functions.allowance(Web3.toChecksumAddress(settings['WALLETADDRESS']), routerAddress).call()
-
- if int(allowance) < int(balance):
-
- if settings["EXCHANGE"].lower() == 'quickswap':
- print("Revert to Zero To change approval")
- tx = approve(address, 0)
- wait_for_tx(tx, address, False)
- tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
- wait_for_tx(tx, address, False)
- else:
- tx = approve(address, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
- wait_for_tx(tx, address, False)
-
- return
-
- else:
- pass
-
-
-def check_bnb_balance():
- balance = client.eth.getBalance(settings['WALLETADDRESS'])
- print(timestamp(), "Current Wallet Balance is :", Web3.fromWei(balance, 'ether'), base_symbol)
- return balance
-
-
-def check_balance(address, symbol):
- address = Web3.toChecksumAddress(address)
- DECIMALS = decimals(address)
- balanceContract = client.eth.contract(address=address, abi=standardAbi)
- balance = balanceContract.functions.balanceOf(settings['WALLETADDRESS']).call()
- print(timestamp(), "Current Wallet Balance is: " + str(balance / DECIMALS) + " " + symbol)
-
- return balance
-
-
-def fetch_pair(inToken, outToken):
- print(timestamp(), "Fetching Pair Address")
- pair = factoryContract.functions.getPair(inToken, outToken).call()
- print(timestamp(), "Pair Address = ", pair)
- return pair
-
-
-def sync(inToken, outToken):
- pair = factoryContract.functions.getPair(inToken, outToken).call()
- syncContract = client.eth.contract(address=Web3.toChecksumAddress(pair), abi=lpAbi)
- sync = syncContract.functions.sync().call()
-
-
-def check_pool(inToken, outToken, symbol):
- # This function is made to calculate Liquidity of a token
- pair_address = factoryContract.functions.getPair(inToken, outToken).call()
- DECIMALS = decimals(outToken)
- pair_contract = client.eth.contract(address=pair_address, abi=lpAbi)
- reserves = pair_contract.functions.getReserves().call()
- pooled = reserves[1] / DECIMALS
- # print("Debug LIQUIDITYAMOUNT line 627 :", pooled, "in token:", outToken)
-
- return pooled
-
-
-def check_price(inToken, outToken, symbol, base, custom, routing, buypriceinbase, sellpriceinbase):
- # CHECK GET RATE OF THE TOKEn
-
- DECIMALS = decimals(inToken)
- stamp = timestamp()
-
- if custom.lower() == 'false':
- base = base_symbol
- else:
- pass
-
- if routing == 'true':
- if outToken != weth:
- price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth, outToken]).call()[-1]
- DECIMALS = decimals(outToken)
- tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
- "//// your sellprice =", sellpriceinbase, base)
- else:
- price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
- DECIMALS = decimals(outToken)
- tokenPrice = price_check / DECIMALS
- price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
- "//// your sellprice =", sellpriceinbase, base)
-
- else:
- if outToken != weth:
- price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, outToken]).call()[-1]
- DECIMALS = decimals(outToken)
- tokenPrice = price_check / DECIMALS
- print(stamp, symbol, " Price ", tokenPrice, base, "//// your buyprice =", buypriceinbase, base,
- "//// your sellprice =", sellpriceinbase, base)
- else:
- price_check = routerContract.functions.getAmountsOut(1 * DECIMALS, [inToken, weth]).call()[-1]
- DECIMALS = decimals(outToken)
- tokenPrice = price_check / DECIMALS
- price_output = "{:.18f}".format(tokenPrice)
- print(stamp, symbol, "Price =", price_output, base, "//// your buyprice =", buypriceinbase, base,
- "//// your sellprice =", sellpriceinbase, base)
-
- return tokenPrice
-
-
-def wait_for_tx(tx_hash, address, check):
- print(timestamp(), "............Waiting 1 minute for TX to Confirm............")
- timeout = time() + 60
- while True:
- print(timestamp(), "............Waiting 1 minute for TX to Confirm............")
- sleep(1)
- try:
- txn_receipt = client.eth.getTransactionReceipt(tx_hash)
- return txn_receipt['status']
-
- except Exception as e:
- txn_receipt = None
-
- if txn_receipt is not None and txn_receipt['blockHash'] is not None:
- return txn_receipt['status']
-
- elif time() > timeout:
- print(style.RED + "\n")
- print(timestamp(), "Transaction was not confirmed after 1 minute : something wrong happened.\n"
- "Please check if :\n"
- "- your node is running correctly\n"
- "- you have enough Gaslimit (check 'Gas Used by Transaction') if you have a failed Tx")
- print(style.RESET + "\n")
- failedtransactionsamount += 1
- logging.info("Transaction was not confirmed after 1 minute, breaking Check Cycle....")
- sleep(5)
- break
-
- # loop to check for balance after purchase
- if check == True:
- timeout = time() + 30
- print(style.RESET + "\n")
-
- while True:
- print(timestamp(), ".........Waiting 30s to check tokens balance in your wallet after purchase............")
- sleep(1)
-
- balance = check_balance(address, address)
-
- if balance > 0:
- break
- elif time() > timeout:
- print(timestamp(),
- "NO BUY FOUND, WE WILL CHECK A FEW TIMES TO SEE IF THERE IS BLOCKCHAIN DELAY, IF NOT WE WILL ASSUME THE TX HAS FAILED")
- logging.info(
- "NO BUY FOUND, WE WILL CHECK A FEW TIMES TO SEE IF THERE IS BLOCKCHAIN DELAY, IF NOT WE WILL ASSUME THE TX HAS FAILED")
- break
-
-
-def preapprove(tokens):
- for token in tokens:
- check_approval(token['ADDRESS'], 115792089237316195423570985008687907853269984665640564039457584007913129639934)
-
- if token['USECUSTOMBASEPAIR'].lower() == 'false':
- check_approval(weth, 115792089237316195423570985008687907853269984665640564039457584007913129639934)
- else:
- check_approval(token['BASEADDRESS'],
- 115792089237316195423570985008687907853269984665640564039457584007913129639934)
-
-
-def buy(amount, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, base, routing, waitseconds,
- failedtransactionsnumber):
- seconds = int(waitseconds)
- if int(failedtransactionsamount) == int(failedtransactionsnumber):
- print(
- style.RED + "\n ---------------------------------------------------------------\n"
- " Bot has reached maximum FAILED TRANSACTIONS number: it stops\n"
- " ---------------------------------------------------------------\n\n")
-
- logging.info("Bot has reached maximum FAILED TRANSACTIONS number: it stops")
- sleep(10)
- sys.exit()
- else:
-
- if waitseconds != '0':
- print("Bot will wait", waitseconds, " seconds before buy, as you entered in BUYAFTER_XXX_SECONDS parameter")
- sleep(seconds)
-
- print(timestamp(), "Placing New Buy Order for " + symbol)
-
- if int(gaslimit) < 250000:
- print(
- "Your GASLIMIT parameter is too low : LimitSwap has forced it to 300000 otherwise your transaction would fail for sure. We advise you to raise it to 1000000.")
- gaslimit = 300000
-
- if custom.lower() == 'false':
- balance = Web3.fromWei(check_bnb_balance(), 'ether')
- base = base_symbol
- else:
- address = Web3.toChecksumAddress(inToken)
- DECIMALS = decimals(address)
- balance_check = check_balance(inToken, base)
- balance = balance_check / DECIMALS
-
- if balance > Decimal(amount):
- if gas.lower() == 'boost':
- gas_check = client.eth.gasPrice
- gas_price = gas_check / 1000000000
- gas = (gas_price * ((int(boost)) / 100)) + gas_price
- else:
- gas = int(gas)
-
- gaslimit = int(gaslimit)
- slippage = int(slippage)
- DECIMALS = decimals(inToken)
- amount = int(float(amount) * DECIMALS)
-
- if custom.lower() == 'false':
- # if USECUSTOMBASEPAIR = false
- amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
-
- deadline = int(time() + + 60)
-
- # THIS SECTION IS FOR MODIFIED CONTRACTS : EACH EXCHANGE NEEDS TO BE SPECIFIED
- # USECUSTOMBASEPAIR = false
- if modified == True:
-
- if settings["EXCHANGE"].lower() == 'koffeeswap':
- transaction = routerContract.functions.swapExactKCSForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'value': amount,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
- transaction = routerContract.functions.swapExactAVAXForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'value': amount,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
-
- else:
- # USECUSTOMBASEPAIR = false
- # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
-
- # Special condition on Uniswap, to implement EIP-1559
- if settings["EXCHANGE"].lower() == 'uniswap':
- transaction = routerContract.functions.swapExactETHForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # USECUSTOMBASEPAIR = false
- # for all the rest of exchanges with Modified = false
- transaction = routerContract.functions.swapExactETHForTokens(
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'value': amount,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # USECUSTOMBASEPAIR = true
- if inToken == weth:
- # USECUSTOMBASEPAIR = true
- # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
- amount_out = routerContract.functions.getAmountsOut(amount, [weth, outToken]).call()[-1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # LIQUIDITYINNATIVETOKEN = true
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
- if routing.lower() == 'true':
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[
- -1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if settings["EXCHANGE"].lower() == 'uniswap':
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
- # LIQUIDITYINNATIVETOKEN = true
-
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
- # LIQUIDITYINNATIVETOKEN = true
- # Exchange different from Uniswap
-
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
-
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
- if settings['UNLIMITEDSLIPPAGE'].lower() == 'true':
- min_tokens = 100
- else:
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if settings["EXCHANGE"].lower() == 'uniswap':
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
- # Special condition on Uniswap, to implement EIP-1559
-
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # Base Pair different from weth
- # Exchange different from Uniswap
-
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- sync(inToken, outToken)
- signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
-
- try:
- return client.eth.sendRawTransaction(signed_txn.rawTransaction)
- finally:
- print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
- # LOG TX TO JSON
- with open('./transactions.json', 'r') as fp:
- data = json.load(fp)
- tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
- tx_input = {"hash": tx_hash}
- data.append(tx_input)
- with open('./transactions.json', 'w') as fp:
- json.dump(data, fp, indent=2)
- fp.close()
-
- return tx_hash
-
- else:
- print(timestamp(), "Not Enough " + base + " Balance to make buys")
- logging.info("Not Enough " + base + " Balance to make buys")
- return False
-
-
-def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fees, custom, symbol, routing):
- print(timestamp(), "Placing Sell Order " + symbol)
- balance = Web3.fromWei(check_balance(inToken, symbol), 'ether')
- check_approval(inToken, balance * 1000000000)
-
- if int(gaslimit) < 250000:
- gaslimit = 300000
-
- if type(amount) == str:
- amount_check = balance
- else:
- amount_check = Decimal(amount)
-
- if balance >= Decimal(amount_check) and balance > 0.0000000000000001:
-
- if gas.lower() == 'boost':
- gas_check = client.eth.gasPrice
- gas_price = gas_check / 1000000000
- gas = (gas_price * ((int(boost) * 4) / 100)) + gas_price
- else:
- gas = int(gas)
-
- slippage = int(slippage)
- gaslimit = int(gaslimit)
- DECIMALS = decimals(inToken)
-
- if amount.lower() == 'all':
- balance = check_balance(inToken, symbol)
- moonbag = int(Decimal(moonbag) * DECIMALS)
- amount = int(Decimal(balance - moonbag))
-
- else:
- balance = check_balance(inToken, symbol)
- amount = Decimal(amount) * DECIMALS
- moonbag = int(Decimal(moonbag) * DECIMALS)
-
- if balance < amount:
- print(timestamp(), "Selling Remaining ", symbol)
- amount = int(Decimal(balance - moonbag))
- else:
- amount = int(Decimal(balance - moonbag))
- if amount > 0:
- print(timestamp(), "Selling", amount / DECIMALS, symbol)
- else:
- print("Not enough left to sell, would bust moonbag")
- amount = 0
-
- if custom.lower() == 'false':
- # USECUSTOMBASEPAIR = false
- sync(inToken, weth)
-
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if fees.lower() == 'true':
-
- # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
- if modified == True:
- # USECUSTOMBASEPAIR = false
- # HASFEES = true
-
- if settings["EXCHANGE"].lower() == 'koffeeswap':
- transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- if settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
- transaction = routerContract.functions.swapExactTokensForAVAXSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # This section is for exchange with Modified = false --> uniswap / pancakeswap / apeswap, etc.
- # USECUSTOMBASEPAIR = false
- # HASFEES = true
- transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
- else:
- # USECUSTOMBASEPAIR = false
- # HASFEES = false
-
- # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
- if modified == True:
- # USECUSTOMBASEPAIR = false
- # HASFEES = false
- # Modified = true
-
- if settings["EXCHANGE"].lower() == 'koffeeswap':
- transaction = routerContract.functions.swapExactTokensForKCS(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
- elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
- transaction = routerContract.functions.swapExactTokensForAVAX(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # USECUSTOMBASEPAIR = false
- # HASFEES = false
- # Modified = false --> uniswap / pancakeswap / apeswap, etc.
-
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForETH(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # for all the rest of exchanges with Modified = false
- transaction = routerContract.functions.swapExactTokensForETH(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # USECUSTOMBASEPAIR = true
- if outToken == weth:
- # if user has set WETH or WBNB as Custom base pair
- sync(inToken, outToken)
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth]).call()[-1]
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if fees.lower() == 'true':
- # USECUSTOMBASEPAIR = true
- # HASFEES = true
-
- if int(gaslimit) < 950000:
- gaslimit = 950000
-
- # THIS SECTION IS FOR MODIFIED CONTRACTS AND EACH EXCHANGE IS SPECIFIED
- if modified == True:
- # USECUSTOMBASEPAIR = true
- # HASFEES = true
- # Modified = true
-
- if settings["EXCHANGE"].lower() == 'koffeeswap':
- transaction = routerContract.functions.swapExactTokensForKCSSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- elif settings["EXCHANGE"].lower() == 'pangolin' or settings["EXCHANGE"].lower() == 'traderjoe':
- transaction = routerContract.functions.swapExactTokensForAVAXSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # USECUSTOMBASEPAIR = true
- # HASFEES = true
- # Modified = false
-
- transaction = routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
- else:
- # USECUSTOMBASEPAIR = true
- # HASFEES = false
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
-
- else:
- sync(inToken, outToken)
-
- if routing.lower() == 'false' and outToken != weth:
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, outToken]).call()[-1]
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if fees.lower() == 'true':
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # HASFEES = true
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # for all the rest of exchanges
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # HASFEES = false
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- # for all the rest of exchanges
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- elif routing.lower() == 'false' and outToken == weth:
- # LIQUIDITYINNATIVETOKEN = false
- # USECUSTOMBASEPAIR = true
- # but user chose to put WETH or WBNB contract as CUSTOMBASEPAIR address
- print(
- "ERROR IN YOUR TOKENS.JSON : YOU NEED TO CHOOSE THE PROPER BASE PAIR AS SYMBOL IF YOU ARE TRADING OUTSIDE OF NATIVE LIQUIDITY POOL")
-
- else:
- amount_out = routerContract.functions.getAmountsOut(amount, [inToken, weth, outToken]).call()[-1]
- min_tokens = int(amount_out * (1 - (slippage / 100)))
- deadline = int(time() + + 60)
-
- if fees.lower() == 'true':
- # HASFEES = true
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
-
- else:
- transaction = routerContract.functions.swapExactTokensForTokensSupportingFeeOnTransferTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- else:
- # HASFEES = false
- if settings["EXCHANGE"].lower() == 'uniswap':
- # Special condition on Uniswap, to implement EIP-1559
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'maxFeePerGas': Web3.toWei(gas, 'gwei'),
- 'maxPriorityFeePerGas': Web3.toWei('1.5', 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS']),
- 'type': "0x02"
- })
- else:
- transaction = routerContract.functions.swapExactTokensForTokens(
- amount,
- min_tokens,
- [inToken, weth, outToken],
- Web3.toChecksumAddress(settings['WALLETADDRESS']),
- deadline
- ).buildTransaction({
- 'gasPrice': Web3.toWei(gas, 'gwei'),
- 'gas': gaslimit,
- 'from': Web3.toChecksumAddress(settings['WALLETADDRESS']),
- 'nonce': client.eth.getTransactionCount(settings['WALLETADDRESS'])
- })
-
- sync(inToken, outToken)
- signed_txn = client.eth.account.signTransaction(transaction, private_key=settings['PRIVATEKEY'])
-
- try:
- return client.eth.sendRawTransaction(signed_txn.rawTransaction)
- finally:
- print(timestamp(), "Transaction Hash = ", Web3.toHex(client.keccak(signed_txn.rawTransaction)))
- # LOG TX TO JSON
- with open('./transactions.json', 'r') as fp:
- data = json.load(fp)
- tx_hash = client.toHex(client.keccak(signed_txn.rawTransaction))
- tx_input = {"hash": tx_hash}
- data.append(tx_input)
- with open('./transactions.json', 'w') as fp:
- json.dump(data, fp, indent=2)
- fp.close()
-
- return tx_hash
- else:
- pass
-
-
-def run():
- global failedtransactionsamount
-
- try:
-
- tokens = load_tokens_file(command_line_args.tokens, True)
-
- eth_balance = Web3.fromWei(client.eth.getBalance(settings['WALLETADDRESS']), 'ether')
-
- if eth_balance > 0.05:
- pass
- else:
- print(
- style.RED + "\nYou have less than 0.05 ETH/BNB/FTM/MATIC/Etc. token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet")
- logging.info(
- "You have less than 0.05 ETH/BNB/FTM/MATIC or network gas token in your wallet, bot needs at least 0.05 to cover fees : please add some more in your wallet.")
- sleep(10)
- sys.exit()
-
- if settings['PREAPPROVE'].lower() == 'true':
- preapprove(tokens)
- else:
- pass
-
- for token in tokens:
- # Initialization of values, in case the user re-used some old tokens.json files
- if 'RUGDOC_CHECK' not in token:
- token['RUGDOC_CHECK'] = 'false'
- if 'BUYAFTER_XXX_SECONDS' not in token:
- token['BUYAFTER_XXX_SECONDS'] = 0
- if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
- # End of initialization of values
-
- if token['RUGDOC_CHECK'].lower() == 'true':
-
- honeypot = honeypot_check(address=token['ADDRESS'])
- d = json.loads(honeypot.content)
- for key, value in interpretations.items():
- if d["status"] in key:
- honeypot_status = value
- honeypot_code = key
- print(honeypot_status)
-
- decision = ""
- while decision != "y" and decision != "n":
- print(style.RESET + "\nWhat is your decision?")
- decision = input("Would you like to snipe this token? (y/n): ")
-
- if decision == "y":
- print(style.RESET + "\nOK let's go!!\n")
- pass
- else:
- sys.exit()
-
- else:
- pass
-
- while True:
- tokens = load_tokens_file(command_line_args.tokens, False)
-
- for token in tokens:
- # Initialization of values, in case the user re-used some old tokens.json files
- if 'RUGDOC_CHECK' not in token:
- token['RUGDOC_CHECK'] = 'false'
- if 'BUYAFTER_XXX_SECONDS' not in token:
- token['BUYAFTER_XXX_SECONDS'] = 0
- if 'MAX_FAILED_TRANSACTIONS_IN_A_ROW' not in token:
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'] = 2
- # End of initialization of values
-
- if token['ENABLED'].lower() == 'true':
- inToken = Web3.toChecksumAddress(token['ADDRESS'])
-
- if token['USECUSTOMBASEPAIR'].lower() == 'true':
- outToken = Web3.toChecksumAddress(token['BASEADDRESS'])
- else:
- outToken = weth
-
- try:
- quote = check_price(inToken, outToken, token['SYMBOL'], token['BASESYMBOL'],
- token['USECUSTOMBASEPAIR'], token['LIQUIDITYINNATIVETOKEN'],
- token['BUYPRICEINBASE'], token['SELLPRICEINBASE'])
- pool = check_pool(inToken, outToken, token['BASESYMBOL'])
- # print("Debug Liquidity Reserves ligne 1267:", float(pool))
- # print("Debug inToken : ", inToken, "outToken :", outToken)
-
- except Exception:
- print(timestamp(), token['SYMBOL'],
- " Not Listed For Trade Yet... waiting for liquidity to be added on exchange")
- quote = 0
-
- if quote < Decimal(token['BUYPRICEINBASE']) and quote != 0:
- balance = check_balance(inToken, token['SYMBOL'])
- DECIMALS = decimals(inToken)
- if Decimal(balance / DECIMALS) < Decimal(token['MAXTOKENS']):
-
- if token["LIQUIDITYCHECK"].lower() == 'true':
- pool = check_pool(inToken, outToken, token['BASESYMBOL'])
- print(timestamp(), "You have set LIQUIDITYCHECK = true.")
- print(timestamp(), "Current", token['SYMBOL'], "Liquidity = ", int(pool), "in token:",
- outToken)
-
- if float(token['LIQUIDITYAMOUNT']) <= float(pool):
- print(timestamp(), "LIQUIDITYAMOUNT parameter =", int(token['LIQUIDITYAMOUNT']),
- " --> Enough liquidity detected : Buy Signal Found!")
- log_price = "{:.18f}".format(quote)
- logging.info("BuySignal Found @" + str(log_price))
- tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
- token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
- token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
- token['BASESYMBOL'], token['LIQUIDITYINNATIVETOKEN'],
- token['BUYAFTER_XXX_SECONDS'], token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
-
- if tx != False:
- tx = wait_for_tx(tx, token['ADDRESS'], True)
- print(
- style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
- print(style.RESET + "")
- sleep(3)
- check_balance(token['ADDRESS'], token['SYMBOL'])
- print(style.RESET + "\n")
- sleep(3)
-
- if tx != 1:
- # transaction is a FAILURE
- print(
- style.RED + "\n -------------------------------------------------\n"
- " FAILURE ! Plese check your wallet. \n"
- " Cause of failure can be : \n"
- " - GASLIMIT too low\n"
- " - SLIPPAGE too low\n"
- " -------------------------------------------------\n\n")
- print(style.RESET + "")
- failedtransactionsamount += 1
- preapprove(tokens)
- else:
- # transaction is a SUCCESS
- print(
- style.GREEN + "\n ----------------------------------\n"
- " SUCCESS : your Tx is confirmed :)\n"
- " ----------------------------------\n")
- print(style.RESET + "")
- pass
-
- else:
- # print("debug 1450")
- pass
- else:
- print(timestamp(), "LIQUIDITYAMOUNT parameter =", int(token['LIQUIDITYAMOUNT']),
- " : not enough liquidity, bot will not buy")
-
- else:
- print(timestamp(), "Buy Signal Found!")
- log_price = "{:.18f}".format(quote)
- logging.info("BuySignal Found @" + str(log_price))
- tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'], token['SLIPPAGE'],
- token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
- token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['BASESYMBOL'],
- token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
-
- if tx != False:
- tx = wait_for_tx(tx, token['ADDRESS'], True)
- print(
- style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
- print(style.RESET + "")
- sleep(3)
- check_balance(token['ADDRESS'], token['SYMBOL'])
- print(style.RESET + "\n")
- sleep(3)
-
- if tx != 1:
- # transaction is a FAILURE
- print(
- style.RED + "\n -------------------------------------------------\n"
- " FAILURE ! Please check your wallet. \n"
- " Cause of failure can be : \n"
- " - GASLIMIT too low\n"
- " - SLIPPAGE too low\n"
- " -------------------------------------------------\n\n")
- print(style.RESET + "")
- failedtransactionsamount += 1
- preapprove(tokens)
- else:
- # transaction is a SUCCESS
- print(
- style.GREEN + "\n ----------------------------------\n"
- " SUCCESS : your Tx is confirmed :)\n"
- " ----------------------------------\n")
- print(style.RESET + "")
- pass
- else:
- # print("debug 1497")
- pass
-
-
- else:
- print(timestamp(), "You own more tokens than your MAXTOKENS parameter for ",
- token['SYMBOL'])
-
- if quote > Decimal(token['SELLPRICEINBASE']):
- DECIMALS = decimals(inToken)
- balance = check_balance(inToken, token['SYMBOL'])
- moonbag = int(Decimal(token['MOONBAG']) * DECIMALS)
- balance = int(Decimal(balance - moonbag))
-
- if balance > 0:
- print(timestamp(), "Sell Signal Found " + token['SYMBOL'])
- log_price = "{:.18f}".format(quote)
- logging.info("Sell Signal Found @" + str(log_price))
- tx = sell(token['SELLAMOUNTINTOKENS'], token['MOONBAG'], inToken, outToken,
- token['GAS'], token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
- token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
- token['LIQUIDITYINNATIVETOKEN'])
- wait_for_tx(tx, token['ADDRESS'], False)
- print(
- style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
- sleep(5)
- print(style.RESET + "")
- else:
- pass
-
-
- elif quote > Decimal(token['SELLPRICEINBASE']) and quote != 0:
- DECIMALS = decimals(inToken)
- balance = check_balance(inToken, token['SYMBOL'])
- moonbag = int(Decimal(token['MOONBAG']) * DECIMALS)
- balance = int(Decimal(balance - moonbag))
-
- if balance > 0:
- print(timestamp(), "Sell Signal Found " + token['SYMBOL'])
- log_price = "{:.18f}".format(quote)
- logging.info("Sell Signal Found @" + str(log_price))
- tx = sell(token['SELLAMOUNTINTOKENS'], token['MOONBAG'], inToken, outToken, token['GAS'],
- token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'], token["HASFEES"],
- token['USECUSTOMBASEPAIR'], token['SYMBOL'], token['LIQUIDITYINNATIVETOKEN'])
- wait_for_tx(tx, token['ADDRESS'], False)
- print(
- style.RESET + "\n --------------------------------------\n"
- " √ Tx done. Check your wallet \n"
- " --------------------------------------")
- sleep(5)
- print(style.RESET + "")
-
- else:
- # Double Check For Buy if Sell Signal Triggers
- if quote < Decimal(token['BUYPRICEINBASE']):
- balance = check_balance(inToken, token['SYMBOL'])
- if Web3.fromWei(balance, 'ether') < Decimal(token['MAXTOKENS']):
- print(timestamp(), "Buy Signal Found!")
- log_price = "{:.18f}".format(quote)
- logging.info("Sell Signal Found @" + str(log_price))
- tx = buy(token['BUYAMOUNTINBASE'], outToken, inToken, token['GAS'],
- token['SLIPPAGE'], token['GASLIMIT'], token['BOOSTPERCENT'],
- token["HASFEES"], token['USECUSTOMBASEPAIR'], token['SYMBOL'],
- token['LIQUIDITYINNATIVETOKEN'], token['BUYAFTER_XXX_SECONDS'],
- token['MAX_FAILED_TRANSACTIONS_IN_A_ROW'])
- wait_for_tx(tx, token['ADDRESS'], False)
- else:
- print(timestamp(), "Bot has reached MAXTOKENS Position Size for ", token['SYMBOL'])
- pass
- else:
- pass
-
- sleep(cooldown)
-
- except Exception as ee:
- print(timestamp(), "ERROR. Please go to /log folder and open your error logs : you will find more details.")
- logging.exception(ee)
- logger1.exception(ee)
- sleep(10)
- print("Restarting LimitSwap")
- logging.info("Restarting LimitSwap")
- # Cooldown Logic
- timeout = 10
- nonce = 0
- while True:
- print(".........Restart Cooldown left " + str(timeout - nonce) + " seconds.............")
- nonce += 1
- sleep(1)
- if nonce > timeout:
- run()
-
-
-try:
-
- check_logs()
-
- # Get the user password on first run
- userpassword = get_password()
-
- # Handle any proccessing that is necessary to load the private key for the wallet
- parse_wallet_settings(settings, userpassword)
-
- # The LIMIT balance of the user.
- true_balance = auth()
-
- version = 3.36
- logging.info("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
- print("YOUR BOT IS CURRENTLY RUNNING VERSION " + str(version))
- check_release()
-
- if true_balance >= 50:
- print(timestamp(), "Professional Subscriptions Active")
- cooldown = 0.01
- run()
-
- elif true_balance >= 25 and true_balance < 50:
- print(timestamp(), "Trader Subscriptions Active")
- cooldown = 3
- run()
- elif true_balance >= 10 and true_balance < 25:
- print(timestamp(), "Casual Subscriptions Active")
- cooldown = 6
- run()
- else:
- print(timestamp(),
- "10 - 50 $LIMIT tokens needed to use this bot, please visit the LimitSwap.com for more info or buy more tokens on Uniswap to use!")
- logging.exception(
- "10 - 50 $LIMIT tokens needed to use this bot, please visit the LimitSwap.com for more info or buy more tokens on Uniswap to use!")
-
-
-except Exception as e:
- print(timestamp(), "ERROR. Please go to /log folder and open your error logs : you will find more details.")
- logging.exception(e)
- logger1.exception(e)
- print("Restarting LimitSwap")
- logging.info("Restarting LimitSwap")
- # Cooldown Logic
- timeout = 10
- nonce = 0
- while True:
- print(".........Restart Cooldown left " + str(timeout - nonce) + " seconds.............")
- nonce += 1
- sleep(1)
- if nonce > timeout:
- run()
-
From 89c366b7ff2cea5ea5e65e90e3ad123297a04729 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:31:23 +0100
Subject: [PATCH 10/16] Update LimitSwap.py
---
LimitSwap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 72b4b67..73eb7ef 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -192,7 +192,7 @@ def load_tokens_file(tokens_path, load_message=True):
'MAXTOKENS': 0,
'MOONBAG': 0,
'SELLAMOUNTINTOKENS': 'all',
- 'GAS': 20,
+ 'GAS': 8,
'BOOSTPERCENT': 50,
'GASLIMIT': 1000000
From 64104bf9afddaf27828c6061c84fdf25dea204a7 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:36:54 +0100
Subject: [PATCH 11/16] Update README.md
---
README.md | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e3b2944..e6d9c9b 100644
--- a/README.md
+++ b/README.md
@@ -14,13 +14,18 @@ There are 2 ways to install LimitSwap :
-### 1.) Run The Python Code Locally [*this is most ideal and can work on any OS*]
+### 1. Run The Python Code Locally [*this is most ideal and can work on any OS*]
Here is a tutorial step-by-step:
- Download last LimitSwap code here :
- Unzip file
-- Install Python on your computer : https://www.python.org/downloads/
+- Install Python on your computer : https://www.python.org/downloads/
+
+**PLEASE ADD IT TO PATH BY CHECKING THIS OPTION:**
+
+
+
- Install Visual Studio : https://visualstudio.microsoft.com/fr/thank-you-downloading-visual-studio/?sku=Community&rel=17
Please install the default package and all those options :
@@ -44,7 +49,7 @@ Simply **double-click on "LimitSwap.py"** and it will run, since you've installe
-### 2.) Download the pre-compiled package [*This can lag behind current version*]
+### 2. Download the pre-compiled package [*This can lag behind current version*]
That we provide on the Release page : it's a .exe file that you can run on your computer.
https://github.com/CryptoGnome/LimitSwap/releases
From 203ee8bf0cc96e54028c32f4ffa7ffc087580624 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:46:01 +0100
Subject: [PATCH 12/16] Update README.md
---
README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e6d9c9b..2f573ce 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,8 @@ LimitSwap is a trading bot for UniSwap & Many Other DEXs. It has the ability to
-## Install LimitSwap
-There are 2 ways to install LimitSwap :
+## HOW TO INSTALL LimitSwap
+There are 3 ways to install LimitSwap :
@@ -33,7 +33,7 @@ Please install the default package and all those options :
- Open **Windows Powershell** (or Mac Terminal on MacOs)
- Navigate into the unzipped folder
-- Run command: "**pip install -r requirements.txt**" --> this will install all the packages needed to run LimitSwap
+- Run command: `pip install -r requirements.txt` --> this will install all the packages needed to run LimitSwap
==> And it's done! ✅
@@ -58,6 +58,47 @@ https://github.com/CryptoGnome/LimitSwap/releases
🔴 : it's pre-compiled, so you cannot check the Source Code
+
+
+
+### 3. With Docker
+
+#### Requirements
+MacOS and Windows users require Docker for Desktop https://www.docker.com/products/docker-desktop
+Ubuntu Linux require Docker installed `sudo apt-get install docker.io`
+
+#### Usage
+Navigate into the bot directory and build the Docker image by executing the following command:
+
+`docker build -t limit_swap_v4 .`
+
+(For MacOS and Linux) Still within the main directory you can run Docker via:
+
+`docker run --rm --name limit-swap_v4 -it -v $(pwd)/settings.json:/app/settings.json -v $(pwd)/tokens.json:/app/tokens.json limit_swap_v4`
+
+(For Windows with Powershell)
+
+`docker run --rm --name limit-swap_v4 -it -v $PWD/settings.json:/app/settings.json -v $PWD/tokens.json:/app/tokens.json limit_swap_v4`
+
+If you wish to run the container in the background please include -d for detached.
+
+The streaming container logs can be visualised with `docker logs -f limit_swap_v4`
+
+To stop the bot `docker stop limit_swap_v4`
+
+#### Pros and cons
+🟢 : easy to setup if you know Docker
+
+🔴 : needs Docker
+
+
+
+
+
+
+
+
+
## Developers 🔧
Want to help contribute to LimitSwap, reach out on telegram all you need to do is make changes or fix bugs and we will pay developer bounties in $LIMIT for helping make the bot batter!
From 967dd1d32c445517488639d16d8d23559ef67559 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 22:47:31 +0100
Subject: [PATCH 13/16] Update settings.json
---
settings.json | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/settings.json b/settings.json
index b1cd58c..cef0366 100644
--- a/settings.json
+++ b/settings.json
@@ -1,10 +1,10 @@
[
{
- "LIMITWALLETPRIVATEKEY": "private key to wallet that hold LIMIT goes here - see secuirity tips on wiki!!!",
- "LIMITWALLETADDRESS": "wallet the holds LIMIT",
- "WALLETADDRESS": "wallet address you want to trade on",
- "PRIVATEKEY": "private key to trading wallet here - see secuirity tips on wiki!!!",
- "USECUSTOMNODE": "false",
+ "LIMITWALLETPRIVATEKEY": "do not enter it manually, open the bot : it will encrypt it",
+ "LIMITWALLETADDRESS": "wallet address where you hold your LIMIT tokens",
+ "WALLETADDRESS": "wallet address you want to trade on : can be different from LIMIT wallet",
+ "PRIVATEKEY": "do not enter it manually, open the bot : it will encrypt it",
+ "USECUSTOMNODE": "false",
"CUSTOMNODE": "put your own node here if you want and make, USECUSTOMNODE = TRUE",
"EXCHANGE": "pancakeswap",
"EXCHANGEVERSION": "2",
From 179bf002d6a15b418243e2008d5b8836efa2df38 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 23:14:35 +0100
Subject: [PATCH 14/16] Update README.md
---
README.md | 40 +++++++++++++++++++++++++++++-----------
1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
index 2f573ce..d44b5e4 100644
--- a/README.md
+++ b/README.md
@@ -16,28 +16,48 @@ There are 3 ways to install LimitSwap :
### 1. Run The Python Code Locally [*this is most ideal and can work on any OS*]
Here is a tutorial step-by-step:
-- Download last LimitSwap code here :
+- [x] Download last LimitSwap code here :
-- Unzip file
-- Install Python on your computer : https://www.python.org/downloads/
+- [x] Unzip file
+- [x] Install Python on your computer : https://www.python.org/downloads/
**PLEASE ADD IT TO PATH BY CHECKING THIS OPTION:**
-- Install Visual Studio : https://visualstudio.microsoft.com/fr/thank-you-downloading-visual-studio/?sku=Community&rel=17
+- [x] Install Visual Studio : https://visualstudio.microsoft.com/fr/thank-you-downloading-visual-studio/?sku=Community&rel=17
Please install the default package and all those options :

-- Open **Windows Powershell** (or Mac Terminal on MacOs)
-- Navigate into the unzipped folder
-- Run command: `pip install -r requirements.txt` --> this will install all the packages needed to run LimitSwap
+- [x] Open **Windows Powershell** (or Mac Terminal on MacOs)
-==> And it's done! ✅
+- [X] Run this command to locate LimitSwap folder :
-Simply **double-click on "LimitSwap.py"** and it will run, since you've installed Python 👍👍
+`Get-ChildItem -Filter LimitSwap.py -Recurse -ErrorAction SilentlyContinue -Force`
+
+- [X] Copy the Directory
+
+(example : `C:\Users\Administrator\Desktop\LimitSwap-master`)
+
+- [X] Paste the Directory after the "cd" command to navigate through the bot folder
+
+(example : ` cd C:\Users\Administrator\Desktop\LimitSwap-master`)
+
+- [x] It should look like this:
+
+
+
+- [x] Run command: `pip install -r requirements.txt` --> this will install all the packages needed to run LimitSwap
+
+
+
+✅ ✅ ✅ And it's done! ✅ ✅ ✅
+
+
+
+- [x] Simply **double-click on "LimitSwap.py"** and it will run, since you've installed Python 👍👍
@@ -97,8 +117,6 @@ To stop the bot `docker stop limit_swap_v4`
-
-
## Developers 🔧
Want to help contribute to LimitSwap, reach out on telegram all you need to do is make changes or fix bugs and we will pay developer bounties in $LIMIT for helping make the bot batter!
From 5e7341ae87a5d070071c1cb3315b04265d69ef59 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sat, 11 Dec 2021 23:51:26 +0100
Subject: [PATCH 15/16] Update LimitSwap.py
---
LimitSwap.py | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 73eb7ef..3fda5f3 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -972,9 +972,23 @@ def check_pool(inToken, outToken, symbol):
DECIMALS = decimals(outToken)
pair_contract = client.eth.contract(address=pair_address, abi=lpAbi)
reserves = pair_contract.functions.getReserves().call()
- pooled = reserves[1] / DECIMALS
- # print("Debug LIQUIDITYAMOUNT line 627 :", pooled, "in token:", outToken)
+ # This is a little trick to improve reliability of LIQUIDITYCHECK, before we're able to solve this bug completely
+ # We check if reserves[1] is a "regular number", otherwise we use reserves[0]. No better idea for now.
+ # print("----------------------------------------------------------------------")
+ if 0.01 <= (int(reserves[1]) / DECIMALS) <= 10000000:
+ pooled = reserves[1] / DECIMALS
+ # print("on choisit reserves[1]")
+ else:
+ pooled = reserves[0] / DECIMALS
+ # print("on choisit reserves[0]")
+ # print("----------------------------------------------------------------------")
+ # print("Debug reserves[0] line 982: ", reserves[0] / DECIMALS)
+ # print("Debug reserves[1] line 982: ", reserves[1] / DECIMALS)
+ # print("----------------------------------------------------------------------")
+ # print("Debug LIQUIDITYAMOUNT line 981 :", pooled, "in token:", outToken)
+ # print("----------------------------------------------------------------------")
+ # sleep(50)
return pooled
From 80117706604fddec7244d63b0579253bac56fc24 Mon Sep 17 00:00:00 2001
From: TsarBuig <70858574+tsarbuig@users.noreply.github.com>
Date: Sun, 12 Dec 2021 11:54:55 +0100
Subject: [PATCH 16/16] Update LimitSwap.py
---
LimitSwap.py | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/LimitSwap.py b/LimitSwap.py
index 3fda5f3..4d3bd65 100755
--- a/LimitSwap.py
+++ b/LimitSwap.py
@@ -973,22 +973,26 @@ def check_pool(inToken, outToken, symbol):
pair_contract = client.eth.contract(address=pair_address, abi=lpAbi)
reserves = pair_contract.functions.getReserves().call()
- # This is a little trick to improve reliability of LIQUIDITYCHECK, before we're able to solve this bug completely
- # We check if reserves[1] is a "regular number", otherwise we use reserves[0]. No better idea for now.
- # print("----------------------------------------------------------------------")
- if 0.01 <= (int(reserves[1]) / DECIMALS) <= 10000000:
- pooled = reserves[1] / DECIMALS
- # print("on choisit reserves[1]")
- else:
+ # Tokens are ordered by the token contract address
+ # The token contract address can be interpreted as a number
+ # And the smallest one will be token0 internally
+
+ ctnb1 = int(inToken, 16)
+ ctnb2 = int(outToken, 16)
+
+ if (ctnb1 > ctnb2):
+ # print("reserves[0] is for outToken:")
pooled = reserves[0] / DECIMALS
- # print("on choisit reserves[0]")
+ else:
+ # print("reserves[0] is for inToken:")
+ pooled = reserves[1] / DECIMALS
+
# print("----------------------------------------------------------------------")
# print("Debug reserves[0] line 982: ", reserves[0] / DECIMALS)
# print("Debug reserves[1] line 982: ", reserves[1] / DECIMALS)
# print("----------------------------------------------------------------------")
# print("Debug LIQUIDITYAMOUNT line 981 :", pooled, "in token:", outToken)
# print("----------------------------------------------------------------------")
- # sleep(50)
return pooled