GithubHelp home page GithubHelp logo

apeworx / ape-tokens Goto Github PK

View Code? Open in Web Editor NEW
9.0 5.0 7.0 48 KB

Tokens converter plugin for the Ape Framework

Home Page: https://www.apeworx.io/

License: Apache License 2.0

Python 100.00%
python apeworx tokenlist tokens ape

ape-tokens's Introduction

Quick Start

A series of utilities for working with tokens, based on the py-tokenlists.

Dependencies

Installation

via pip

You can install the latest release via pip:

pip install ape-tokens

via setuptools

You can clone the repository and use setuptools for the most up-to-date version:

git clone https://github.com/ApeWorX/ape-tokens.git
cd ape-tokens
python3 setup.py install

Quick Usage

CLI Usage

First, install a token list, such as the 1inch token list, which contains many tokens that you can use:

ape tokens install tokens.1inch.eth

To see all the tokens you can use, run command:

ape tokens list-tokens

To see other available CLI commands, run:

ape tokens --help

Python Usage

One of the main reasons to use the ape-tokens plugin is to have nicer UX for providing token amounts to contract transactions. For example, let's say you have a smart-contract named MyContract with a function provideLinkToken() that takes a decimal value of LINK tokens. The following is an example script that deploys the contract and makes a transaction by expressing the value of LINK as 8.23 LINK:

from ape import accounts, project

my_account = accounts[0]
contract = my_account.deploy(project.MyContract)

contract.provideLinkTokens("8.23 LINK")

Alternatively, if you need the converted value returned to you, you can use the convert tool from the root ape namespace:

from ape import convert

convert("100.1234 BAT", int)

Lastly, to get information about a token, including its contract address, you can do so by importing the tokens member from the root ape_tokens namespace:

from ape_tokens import tokens

bat = tokens["BAT"]

print(bat.address)

ape-tokens's People

Contributors

101chaos avatar antazoey avatar dtdang avatar fubuloubu avatar mikeshultz avatar ninjagod1251 avatar notpeopling2day avatar sabotagebeats avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ape-tokens's Issues

Add config for custom tokenlist [APE-1534]

Overview

Add config item for tokens that supports an ad-hoc list of custom tokens for a project to use (or a global custom list)

Specification

Using the TokenInfo type from py-tokenlists:

tokens:
- name: "cHaOSneT Credits"
  address: 0x0579fc0e764e7cc10c7175533b1330b184b8d505
  symbol: CHAOS
  decimals: 18
  chainId: 11155111
- ... # More tokens

Also, merge the global list (under ~/.ape/ape-config.yaml) with a local project's

Dependencies

Include links to any open issues that must be resolved before this feature can be implemented.

Add Price Info

Overview

Add a way to query live and historical pricing information

Specification

Might be too much to ask here, but could define a query type that could be fulfilled by like uniswap or other sources of pricing information in order to fetch prices (maybe coinbase, coingecko, etc.)

>>> from ape_tokens import price
>>> price["USDC"]["$"]
Decimal("1.00")
>>> price.query(quote="USDC", base="$", start_block=1000000, stop_block=1200000)
# dataframe containing per-block prices

Dependencies

n/a

Attempt to use Contract(addr) first before ERC20(addr)

Overview

Currently the library only uses the default built-in ERC20 interface to return the ContractContainer for a given token. It should first try to do Contract(token_info.address) before returning ERC20(token_info.address) if an interface is not available for whatever reason

When a token is in a list multiple times, it fails to load the token info

Environment information

  • ape and plugin versions:
$ ape --version
0.2.7

$ ape plugins list
Installed Plugins:
  hardhat      0.2.2
  solidity     0.2.3
  tokens       0.2.0
  infura       0.2.0
  etherscan    0.2.1
  alchemy      0.2.0
  foundry      0.2.0
  vyper        0.2.0
  ens          0.2.0
  • Python Version: 3.9.9
  • OS: linux

What went wrong?

Not quite sure what happens here, and may be related to the error shown in #18, but it appears that if a token is in a list multiple times, it will not properly handle that result and fail to find a matching token.

$ ape tokens list-tokens --search APE
...
0x4d224452801aced8b2f0aebe155379bb5d594381 (APE)
0x40e0a6ef9dbadfc83c5e0d15262feb4638588d77 (APE)
...
0x26ea1f595f6567b7050fbba24f6a66e19db4d560 (APE)

How can it be fixed?

May have to expose alternative flags to filter down on, like what decimals it has, address, etc.
Or, offer a way to ignore specific entries in a list in this scenario.

Might need to be moved to py-tokenlists

bug: black doesn't work

Environment information

  • ape and plugin versions:
$ ape --version
# ...copy and paste result of above command here...

$ ape plugins list
# ...copy and paste result of above command here...
  • Python Version: x.x.x
  • OS: osx/linux/win

What went wrong?

Please include information like:

  • what command you ran
  • the code that caused the failure (see this link for help with formatting code)
  • full output of the error you received

How can it be fixed?

update black version to newest version in setup

bug: `ValueError: Default token list has not been set.`

Environment information

  • ape and plugin versions:
$ ape --version
# ...copy and paste result of above command here...

$ ape plugins list
# ...copy and paste result of above command here...
  • Python Version: x.x.x
  • OS: osx/linux/win

What went wrong?

Please include information like:

  • what command you ran
  • the code that caused the failure (see this link for help with formatting code)
  • full output of the error you received

How can it be fixed?

will be in PR shortly

Allow converting prices to token amounts

Overview

Really not sure if this is a good idea for safety reasons, but it would be awesome to be able to specify a price like $1000 and then have it convert to the relevant token amount you want

Specification

>>> convert("$1000 in USDC", int)
1000000000

Dependencies

#40

Make an easy function for converting token balance integers to decimal token values [APE-1114]

Overview

It would be nice to render a token value back to a human-readable amount

Specification

from ape_tokens import tokens

weth = tokens["WETH"]

# Look up conversion factor by symbol
assert tokens.render(weth.balanceOf(acct), "WETH") == "1.27 WETH"
# OR allow using any token contract (which has `.symbol()` and `.decimals()` methods)
assert tokens.render(weth.balanceOf(acct), weth) == "1.27 WETH"

Get Token Address By Chain [APE-1401]

Overview

I'm looking to bridge a token to another chain and it would be helpful to get the contract address on the destination chain without having to switch networks....

Specification

Would be helpful to pass an optional argument to the getitem method and conditionally retrieve the address on that chain.

    def __getitem__(self, symbol: str, chain_id: int) -> ContractInstance:
        try:
            token_info = self._manager.get_token_info(
                symbol, chain_id=chain_id if chain_id else self.network_manager.network.chain_id
            )

Dependencies

None

Big long incompreshensible message if no token found

Environment information

  • ape and plugin versions:
$ ape --version
0.2.7

$ ape plugins list
Installed Plugins:
  hardhat      0.2.2
  solidity     0.2.3
  tokens       0.2.0
  infura       0.2.0
  etherscan    0.2.1
  alchemy      0.2.0
  foundry      0.2.0
  vyper        0.2.0
  ens          0.2.0
  • Python Version: 3.9.9
  • OS: linux

What went wrong?

...19d4900d3e5069f1', name='A4 Finance', decimals=6, symbol='A4', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/21992/thumb/ba384ad07217a4be75cb85314f5760f7.jpg?1640582786', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/21992/thumb/ba384ad07217a4be75cb85314f5760f7.jpg', query='1640582786'), tags=None, extensions=None), TokenInfo(chainId=1, address='0xd35c06a2781f648c75290976ecf71e71582188b7', name='Quarashi', decimals=18, symbol='QUA', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/25589/thumb/Lk2A7ta.png?1652769197', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/25589/thumb/Lk2A7ta.png', query='1652769197'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x7a5d3a9dcd33cb8d527f7b5f96eb4fef43d55636', name='RadioShack', decimals=18, symbol='RADIO', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/25307/thumb/ZVoPiysPJq6dPIZm_Se-6vjmsBepwhHlTQfdYZRILbHyVVTRUYCO-wmJJ4zT10HXCGv1j-ZyWr2u2sBaVlap5Y-ILqeXZuIquWdBDxxG0E0qDpgH7omLqYdgWWLSM_TUK9d1PiiYdu6bERdCDaucgFjlqwmhVQK4uV4jyUiXzchVUnu8Qt6SnxlNxz88G0mQ_tfiwkFv_vKqtgb1CcPycVZVz9.jpg?1651211260', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/25307/thumb/ZVoPiysPJq6dPIZm_Se-6vjmsBepwhHlTQfdYZRILbHyVVTRUYCO-wmJJ4zT10HXCGv1j-ZyWr2u2sBaVlap5Y-ILqeXZuIquWdBDxxG0E0qDpgH7omLqYdgWWLSM_TUK9d1PiiYdu6bERdCDaucgFjlqwmhVQK4uV4jyUiXzchVUnu8Qt6SnxlNxz88G0mQ_tfiwkFv_vKqtgb1CcPycVZVz9.jpg', query='1651211260'), tags=None, extensions=None), TokenInfo(chainId=1, address='0xcafe34bae6f1b23a6b575303edcc0578d2188131', name='Minter Network', decimals=18, symbol='BIP', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/9982/thumb/Nvoj_6Mu_400x400.jpg?1587968303', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/9982/thumb/Nvoj_6Mu_400x400.jpg', query='1587968303'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x57d579f483854c62fef850b8a5332b0d8424b7e2', name='OpenSwap One', decimals=18, symbol='OPENX', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/19274/thumb/oswap_asset.96f04d15.png?1634869019', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/19274/thumb/oswap_asset.96f04d15.png', query='1634869019'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x80cd73badb406ea36b9a7cdeb8df06aefa7e12d9', name='SleepFuture', decimals=18, symbol='SLEEPEE', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/25469/thumb/sleepee.png?1651916574', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/25469/thumb/sleepee.png', query='1651916574'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x64875aaa68d1d5521666c67d692ee0b926b08b2f', name='CelsiusX Wrapped ADA', decimals=18, symbol='CXADA', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/23536/thumb/cxADA_128x128.png?1644388456', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/23536/thumb/cxADA_128x128.png', query='1644388456'), tags=None, extensions=None), TokenInfo(chainId=1, address='0xf9e293d5d793ddc1ae4f778761e0b3e4aa7cf2dd', name='CelsiusX Wrapped DOGE', decimals=18, symbol='CXDOGE', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/23683/thumb/R2747rb.png?1644997607', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/23683/thumb/R2747rb.png', query='1644997607'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x471ea49dd8e60e697f4cac262b5fafcc307506e4', name='RMRK', decimals=10, symbol='RMRK', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/18656/thumb/download_%281%29_%281%29.png?1632865271', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/18656/thumb/download_%281%29_%281%29.png', query='1632865271'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x93581991f68dbae1ea105233b67f7fa0d6bdee7b', name='Evmos', decimals=18, symbol='EVMOS', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/24023/thumb/evmos.png?1653958927', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/24023/thumb/evmos.png', query='1653958927'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x4c3a8eceb656ec63eae80a4ebd565e4887db6160', name='SokuSwap', decimals=18, symbol='SOKU', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/18378/thumb/VCIEHaG.png?1653547690', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/18378/thumb/VCIEHaG.png', query='1653547690'), tags=None, extensions=None), TokenInfo(chainId=1, address='0xc7230badf274995f1933598c249c824fde26f426', name='Suteku', decimals=18, symbol='SUTEKU', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/20824/thumb/hJIxZGE.png?1653548066', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/20824/thumb/hJIxZGE.png', query='1653548066'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x88536c9b2c4701b8db824e6a16829d5b5eb84440', name='Atlas USV', decimals=9, symbol='USV', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/22066/thumb/7iUyjg5t.png?1640744823', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/22066/thumb/7iUyjg5t.png', query='1640744823'), tags=None, extensions=None), TokenInfo(chainId=1, address='0xeeeeeb57642040be42185f49c52f7e9b38f8eeee', name='Elk Finance', decimals=18, symbol='ELK', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/17813/thumb/elk.png?1629336971', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/17813/thumb/elk.png', query='1629336971'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x2e7b0d4f9b2eaf782ed3d160e3a0a4b1a7930ada', name='Ceres', decimals=18, symbol='CERES', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/17959/thumb/sQLDgqx.png?1648442923', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/17959/thumb/sQLDgqx.png', query='1648442923'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x06ebc9c542357e2129d16717cd02c02fbc835d33', name='Coinage Finance', decimals=18, symbol='CAGE', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/22300/thumb/Coinage_v2_200x200_white.png?1653464214', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/22300/thumb/Coinage_v2_200x200_white.png', query='1653464214'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x7162469321ae5880f077d250b626f3271b21b903', name='KillSwitch', decimals=18, symbol='KSW', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/20215/thumb/logo_%2824%29.png?1636670633', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/20215/thumb/logo_%2824%29.png', query='1636670633'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x3e362283b86c1b45097cc3fb02213b79cf6211df', name='CatCoin com', decimals=9, symbol='CATCOIN', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/25279/thumb/logo_%281%29.png?1651126078', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/25279/thumb/logo_%281%29.png', query='1651126078'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x4bf5cd1ac6fff12e88aedd3c70eb4148f90f8894', name='Orbit', decimals=18, symbol='ORBIT', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/25807/thumb/apple-touch-icon.png?1653978963', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/25807/thumb/apple-touch-icon.png', query='1653978963'), tags=None, extensions=None), TokenInfo(chainId=1, address='0x0b5326da634f9270fb84481dd6f94d3dc2ca7096', name='Etho Protocol', decimals=18, symbol='ETHO', logoURI=AnyUrl('https://assets.coingecko.com/coins/images/5194/thumb/ether1new-transparent.png?1578298993', scheme='https', host='assets.coingecko.com', tld='com', host_type='domain', path='/coins/images/5194/thumb/ether1new-transparent.png', query='1578298993'), tags=None, extensions=None)] keywords=['defi'] tags=None logoURI=AnyUrl('https://www.coingecko.com/assets/thumbnail-007177f3eca19695592f0b8b0eabbdae282b54154e1be912285c9034ea6cbaf2.png', scheme='https', host='www.coingecko.com', tld='com', host_type='domain', path='/assets/thumbnail-007177f3eca19695592f0b8b0eabbdae282b54154e1be912285c9034ea6cbaf2.png')' token list.

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
Input In [1], in <module>
      1 from ape_tokens import tokens
----> 3 ape = tokens["APE"]

File site-packages/ape_tokens/managers.py:124, in TokenManager.__getitem__(self, symbol)
    121     token_info = self._manager.get_token_info(symbol)
    123 except ValueError as e:
--> 124     raise KeyError(f"Symbol '{symbol}' is not a known token symbol") from e
    126 return self._Contract(to_checksum_address(token_info.address), contract_type=ERC20)

How can it be fixed?

I think the __repr__ method needs to be overridden either here or with py-tokenlists

Add query subclasses for querying token information [APE-1243]

Overview

There are lots of indexes out there that index specific token information such as totalSupply and balanceOf over ranges of block history, such as Etherscan. Define several subclasses of the query definition in ApeWorX/ape#380 to define an easier way to source this information from these indexes.

Specification

Might look something like this:

from ape.api.query import ContractCallQuery
# ...or whatever the linked issue calls the base class for querying view calls


class TokenBalanceQuery(ContractCallQuery):
    token: Address
    account: Address
    from_block: int
    to_block: int

# Other queries such as `TokenSupplyQuery`, etc.

Also, to be most useful it would need to have the ability to use ORDER BY and LIMIT semantics to do queries like "get me the top 20 accounts over the last 1000 blocks for token X by % of total supply", something like:

from ape_tokens import tokens

usdc = tokens["USDC"]

top_20_accounts = usdc.balanceOf.query("*", order_by_result=True, limit=20, starting_block=-1000)
print(top_20_accounts / usdc.totalSupply.query(starting_block=-1000))

NOTE: Above is just a sketch, needs work

Dependencies

ApeWorX/ape#380

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.