diff --git a/LimitSwap.py b/LimitSwap.py
index ab783fe..4d3bd65 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
@@ -16,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.
#
@@ -31,6 +32,10 @@
# 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'
@@ -44,27 +49,36 @@ 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")
+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
# ----------------------------
@@ -72,7 +86,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
@@ -80,9 +95,10 @@ def printt_v(*print_args):
# 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)))
+ print(timestamp(), ' '.join(map(str, print_args)))
+
def printt_err(*print_args):
# Function: printt_err
@@ -91,9 +107,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
@@ -102,24 +119,24 @@ def load_settings_file(settings_path, load_message = True):
# 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.")
+ 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()
@@ -127,14 +144,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
@@ -146,7 +164,7 @@ def load_tokens_file(tokens_path, load_message = True):
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()
@@ -156,32 +174,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': 8,
+ '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()
@@ -393,7 +413,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']
@@ -577,7 +597,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 +608,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,7 +620,7 @@ 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
@@ -616,18 +636,18 @@ def get_password():
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 +672,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)
@@ -663,17 +686,17 @@ 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'], 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.")
+ # 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
@@ -693,7 +716,7 @@ def parse_wallet_settings(settings, pwd):
# Accepts user input for new private keys and wallet addresses
#
# returns: none (exits on incorrect password)
-
+
settings_changed = False
# Check for limit wallet information
@@ -714,10 +737,10 @@ def parse_wallet_settings(settings, pwd):
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,7 +754,7 @@ 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)
@@ -739,8 +762,6 @@ def parse_wallet_settings(settings, pwd):
save_settings(settings, pwd)
-
-
def decimals(address):
try:
balanceContract = client.eth.contract(address=Web3.toChecksumAddress(address), abi=standardAbi)
@@ -852,8 +873,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,9 +898,9 @@ 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.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()
@@ -890,17 +910,26 @@ 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:
+ 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)
+ print(style.YELLOW + "\n ---------------------------------------------------------------------------\n"
+ " You need to APPROVE this token before selling it : LimitSwap will do it now\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"
+ " ---------------------------------------------------------")
+ print(style.RESET + "\n")
return
@@ -943,13 +972,31 @@ 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)
+ # 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
+ 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("----------------------------------------------------------------------")
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 +1012,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)
+ 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 +1068,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 +1100,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 +1121,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 +1148,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 +1157,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 +1191,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 +1227,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 +1238,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 +1269,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 +1402,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 +1429,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 +1447,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 +1458,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 +1490,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 +1506,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 +1543,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 +1630,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 +1647,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 +1667,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 +1758,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,7 +1845,6 @@ def sell(amount, moonbag, inToken, outToken, gas, slippage, gaslimit, boost, fee
def run():
-
global failedtransactionsamount
try:
@@ -1600,8 +1856,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" + 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 +1868,15 @@ def run():
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':
@@ -1632,11 +1890,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,17 +1903,17 @@ def run():
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'])
@@ -1668,7 +1926,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 +1955,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 +1973,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 +2005,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 +2022,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:
@@ -1781,8 +2046,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)
@@ -1799,6 +2064,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 +2088,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 +2106,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'])
@@ -1909,6 +2188,3 @@ def run():
sleep(1)
if nonce > timeout:
run()
-
-
-
diff --git a/README.md b/README.md
index e3b2944..d44b5e4 100644
--- a/README.md
+++ b/README.md
@@ -7,32 +7,57 @@ 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 :
-### 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 :
+- [x] Download last LimitSwap code here :
-- Unzip file
-- Install Python on your computer : https://www.python.org/downloads/
-- Install Visual Studio : https://visualstudio.microsoft.com/fr/thank-you-downloading-visual-studio/?sku=Community&rel=17
+- [x] Unzip file
+- [x] Install Python on your computer : https://www.python.org/downloads/
+
+**PLEASE ADD IT TO PATH BY CHECKING THIS OPTION:**
+
+
+
+- [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)
+
+- [X] Run this command to locate LimitSwap folder :
+
+`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:
-==> And it's done! ✅
+
-Simply **double-click on "LimitSwap.py"** and it will run, since you've installed Python 👍👍
+- [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 👍👍
@@ -44,7 +69,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
@@ -53,6 +78,45 @@ 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!
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",