24 Comments
Feb 23, 2022Liked by BowTiedDevil

you're such a great teacher...thank you so much!

Expand full comment
Dec 18, 2021Liked by BowTiedDevil

"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.

Expand full comment
Feb 11, 2022Liked by BowTiedDevil

Thank you for this!

This is a lot of fun and you are doing great in your explanations.

Expand full comment
author

You're very welcome, glad to hear that you are enjoying 🥂

Expand full comment
Oct 16, 2022Liked by BowTiedDevil

the router contract doc link for trader joe is no longer working => https://docs.traderjoexyz.com/main/the-project/contracts

Expand full comment
author

Thanks for the heads up! I've edited the post to target the new address (https://help.traderjoexyz.com/en/security-and-contracts/contracts)

Expand full comment
Sep 28, 2023·edited Sep 28, 2023

Another redirection needed for the traderjoe contracts link again, I believe it's https://support.traderjoexyz.com/en/articles/6807983-contracts-api atm

Expand full comment
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

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!

Expand full comment
author

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!

Expand full comment
Dec 22, 2021·edited Dec 22, 2021Liked by BowTiedDevil

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?

Expand full comment
author

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.

Expand full comment
Dec 17, 2021Liked by BowTiedDevil

Looks like some text is missing:

"...Our old friend WAVAX will also make an appearance at"

Right before the subtitle "Brownie Hands-On"

Expand full comment
author

Good catch, thank you. I've added the WAVAX contract address to the post above.

Expand full comment

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

Expand full comment

This is brilliant! Keep doing the great work

Expand full comment

Can you add / update next post link in the article same itself if possible? Have to scroll down a lot to continue reading.

Expand full comment

Hey is there any discord something i want to ask about flashbot problem bribes and how to bribe in gwei ?

Expand full comment
author

Yes, there is an invite link here — https://degencode.substack.com/p/discord-info

Expand full comment

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!

Expand full comment

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?

Expand full comment
author

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.

Expand full comment

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?

Expand full comment
author

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

Expand full comment

Expand full comment