From nostr-protocol/nips#2332 (comment)
I'm not confident I could submit a PR adding this without breaking your original... but do you think ChatGPT or another could do it correctly if I just provide the URLs to this & the .py & say some magic words?
Hopefully get it on https://openetr.org/bitcoin/check-balance as its own box beneath Taproot Wallet Details, formatted much the same way?
Full Reference Implementation (Python)
import hashlib
import base58
from Crypto.Hash import RIPEMD160
from bech32 import bech32_encode, convertbits
# -----------------------------
# HASH160 (Bitcoin standard)
# -----------------------------
def hash160(data: bytes) -> bytes:
sha = hashlib.sha256(data).digest()
ripemd = RIPEMD160.new()
ripemd.update(sha)
return ripemd.digest()
# -----------------------------
# x-only -> compressed pubkey
# -----------------------------
def xonly_to_compressed_pubkey(xonly_pubkey: bytes) -> bytes:
"""
Deterministic compatibility rule:
Prefix x-only secp256k1 pubkey with 0x02 (even-y assumption)
to produce a valid compressed ECDSA public key.
This is a convention ONLY and not a reconstruction of the
original elliptic curve point.
"""
if len(xonly_pubkey) != 32:
raise ValueError("Invalid x-only pubkey length")
return b"\x02" + xonly_pubkey
# -----------------------------
# P2PKH (legacy)
# -----------------------------
def pubkey_to_p2pkh(pubkey: bytes) -> str:
h160 = hash160(pubkey)
payload = b"\x00" + h160 # mainnet version byte
checksum = hashlib.sha256(
hashlib.sha256(payload).digest()
).digest()[:4]
return base58.b58encode(payload + checksum).decode()
# -----------------------------
# P2WPKH (SegWit v0)
# -----------------------------
def pubkey_to_p2wpkh(pubkey: bytes) -> str:
h160 = hash160(pubkey)
data = [0] + convertbits(h160, 8, 5)
return bech32_encode("bc", data)
# -----------------------------
# Compatibility API
# -----------------------------
def nostr_xonly_to_legacy_bitcoin_addresses(xonly_pubkey: bytes) -> dict:
"""
Optional compatibility layer.
Not part of Taproot or core Nostr semantics.
Provides deterministic legacy Bitcoin address derivation
from x-only secp256k1 pubkeys.
"""
compressed_pubkey = xonly_to_compressed_pubkey(xonly_pubkey)
return {
"compressed_pubkey_hex": compressed_pubkey.hex(),
"p2pkh": pubkey_to_p2pkh(compressed_pubkey),
"p2wpkh": pubkey_to_p2wpkh(compressed_pubkey),
}
And... probably out of scope for your website if you wouldn't want to be touching nsecs+passphrases and/or nobody would want to risk putting them in your site, but there's also hardening them via salting.
From nostr-protocol/nips#2332 (comment)
I'm not confident I could submit a PR adding this without breaking your original... but do you think ChatGPT or another could do it correctly if I just provide the URLs to this & the .py & say some magic words?
Hopefully get it on https://openetr.org/bitcoin/check-balance as its own box beneath Taproot Wallet Details, formatted much the same way?
Full Reference Implementation (Python)
And... probably out of scope for your website if you wouldn't want to be touching nsecs+passphrases and/or nobody would want to risk putting them in your site, but there's also hardening them via salting.