CPRCPR ENS Toolkit Document 5 of 6
CPR ENS Toolkit · Developer Toolkit

Scripts to do it faster

Everything in this toolkit can be done by hand. But if you are comfortable running a command or two, these small Python scripts make it quick and exact — pinning a page as a canonical bafkrei CID, and generating your seven records without a single typo. No private keys, ever.

01Download the scripts

cpr-dev-scripts.zip
3 Python scripts + README · no dependencies beyond requests
Download

What you need first

Python 3 installed (on Windows, tick "Add Python to PATH" during install), and one library. In a terminal:

pip install requests

You will also need a Pinata JWT — see Document 2 for how to create one.

02pinata_upload.py — pin one page

Pins a single HTML file and returns a canonical bafkrei CID. The key line is options = {"cidVersion": 1} — that is what makes the CID bafkrei instead of the bafybei you get from the website. The script also warns you if the result is not bafkrei.

pinata_upload.py
#!/usr/bin/env python3
"""
CPR ENS Toolkit — Pinata upload (single file)
=============================================
Pins ONE HTML file to IPFS and returns a canonical bafkrei... CID.

WHY THIS SCRIPT (and not just the Pinata website):
  The website's upload gives you a bafybei... CID. This script forces
  cidVersion:1, which gives you a bafkrei... CID — the canonical CPR
  format. Both resolve, but bafkrei is the CPR standard.

USAGE:
  1. Paste your Pinata JWT below (between the quotes).
  2. pip install requests
  3. python pinata_upload.py yourpage.html
  4. It prints your CID and the exact ipfs://... line to paste into
     your ENS name's Content Hash field.

Your JWT is a secret — never share this file with the JWT filled in.
"""
import os, json, sys

# ---- paste your Pinata JWT between the quotes ----
PINATA_JWT = "PASTE_YOUR_JWT_HERE"
# --------------------------------------------------

PIN_ENDPOINT = "https://api.pinata.cloud/pinning/pinFileToIPFS"


def main():
    try:
        import requests
    except ImportError:
        sys.exit("Run:  pip install requests   then try again.")

    if PINATA_JWT == "PASTE_YOUR_JWT_HERE" or not PINATA_JWT.strip():
        sys.exit("Paste your Pinata JWT into PINATA_JWT first.")

    if len(sys.argv) < 2:
        sys.exit("Usage:  python pinata_upload.py yourpage.html")

    path = sys.argv[1]
    if not os.path.exists(path):
        sys.exit(f"File not found: {path}")

    name = os.path.basename(path)
    headers = {"Authorization": f"Bearer {PINATA_JWT}"}

    with open(path, "rb") as fh:
        files = {"file": (name, fh, "text/html")}
        meta = {"name": name}
        options = {"cidVersion": 1}            # <-- forces bafkrei... CIDs
        data = {
            "pinataMetadata": json.dumps(meta),
            "pinataOptions": json.dumps(options),
        }
        r = requests.post(PIN_ENDPOINT, headers=headers, files=files, data=data, timeout=60)

    if r.status_code == 200:
        cid = r.json()["IpfsHash"]
        print(f"\n  Pinned: {name}")
        print(f"  CID:    {cid}")
        if not cid.startswith("bafkrei"):
            print("  [WARNING] CID is not bafkrei — check that cidVersion:1 is set.")
        print(f"\n  Paste this into your ENS name's Content Hash field:")
        print(f"  ipfs://{cid}\n")
    else:
        sys.exit(f"  ERROR {r.status_code}: {r.text[:200]}")


if __name__ == "__main__":
    main()

Run it

python pinata_upload.py yourpage.html

It prints your CID and the exact ipfs://... line to paste into your name's Content Hash field.

Your JWT is a secret. Never share this file with the JWT pasted in. If it leaks, revoke it in Pinata and make a new one.

03records_helper.py — generate your 7 records

Builds the seven CPR record values for your name, ready to paste into the ENS app. It does not touch the blockchain and never asks for a private key — you set and sign the records yourself in the ENS app, which is the safe way.

records_helper.py
#!/usr/bin/env python3
"""
CPR ENS Toolkit — Records generator
===================================
Builds the seven canonical CPR records for a name, ready to paste into
the ENS app. It does NOT touch the blockchain and never asks for a
private key — you set and sign the records yourself in the ENS app,
which is the safe way.

USAGE:
  python records_helper.py <name> <hyphenated-root> <VERTICAL>

EXAMPLE:
  python records_helper.py agenticorchestrator agentic-orchestrator DEV.ORCHESTRATOR

  ...prints:
     cat       dev-infrastructure
     type      agentic-orchestrator-root
     purpose   canonical-agentic-orchestrator
     rights    lease-eligible
     mapping   inheritance:infra
     schema    ensv2-taxonomy-v1
     vertical  DEV.ORCHESTRATOR

NOTES:
  - <name>            : your name without .eth   (e.g. agenticorchestrator)
  - <hyphenated-root> : the same name with word breaks (e.g. agentic-orchestrator)
  - <VERTICAL>        : the CPR vertical in dot form, UPPERCASE (e.g. DEV.ORCHESTRATOR)
  Get your vertical and the correct hyphenation from the CPR ENS Scorer —
  it shows all seven values for any T8+ name already.
"""
import sys

SCHEMA = "ensv2-taxonomy-v1"
MAPPING = "inheritance:infra"
RIGHTS = "lease-eligible"


def build_records(name, hyphenated, vertical):
    family = vertical.split(".")[0].lower()      # CHAIN.L2.DA -> chain
    return {
        "cat":      f"{family}-infrastructure",
        "type":     f"{hyphenated}-root",
        "purpose":  f"canonical-{hyphenated}",
        "rights":   RIGHTS,
        "mapping":  MAPPING,
        "schema":   SCHEMA,
        "vertical": vertical.upper(),
    }


def main():
    if len(sys.argv) != 4:
        sys.exit("Usage: python records_helper.py <name> <hyphenated-root> <VERTICAL>")
    name, hyphenated, vertical = sys.argv[1], sys.argv[2], sys.argv[3]
    recs = build_records(name, hyphenated, vertical)
    print(f"\n  Seven records for {name}.eth")
    print(f"  (paste each key/value as a Text record in the ENS app)\n")
    for k, v in recs.items():
        print(f"     {k:9} {v}")
    print("\n  Then set Content Hash separately to your ipfs://... CID.\n")


if __name__ == "__main__":
    main()

Run it

python records_helper.py agenticorchestrator agentic-orchestrator DEV.ORCHESTRATOR

It prints all seven records. Get your vertical and the correct word-break from the CPR ENS Scorer — it already shows all seven for any T8+ name.

Why no on-chain script? Setting records on-chain from a script would require pasting your wallet's private key into code — a common way people get drained. We will not teach that. Generate the values here, then set and sign them safely in the ENS app.

04cpr_batch_upload.py — many pages at once (advanced)

If you manage a portfolio of names, the download includes a batch version — the same script CPR uses to pin its own redirect files. Put your HTML files in a ./redirects folder named <name>.html, list them in the script, and it pins them all (still cidVersion:1, still checking for bafkrei), writing a cids.json table. It is in the zip as cpr_batch_upload.py.

05The whole flow

Put together with the rest of the toolkit:

1. Make your page (Document 4 starter template) 2. python pinata_upload.py yourpage.html -> CID 3. python records_helper.py ... -> 7 records 4. ENS app: set 7 records + contenthash, sign once 5. open yourname.eth.limo -> live
That is the full developer path. The last document is a one-page Quick Reference — every value, command, and link in one place to keep handy.
canonicalprotocolregistry.com  ·  © Craig Vsetula LLC · USPTO #99766227