"""Watch-only wallets with BIP32 public (CKDpub) derivation.

Exports an account-level xpub, imports it on a hypothetical online system, and
derives receive addresses without any private key. Public derivation reproduces
exactly the same addresses that private derivation would produce.
"""
from libcrypto import HDNode, HDWallet, PublicKey


def main() -> None:
    seed = bytes.fromhex("000102030405060708090a0b0c0d0e0f")
    wallet = HDWallet(seed)

    # Offline: derive the hardened account node and export only its xpub.
    account = wallet.derive_from_path("m/44'/0'/0'")
    account_xpub = account.neuter().serialize_public()
    print("Account xpub:", account_xpub)

    # Online (watch-only): import the xpub, derive external chain addresses.
    watch_only = HDNode.deserialize(account_xpub)
    assert watch_only.is_private is False

    external_chain = watch_only.derive_child(0)  # m/44'/0'/0'/0
    print("\nWatch-only receive addresses:")
    for index in range(3):
        public_child = external_chain.derive_child(index)
        address = PublicKey(public_child.public_key).get_address("p2pkh", "bitcoin")
        print(f"  m/44'/0'/0'/0/{index}: {address}")

        # Confirm it matches full private derivation.
        private_child = wallet.derive_from_path(f"m/44'/0'/0'/0/{index}")
        assert public_child.public_key == private_child.public_key

    print("\nWatch-only public derivation matches private derivation.")


if __name__ == "__main__":
    main()
