Created
August 8, 2022 03:50
-
-
Save normanlmfung/d1fedb7600698735d89d7cbf7253bd71 to your computer and use it in GitHub Desktop.
Fetch historical price of SINGLE/USDC from VVS/CRONOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This script gets the buy/sell prices from the vvs finance (https://vvs.finance/swap) smart contracts | |
for a given block number and path. | |
""" | |
from datetime import datetime | |
from dataclasses import dataclass | |
from typing import ( | |
Dict, | |
List, | |
Literal, | |
Optional, | |
Union, | |
) | |
from web3 import Web3 | |
from web3.types import ( | |
ChecksumAddress | |
) | |
w3_cro = Web3(Web3.HTTPProvider("https://evm.cronos.org")) | |
vvs_router_abi = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]' # noqa | |
vvs_router_address = Web3.toChecksumAddress("0x145863Eb42Cf62847A6Ca784e6416C1682b1b2Ae") | |
vvs_contract = w3_cro.eth.contract(address=vvs_router_address, abi=vvs_router_abi) | |
@dataclass | |
class Token: | |
address: ChecksumAddress | |
symbol: str | |
decimals: int | |
def __init__(self, address: Union[str, ChecksumAddress], symbol: str, decimals: int) -> None: | |
self.address = Web3.toChecksumAddress(address) | |
self.symbol = symbol | |
self.decimals = decimals | |
def __eq__(self, other) -> bool: | |
if not isinstance(other, Token): | |
return False | |
return self.address == other.address | |
token_by_symbol: Dict[str, Token] = { | |
"USDC": Token("0xc21223249CA28397B4B6541dfFaEcC539BfF0c59", "USDC", 6), | |
"USDT": Token("0x66e428c3f67a68878562e79A0234c1F83c208770", "USDT", 6), | |
"SINGLE": Token("0x0804702a4E749d39A35FDe73d1DF0B1f1D6b8347", "SINGLE", 18), | |
} | |
def get_buy_price( | |
path_with_symbols: List[str], | |
block_number: Optional[int] = None, | |
quote_token_qty: float = 1000) -> float: | |
""" | |
This function computes the buy price given by the vvs finance smart contracts, providing no one front-run you, and including the exchange 0.3% fee # noqa | |
:param path_with_symbols: a list of 2 or 3 symbols, starting with the quote token. Ex ["USDC", "SINGLE"] or ["USDT", "USDC", "SINGLE"] # noqa | |
:param block_number: the block number at which we want the price. Default is None and gives the current price | |
:param quote_token_qty: The quantity of quote tokens used to get the price. Default to 1000. | |
:return: The buy price | |
""" | |
path = [token_by_symbol[symbol].address for symbol in path_with_symbols] | |
quote_token = token_by_symbol[path_with_symbols[0]] | |
base_token = token_by_symbol[path_with_symbols[-1]] | |
in_quantity = int(quote_token_qty * 10**quote_token.decimals) | |
block_identifier: Union[Literal['latest'], int] = block_number if block_number else 'latest' | |
out_quantity = vvs_contract.functions.getAmountsOut(in_quantity, path).call(block_identifier=block_identifier)[-1] | |
buy_price = quote_token_qty / (out_quantity / 10**base_token.decimals) | |
return buy_price | |
def get_sell_price( | |
path_with_symbols: List[str], | |
block_number: Optional[int] = None, | |
quote_token_qty: float = 1000) -> float: | |
""" | |
This function computes the sell price given by the vvs finance smart contracts, providing no one front-run you, and including the exchange 0.3% fee # noqa | |
:param path_with_symbols: a list of 2 or 3 symbols, ending with the quote token. Ex ["SINGLE", "USDC"] or ["SINGLE", "USDC", "USDT"] # noqa | |
:param block_number: the block number at which we want the price. Default is None and gives the current price | |
:param quote_token_qty: The quantity of quote tokens used to get the price. Default to 1000. | |
:return: The sell price | |
""" | |
path = [token_by_symbol[symbol].address for symbol in path_with_symbols] | |
quote_token = token_by_symbol[path_with_symbols[-1]] | |
base_token = token_by_symbol[path_with_symbols[0]] | |
out_quantity = int(quote_token_qty * 10 ** quote_token.decimals) | |
block_identifier: Union[Literal['latest'], int] = block_number if block_number else 'latest' | |
in_quantity = vvs_contract.functions.getAmountsIn(out_quantity, path).call(block_identifier=block_identifier)[0] | |
sell_price = quote_token_qty / (in_quantity / 10**base_token.decimals) | |
return sell_price | |
if __name__ == "__main__": | |
""" | |
Usage examples | |
""" | |
block_number = 2940370 | |
sample_block = w3_cro.eth.get_block(block_number) | |
print(f"block#: {block_number}, {datetime.utcfromtimestamp(sample_block.timestamp)}") | |
print(get_buy_price(["USDC", "SINGLE"], block_number=block_number, quote_token_qty=10000)) | |
block_number = 2940383 | |
sample_block = w3_cro.eth.get_block(block_number) | |
print(f"block#: {block_number}, {datetime.utcfromtimestamp(sample_block.timestamp)}") | |
print(get_buy_price(["USDT", "USDC", "SINGLE"], block_number=block_number, quote_token_qty=10000)) | |
block_number = 2940348 | |
sample_block = w3_cro.eth.get_block(block_number) | |
print(f"block#: {block_number}, {datetime.utcfromtimestamp(sample_block.timestamp)}") | |
print(get_sell_price(["SINGLE", "USDC"], block_number=block_number, quote_token_qty=10000)) | |
block_number = 2940395 | |
sample_block = w3_cro.eth.get_block(block_number) | |
print(f"block#: {block_number}, {datetime.utcfromtimestamp(sample_block.timestamp)}") | |
print(get_sell_price(["SINGLE", "USDC", "USDT"], block_number=block_number, quote_token_qty=10000)) | |
# Get latest | |
print(get_buy_price(["USDC", "SINGLE"])) # get the current buy price for the default amount (1000 USDC) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment