Last active
July 31, 2019 14:04
-
-
Save godsflaw/24a70331ebb06ef4df0807f1a2315531 to your computer and use it in GitHub Desktop.
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
#!/usr/bin/env python3 | |
import json | |
import click | |
import appdirs | |
import requests | |
from pathlib import Path | |
from graphqlclient import GraphQLClient | |
from web3.auto import w3 | |
# | |
# WEB3_PROVIDER_URI=https://parity.expotrading.com/ | |
# | |
TUB = '0x448a5065aebb8e423f0896e6c5d525c040f59af3' | |
GQLURL = 'https://sai-mainnet.makerfoundation.com/v1' | |
QUERY = ''' | |
{ | |
allCups(condition: {deleted: false}, filter: {art: {greaterThan: "1.00"}}, orderBy: ID_ASC) { | |
nodes { | |
id | |
ire | |
art | |
} | |
} | |
} | |
''' | |
cache = Path(appdirs.user_cache_dir('contracts')) | |
cache.mkdir(exist_ok=True) | |
def to_32byte_hex(val): | |
return w3.toHex(w3.toBytes(val).rjust(32, b'\0')) | |
def wad(val): | |
return val/1000000000000000000000000000 | |
def get_contract(address): | |
'''Get contract interface and cache it.''' | |
f = cache / f'{address}.json' | |
if not f.exists(): | |
# cache the response | |
abi = get_contract_abi(address) | |
f.write_text(json.dumps(abi)) | |
abi = json.loads(f.read_text()) | |
return w3.eth.contract(w3.toChecksumAddress(address), abi=abi) | |
def get_contract_abi(address): | |
'''Get contract interface from Etherscan.''' | |
resp = requests.get('http://api.etherscan.io/api', params={ | |
'module': 'contract', | |
'action': 'getabi', | |
'format': 'raw', | |
'address': address, | |
}) | |
try: | |
return resp.json() | |
except json.JSONDecodeError: | |
return | |
def output_cdp_sf_over_liquidation(cdps): | |
'''output cdps with SF over the liquidation penalty of 13% in red''' | |
tub = get_contract(TUB) | |
click.secho( | |
f'{"id":>6} {"◈ Debt":>12} {"◈ LP":>12} {"◈ Fee":>12}', | |
fg='cyan', | |
bold=True | |
) | |
click.secho( | |
f'==============================================', | |
fg='cyan', | |
bold=True | |
) | |
for cdp in cdps: | |
uncollected_fees = 0.0 | |
uncollected_fees = 0.0 | |
debt = float(cdp["art"]) | |
lp = debt * 0.13 | |
ire = float(cdp["ire"]) | |
rhi = wad(tub.functions.rhi().call()) | |
fee = (ire * rhi) - debt; | |
if fee <= lp: | |
click.secho( | |
f'{cdp["id"]:>6}: {debt:>12,.2f} {lp:>12,.2f} {fee:>12,.2f}', | |
fg='green' if fee/lp <= .75 else 'yellow', | |
bold=True | |
) | |
else: | |
uncollected_fees += (fee - lp); | |
click.secho( | |
f'{cdp["id"]:>6}: {debt:>12,.2f} {lp:>12,.2f} {fee:>12,.2f}', | |
fg='orange' if lp/fee >= .1 else 'red', | |
bold=True | |
) | |
click.secho( | |
f'==============================================', | |
fg='cyan', | |
bold=True | |
) | |
click.secho( | |
f'Uncollected Fees: ◈{uncollected_fees}DAI', | |
fg='green' if uncollected_fees == 0.0 else 'red', | |
bold=True | |
) | |
def main(): | |
client = GraphQLClient(GQLURL) | |
result = client.execute(QUERY) | |
data = json.loads(result) | |
output_cdp_sf_over_liquidation(data["data"]["allCups"]["nodes"]) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
run with:
colors: