Skip to content
This repository was archived by the owner on Dec 16, 2022. It is now read-only.

Commit 22eb4a1

Browse files
authored
Merge pull request #8 from forkdelta/v2
V2
2 parents a73bdea + 6815c3c commit 22eb4a1

File tree

1,838 files changed

+169928
-54278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,838 files changed

+169928
-54278
lines changed

scripts/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.6-alpine
1+
FROM python:3.8-alpine3.11
22

33
WORKDIR /usr/src/scripts
44

scripts/build_json.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
import json
33
import yaml
44

5-
from helpers import read_entry
5+
from entry_io import read_entry
66

7-
INDEX_KEYS = ["id", "address", "name", "symbol", "website_slug"]
7+
INDEX_KEYS = ["id", "address", "name", "symbol", "slug", "status", "rank"]
88

99

1010
def abridged_entry(entry):
11-
return {k: entry[k] for k in INDEX_KEYS}
11+
return {k: entry.get(k) for k in INDEX_KEYS}
1212

1313

1414
if __name__ == "__main__":

scripts/convert_v1_v2.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from glob import glob
2+
from itertools import groupby
3+
import re
4+
5+
from entry_io import (read_entry, write_token_entry)
6+
7+
OVERRIDES = {"Technical Documentation": "technical_doc"}
8+
9+
10+
def update_key_format(k):
11+
human_k = re.sub(r' (\d+)$', '', k)
12+
return OVERRIDES.get(human_k, human_k.lower().replace(' ', '_'))
13+
14+
15+
def convert_links(links):
16+
link_tuples = [(update_key_format(k), v) for (k, v) in links.items()]
17+
return {
18+
group_name: [value for (_, value) in name_value_tuples]
19+
for (group_name, name_value_tuples
20+
) in groupby(sorted(link_tuples), key=lambda e: e[0])
21+
}
22+
23+
24+
entry_files = sorted(glob("tokens/0x*.yaml"))
25+
for entry in (read_entry(fn) for fn in entry_files):
26+
address = entry.pop("address")
27+
entry.update({
28+
"markets": [],
29+
"links": convert_links(entry['links']),
30+
})
31+
if "tags" in entry:
32+
del entry["tags"]
33+
del entry["website_slug"]
34+
write_token_entry(address, entry)

scripts/entry_io.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import yaml
2+
3+
YAML_WIDTH = 100
4+
YAML_INDENT = 2
5+
6+
7+
def read_entry(fn):
8+
with open(fn) as infile:
9+
return yaml.safe_load(infile)
10+
11+
12+
def write_token_entry(address, listing):
13+
with open("tokens/{}.yaml".format(address), "w") as outfile:
14+
outfile.write(
15+
yaml.dump(
16+
dict(
17+
address=address,
18+
**{k: v
19+
for (k, v) in listing.items() if v}),
20+
explicit_start=True,
21+
width=YAML_WIDTH,
22+
indent=YAML_INDENT,
23+
default_flow_style=False,
24+
allow_unicode=True))
25+
26+
27+
def update_token_entry(address, partial_update):
28+
old_listing = read_entry("tokens/{}.yaml".format(address))
29+
old_listing.update(partial_update)
30+
del old_listing["address"]
31+
write_token_entry(address, old_listing)

scripts/generate.py

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
import logging
44
import requests
55

6-
from helpers import (DEFAULT_HEADERS, process_listing, read_entry,
7-
write_token_entry)
6+
from helpers import (DEFAULT_HEADERS, process_listing)
7+
from entry_io import (read_entry, write_token_entry, update_token_entry)
88

99
CMC_LISTINGS_API_URL = "https://api.coinmarketcap.com/v2/listings/"
1010

1111

12-
def get_listings():
12+
def get_api_listings():
1313
"""
1414
Returns a list of CoinMarketCap-listed currencies via /v2/listings/ API endpoint.
1515
@@ -20,12 +20,12 @@ def get_listings():
2020
return r.json()["data"]
2121

2222

23-
def map_existing_entries(files, exclude_deprecated=True):
23+
def map_entries_to_sets(files, key, exclude_deprecated=True):
2424
"""
25-
Returns a hash keyed by CoinMarketCap asset ID with sets of Ethereum addresses
26-
known to be associated with that asset ID.
25+
Returns a dict keyed by CoinMarketCap asset ID with sets of values for
26+
the given key known to be associated with that asset ID.
2727
"""
28-
entries = ((entry["id"], entry["address"])
28+
entries = ((entry["id"], entry[key])
2929
for entry in (read_entry(fn) for fn in files)
3030
if not (exclude_deprecated and entry.get("_DEPRECATED", False)))
3131

@@ -35,46 +35,71 @@ def map_existing_entries(files, exclude_deprecated=True):
3535
}
3636

3737

38-
def deprecate_token_entry(address):
39-
old_listing = read_entry("tokens/{}.yaml".format(address))
40-
old_listing.update({"_DEPRECATED": True})
41-
del old_listing["address"]
42-
write_token_entry(address, old_listing)
38+
def map_entries_to_discrete(files, key, exclude_deprecated=True):
39+
return {
40+
entry["id"]: entry[key]
41+
for entry in (read_entry(fn) for fn in files)
42+
if not (exclude_deprecated and entry.get("_DEPRECATED", False))
43+
}
4344

4445

45-
def main(listings):
46+
def main():
4647
from time import sleep
4748

48-
id_to_address = map_existing_entries(sorted(glob("tokens/0x*.yaml")))
49+
existing_files = sorted(glob("tokens/0x*.yaml"))
50+
id_to_addresses = map_entries_to_sets(existing_files, "address")
51+
slugs = map_entries_to_discrete(existing_files, "slug")
52+
53+
api_listings = get_api_listings()
54+
api_slugs = {e["id"]: e["website_slug"] for e in api_listings}
55+
56+
slugs.update(api_slugs)
4957

50-
for listing in listings:
58+
for (asset_id, asset_website_slug) in slugs.items():
5159
try:
52-
result = process_listing(listing)
60+
result = process_listing(asset_website_slug)
5361
except:
5462
logging.exception(
5563
"Final error when trying to process listing for '%s'",
56-
listing["website_slug"])
64+
asset_website_slug)
5765
continue
5866

59-
(updated_listing, current_addresses) = result
60-
61-
existing_addresses = id_to_address.get(listing["id"], set())
62-
for address in existing_addresses - current_addresses:
63-
logging.warning("'%s' has deprecated %s", listing["website_slug"],
64-
address)
65-
deprecate_token_entry(address)
67+
(listing, current_addresses) = result
68+
69+
if listing:
70+
assert listing["id"] == asset_id
71+
72+
if asset_website_slug != listing["slug"]:
73+
logging.warning("'%s' redirected to slug '%s' when queried",
74+
asset_website_slug, listing['slug'])
75+
76+
existing_addresses = id_to_addresses.get(asset_id, set())
77+
# Deal with delisted assets and deprecated addresses
78+
if existing_addresses and listing is None:
79+
# listing is None when the page failed to fetch (404ed)
80+
logging.warning("'%s' has been delisted", asset_website_slug)
81+
for address in existing_addresses:
82+
update_token_entry(address, {
83+
"status": "delisted",
84+
"markets": [],
85+
"rank": None
86+
})
87+
else:
88+
for address in existing_addresses - current_addresses:
89+
logging.warning("'%s' has deprecated %s", asset_website_slug,
90+
address)
91+
update_token_entry(
92+
address, {
93+
"_DEPRECATED": True,
94+
"status": "deprecated",
95+
"markets": [],
96+
"rank": None
97+
})
6698

6799
for address in current_addresses:
68-
write_token_entry(address, updated_listing)
69-
70-
listings_ids = [e["id"] for e in listings]
71-
ids_removed_from_listings = id_to_address.keys() - listings_ids
72-
for removed_id in ids_removed_from_listings:
73-
for removed_asset_address in id_to_address[removed_id]:
74-
deprecate_token_entry(removed_asset_address)
100+
write_token_entry(address, listing)
75101

76102

77103
if __name__ == "__main__":
78104
logging.getLogger().setLevel(logging.DEBUG)
79-
80-
main(get_listings())
105+
main()

0 commit comments

Comments
 (0)