"In the manner typical of programmers,..."; this itself may be a clue on how to better extract the value one is seeking from documentation.
Here's a thing that: does...when... only if... except when... unless.....otherwise; ....
Now compose a few handful of these seemingly cryptic definitions into a larger panic inducing monstrosity & viola! You've got yourself some code magic;
Thanks for taking the time to expose the necessary mechanics for those of us whose attention might blink thus disassembling the house of cards constructing method definitions, use cases, gotchas & forever battling the remainder of will left after endless $#%#$!%!#@!! & hair pulling.
Jun 14, 2022·edited Jun 14, 2022Liked by BowTiedDevil
Cool post.
Was going over this paragraph:
"The equivalent “human readable” amounts should be 1000000 / (10 ** 6), 9641292951465110 / (10 ** 18), and 944807 / (10 ** 6). But since we get the full integers from getAmountsOut(), we have to be sure to account for them later when we’re working with simple human brains."
And I thought to myself... In human terms shouldn't one multiply the second value in the array / result by the price of wavax because it's expressed in wavax, to see how the swap went in usdc terms? But then later I thought, compared to what? And how would you gauge if its a good swap or not. So I think I messed up there. Maybe an oracle would help here... But ultimately the resulting USDT is the main comparison here. Normally I would triangulate between three tokens and end with the first. But because we are dealing with USDC/USDT it perhaps shows value change more clearly. I guess that was the point.
Then I started playing around... with the result / array. Some weird stuff happened. I guess I need to look up how these array things work... There is probably alot of inbuilt logic here that I don't grasp:
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
There's a lot going on here, so I recommend reading about how to access elements by index in Python, as well as a concept called "slicing" which is what you're doing with the colon. Also read up on negative indexes, as well as negative slicing. This will help clear up a lot of these questions!
When we get deeper into the bot development, I'll show you how to manage that internally and avoid user errors. The goal is to have the bot handle all that, and letting it track the real Ethereum integer balance instead of the human readable balance is the way to ensure success.
So I might be a little late to the boat here (still learning a lot) - but thought I would share something in case anyone else hits the same road block. Essentially the road block I hit here was in relation to loading the usdc_contract using .from_explorer. It kept throwing a Snowtrace Rate Limit API error - but only on that contract - none of the others would throw the error (I have no idea why - maybe because it queries two contracts in quick succession? the usdc followed by the proxy? which may hit some sort of per second rate limit or something odd like that).
Anyway so I spent some time getting an API key from Snowtrace - but struggled to work out how to implement this as an environment variable as it describes in the error.
Background - i'm on a windows machine - and had tried to implment on the machine regularly in System Properties - environment variables - added both to the user variables and system variables - but nothing seemed to work.
In the end - I worked out the problem must be related to the virtual environment that had been setup - and that somehow the (.venv) environment variables were different/wall gardened from my main system (i guess that makes sense - just i'm very new to using a virtual environemnt). Anyway, the solution that fixed it for me was adding a line to
the Activate.ps1 file in the .venv/Scripts/ location. I'm using powershell - so for me the line I added to this file was:
$env:SNOWTRACE_TOKEN = 'REPLACE-WITH-API-TOKEN'
It's worth noting that if you are using regular cmd console - the above line will be different slightly - and you would be editing the activate.bat file instead.
I hope that helps anyone else that might hit the same wall!
I got this error making all steps in the doc after this input: router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, wa
Check your spelling and use tab-completion as needed. usdt_contract is an object that we create in the "Brownie Hands-on" section. Unless you skipped a step or the command failed, you should have access to that object.
ValueError: Failed to retrieve data from API: {'status': '0', 'message': 'NOTOK', 'result': 'Max rate limit reached, please use API Key for higher rate limit'}
have a key, but not sure where to store it for brownie to use...
you're such a great teacher...thank you so much!
"In the manner typical of programmers,..."; this itself may be a clue on how to better extract the value one is seeking from documentation.
Here's a thing that: does...when... only if... except when... unless.....otherwise; ....
Now compose a few handful of these seemingly cryptic definitions into a larger panic inducing monstrosity & viola! You've got yourself some code magic;
Thanks for taking the time to expose the necessary mechanics for those of us whose attention might blink thus disassembling the house of cards constructing method definitions, use cases, gotchas & forever battling the remainder of will left after endless $#%#$!%!#@!! & hair pulling.
Thank you for this!
This is a lot of fun and you are doing great in your explanations.
You're very welcome, glad to hear that you are enjoying 🥂
the router contract doc link for trader joe is no longer working => https://docs.traderjoexyz.com/main/the-project/contracts
Thanks for the heads up! I've edited the post to target the new address (https://help.traderjoexyz.com/en/security-and-contracts/contracts)
Another redirection needed for the traderjoe contracts link again, I believe it's https://support.traderjoexyz.com/en/articles/6807983-contracts-api atm
Cool post.
Was going over this paragraph:
"The equivalent “human readable” amounts should be 1000000 / (10 ** 6), 9641292951465110 / (10 ** 18), and 944807 / (10 ** 6). But since we get the full integers from getAmountsOut(), we have to be sure to account for them later when we’re working with simple human brains."
And I thought to myself... In human terms shouldn't one multiply the second value in the array / result by the price of wavax because it's expressed in wavax, to see how the swap went in usdc terms? But then later I thought, compared to what? And how would you gauge if its a good swap or not. So I think I messed up there. Maybe an oracle would help here... But ultimately the resulting USDT is the main comparison here. Normally I would triangulate between three tokens and end with the first. But because we are dealing with USDC/USDT it perhaps shows value change more clearly. I guess that was the point.
Then I started playing around... with the result / array. Some weird stuff happened. I guess I need to look up how these array things work... There is probably alot of inbuilt logic here that I don't grasp:
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[-3:-1]
(1000000, 64395931876068061)
Nice the first two results... outputs
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[-4:-1]
(1000000, 64170669274185241)
Oh, again, the first two?
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[-4]
File "<console>", line 1, in <module>
File "brownie/convert/datatypes.py", line 337, in __getitem__
return super().__getitem__(key)
IndexError: tuple index out of range
ahh, now, it can't find it.
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[0:2]
(1000000, 63976823062175739)
Now first two, but what about three?
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[0:3]
(1000000, 63976823062175739, 992898)
So now, 0:3, refers to the first three, and 0 is not filled? Seems like this might be the case for -4 too
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[1:3]
(63976823062175739, 990665)
why no 1?
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[0:]
(1000000, 63976823062175739, 988809)
Ahh, shows all. What about 0...
>>> router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, w
avax_contract.address, usdc_contract.address ])[0]
1000000
Anyway, thanks for the post!
There's a lot going on here, so I recommend reading about how to access elements by index in Python, as well as a concept called "slicing" which is what you're doing with the colon. Also read up on negative indexes, as well as negative slicing. This will help clear up a lot of these questions!
Man I really better be habituated to using the .decimal() method whenever I actually need to call it.
Imagine the disaster if you send n ** 12 instead of n * 6 ... would this therefore be a best practice?
When we get deeper into the bot development, I'll show you how to manage that internally and avoid user errors. The goal is to have the bot handle all that, and letting it track the real Ethereum integer balance instead of the human readable balance is the way to ensure success.
Looks like some text is missing:
"...Our old friend WAVAX will also make an appearance at"
Right before the subtitle "Brownie Hands-On"
Good catch, thank you. I've added the WAVAX contract address to the post above.
Adding this incase someone gets stuck with loading the USDC contract
export SNOWTRACE_TOKEN=your_api_key_here # Just put that in your terminal before you load the brownie console and you're gtg
This is brilliant! Keep doing the great work
Can you add / update next post link in the article same itself if possible? Have to scroll down a lot to continue reading.
Hey is there any discord something i want to ask about flashbot problem bribes and how to bribe in gwei ?
Yes, there is an invite link here — https://degencode.substack.com/p/discord-info
So I might be a little late to the boat here (still learning a lot) - but thought I would share something in case anyone else hits the same road block. Essentially the road block I hit here was in relation to loading the usdc_contract using .from_explorer. It kept throwing a Snowtrace Rate Limit API error - but only on that contract - none of the others would throw the error (I have no idea why - maybe because it queries two contracts in quick succession? the usdc followed by the proxy? which may hit some sort of per second rate limit or something odd like that).
Anyway so I spent some time getting an API key from Snowtrace - but struggled to work out how to implement this as an environment variable as it describes in the error.
Background - i'm on a windows machine - and had tried to implment on the machine regularly in System Properties - environment variables - added both to the user variables and system variables - but nothing seemed to work.
In the end - I worked out the problem must be related to the virtual environment that had been setup - and that somehow the (.venv) environment variables were different/wall gardened from my main system (i guess that makes sense - just i'm very new to using a virtual environemnt). Anyway, the solution that fixed it for me was adding a line to
the Activate.ps1 file in the .venv/Scripts/ location. I'm using powershell - so for me the line I added to this file was:
$env:SNOWTRACE_TOKEN = 'REPLACE-WITH-API-TOKEN'
It's worth noting that if you are using regular cmd console - the above line will be different slightly - and you would be editing the activate.bat file instead.
I hope that helps anyone else that might hit the same wall!
File "<console>", line 1, in <module>
NameError: name 'usdt_contract' is not defined
I got this error making all steps in the doc after this input: router_contract.getAmountsOut(1*( 10**usdt_contract.decimals()), [usdt_contract.address, wa
vax_contract.address, usdc_contract.address])
Does somone have the same error?
Check your spelling and use tab-completion as needed. usdt_contract is an object that we create in the "Brownie Hands-on" section. Unless you skipped a step or the command failed, you should have access to that object.
trying to implement with "bsc-main" network;
getting:
ValueError: Failed to retrieve data from API: {'status': '0', 'message': 'NOTOK', 'result': 'Max rate limit reached, please use API Key for higher rate limit'}
have a key, but not sure where to store it for brownie to use...
anyone else implemented API keys?
Brownie can work with a bscscan API key using the environment variable BSCSCAN_TOKEN
https://github.com/eth-brownie/brownie/blob/v1.19.0/brownie/network/contract.py
✅