-
Notifications
You must be signed in to change notification settings - Fork 382
Expand file tree
/
Copy pathcli.py
More file actions
117 lines (102 loc) · 3.44 KB
/
cli.py
File metadata and controls
117 lines (102 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import logging
import os
from typing import Optional
import click
from dotenv import load_dotenv
from web3 import Web3
from .constants import ETH_ADDRESS
from .fee import FeeTier
from .token import BaseToken
from .tokens import get_tokens
from .uniswap import AddressLike, Uniswap, _str_to_addr
logger = logging.getLogger(__name__)
# Global used in _coerce_to_checksum to look up tokens
_uni: Optional[Uniswap] = None
def _coerce_to_checksum(addr: str) -> str:
assert _uni
tokens = get_tokens(_uni.netname)
if not addr.startswith("0x"):
if addr.upper() in tokens:
return tokens[addr.upper()]
else:
raise ValueError(
"token was not an address, and a shorthand was not found in the token db"
)
if Web3.is_checksum_address(addr):
return addr
else:
return Web3.to_checksum_address(addr)
@click.group()
@click.option("-v", "--verbose", is_flag=True)
@click.option(
"--version",
type=click.Choice(["1", "2", "3"]),
default=os.getenv("UNISWAP_VERSION", "3"),
)
@click.pass_context
def main(ctx: click.Context, verbose: bool, version: str) -> None:
logging.basicConfig(level=logging.INFO if verbose else logging.WARNING)
load_dotenv()
ctx.ensure_object(dict)
ctx.obj["VERBOSE"] = verbose
ctx.obj["UNISWAP"] = Uniswap(None, None, version=int(version))
global _uni
_uni = ctx.obj["UNISWAP"]
@main.command()
@click.argument("token_in", type=_coerce_to_checksum)
@click.argument("token_out", type=_coerce_to_checksum)
@click.option(
"--raw",
is_flag=True,
help="Don't normalize the quoted price to the output token's decimals",
)
@click.option(
"--quantity",
help="Quantity of output tokens to get price of. Falls back to one full unit of the input token by default (10**18 for WETH, for example).",
)
@click.pass_context
def price(
ctx: click.Context,
token_in: AddressLike,
token_out: AddressLike,
raw: bool,
quantity: Optional[int] = None,
) -> None:
"""Returns the price of ``quantity`` tokens of ``token_in`` quoted in ``token_out``."""
uni: Uniswap = ctx.obj["UNISWAP"]
if quantity is None:
if token_in == ETH_ADDRESS:
decimals = 18
else:
decimals = uni.get_token(token_in).decimals
quantity = 10**decimals
price = uni.get_price_input(token_in, token_out, qty=quantity, fee=FeeTier.TIER_3000)
if raw:
click.echo(price)
else:
if token_in == ETH_ADDRESS:
decimals = 18
else:
decimals = uni.get_token(token_out).decimals
click.echo(price / 10**decimals)
@main.command()
@click.argument("token", type=_coerce_to_checksum)
@click.pass_context
def token(ctx: click.Context, token: AddressLike) -> None:
"""Show metadata for token"""
uni: Uniswap = ctx.obj["UNISWAP"]
t1 = uni.get_token(token)
click.echo(t1)
@main.command()
@click.option("--metadata", is_flag=True, help="Also get metadata for tokens")
@click.pass_context
def tokendb(ctx: click.Context, metadata: bool) -> None:
"""List known token addresses"""
uni: Uniswap = ctx.obj["UNISWAP"]
for symbol, addr in get_tokens(uni.netname).items():
if metadata and addr != "0x0000000000000000000000000000000000000000":
data = uni.get_token(_str_to_addr(addr))
assert data.symbol.lower() == symbol.lower()
click.echo(data)
else:
click.echo(BaseToken(symbol, addr))