@thurinlabs/identity-kit 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MYKKWPBY.cjs → chunk-7XL2ZMIT.cjs} +41 -24
- package/dist/chunk-7XL2ZMIT.cjs.map +1 -0
- package/dist/{chunk-4H57JHDJ.js → chunk-M4OVDLXW.js} +40 -23
- package/dist/chunk-M4OVDLXW.js.map +1 -0
- package/dist/core.cjs +4 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +35 -4
- package/dist/core.d.ts +35 -4
- package/dist/core.js +3 -1
- package/dist/embed.global.js +26 -17
- package/dist/embed.global.js.map +1 -1
- package/dist/index.cjs +29 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-4H57JHDJ.js.map +0 -1
- package/dist/chunk-MYKKWPBY.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/abi.ts","../src/core/contract.ts","../src/core/fingerprint.ts","../src/core/pgp.ts","../src/core/efp.ts","../src/core/proofs.ts","../src/core/ensHint.ts","../src/core/authorization.ts","../src/core/records.ts"],"sourcesContent":["// Generated from pgp-registry: `forge inspect PGPRegistry abi --json`. Do not edit by hand.\nexport const REGISTRY_ABI = [\n {\n \"type\": \"function\",\n \"name\": \"ATTEST_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"DOMAIN_SEPARATOR\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"EIP712_NAME\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"string\",\n \"internalType\": \"string\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"EIP712_VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"string\",\n \"internalType\": \"string\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_KEY_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_RECORD_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_SIG_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MESSAGE_VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"REATTEST_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"REVOKE_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"SET_RECORD_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"UPDATE_KEY_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesFor\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"address[]\",\n \"internalType\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesForCount\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesForRange\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"address[]\",\n \"internalType\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attest\",\n \"inputs\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationCount\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationsOf\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct PGPRegistry.Attestation[]\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationsOfRange\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct PGPRegistry.Attestation[]\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"cancelAuthorization\",\n \"inputs\": [],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"current\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"found\",\n \"type\": \"bool\",\n \"internalType\": \"bool\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"attestation\",\n \"type\": \"tuple\",\n \"internalType\": \"struct PGPRegistry.Attestation\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyId\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes[]\",\n \"internalType\": \"bytes[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyIdCount\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyIdRange\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"bytes[]\",\n \"internalType\": \"bytes[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"getAttestation\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"tuple\",\n \"internalType\": \"struct PGPRegistry.Attestation\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"getPayload\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"nonces\",\n \"inputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"reattest\",\n \"inputs\": [\n {\n \"name\": \"revokeIndex\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"reattestFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"revokeIndex\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"record\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"revoke\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"revokeFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"setRecord\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"value\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"setRecordFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"value\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"updateKey\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"updateKeyFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"event\",\n \"name\": \"Attested\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"indexed\": false,\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"indexed\": false,\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"KeyUpdated\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"oldKeyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"newKeyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"NonceUsed\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"nonce\",\n \"type\": \"uint256\",\n \"indexed\": false,\n \"internalType\": \"uint256\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"RecordSet\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"Revoked\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"error\",\n \"name\": \"AlreadyRevoked\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"AuthorizationExpired\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"DeploymentFailed\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"DuplicateActiveFingerprint\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"EmptyPublicKey\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"EmptySignature\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"IndexOutOfBounds\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidAuthorization\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidFingerprintLength\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidPointer\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"PublicKeyTooLarge\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"RecordTooLarge\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"SignatureTooLarge\",\n \"inputs\": []\n }\n] as const\n","import { mainnet, sepolia, foundry } from 'viem/chains'\nexport { REGISTRY_ABI } from './abi'\n\n/**\n * PGPRegistry v2 is deployed with CREATE2, so it has the same address on every\n * network. (v1 lived at 0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb on mainnet and\n * is no longer read by Thurin.)\n */\nexport const REGISTRY_ADDRESS = '0x9302E02e2869e129aC8516fE5eFFd51EA3082c09' as const\n\n/** Networks the PGPRegistry is deployed on. `mainnet` is the default everywhere. */\nexport type NetworkName = 'mainnet' | 'sepolia' | 'local'\n\nexport interface RegistryDeployment {\n chainId: number\n address: `0x${string}`\n /** Block the registry was deployed in (informational; v2 needs no log scans). */\n deployBlock: bigint\n /** Block explorer base URL for address/tx links. Empty when there is none. */\n explorerUrl: string\n /** Keyless public RPC used when no rpcUrl is configured. */\n defaultRpcUrl: string\n}\n\nexport const NETWORKS: Record<NetworkName, RegistryDeployment> = {\n mainnet: {\n chainId: 1,\n address: REGISTRY_ADDRESS,\n deployBlock: 25962908n, // 2026-09-12, tx 0xda4c3a19cae4e71ffb02559a048403f664d5a7967c19d42158c39600ec63bad8\n explorerUrl: 'https://etherscan.io',\n defaultRpcUrl: 'https://ethereum.publicnode.com', // same service as ethereum-rpc.publicnode.com; this hostname resolves on more networks\n },\n sepolia: {\n chainId: 11155111,\n address: REGISTRY_ADDRESS,\n deployBlock: 11683667n, // 2026-09-11, tx 0x3e40e8f5b9fbf82a4b8943561bcc9b964b2987de10640ac8ff3a1b4ef0725322\n explorerUrl: 'https://sepolia.etherscan.io',\n defaultRpcUrl: 'https://ethereum-sepolia.publicnode.com',\n },\n /** A local anvil instance (`anvil`, chain id 31337). Deploy with pgp-registry's Deploy script. */\n local: {\n chainId: 31337,\n address: REGISTRY_ADDRESS,\n deployBlock: 0n,\n explorerUrl: '',\n defaultRpcUrl: 'http://127.0.0.1:8545',\n },\n}\n\nexport function isNetworkName(value: unknown): value is NetworkName {\n return value === 'mainnet' || value === 'sepolia' || value === 'local'\n}\n\n/**\n * The registry deployment for a network. `addressOverride` swaps the contract\n * address (e.g. a local deploy that landed somewhere else).\n */\nexport function getRegistry(network: NetworkName = 'mainnet', addressOverride?: string): RegistryDeployment {\n const r = NETWORKS[network]\n if (!r) throw new Error(`Unknown network: ${network}`)\n if (addressOverride && /^0x[0-9a-fA-F]{40}$/.test(addressOverride)) {\n return { ...r, address: addressOverride as `0x${string}` }\n }\n return r\n}\n\n/** The viem chain object for a network name. */\nexport function chainFor(network: NetworkName = 'mainnet') {\n if (network === 'sepolia') return sepolia\n if (network === 'local') return foundry\n return mainnet\n}\n","import { keccak256, type Hex } from 'viem'\n\n/** 40 hex chars (OpenPGP v4) or 64 hex chars (v6), spaces/0x tolerated. */\nconst FINGERPRINT_HEX = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/\n\n/** Normalize a fingerprint to lowercase hex with no prefix or spaces. Returns null if malformed. */\nexport function normalizeFingerprint(input: string): string | null {\n const hex = input.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase()\n return FINGERPRINT_HEX.test(hex) ? hex : null\n}\n\n/** Fingerprint → the raw `bytes` argument the v2 registry takes (0x-prefixed, 20 or 32 bytes). */\nexport function fingerprintToBytes(fingerprint: string): Hex {\n const hex = normalizeFingerprint(fingerprint)\n if (!hex) throw new Error(`Invalid PGP fingerprint: ${fingerprint}`)\n return `0x${hex}`\n}\n\n/** Raw `bytes` from the registry → lowercase hex fingerprint without 0x. */\nexport function bytesToFingerprint(bytes: Hex | string): string {\n return bytes.replace(/^0x/i, '').toLowerCase()\n}\n\n/** keccak256 of the raw fingerprint bytes — the `fingerprintHash` the registry indexes by. */\nexport function fingerprintHash(fingerprint: string): Hex {\n return keccak256(fingerprintToBytes(fingerprint))\n}\n\n/**\n * The long key ID as the `bytes8` the registry indexes by. Per RFC 9580 §5.5.4 it is the\n * low-order 8 bytes of a v4 (20-byte) fingerprint and the high-order 8 bytes of a v6\n * (32-byte) fingerprint — the same value `gpg --keyid-format long` prints.\n */\nexport function keyIdOf(fingerprint: string): Hex {\n const hex = normalizeFingerprint(fingerprint)\n if (!hex) throw new Error(`Invalid PGP fingerprint: ${fingerprint}`)\n return `0x${keyIdHex(hex)}`\n}\n\n/** Long key ID (16 lowercase hex chars) of a normalized fingerprint. */\nexport function keyIdHex(normalizedFingerprint: string): string {\n return normalizedFingerprint.length === 64 ? normalizedFingerprint.slice(0, 16) : normalizedFingerprint.slice(-16)\n}\n\n/** A 16-hex long key ID (spaces/0x tolerated) → `bytes8`. */\nexport function keyIdToBytes(keyId: string): Hex | null {\n const hex = keyId.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase()\n return /^[0-9a-f]{16}$/.test(hex) ? `0x${hex}` : null\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\n/**\n * openpgp.js refuses secp256k1 by default because RFC 9580 does not list the\n * curve — a compatibility choice, not a security one. A secp256k1 PGP key is a\n * valid key (and, incidentally, doubles as an Ethereum key: the address falls out\n * of the same public point). Thurin verifies signatures over any curve openpgp.js\n * can compute; whether a holder reuses such a key as a wallet is their business.\n * In Node, openpgp.js needs the optional `eckey-utils` package for this curve;\n * the browser build does not.\n *\n * The low-level packet/key methods take a *complete* config (they index into\n * it), so this builds one from the library's defaults rather than passing a\n * partial object.\n */\nfunction pgpConfig(openpgp: typeof import('openpgp')) {\n return { ...openpgp.config, rejectCurves: new Set() as Set<never> }\n}\n\n/** Human-readable algorithm for a key or subkey packet: \"Ed25519\", \"Cv25519\", \"RSA 4096\", \"NIST P-256\", … */\nfunction algorithmName(keyOrSubkey: any): string {\n try {\n const info = keyOrSubkey.getAlgorithmInfo() as { algorithm: string; bits?: number; curve?: string }\n const curve = (info.curve || '').toLowerCase()\n if (curve.startsWith('ed25519') || info.algorithm === 'ed25519' || info.algorithm === 'eddsaLegacy') return 'Ed25519'\n if (curve.startsWith('curve25519') || info.algorithm === 'x25519') return 'Cv25519'\n if (curve.startsWith('ed448')) return 'Ed448'\n if (curve.startsWith('curve448') || info.algorithm === 'x448') return 'X448'\n if (curve.startsWith('nistp') || curve.startsWith('p')) return `NIST P-${curve.replace(/\\D/g, '')}`\n if (curve.startsWith('secp')) return curve\n if (curve.startsWith('brainpool')) return curve\n if (info.algorithm.startsWith('rsa')) return info.bits ? `RSA ${info.bits}` : 'RSA'\n if (info.algorithm.startsWith('dsa')) return info.bits ? `DSA ${info.bits}` : 'DSA'\n if (info.algorithm.startsWith('elgamal')) return info.bits ? `ElGamal ${info.bits}` : 'ElGamal'\n return info.curve || info.algorithm\n } catch {\n return String(keyOrSubkey.keyPacket?.algorithm ?? 'unknown')\n }\n}\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const openpgp = await import('openpgp')\n const { readKey } = openpgp\n const config = pgpConfig(openpgp)\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const algorithm = algorithmName(key)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n // openpgp does not verify certification signatures when a key is parsed —\n // it groups them by issuer key ID only. A key's fingerprint also covers\n // only the primary key packet, not its user IDs or their certifications.\n // Each self-certification is therefore verified against the primary key\n // here before its user ID and notations are treated as authoritative.\n const userIDs: string[] = []\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n const certs = (user as any).selfCertifications\n if (!certs || certs.length === 0) continue\n\n let userVerified = false\n for (const cert of certs) {\n try {\n await cert.verify(\n key.keyPacket,\n cert.signatureType,\n { userID: (user as any).userID, key: key.keyPacket },\n undefined, // date: now\n undefined, // detached\n config,\n )\n } catch {\n continue // signature not made by this key — ignore this certification\n }\n userVerified = true\n\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n // Dedupe by value alone: the same proof target is often present\n // under both proof@thurin.id and proof@ariadne.id, and should\n // surface once, not once per namespace.\n if (!seen.has(value)) {\n seen.add(value)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n\n if (userVerified) {\n const uid = (user as any).userID?.userID\n if (uid) userIDs.push(uid)\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: algorithmName(sk),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const openpgp = await import('openpgp')\n const { readKey, readCleartextMessage, LiteralDataPacket } = openpgp\n const config = pgpConfig(openpgp)\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n\n // Verify the way gpg does: the key (or subkey) must be valid *now* — bound to\n // this primary, unrevoked, unexpired — and the signature must be sound. We\n // deliberately do not ask openpgp.verify(), which also demands the key was\n // valid at the instant the signature was made. Thurin's update flow tells\n // people to `export-minimal` after editing notations, which keeps only the\n // newest self-certification; when that postdates the attest signature\n // (Ben's own key, 2026-09-14: notations edited 16 minutes after signing),\n // openpgp.verify() reports \"Could not find valid self-signature\" for a\n // signature gpg verifies fine. A key that has since been revoked or expired\n // still fails here, as it should.\n // These are internals the .d.ts does not expose (the signature packet list,\n // the CRLF-normalised text, LiteralDataPacket.setText); they are stable across\n // openpgp.js 6 and exercised by the real-data tests in attestation.test.ts.\n const msg = message as any\n const now = new Date()\n let signed = false\n for (const sig of msg.signature.packets) {\n if (!publicKey.getKeys(sig.issuerKeyID).length) continue\n const signingKey = await publicKey.getSigningKey(sig.issuerKeyID, now, undefined, config)\n const literal: any = new LiteralDataPacket()\n literal.setText(msg.text ?? message.getText().replace(/\\r?\\n/g, '\\r\\n'))\n await sig.verify(signingKey.keyPacket, sig.signatureType, literal, now, true, config)\n signed = true\n break\n }\n if (!signed) return { verified: false, reason: 'Message is not signed by this key' }\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nexport interface StrippedKey {\n /** Armored public key containing only the non-email user IDs. */\n armored: string\n /** User IDs kept (no `@`). */\n kept: string[]\n /** User IDs removed (contained an `@`). */\n removed: string[]\n}\n\nconst EMAIL_UID = /@/\n\n/**\n * Remove every user ID that contains an email address, keeping the rest (and\n * their self-certifications, so proof notations on a non-email user ID survive).\n * Returns null when nothing would remain — openpgp needs at least one\n * self-certified user ID to verify signatures, so such a key must not be\n * published. The key material and subkeys are untouched; the fingerprint is\n * unchanged.\n */\nexport async function stripEmailUserIDs(armoredKey: string): Promise<StrippedKey | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const kept: string[] = []\n const removed: string[] = []\n const users = (key as any).users.filter((u: any) => {\n const uid: string | undefined = u.userID?.userID\n if (!uid) return false\n if (EMAIL_UID.test(uid)) { removed.push(uid); return false }\n kept.push(uid)\n return true\n })\n if (users.length === 0) return null\n ;(key as any).users = users\n return { armored: key.armor(), kept, removed }\n } catch {\n return null\n }\n}\n\n/** True when any user ID on the key contains an email address. */\nexport async function hasEmailUserID(armoredKey: string): Promise<boolean> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n return (key as any).users.some((u: any) => EMAIL_UID.test(u.userID?.userID ?? ''))\n } catch {\n return false\n }\n}\n","import type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\n/**\n * EFP social graph for an address. Followers are counted by EFP for any address,\n * whether or not it has published a list of its own; following and top-8 exist\n * only when it has (its \"primary list\"). An address with followers but no list\n * — a project account that has never followed anyone — is still on EFP.\n */\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const [statsResp, listsResp] = await Promise.all([\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/users/${address}/lists`),\n ])\n if (!statsResp.ok && !listsResp.ok) return null\n\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const listsData = listsResp.ok ? await listsResp.json() : {}\n const followers = parseInt(statsData.followers_count) || 0\n const listId = listsData.primary_list\n\n let following = 0\n let top8: string[] = []\n if (listId) {\n const [followingResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n following = (followingData.following || []).length\n top8 = (top8Data.following || []).map((f: any) => f.data)\n }\n\n return { followers, following, top8, hasEfp: !!listId || followers > 0 }\n } catch {\n return null\n }\n}\n","import { keyIdHex } from './fingerprint'\nimport type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n // A repository's description — the form an organisation can use, since\n // gists belong to user accounts only. Same shape as the Codeberg proof.\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/github\\.com\\/([A-Za-z0-9-]+)\\/([A-Za-z0-9._-]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n // domain is restricted to a hostname (labels may include underscores for\n // records like _thurin.example.com); rejects slashes, userinfo, and spaces.\n pattern: /^dns:([a-z0-9._-]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n // instance is restricted to a bare hostname (optional port) so a value\n // like \"mastodon.social@evil.com\" can't redirect the lookup elsewhere.\n pattern: /^https:\\/\\/([a-z0-9.-]+(?::\\d+)?)\\/@([^/@?#\\s]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (notation.name !== 'proof@thurin.id') return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n if (proof.repo) return verifyGitHubRepo(proof, fingerprint)\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n // A gist is identified solely by its globally-unique ID; the username in\n // the URL is not authoritative. Confirm the gist owner matches the claimed\n // account before trusting the token it contains.\n if (data.owner?.login?.toLowerCase() !== proof.user!.toLowerCase()) {\n return { verified: false, reason: 'Gist owner does not match claimed user' }\n }\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyGitHubRepo(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://api.github.com/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n // GitHub follows renames and redirects, so the API may answer for a repo\n // under a different owner than the URL names. Only trust it if the owner\n // is the account being claimed.\n if (data.owner?.login?.toLowerCase() !== proof.user!.toLowerCase()) {\n return { verified: false, reason: 'Repository owner does not match claimed account' }\n }\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Fingerprint token not found in repository description' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n // TXT records only (type 16) — a CNAME or other record in the resolution\n // chain must not be eligible to match the token.\n if (answer.type !== 16) continue\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n // A short cast-hash prefix can match multiple casts; keep scanning\n // rather than stopping at the first prefix match without the token.\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n // The instance host is user-supplied and interpolated into the request URL,\n // so restrict it to a bare hostname (optional port) before use — otherwise a\n // value such as \"mastodon.social@evil.com\" would send the lookup to another\n // server while still displaying as a legitimate handle.\n if (!proof.instance || !/^[a-z0-9.-]+(?::\\d+)?$/i.test(proof.instance)) {\n return { verified: false, reason: 'Invalid Mastodon instance host' }\n }\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = keyIdHex(fingerprint.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase())\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { namehash, normalize } from 'viem/ens'\nimport { normalizeFingerprint } from './fingerprint'\n\n/**\n * The `id.thurin` ENS text record: a name points at the PGP key claimed on the Thurin\n * registry by the address the name resolves to. It is a discovery hint, not part of the\n * trust chain — the name owner set the address, the address signed the claim, so a reader\n * verifies by resolving the name and reading the registry. The record only says where to\n * look. `id.thurin` is a service key under ENSIP-5 (reverse-dot of thurin.id); ENSIP-18\n * says service-key values are bare, so the value is the 40-hex fingerprint, uppercase.\n */\nexport const ENS_HINT_KEY = 'id.thurin' as const\n\nexport type EnsHintState = 'match' | 'unset' | 'mismatch'\n\nexport interface EnsHint {\n key: typeof ENS_HINT_KEY\n state: EnsHintState\n /** The raw record value, or null when the name carries no record. */\n record: string | null\n /** The record as a lowercase fingerprint, or null when it does not parse as one. */\n fingerprint: string | null\n /** The verified claim's fingerprint (lowercase) the record is compared against, if any. */\n expected: string | null\n /** Why a record does not match; absent for `match` and `unset`. */\n reason?: string\n}\n\n/**\n * Compare a name's `id.thurin` record with the fingerprint the registry verifies for the\n * name's address. Parsing is lenient (case, spaces, 0x); what Thurin writes is strict.\n */\nexport function ensHintFor(record: string | null | undefined, verifiedFingerprint: string | null | undefined): EnsHint {\n const raw = record?.trim() ?? ''\n const expected = verifiedFingerprint ? normalizeFingerprint(verifiedFingerprint) : null\n if (!raw) return { key: ENS_HINT_KEY, state: 'unset', record: null, fingerprint: null, expected }\n const fingerprint = normalizeFingerprint(raw)\n if (!fingerprint) return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint: null, expected, reason: 'The record is not a PGP fingerprint' }\n if (!expected) return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint, expected, reason: 'The address has no verified claim' }\n if (fingerprint === expected) return { key: ENS_HINT_KEY, state: 'match', record: raw, fingerprint, expected }\n return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint, expected, reason: 'The record names a key this address has not claimed' }\n}\n\n/** The value Thurin writes: the fingerprint, uppercase, bare. */\nexport function ensHintValue(fingerprint: string): string {\n const fp = normalizeFingerprint(fingerprint)\n if (!fp) throw new Error(`Not a fingerprint: ${fingerprint}`)\n return fp.toUpperCase()\n}\n\n/** The `text` / `setText` pair every ENS resolver speaks (ENSIP-5); the same on ENSv2. */\nexport const ENS_TEXT_RESOLVER_ABI = [\n { type: 'function', name: 'text', stateMutability: 'view', inputs: [{ name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }], outputs: [{ name: '', type: 'string' }] },\n { type: 'function', name: 'setText', stateMutability: 'nonpayable', inputs: [{ name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }, { name: 'value', type: 'string' }], outputs: [] },\n] as const\n\n/**\n * The `setText` call that links a name to a claim. The resolver address is not part of it\n * on purpose: look it up at write time (`client.getEnsResolver({ name })`) — on ENSv2 every\n * account has its own resolver, so a cached or hardcoded one is the wrong contract.\n */\nexport function ensHintWrite(name: string, fingerprint: string) {\n const normalized = normalize(name)\n return {\n abi: ENS_TEXT_RESOLVER_ABI,\n functionName: 'setText' as const,\n args: [namehash(normalized), ENS_HINT_KEY, ensHintValue(fingerprint)] as const,\n name: normalized,\n }\n}\n\n/** Minimal client shape: viem's PublicClient has both. */\nexport interface EnsTextReader {\n getEnsText(args: { name: string; key: string }): Promise<string | null>\n}\n\n/** Read a name's `id.thurin` record and compare it with the verified fingerprint. */\nexport async function fetchEnsHint(client: EnsTextReader, name: string, verifiedFingerprint: string | null | undefined): Promise<EnsHint> {\n const record = await client.getEnsText({ name: normalize(name), key: ENS_HINT_KEY })\n return ensHintFor(record, verifiedFingerprint)\n}\n","import { hashTypedData, keccak256, stringToHex, type Hex, type TypedDataDomain } from 'viem'\nimport { fingerprintToBytes } from './fingerprint'\n\n/**\n * EIP-712 authorizations for the registry's relayed writes (`attestFor`, `reattestFor`,\n * `updateKeyFor`, `revokeFor`, `setRecordFor`). The owner signs one of these typed\n * structs; anyone can then submit the matching call and pay the gas. Every field is\n * bound, plus the owner's current `nonce` (read with `nonces(owner)`) and a `deadline`.\n *\n * The domain includes the chain id, so an authorization for one network cannot be\n * replayed on another even though the registry has the same address everywhere.\n */\nexport const EIP712_NAME = 'Thurin PGPRegistry'\nexport const EIP712_VERSION = '2'\n\nexport function registryDomain(chainId: number, verifyingContract: Hex): TypedDataDomain {\n return { name: EIP712_NAME, version: EIP712_VERSION, chainId, verifyingContract }\n}\n\nexport const AUTHORIZATION_TYPES = {\n Attest: [\n { name: 'owner', type: 'address' },\n { name: 'fingerprint', type: 'bytes' },\n { name: 'pgpSignature', type: 'bytes' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n Reattest: [\n { name: 'owner', type: 'address' },\n { name: 'revokeIndex', type: 'uint256' },\n { name: 'fingerprint', type: 'bytes' },\n { name: 'pgpSignature', type: 'bytes' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n UpdateKey: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n Revoke: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n SetRecord: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'kind', type: 'bytes32' },\n { name: 'value', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n} as const\n\nexport type AuthorizationAction = keyof typeof AUTHORIZATION_TYPES\n\ninterface Common { owner: Hex; nonce: bigint; deadline: bigint }\nexport type AttestAuthorization = Common & { fingerprint: string; pgpSignature: string; pgpPublicKey: string }\nexport type ReattestAuthorization = AttestAuthorization & { revokeIndex: bigint }\nexport type UpdateKeyAuthorization = Common & { index: bigint; pgpPublicKey: string }\nexport type RevokeAuthorization = Common & { index: bigint }\nexport type SetRecordAuthorization = Common & { index: bigint; kind: Hex; value: Hex }\n\n/**\n * Build the object to pass to viem/wagmi `signTypedData`. `fingerprint` is the hex\n * fingerprint; `pgpSignature` / `pgpPublicKey` are the armored text exactly as they\n * will be submitted (they are hashed as UTF-8 bytes).\n */\nexport function attestTypedData(chainId: number, registry: Hex, a: AttestAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { Attest: AUTHORIZATION_TYPES.Attest },\n primaryType: 'Attest' as const,\n message: {\n owner: a.owner,\n fingerprint: fingerprintToBytes(a.fingerprint),\n pgpSignature: stringToHex(a.pgpSignature),\n pgpPublicKey: stringToHex(a.pgpPublicKey),\n nonce: a.nonce,\n deadline: a.deadline,\n },\n }\n}\n\nexport function reattestTypedData(chainId: number, registry: Hex, a: ReattestAuthorization) {\n const base = attestTypedData(chainId, registry, a)\n return {\n domain: base.domain,\n types: { Reattest: AUTHORIZATION_TYPES.Reattest },\n primaryType: 'Reattest' as const,\n message: { ...base.message, revokeIndex: a.revokeIndex },\n }\n}\n\nexport function updateKeyTypedData(chainId: number, registry: Hex, a: UpdateKeyAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { UpdateKey: AUTHORIZATION_TYPES.UpdateKey },\n primaryType: 'UpdateKey' as const,\n message: { owner: a.owner, index: a.index, pgpPublicKey: stringToHex(a.pgpPublicKey), nonce: a.nonce, deadline: a.deadline },\n }\n}\n\nexport function revokeTypedData(chainId: number, registry: Hex, a: RevokeAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { Revoke: AUTHORIZATION_TYPES.Revoke },\n primaryType: 'Revoke' as const,\n message: { owner: a.owner, index: a.index, nonce: a.nonce, deadline: a.deadline },\n }\n}\n\nexport function setRecordTypedData(chainId: number, registry: Hex, a: SetRecordAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { SetRecord: AUTHORIZATION_TYPES.SetRecord },\n primaryType: 'SetRecord' as const,\n message: { owner: a.owner, index: a.index, kind: a.kind, value: a.value, nonce: a.nonce, deadline: a.deadline },\n }\n}\n\n/** The digest the registry recovers the signer from — handy for tests and CLIs. */\nexport function authorizationDigest(typedData: ReturnType<typeof attestTypedData | typeof reattestTypedData | typeof updateKeyTypedData | typeof revokeTypedData | typeof setRecordTypedData>): Hex {\n return hashTypedData(typedData as any)\n}\n\n/** `bytes32 kind` for a record from a human-readable name, e.g. recordKind('thurin.vouch'). */\nexport function recordKind(name: string): Hex {\n return keccak256(stringToHex(name))\n}\n","import { hexToString, stringToHex, type Hex } from 'viem'\nimport { normalizeFingerprint } from './fingerprint'\nimport { recordKind } from './authorization'\nexport { recordKind }\n\n/**\n * Records: one small value per claim per kind, set only by the owner (or by anyone holding\n * the owner's `setRecordFor` authorization), readable by anyone, clearable. The contract looks\n * a record up by kind and cannot list them, so readers ask for the kinds they know.\n *\n * Conventions: kind = keccak256(\"thurin.<name>\"); simple kinds are UTF-8 text, structured\n * kinds small JSON with a `v`, encrypted kinds an armored PGP message; readers ignore unknown\n * fields. Third parties use reverse-dot names (`com.example.thing`) without asking. 1 KB max.\n */\nexport const MAX_RECORD_BYTES = 1024\n\n/** `thurin.` is the default namespace: kindName('canary') === 'thurin.canary'. Dotted names pass through. */\nexport function kindName(input: string): string {\n return input.includes('.') ? input : `thurin.${input}`\n}\n\n/** Every kind Thurin defines. `thurin.pointer` is the Thurin Labs release list (CLI only; not shown on identity pages). */\nexport const KNOWN_KINDS = [\n 'thurin.railgun', 'thurin.security', 'thurin.successor', 'thurin.affiliation', 'thurin.canary',\n 'thurin.private', 'thurin.disclosure', 'thurin.pointer',\n] as const\nexport type KnownKind = (typeof KNOWN_KINDS)[number]\n\n/** The kinds an identity page shows, in display order. */\nexport const IDENTITY_KINDS: readonly KnownKind[] = [\n 'thurin.railgun', 'thurin.security', 'thurin.successor', 'thurin.affiliation', 'thurin.canary',\n 'thurin.private', 'thurin.disclosure',\n]\n\nexport function encodeRecord(value: string): Hex {\n const bytes = new TextEncoder().encode(value).length\n if (bytes > MAX_RECORD_BYTES) throw new Error(`Record is ${bytes} bytes; the registry accepts up to ${MAX_RECORD_BYTES}`)\n return stringToHex(value)\n}\n\nexport function decodeRecord(hex: Hex): string {\n return hex === '0x' ? '' : hexToString(hex)\n}\n\n// ─── thurin.pointer (release list; Thurin Labs' own) ───────────────────────────────────────\n\nexport interface PointerEntry { name: string; sha256: string; date: string; url?: string }\nexport interface PointerRecord { v: 1; releases: PointerEntry[] }\n\nexport function parsePointer(text: string): PointerRecord {\n const p = JSON.parse(text)\n if (p?.v !== 1 || !Array.isArray(p.releases)) throw new Error('Not a v1 thurin.pointer record')\n return p\n}\n\n/** Add a release, newest first; drop the oldest until it fits the 1 KB slot. */\nexport function addPointer(existing: PointerRecord | null, entry: PointerEntry): { record: PointerRecord; dropped: PointerEntry[] } {\n if (!/^[0-9a-f]{64}$/i.test(entry.sha256)) throw new Error('sha256 must be 64 hex characters')\n const releases = [entry, ...(existing?.releases ?? []).filter(r => r.name !== entry.name)]\n const dropped: PointerEntry[] = []\n const record: PointerRecord = { v: 1, releases }\n while (new TextEncoder().encode(JSON.stringify(record)).length > MAX_RECORD_BYTES && releases.length > 1) dropped.push(releases.pop()!)\n return { record, dropped }\n}\n\nexport function renderPointer(p: PointerRecord): string {\n return p.releases.map(r => `${r.name.padEnd(22)} ${r.date} sha256 ${r.sha256}${r.url ? ` ${r.url}` : ''}`).join('\\n')\n}\n\n// ─── The user-facing kinds ─────────────────────────────────────────────────────────────────\n\n/** A record as the identity page shows it: what was stored, and what it means if it parses. */\nexport interface ParsedRecord {\n kind: string\n /** The raw UTF-8 value. */\n text: string\n bytes: number\n /** True when the value has the shape the kind defines. A malformed record is still shown, as text. */\n valid: boolean\n /** Why it is not valid, when it is not. */\n reason?: string\n /** Kind-specific fields, when valid. */\n data: RecordData\n}\n\nexport type RecordData =\n | { type: 'railgun'; address: string }\n | { type: 'security'; contact: string; url: string | null }\n | { type: 'successor'; fingerprint: string }\n | { type: 'affiliation'; with: string; role: string | null }\n | { type: 'canary'; date: string; statement: string; clearsigned: boolean }\n | { type: 'encrypted'; recipients: number | null }\n | { type: 'pointer'; releases: PointerEntry[] }\n | { type: 'text' }\n\n/** Railgun 0zk addresses: bech32m with the `0zk` prefix (`0zk1…`, 127 chars). Charset and length only; the wallet checks the checksum. */\nconst RAILGUN_ADDRESS = /^0zk1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{60,200}$/\nconst ISO_DATE = /\\b(\\d{4}-\\d{2}-\\d{2})\\b/\n\n/**\n * Parse a record of a known kind. Never throws: a value that does not fit its kind comes back\n * with `valid: false` and a reason, so a page can still show what is there.\n */\nexport async function parseRecord(kind: string, text: string): Promise<ParsedRecord> {\n const bytes = new TextEncoder().encode(text).length\n const base = { kind, text, bytes }\n const invalid = (reason: string, data: RecordData = { type: 'text' }): ParsedRecord => ({ ...base, valid: false, reason, data })\n const t = text.trim()\n switch (kind) {\n case 'thurin.railgun': {\n if (!RAILGUN_ADDRESS.test(t)) return invalid('Not a 0zk address')\n return { ...base, valid: true, data: { type: 'railgun', address: t } }\n }\n case 'thurin.security': {\n if (!t) return invalid('Empty')\n const url = /^https?:\\/\\/\\S+$/.test(t) ? t : null\n return { ...base, valid: true, data: { type: 'security', contact: t, url } }\n }\n case 'thurin.successor': {\n const fp = normalizeFingerprint(t)\n if (!fp) return invalid('Not a PGP fingerprint')\n return { ...base, valid: true, data: { type: 'successor', fingerprint: fp } }\n }\n case 'thurin.affiliation': {\n try {\n const j = JSON.parse(t)\n if (j?.v !== 1 || typeof j.with !== 'string' || !j.with) return invalid('Not a v1 affiliation: expected {\"v\":1,\"with\":\"<address or name>\"}')\n return { ...base, valid: true, data: { type: 'affiliation', with: j.with, role: typeof j.role === 'string' ? j.role : null } }\n } catch { return invalid('Not JSON') }\n }\n case 'thurin.canary': {\n const date = t.match(ISO_DATE)?.[1]\n if (!date) return invalid('No date in the statement')\n const clearsigned = t.startsWith('-----BEGIN PGP SIGNED MESSAGE-----')\n const statement = clearsigned ? (t.split(/\\r?\\n\\r?\\n/)[1] ?? '').split('-----BEGIN PGP SIGNATURE-----')[0].trim() : t\n return { ...base, valid: true, data: { type: 'canary', date, statement, clearsigned } }\n }\n case 'thurin.private':\n case 'thurin.disclosure': {\n if (!t.startsWith('-----BEGIN PGP MESSAGE-----')) return invalid('Not a PGP message')\n let recipients: number | null = null\n try {\n const { readMessage } = await import('openpgp') // lazy, like pgp.ts: a static import breaks under jsdom\n recipients = (await readMessage({ armoredMessage: t })).getEncryptionKeyIDs().length\n } catch { return invalid('PGP message does not parse') }\n return { ...base, valid: true, data: { type: 'encrypted', recipients } }\n }\n case 'thurin.pointer': {\n try { return { ...base, valid: true, data: { type: 'pointer', releases: parsePointer(t).releases } } }\n catch { return invalid('Not a v1 pointer record') }\n }\n default:\n return { ...base, valid: true, data: { type: 'text' } }\n }\n}\n\n/** Minimal client shape: viem's PublicClient has it. */\nexport interface RecordReader {\n readContract(args: { address: `0x${string}`; abi: unknown; functionName: 'record'; args: readonly [`0x${string}`, bigint, Hex] }): Promise<unknown>\n}\n\n/**\n * Read and parse the given kinds on one claim. Kinds with no record are left out.\n * `registry` is the contract address; pass the kit's REGISTRY_ABI.\n */\nexport async function fetchRecords(\n client: RecordReader, registry: `0x${string}`, abi: unknown,\n owner: `0x${string}`, index: number | bigint, kinds: readonly string[] = IDENTITY_KINDS,\n): Promise<ParsedRecord[]> {\n const out: ParsedRecord[] = []\n for (const kind of kinds) {\n const hex = await client.readContract({ address: registry, abi, functionName: 'record', args: [owner, BigInt(index), recordKind(kind)] }) as Hex\n const text = decodeRecord(hex)\n if (text) out.push(await parseRecord(kind, text))\n }\n return out\n}\n"],"mappings":"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","names":["keccak256","keccak256","stringToHex","stringToHex"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ben/code/thurinlabs/identity-kit/dist/chunk-MYKKWPBY.cjs","../src/core/abi.ts","../src/core/contract.ts","../src/core/fingerprint.ts","../src/core/pgp.ts","../src/core/efp.ts","../src/core/proofs.ts","../src/core/ensHint.ts","../src/core/authorization.ts","../src/core/records.ts"],"names":["stringToHex"],"mappings":"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CT;AAGoI;AACjF,EAAA;AACG,EAAA;AACnB,EAAA;AACc,EAAA;AACA,EAAA;AACtB,EAAA;AAC3B;AAEwD;AACP,EAAA;AACjD;AA6BwB;AACP;AAMoE;AACtC,EAAA;AACZ,EAAA;AACkC,EAAA;AAC/C,EAAA;AACN,EAAA;AACW,IAAA;AACwB,MAAA;AACA,MAAA;AAC/C,IAAA;AACwB,IAAA;AACQ,MAAA;AACe,MAAA;AACA,MAAA;AAC/C,IAAA;AACyB,IAAA;AACU,MAAA;AACc,MAAA;AACF,MAAA;AAC/C,IAAA;AAC2B,IAAA;AACrB,MAAA;AACoB,QAAA;AACc,QAAA;AACS,QAAA;AACvC,MAAA;AAA2B,QAAA;AAAE,MAAA;AACvC,IAAA;AACsB,IAAA;AACc,MAAA;AACR,MAAA;AACO,MAAA;AACQ,MAAA;AACI,MAAA;AAC/C,IAAA;AACK,IAAA;AACqB,IAAA;AACuB,MAAA;AACf,MAAA;AAC5B,MAAA;AAC4C,QAAA;AACZ,QAAA;AAC5B,MAAA;AAA6C,QAAA;AAAE,MAAA;AACV,MAAA;AAC/C,IAAA;AACuB,IAAA;AACjB,MAAA;AAA+C,QAAA;AAC7C,MAAA;AAA0C,QAAA;AAAE,MAAA;AACpD,IAAA;AACA,IAAA;AAC+C,MAAA;AACjD,EAAA;AACF;AAaE;AAE6B,EAAA;AACH,EAAA;AACyB,IAAA;AACpB,IAAA;AACmB,IAAA;AAClD,EAAA;AACO,EAAA;AACT;ATovDsD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/ben/code/thurinlabs/identity-kit/dist/chunk-MYKKWPBY.cjs","sourcesContent":[null,"// Generated from pgp-registry: `forge inspect PGPRegistry abi --json`. Do not edit by hand.\nexport const REGISTRY_ABI = [\n {\n \"type\": \"function\",\n \"name\": \"ATTEST_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"DOMAIN_SEPARATOR\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"EIP712_NAME\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"string\",\n \"internalType\": \"string\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"EIP712_VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"string\",\n \"internalType\": \"string\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_KEY_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_RECORD_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_SIG_BYTES\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MESSAGE_VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"REATTEST_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"REVOKE_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"SET_RECORD_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"UPDATE_KEY_TYPEHASH\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesFor\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"address[]\",\n \"internalType\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesForCount\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"addressesForRange\",\n \"inputs\": [\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"address[]\",\n \"internalType\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attest\",\n \"inputs\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationCount\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationsOf\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct PGPRegistry.Attestation[]\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"attestationsOfRange\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct PGPRegistry.Attestation[]\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"cancelAuthorization\",\n \"inputs\": [],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"current\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"found\",\n \"type\": \"bool\",\n \"internalType\": \"bool\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"attestation\",\n \"type\": \"tuple\",\n \"internalType\": \"struct PGPRegistry.Attestation\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyId\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes[]\",\n \"internalType\": \"bytes[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyIdCount\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"fingerprintsForKeyIdRange\",\n \"inputs\": [\n {\n \"name\": \"keyId\",\n \"type\": \"bytes8\",\n \"internalType\": \"bytes8\"\n },\n {\n \"name\": \"start\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"count\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"out\",\n \"type\": \"bytes[]\",\n \"internalType\": \"bytes[]\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"getAttestation\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"tuple\",\n \"internalType\": \"struct PGPRegistry.Attestation\",\n \"components\": [\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"createdAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"revokedAt\",\n \"type\": \"uint64\",\n \"internalType\": \"uint64\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"getPayload\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"nonces\",\n \"inputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"reattest\",\n \"inputs\": [\n {\n \"name\": \"revokeIndex\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"reattestFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"revokeIndex\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpSignature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"record\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"revoke\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"revokeFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"setRecord\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"value\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"setRecordFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"value\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"updateKey\",\n \"inputs\": [\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"updateKeyFor\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"pgpPublicKey\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"deadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"signature\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"event\",\n \"name\": \"Attested\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"fingerprint\",\n \"type\": \"bytes\",\n \"indexed\": false,\n \"internalType\": \"bytes\"\n },\n {\n \"name\": \"messageVersion\",\n \"type\": \"uint8\",\n \"indexed\": false,\n \"internalType\": \"uint8\"\n },\n {\n \"name\": \"keyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"sigPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"KeyUpdated\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"oldKeyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"newKeyPtr\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"NonceUsed\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"nonce\",\n \"type\": \"uint256\",\n \"indexed\": false,\n \"internalType\": \"uint256\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"RecordSet\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"kind\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"Revoked\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"fingerprintHash\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"index\",\n \"type\": \"uint256\",\n \"indexed\": true,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"submitter\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"error\",\n \"name\": \"AlreadyRevoked\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"AuthorizationExpired\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"DeploymentFailed\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"DuplicateActiveFingerprint\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"EmptyPublicKey\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"EmptySignature\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"IndexOutOfBounds\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidAuthorization\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidFingerprintLength\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidPointer\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"PublicKeyTooLarge\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"RecordTooLarge\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"SignatureTooLarge\",\n \"inputs\": []\n }\n] as const\n","import { mainnet, sepolia, foundry } from 'viem/chains'\nexport { REGISTRY_ABI } from './abi'\n\n/**\n * PGPRegistry v2 is deployed with CREATE2, so it has the same address on every\n * network. (v1 lived at 0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb on mainnet and\n * is no longer read by Thurin.)\n */\nexport const REGISTRY_ADDRESS = '0x9302E02e2869e129aC8516fE5eFFd51EA3082c09' as const\n\n/** Networks the PGPRegistry is deployed on. `mainnet` is the default everywhere. */\nexport type NetworkName = 'mainnet' | 'sepolia' | 'local'\n\nexport interface RegistryDeployment {\n chainId: number\n address: `0x${string}`\n /** Block the registry was deployed in (informational; v2 needs no log scans). */\n deployBlock: bigint\n /** Block explorer base URL for address/tx links. Empty when there is none. */\n explorerUrl: string\n /** Keyless public RPC used when no rpcUrl is configured. */\n defaultRpcUrl: string\n}\n\nexport const NETWORKS: Record<NetworkName, RegistryDeployment> = {\n mainnet: {\n chainId: 1,\n address: REGISTRY_ADDRESS,\n deployBlock: 25962908n, // 2026-09-12, tx 0xda4c3a19cae4e71ffb02559a048403f664d5a7967c19d42158c39600ec63bad8\n explorerUrl: 'https://etherscan.io',\n defaultRpcUrl: 'https://ethereum.publicnode.com', // same service as ethereum-rpc.publicnode.com; this hostname resolves on more networks\n },\n sepolia: {\n chainId: 11155111,\n address: REGISTRY_ADDRESS,\n deployBlock: 11683667n, // 2026-09-11, tx 0x3e40e8f5b9fbf82a4b8943561bcc9b964b2987de10640ac8ff3a1b4ef0725322\n explorerUrl: 'https://sepolia.etherscan.io',\n defaultRpcUrl: 'https://ethereum-sepolia.publicnode.com',\n },\n /** A local anvil instance (`anvil`, chain id 31337). Deploy with pgp-registry's Deploy script. */\n local: {\n chainId: 31337,\n address: REGISTRY_ADDRESS,\n deployBlock: 0n,\n explorerUrl: '',\n defaultRpcUrl: 'http://127.0.0.1:8545',\n },\n}\n\nexport function isNetworkName(value: unknown): value is NetworkName {\n return value === 'mainnet' || value === 'sepolia' || value === 'local'\n}\n\n/**\n * The registry deployment for a network. `addressOverride` swaps the contract\n * address (e.g. a local deploy that landed somewhere else).\n */\nexport function getRegistry(network: NetworkName = 'mainnet', addressOverride?: string): RegistryDeployment {\n const r = NETWORKS[network]\n if (!r) throw new Error(`Unknown network: ${network}`)\n if (addressOverride && /^0x[0-9a-fA-F]{40}$/.test(addressOverride)) {\n return { ...r, address: addressOverride as `0x${string}` }\n }\n return r\n}\n\n/** The viem chain object for a network name. */\nexport function chainFor(network: NetworkName = 'mainnet') {\n if (network === 'sepolia') return sepolia\n if (network === 'local') return foundry\n return mainnet\n}\n","import { keccak256, type Hex } from 'viem'\n\n/** 40 hex chars (OpenPGP v4) or 64 hex chars (v6), spaces/0x tolerated. */\nconst FINGERPRINT_HEX = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/\n\n/** Normalize a fingerprint to lowercase hex with no prefix or spaces. Returns null if malformed. */\nexport function normalizeFingerprint(input: string): string | null {\n const hex = input.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase()\n return FINGERPRINT_HEX.test(hex) ? hex : null\n}\n\n/** Fingerprint → the raw `bytes` argument the v2 registry takes (0x-prefixed, 20 or 32 bytes). */\nexport function fingerprintToBytes(fingerprint: string): Hex {\n const hex = normalizeFingerprint(fingerprint)\n if (!hex) throw new Error(`Invalid PGP fingerprint: ${fingerprint}`)\n return `0x${hex}`\n}\n\n/** Raw `bytes` from the registry → lowercase hex fingerprint without 0x. */\nexport function bytesToFingerprint(bytes: Hex | string): string {\n return bytes.replace(/^0x/i, '').toLowerCase()\n}\n\n/** keccak256 of the raw fingerprint bytes — the `fingerprintHash` the registry indexes by. */\nexport function fingerprintHash(fingerprint: string): Hex {\n return keccak256(fingerprintToBytes(fingerprint))\n}\n\n/**\n * The long key ID as the `bytes8` the registry indexes by. Per RFC 9580 §5.5.4 it is the\n * low-order 8 bytes of a v4 (20-byte) fingerprint and the high-order 8 bytes of a v6\n * (32-byte) fingerprint — the same value `gpg --keyid-format long` prints.\n */\nexport function keyIdOf(fingerprint: string): Hex {\n const hex = normalizeFingerprint(fingerprint)\n if (!hex) throw new Error(`Invalid PGP fingerprint: ${fingerprint}`)\n return `0x${keyIdHex(hex)}`\n}\n\n/** Long key ID (16 lowercase hex chars) of a normalized fingerprint. */\nexport function keyIdHex(normalizedFingerprint: string): string {\n return normalizedFingerprint.length === 64 ? normalizedFingerprint.slice(0, 16) : normalizedFingerprint.slice(-16)\n}\n\n/** A 16-hex long key ID (spaces/0x tolerated) → `bytes8`. */\nexport function keyIdToBytes(keyId: string): Hex | null {\n const hex = keyId.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase()\n return /^[0-9a-f]{16}$/.test(hex) ? `0x${hex}` : null\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\n/**\n * openpgp.js refuses secp256k1 by default because RFC 9580 does not list the\n * curve — a compatibility choice, not a security one. A secp256k1 PGP key is a\n * valid key (and, incidentally, doubles as an Ethereum key: the address falls out\n * of the same public point). Thurin verifies signatures over any curve openpgp.js\n * can compute; whether a holder reuses such a key as a wallet is their business.\n * In Node, openpgp.js needs the optional `eckey-utils` package for this curve;\n * the browser build does not.\n *\n * The low-level packet/key methods take a *complete* config (they index into\n * it), so this builds one from the library's defaults rather than passing a\n * partial object.\n */\nfunction pgpConfig(openpgp: typeof import('openpgp')) {\n return { ...openpgp.config, rejectCurves: new Set() as Set<never> }\n}\n\n/** Human-readable algorithm for a key or subkey packet: \"Ed25519\", \"Cv25519\", \"RSA 4096\", \"NIST P-256\", … */\nfunction algorithmName(keyOrSubkey: any): string {\n try {\n const info = keyOrSubkey.getAlgorithmInfo() as { algorithm: string; bits?: number; curve?: string }\n const curve = (info.curve || '').toLowerCase()\n if (curve.startsWith('ed25519') || info.algorithm === 'ed25519' || info.algorithm === 'eddsaLegacy') return 'Ed25519'\n if (curve.startsWith('curve25519') || info.algorithm === 'x25519') return 'Cv25519'\n if (curve.startsWith('ed448')) return 'Ed448'\n if (curve.startsWith('curve448') || info.algorithm === 'x448') return 'X448'\n if (curve.startsWith('nistp') || curve.startsWith('p')) return `NIST P-${curve.replace(/\\D/g, '')}`\n if (curve.startsWith('secp')) return curve\n if (curve.startsWith('brainpool')) return curve\n if (info.algorithm.startsWith('rsa')) return info.bits ? `RSA ${info.bits}` : 'RSA'\n if (info.algorithm.startsWith('dsa')) return info.bits ? `DSA ${info.bits}` : 'DSA'\n if (info.algorithm.startsWith('elgamal')) return info.bits ? `ElGamal ${info.bits}` : 'ElGamal'\n return info.curve || info.algorithm\n } catch {\n return String(keyOrSubkey.keyPacket?.algorithm ?? 'unknown')\n }\n}\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const openpgp = await import('openpgp')\n const { readKey } = openpgp\n const config = pgpConfig(openpgp)\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const algorithm = algorithmName(key)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n // openpgp does not verify certification signatures when a key is parsed —\n // it groups them by issuer key ID only. A key's fingerprint also covers\n // only the primary key packet, not its user IDs or their certifications.\n // Each self-certification is therefore verified against the primary key\n // here before its user ID and notations are treated as authoritative.\n const userIDs: string[] = []\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n const certs = (user as any).selfCertifications\n if (!certs || certs.length === 0) continue\n\n let userVerified = false\n for (const cert of certs) {\n try {\n await cert.verify(\n key.keyPacket,\n cert.signatureType,\n { userID: (user as any).userID, key: key.keyPacket },\n undefined, // date: now\n undefined, // detached\n config,\n )\n } catch {\n continue // signature not made by this key — ignore this certification\n }\n userVerified = true\n\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n // Dedupe by value alone: the same proof target is often present\n // under both proof@thurin.id and proof@ariadne.id, and should\n // surface once, not once per namespace.\n if (!seen.has(value)) {\n seen.add(value)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n\n if (userVerified) {\n const uid = (user as any).userID?.userID\n if (uid) userIDs.push(uid)\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: algorithmName(sk),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const openpgp = await import('openpgp')\n const { readKey, readCleartextMessage, LiteralDataPacket } = openpgp\n const config = pgpConfig(openpgp)\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n\n // Verify the way gpg does: the key (or subkey) must be valid *now* — bound to\n // this primary, unrevoked, unexpired — and the signature must be sound. We\n // deliberately do not ask openpgp.verify(), which also demands the key was\n // valid at the instant the signature was made. Thurin's update flow tells\n // people to `export-minimal` after editing notations, which keeps only the\n // newest self-certification; when that postdates the attest signature\n // (Ben's own key, 2026-09-14: notations edited 16 minutes after signing),\n // openpgp.verify() reports \"Could not find valid self-signature\" for a\n // signature gpg verifies fine. A key that has since been revoked or expired\n // still fails here, as it should.\n // These are internals the .d.ts does not expose (the signature packet list,\n // the CRLF-normalised text, LiteralDataPacket.setText); they are stable across\n // openpgp.js 6 and exercised by the real-data tests in attestation.test.ts.\n const msg = message as any\n const now = new Date()\n let signed = false\n for (const sig of msg.signature.packets) {\n if (!publicKey.getKeys(sig.issuerKeyID).length) continue\n const signingKey = await publicKey.getSigningKey(sig.issuerKeyID, now, undefined, config)\n const literal: any = new LiteralDataPacket()\n literal.setText(msg.text ?? message.getText().replace(/\\r?\\n/g, '\\r\\n'))\n await sig.verify(signingKey.keyPacket, sig.signatureType, literal, now, true, config)\n signed = true\n break\n }\n if (!signed) return { verified: false, reason: 'Message is not signed by this key' }\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nexport interface StrippedKey {\n /** Armored public key containing only the non-email user IDs. */\n armored: string\n /** User IDs kept (no `@`). */\n kept: string[]\n /** User IDs removed (contained an `@`). */\n removed: string[]\n}\n\nconst EMAIL_UID = /@/\n\n/**\n * Remove every user ID that contains an email address, keeping the rest (and\n * their self-certifications, so proof notations on a non-email user ID survive).\n * Returns null when nothing would remain — openpgp needs at least one\n * self-certified user ID to verify signatures, so such a key must not be\n * published. The key material and subkeys are untouched; the fingerprint is\n * unchanged.\n */\nexport async function stripEmailUserIDs(armoredKey: string): Promise<StrippedKey | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const kept: string[] = []\n const removed: string[] = []\n const users = (key as any).users.filter((u: any) => {\n const uid: string | undefined = u.userID?.userID\n if (!uid) return false\n if (EMAIL_UID.test(uid)) { removed.push(uid); return false }\n kept.push(uid)\n return true\n })\n if (users.length === 0) return null\n ;(key as any).users = users\n return { armored: key.armor(), kept, removed }\n } catch {\n return null\n }\n}\n\n/** True when any user ID on the key contains an email address. */\nexport async function hasEmailUserID(armoredKey: string): Promise<boolean> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n return (key as any).users.some((u: any) => EMAIL_UID.test(u.userID?.userID ?? ''))\n } catch {\n return false\n }\n}\n","import type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\n/**\n * EFP social graph for an address. Followers are counted by EFP for any address,\n * whether or not it has published a list of its own; following and top-8 exist\n * only when it has (its \"primary list\"). An address with followers but no list\n * — a project account that has never followed anyone — is still on EFP.\n */\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const [statsResp, listsResp] = await Promise.all([\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/users/${address}/lists`),\n ])\n if (!statsResp.ok && !listsResp.ok) return null\n\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const listsData = listsResp.ok ? await listsResp.json() : {}\n const followers = parseInt(statsData.followers_count) || 0\n const listId = listsData.primary_list\n\n let following = 0\n let top8: string[] = []\n if (listId) {\n const [followingResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n following = (followingData.following || []).length\n top8 = (top8Data.following || []).map((f: any) => f.data)\n }\n\n return { followers, following, top8, hasEfp: !!listId || followers > 0 }\n } catch {\n return null\n }\n}\n","import { keyIdHex } from './fingerprint'\nimport type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n // A repository's description — the form an organisation can use, since\n // gists belong to user accounts only. Same shape as the Codeberg proof.\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/github\\.com\\/([A-Za-z0-9-]+)\\/([A-Za-z0-9._-]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n // domain is restricted to a hostname (labels may include underscores for\n // records like _thurin.example.com); rejects slashes, userinfo, and spaces.\n pattern: /^dns:([a-z0-9._-]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n // instance is restricted to a bare hostname (optional port) so a value\n // like \"mastodon.social@evil.com\" can't redirect the lookup elsewhere.\n pattern: /^https:\\/\\/([a-z0-9.-]+(?::\\d+)?)\\/@([^/@?#\\s]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (notation.name !== 'proof@thurin.id') return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n if (proof.repo) return verifyGitHubRepo(proof, fingerprint)\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n // A gist is identified solely by its globally-unique ID; the username in\n // the URL is not authoritative. Confirm the gist owner matches the claimed\n // account before trusting the token it contains.\n if (data.owner?.login?.toLowerCase() !== proof.user!.toLowerCase()) {\n return { verified: false, reason: 'Gist owner does not match claimed user' }\n }\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyGitHubRepo(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://api.github.com/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n // GitHub follows renames and redirects, so the API may answer for a repo\n // under a different owner than the URL names. Only trust it if the owner\n // is the account being claimed.\n if (data.owner?.login?.toLowerCase() !== proof.user!.toLowerCase()) {\n return { verified: false, reason: 'Repository owner does not match claimed account' }\n }\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Fingerprint token not found in repository description' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n // TXT records only (type 16) — a CNAME or other record in the resolution\n // chain must not be eligible to match the token.\n if (answer.type !== 16) continue\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n // A short cast-hash prefix can match multiple casts; keep scanning\n // rather than stopping at the first prefix match without the token.\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n // The instance host is user-supplied and interpolated into the request URL,\n // so restrict it to a bare hostname (optional port) before use — otherwise a\n // value such as \"mastodon.social@evil.com\" would send the lookup to another\n // server while still displaying as a legitimate handle.\n if (!proof.instance || !/^[a-z0-9.-]+(?::\\d+)?$/i.test(proof.instance)) {\n return { verified: false, reason: 'Invalid Mastodon instance host' }\n }\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = keyIdHex(fingerprint.replace(/^0x/i, '').replace(/\\s+/g, '').toLowerCase())\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { namehash, normalize } from 'viem/ens'\nimport { normalizeFingerprint } from './fingerprint'\n\n/**\n * The `id.thurin` ENS text record: a name points at the PGP key claimed on the Thurin\n * registry by the address the name resolves to. It is a discovery hint, not part of the\n * trust chain — the name owner set the address, the address signed the claim, so a reader\n * verifies by resolving the name and reading the registry. The record only says where to\n * look. `id.thurin` is a service key under ENSIP-5 (reverse-dot of thurin.id); ENSIP-18\n * says service-key values are bare, so the value is the 40-hex fingerprint, uppercase.\n */\nexport const ENS_HINT_KEY = 'id.thurin' as const\n\nexport type EnsHintState = 'match' | 'unset' | 'mismatch'\n\nexport interface EnsHint {\n key: typeof ENS_HINT_KEY\n state: EnsHintState\n /** The raw record value, or null when the name carries no record. */\n record: string | null\n /** The record as a lowercase fingerprint, or null when it does not parse as one. */\n fingerprint: string | null\n /** The verified claim's fingerprint (lowercase) the record is compared against, if any. */\n expected: string | null\n /** Why a record does not match; absent for `match` and `unset`. */\n reason?: string\n}\n\n/**\n * Compare a name's `id.thurin` record with the fingerprint the registry verifies for the\n * name's address. Parsing is lenient (case, spaces, 0x); what Thurin writes is strict.\n */\nexport function ensHintFor(record: string | null | undefined, verifiedFingerprint: string | null | undefined): EnsHint {\n const raw = record?.trim() ?? ''\n const expected = verifiedFingerprint ? normalizeFingerprint(verifiedFingerprint) : null\n if (!raw) return { key: ENS_HINT_KEY, state: 'unset', record: null, fingerprint: null, expected }\n const fingerprint = normalizeFingerprint(raw)\n if (!fingerprint) return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint: null, expected, reason: 'The record is not a PGP fingerprint' }\n if (!expected) return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint, expected, reason: 'The address has no verified claim' }\n if (fingerprint === expected) return { key: ENS_HINT_KEY, state: 'match', record: raw, fingerprint, expected }\n return { key: ENS_HINT_KEY, state: 'mismatch', record: raw, fingerprint, expected, reason: 'The record names a key this address has not claimed' }\n}\n\n/** The value Thurin writes: the fingerprint, uppercase, bare. */\nexport function ensHintValue(fingerprint: string): string {\n const fp = normalizeFingerprint(fingerprint)\n if (!fp) throw new Error(`Not a fingerprint: ${fingerprint}`)\n return fp.toUpperCase()\n}\n\n/** The `text` / `setText` pair every ENS resolver speaks (ENSIP-5); the same on ENSv2. */\nexport const ENS_TEXT_RESOLVER_ABI = [\n { type: 'function', name: 'text', stateMutability: 'view', inputs: [{ name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }], outputs: [{ name: '', type: 'string' }] },\n { type: 'function', name: 'setText', stateMutability: 'nonpayable', inputs: [{ name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }, { name: 'value', type: 'string' }], outputs: [] },\n] as const\n\n/**\n * The `setText` call that links a name to a claim. The resolver address is not part of it\n * on purpose: look it up at write time (`client.getEnsResolver({ name })`) — on ENSv2 every\n * account has its own resolver, so a cached or hardcoded one is the wrong contract.\n */\nexport function ensHintWrite(name: string, fingerprint: string) {\n const normalized = normalize(name)\n return {\n abi: ENS_TEXT_RESOLVER_ABI,\n functionName: 'setText' as const,\n args: [namehash(normalized), ENS_HINT_KEY, ensHintValue(fingerprint)] as const,\n name: normalized,\n }\n}\n\n/** Minimal client shape: viem's PublicClient has both. */\nexport interface EnsTextReader {\n getEnsText(args: { name: string; key: string }): Promise<string | null>\n}\n\n/** Read a name's `id.thurin` record and compare it with the verified fingerprint. */\nexport async function fetchEnsHint(client: EnsTextReader, name: string, verifiedFingerprint: string | null | undefined): Promise<EnsHint> {\n const record = await client.getEnsText({ name: normalize(name), key: ENS_HINT_KEY })\n return ensHintFor(record, verifiedFingerprint)\n}\n","import { hashTypedData, keccak256, stringToHex, type Hex, type TypedDataDomain } from 'viem'\nimport { fingerprintToBytes } from './fingerprint'\n\n/**\n * EIP-712 authorizations for the registry's relayed writes (`attestFor`, `reattestFor`,\n * `updateKeyFor`, `revokeFor`, `setRecordFor`). The owner signs one of these typed\n * structs; anyone can then submit the matching call and pay the gas. Every field is\n * bound, plus the owner's current `nonce` (read with `nonces(owner)`) and a `deadline`.\n *\n * The domain includes the chain id, so an authorization for one network cannot be\n * replayed on another even though the registry has the same address everywhere.\n */\nexport const EIP712_NAME = 'Thurin PGPRegistry'\nexport const EIP712_VERSION = '2'\n\nexport function registryDomain(chainId: number, verifyingContract: Hex): TypedDataDomain {\n return { name: EIP712_NAME, version: EIP712_VERSION, chainId, verifyingContract }\n}\n\nexport const AUTHORIZATION_TYPES = {\n Attest: [\n { name: 'owner', type: 'address' },\n { name: 'fingerprint', type: 'bytes' },\n { name: 'pgpSignature', type: 'bytes' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n Reattest: [\n { name: 'owner', type: 'address' },\n { name: 'revokeIndex', type: 'uint256' },\n { name: 'fingerprint', type: 'bytes' },\n { name: 'pgpSignature', type: 'bytes' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n UpdateKey: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'pgpPublicKey', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n Revoke: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n SetRecord: [\n { name: 'owner', type: 'address' },\n { name: 'index', type: 'uint256' },\n { name: 'kind', type: 'bytes32' },\n { name: 'value', type: 'bytes' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n} as const\n\nexport type AuthorizationAction = keyof typeof AUTHORIZATION_TYPES\n\ninterface Common { owner: Hex; nonce: bigint; deadline: bigint }\nexport type AttestAuthorization = Common & { fingerprint: string; pgpSignature: string; pgpPublicKey: string }\nexport type ReattestAuthorization = AttestAuthorization & { revokeIndex: bigint }\nexport type UpdateKeyAuthorization = Common & { index: bigint; pgpPublicKey: string }\nexport type RevokeAuthorization = Common & { index: bigint }\nexport type SetRecordAuthorization = Common & { index: bigint; kind: Hex; value: Hex }\n\n/**\n * Build the object to pass to viem/wagmi `signTypedData`. `fingerprint` is the hex\n * fingerprint; `pgpSignature` / `pgpPublicKey` are the armored text exactly as they\n * will be submitted (they are hashed as UTF-8 bytes).\n */\nexport function attestTypedData(chainId: number, registry: Hex, a: AttestAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { Attest: AUTHORIZATION_TYPES.Attest },\n primaryType: 'Attest' as const,\n message: {\n owner: a.owner,\n fingerprint: fingerprintToBytes(a.fingerprint),\n pgpSignature: stringToHex(a.pgpSignature),\n pgpPublicKey: stringToHex(a.pgpPublicKey),\n nonce: a.nonce,\n deadline: a.deadline,\n },\n }\n}\n\nexport function reattestTypedData(chainId: number, registry: Hex, a: ReattestAuthorization) {\n const base = attestTypedData(chainId, registry, a)\n return {\n domain: base.domain,\n types: { Reattest: AUTHORIZATION_TYPES.Reattest },\n primaryType: 'Reattest' as const,\n message: { ...base.message, revokeIndex: a.revokeIndex },\n }\n}\n\nexport function updateKeyTypedData(chainId: number, registry: Hex, a: UpdateKeyAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { UpdateKey: AUTHORIZATION_TYPES.UpdateKey },\n primaryType: 'UpdateKey' as const,\n message: { owner: a.owner, index: a.index, pgpPublicKey: stringToHex(a.pgpPublicKey), nonce: a.nonce, deadline: a.deadline },\n }\n}\n\nexport function revokeTypedData(chainId: number, registry: Hex, a: RevokeAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { Revoke: AUTHORIZATION_TYPES.Revoke },\n primaryType: 'Revoke' as const,\n message: { owner: a.owner, index: a.index, nonce: a.nonce, deadline: a.deadline },\n }\n}\n\nexport function setRecordTypedData(chainId: number, registry: Hex, a: SetRecordAuthorization) {\n return {\n domain: registryDomain(chainId, registry),\n types: { SetRecord: AUTHORIZATION_TYPES.SetRecord },\n primaryType: 'SetRecord' as const,\n message: { owner: a.owner, index: a.index, kind: a.kind, value: a.value, nonce: a.nonce, deadline: a.deadline },\n }\n}\n\n/** The digest the registry recovers the signer from — handy for tests and CLIs. */\nexport function authorizationDigest(typedData: ReturnType<typeof attestTypedData | typeof reattestTypedData | typeof updateKeyTypedData | typeof revokeTypedData | typeof setRecordTypedData>): Hex {\n return hashTypedData(typedData as any)\n}\n\n/** `bytes32 kind` for a record from a human-readable name, e.g. recordKind('thurin.vouch'). */\nexport function recordKind(name: string): Hex {\n return keccak256(stringToHex(name))\n}\n","import { hexToString, stringToHex, type Hex } from 'viem'\nimport { normalizeFingerprint } from './fingerprint'\nimport { recordKind } from './authorization'\nexport { recordKind }\n\n/**\n * Records: one small value per claim per kind, set only by the owner (or by anyone holding\n * the owner's `setRecordFor` authorization), readable by anyone, clearable. The contract looks\n * a record up by kind and cannot list them, so readers ask for the kinds they know.\n *\n * Conventions: kind = keccak256(\"thurin.<name>\"); simple kinds are UTF-8 text, structured\n * kinds small JSON with a `v`, encrypted kinds an armored PGP message; readers ignore unknown\n * fields. Third parties use reverse-dot names (`com.example.thing`) without asking. 1 KB max.\n */\nexport const MAX_RECORD_BYTES = 1024\n\n/** `thurin.` is the default namespace: kindName('canary') === 'thurin.canary'. Dotted names pass through. */\nexport function kindName(input: string): string {\n return input.includes('.') ? input : `thurin.${input}`\n}\n\n/** Every kind Thurin defines. `thurin.pointer` is the Thurin Labs release list (CLI only; not shown on identity pages). */\nexport const KNOWN_KINDS = [\n 'thurin.railgun', 'thurin.security', 'thurin.successor', 'thurin.affiliation', 'thurin.canary',\n 'thurin.private', 'thurin.disclosure', 'thurin.pointer',\n] as const\nexport type KnownKind = (typeof KNOWN_KINDS)[number]\n\n/** The kinds an identity page shows, in display order. */\nexport const IDENTITY_KINDS: readonly KnownKind[] = [\n 'thurin.railgun', 'thurin.security', 'thurin.successor', 'thurin.affiliation', 'thurin.canary',\n 'thurin.private', 'thurin.disclosure',\n]\n\nexport function encodeRecord(value: string): Hex {\n const bytes = new TextEncoder().encode(value).length\n if (bytes > MAX_RECORD_BYTES) throw new Error(`Record is ${bytes} bytes; the registry accepts up to ${MAX_RECORD_BYTES}`)\n return stringToHex(value)\n}\n\nexport function decodeRecord(hex: Hex): string {\n return hex === '0x' ? '' : hexToString(hex)\n}\n\n// ─── thurin.pointer (release list; Thurin Labs' own) ───────────────────────────────────────\n\nexport interface PointerEntry { name: string; sha256: string; date: string; url?: string }\nexport interface PointerRecord { v: 1; releases: PointerEntry[] }\n\nexport function parsePointer(text: string): PointerRecord {\n const p = JSON.parse(text)\n if (p?.v !== 1 || !Array.isArray(p.releases)) throw new Error('Not a v1 thurin.pointer record')\n return p\n}\n\n/** Add a release, newest first; drop the oldest until it fits the 1 KB slot. */\nexport function addPointer(existing: PointerRecord | null, entry: PointerEntry): { record: PointerRecord; dropped: PointerEntry[] } {\n if (!/^[0-9a-f]{64}$/i.test(entry.sha256)) throw new Error('sha256 must be 64 hex characters')\n const releases = [entry, ...(existing?.releases ?? []).filter(r => r.name !== entry.name)]\n const dropped: PointerEntry[] = []\n const record: PointerRecord = { v: 1, releases }\n while (new TextEncoder().encode(JSON.stringify(record)).length > MAX_RECORD_BYTES && releases.length > 1) dropped.push(releases.pop()!)\n return { record, dropped }\n}\n\nexport function renderPointer(p: PointerRecord): string {\n return p.releases.map(r => `${r.name.padEnd(22)} ${r.date} sha256 ${r.sha256}${r.url ? ` ${r.url}` : ''}`).join('\\n')\n}\n\n// ─── The user-facing kinds ─────────────────────────────────────────────────────────────────\n\n/** A record as the identity page shows it: what was stored, and what it means if it parses. */\nexport interface ParsedRecord {\n kind: string\n /** The raw UTF-8 value. */\n text: string\n bytes: number\n /** True when the value has the shape the kind defines. A malformed record is still shown, as text. */\n valid: boolean\n /** Why it is not valid, when it is not. */\n reason?: string\n /** Kind-specific fields, when valid. */\n data: RecordData\n}\n\nexport type RecordData =\n | { type: 'railgun'; address: string }\n | { type: 'security'; contact: string; url: string | null }\n | { type: 'successor'; fingerprint: string }\n | { type: 'affiliation'; with: string; role: string | null }\n | { type: 'canary'; date: string; statement: string; clearsigned: boolean }\n | { type: 'encrypted'; recipients: number | null }\n | { type: 'pointer'; releases: PointerEntry[] }\n | { type: 'text' }\n\n/** Railgun 0zk addresses: bech32m with the `0zk` prefix (`0zk1…`, 127 chars). Charset and length only; the wallet checks the checksum. */\nconst RAILGUN_ADDRESS = /^0zk1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{60,200}$/\nconst ISO_DATE = /\\b(\\d{4}-\\d{2}-\\d{2})\\b/\n\n/**\n * Parse a record of a known kind. Never throws: a value that does not fit its kind comes back\n * with `valid: false` and a reason, so a page can still show what is there.\n */\nexport async function parseRecord(kind: string, text: string): Promise<ParsedRecord> {\n const bytes = new TextEncoder().encode(text).length\n const base = { kind, text, bytes }\n const invalid = (reason: string, data: RecordData = { type: 'text' }): ParsedRecord => ({ ...base, valid: false, reason, data })\n const t = text.trim()\n switch (kind) {\n case 'thurin.railgun': {\n if (!RAILGUN_ADDRESS.test(t)) return invalid('Not a 0zk address')\n return { ...base, valid: true, data: { type: 'railgun', address: t } }\n }\n case 'thurin.security': {\n if (!t) return invalid('Empty')\n const url = /^https?:\\/\\/\\S+$/.test(t) ? t : null\n return { ...base, valid: true, data: { type: 'security', contact: t, url } }\n }\n case 'thurin.successor': {\n const fp = normalizeFingerprint(t)\n if (!fp) return invalid('Not a PGP fingerprint')\n return { ...base, valid: true, data: { type: 'successor', fingerprint: fp } }\n }\n case 'thurin.affiliation': {\n try {\n const j = JSON.parse(t)\n if (j?.v !== 1 || typeof j.with !== 'string' || !j.with) return invalid('Not a v1 affiliation: expected {\"v\":1,\"with\":\"<address or name>\"}')\n return { ...base, valid: true, data: { type: 'affiliation', with: j.with, role: typeof j.role === 'string' ? j.role : null } }\n } catch { return invalid('Not JSON') }\n }\n case 'thurin.canary': {\n const date = t.match(ISO_DATE)?.[1]\n if (!date) return invalid('No date in the statement')\n const clearsigned = t.startsWith('-----BEGIN PGP SIGNED MESSAGE-----')\n const statement = clearsigned ? (t.split(/\\r?\\n\\r?\\n/)[1] ?? '').split('-----BEGIN PGP SIGNATURE-----')[0].trim() : t\n return { ...base, valid: true, data: { type: 'canary', date, statement, clearsigned } }\n }\n case 'thurin.private':\n case 'thurin.disclosure': {\n if (!t.startsWith('-----BEGIN PGP MESSAGE-----')) return invalid('Not a PGP message')\n let recipients: number | null = null\n try {\n const { readMessage } = await import('openpgp') // lazy, like pgp.ts: a static import breaks under jsdom\n recipients = (await readMessage({ armoredMessage: t })).getEncryptionKeyIDs().length\n } catch { return invalid('PGP message does not parse') }\n return { ...base, valid: true, data: { type: 'encrypted', recipients } }\n }\n case 'thurin.pointer': {\n try { return { ...base, valid: true, data: { type: 'pointer', releases: parsePointer(t).releases } } }\n catch { return invalid('Not a v1 pointer record') }\n }\n default:\n return { ...base, valid: true, data: { type: 'text' } }\n }\n}\n\n/** Minimal client shape: viem's PublicClient has it. */\nexport interface RecordReader {\n readContract(args: { address: `0x${string}`; abi: unknown; functionName: 'record'; args: readonly [`0x${string}`, bigint, Hex] }): Promise<unknown>\n}\n\n/**\n * Read and parse the given kinds on one claim. Kinds with no record are left out.\n * `registry` is the contract address; pass the kit's REGISTRY_ABI.\n */\nexport async function fetchRecords(\n client: RecordReader, registry: `0x${string}`, abi: unknown,\n owner: `0x${string}`, index: number | bigint, kinds: readonly string[] = IDENTITY_KINDS,\n): Promise<ParsedRecord[]> {\n const out: ParsedRecord[] = []\n for (const kind of kinds) {\n const hex = await client.readContract({ address: registry, abi, functionName: 'record', args: [owner, BigInt(index), recordKind(kind)] }) as Hex\n const text = decodeRecord(hex)\n if (text) out.push(await parseRecord(kind, text))\n }\n return out\n}\n"]}
|