Whose wallet is this
Put a name to an Ethereum address with its label, the sources behind that label and its ENS name, in three calls.
Give it an address and it answers three questions with three routes: what is it
(/labels/batch with a one-element list), who says so
(/labels/{address}/provenance), and does it have a name
(/wallets/{address}/ens).
export VIKE_API_KEY=...
python oc-whose-wallet.py # the default address is vitalik.eth's
python oc-whose-wallet.py 0x28C6c06298d514Db089934071355E5743bf21d60
python oc-whose-wallet.py --dry-run # prints the requests it would make, calls nothing"""Put a name to an Ethereum address: label, who said so, and its ENS name.
Run: VIKE_API_KEY=... python oc-whose-wallet.py [0xADDRESS] (--dry-run lists the requests and makes none)
"""
import os
import sys
from urllib.parse import urlencode
NAME = "oc-whose-wallet"
BASE = "https://data.vike.io"
DRY = "--dry-run" in sys.argv
ARGS = [a for a in sys.argv[1:] if not a.startswith("--")]
WALLET = ARGS[0] if ARGS else "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
def fail(why):
sys.exit(f"{NAME}: {why}")
def call(path, method="GET", **params):
url = BASE + path + ("?" + urlencode(params) if params else "")
if DRY:
print(method, url)
return None
key = os.environ.get("VIKE_API_KEY") or fail("set VIKE_API_KEY")
import requests
r = requests.request(method, url, headers={"X-API-Key": key}, timeout=60)
if r.status_code != 200:
fail(f"{method} {path} answered HTTP {r.status_code}: {r.text[:200]}")
return r.json()
def main():
# A POST with no body; one address is a one-element list. An address that is not valid comes back as [].
batch = call("/v1/onchain/labels/batch", method="POST", addresses=WALLET)
# Who said it: the consensus plus every source's own claim. A thin list can mean a source is rebuilding.
prov = call(f"/v1/onchain/labels/{WALLET}/provenance")
# Reverse ENS. source says which path answered: local (our store) or rpc (a fresh lookup).
ens = call(f"/v1/onchain/wallets/{WALLET}/ens")
if DRY:
return
if not batch:
fail(f"{WALLET} is not a valid address")
row = batch[0]
print(f"{WALLET}")
if row["found"]:
print(f" label {row['entity']} ({row['wallet_type']}), confidence {row['confidence']}")
print(f" 30 days ${row['volume_30d_usd']:,.0f} volume, {row['tx_30d']} txs, risk flag {row['risk_flag'] or 'none'}")
else:
print(" label none on record")
claims = "; ".join(s["label"] for s in prov.get("sources", []))
print(f" sources {prov.get('source_count', 0)}: {claims or 'none name it'}")
name = ens["ens"]
if name:
print(f" ens {name}")
elif ens["source"] == "rpc":
print(" ens none found, but an rpc miss may only mean the resolvers were unreachable: retry before concluding")
else:
print(" ens no name set")
if __name__ == "__main__":
try:
main()
except Exception as e: # a shape the recipe does not expect fails by name, not by traceback
fail(f"{type(e).__name__}: {e}")Read it this way
- A malformed address comes back as
[]./labels/batchanswers a batch whose every address is malformed with a200and an empty array, so the script checks the length as well as the status. found: falseis not a failure. The address has no label row; the script prints "none on record".risk_flagis the empty string when clean, so the script tests truthiness.- Sources speak for themselves. Each claim is printed in its source's own words, and they can disagree:
vitalik.ethdrew "Vitalik Buterin" and "sushiswap" on 2026-10-19. The provenance route also returns fewer rows rather than failing when a label source is mid-rebuild, so re-query a thin list before concluding.
An ENS miss over rpc is not proof of no name
source says which path answered. local with ens: null is a recorded fact: the address was resolved and has
no name. rpc with ens: null may only mean every resolver was unreachable, and it still comes back as a 200.
The script prints that case differently; retry before treating the address as unnamed.
Measure quoted spreads with DuckDB
Download one day of BTC 5-minute top-of-book quotes from the archive and compute median and p90 spread per token with DuckDB.
Find who is buying a token, and who they are
Screen Ethereum tokens for smart-money inflow, take the top token's biggest buyers and label them in one batch call, flagging the ones that are not exchanges, protocols or bots.