@provex/eas 1.9.2-rc.20260720143033.2906fda
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/README.md +114 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# @provex/eas
|
|
2
|
+
|
|
3
|
+
Ethereum Attestation Service primitives behind Provex identity, age, and
|
|
4
|
+
release credentials — the schema definitions, the per-chain deployment
|
|
5
|
+
addresses, the claim encoders, and the decoders and signature-recovery
|
|
6
|
+
helpers a third party needs to **verify** a Provex credential.
|
|
7
|
+
|
|
8
|
+
Provex issues credentials as Ethereum Attestation Service **off-chain
|
|
9
|
+
attestations**: a signed EIP-712 payload carrying an encoded claim. Anyone
|
|
10
|
+
holding that payload can verify it without a blockchain read and without
|
|
11
|
+
asking Provex.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
npm install @provex/eas viem
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`viem` is a peer dependency.
|
|
20
|
+
|
|
21
|
+
## Entry points
|
|
22
|
+
|
|
23
|
+
| Import path | Contents | Runtime dependencies |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `@provex/eas` | Schema strings, chain deployment addresses, schema unique identifiers, claim encoders, off-chain and delegated builders | `viem`, Ethereum Attestation Service software development kit |
|
|
26
|
+
| `@provex/eas/build` | Claim encoders and attestation builders only | `viem`, Ethereum Attestation Service software development kit |
|
|
27
|
+
| `@provex/eas/verify` | Claim decoders and signature recovery | **`viem` only** |
|
|
28
|
+
|
|
29
|
+
If you are verifying rather than issuing, import from `@provex/eas/verify`.
|
|
30
|
+
That path never touches the Ethereum Attestation Service software
|
|
31
|
+
development kit, at any depth — the invariant is enforced by a test that
|
|
32
|
+
walks the module graph. It keeps browser bundles small and keeps your
|
|
33
|
+
dependency footprint to `viem`.
|
|
34
|
+
|
|
35
|
+
## Schemas
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Identity bytes32 platformHash,string handle,address user,uint64 expiresAt
|
|
39
|
+
Release bytes32 dappKey,bytes32 manifestHash,string domain,string version
|
|
40
|
+
Age bytes32 nullifier,bool overN,uint8 threshold,bool identityVerified,uint64 expiresAt
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Field order is load-bearing: the decoders read positionally.
|
|
44
|
+
|
|
45
|
+
The age claim deliberately carries no personal field. The date of birth,
|
|
46
|
+
legal name, and account identifier stay inside the issuer's trust boundary;
|
|
47
|
+
only `overN` ("is at least `threshold` years old") escapes it. `overN: false`
|
|
48
|
+
is a real signed answer, not an absence. The subject is bound by the
|
|
49
|
+
attestation's `recipient`, not by anything inside the claim.
|
|
50
|
+
|
|
51
|
+
Exported as `PROVEX_IDENTITY_SCHEMA`, `PROVEX_RELEASE_SCHEMA`, and
|
|
52
|
+
`PROVEX_AGE_SCHEMA` from `@provex/eas`.
|
|
53
|
+
|
|
54
|
+
## Schema unique identifiers
|
|
55
|
+
|
|
56
|
+
A schema's unique identifier is derived deterministically from the schema
|
|
57
|
+
itself:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
uid = keccak256(abi.encodePacked(schema, resolver, revocable))
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Provex registers every schema with `resolver = address(0)` and
|
|
64
|
+
`revocable = true`, so the unique identifier is reproducible from the schema
|
|
65
|
+
string alone — you do not have to trust a value we publish. The pinned
|
|
66
|
+
per-chain values are available through `getSchemaUid(chainId)`,
|
|
67
|
+
`getAgeSchemaUid(chainId)`, and `getReleaseSchemaUid(chainId)`.
|
|
68
|
+
|
|
69
|
+
## Verifying a Provex age credential
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import {
|
|
73
|
+
decodeAgeClaim,
|
|
74
|
+
liftWireOffchainAttestation,
|
|
75
|
+
recoverOffchainAttestationSigner,
|
|
76
|
+
} from '@provex/eas/verify'
|
|
77
|
+
|
|
78
|
+
// `wire` is the attestation as it arrived — JSON, so its numeric fields are
|
|
79
|
+
// strings. `liftWireOffchainAttestation` validates the shape and lifts
|
|
80
|
+
// `time` / `expirationTime` back to bigint, which signature recovery needs.
|
|
81
|
+
const attestation = liftWireOffchainAttestation(wire)
|
|
82
|
+
|
|
83
|
+
const { valid, signer } = await recoverOffchainAttestationSigner(
|
|
84
|
+
attestation,
|
|
85
|
+
PROVEX_ATTESTER_ADDRESS, // optional; omit to recover without asserting
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if (!valid) throw new Error('Attestation signature did not verify')
|
|
89
|
+
|
|
90
|
+
const claim = decodeAgeClaim(attestation.message.data)
|
|
91
|
+
|
|
92
|
+
const nowInSeconds = BigInt(Math.floor(Date.now() / 1000))
|
|
93
|
+
const accepted =
|
|
94
|
+
claim.overN &&
|
|
95
|
+
claim.threshold >= 18 &&
|
|
96
|
+
claim.expiresAt > nowInSeconds
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Three things are worth being explicit about:
|
|
100
|
+
|
|
101
|
+
1. **Without `expectedSigner`, `valid` means only that recovery succeeded.**
|
|
102
|
+
The signer could be anyone. Compare `signer` against an attester you
|
|
103
|
+
actually trust before acting on the claim.
|
|
104
|
+
2. **Check `expiresAt` yourself.** Signature validity says nothing about
|
|
105
|
+
freshness.
|
|
106
|
+
3. **Check `threshold` against your own requirement.** A credential attesting
|
|
107
|
+
`overN` at `threshold: 13` is a valid signature that does not establish
|
|
108
|
+
that the holder is 18.
|
|
109
|
+
|
|
110
|
+
The `nullifier` is a stable per-subject identifier you can use to detect the
|
|
111
|
+
same person presenting twice, without learning who they are.
|
|
112
|
+
|
|
113
|
+
Identity and release credentials verify the same way, via `decodeIdentityClaim`
|
|
114
|
+
and `decodeReleaseClaim`.
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@provex/eas",
|
|
3
|
+
"version": "1.9.2-rc.20260720143033.2906fda",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/provex-tech/monorepo.git",
|
|
10
|
+
"directory": "packages/eas"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts"
|
|
19
|
+
},
|
|
20
|
+
"./build": {
|
|
21
|
+
"import": "./dist/eas-builder.js",
|
|
22
|
+
"types": "./dist/eas-builder.d.ts"
|
|
23
|
+
},
|
|
24
|
+
"./verify": {
|
|
25
|
+
"import": "./dist/offchain-verify.js",
|
|
26
|
+
"types": "./dist/offchain-verify.d.ts"
|
|
27
|
+
},
|
|
28
|
+
"./eas": {
|
|
29
|
+
"import": "./dist/eas.js",
|
|
30
|
+
"types": "./dist/eas.d.ts"
|
|
31
|
+
},
|
|
32
|
+
"./eas-builder": {
|
|
33
|
+
"import": "./dist/eas-builder.js",
|
|
34
|
+
"types": "./dist/eas-builder.d.ts"
|
|
35
|
+
},
|
|
36
|
+
"./offchain-verify": {
|
|
37
|
+
"import": "./dist/offchain-verify.js",
|
|
38
|
+
"types": "./dist/offchain-verify.d.ts"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc",
|
|
43
|
+
"test": "node --import tsx --test 'src/**/*.test.ts'",
|
|
44
|
+
"test:watch": "node --import tsx --test --watch 'src/**/*.test.ts'"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"README.md"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@ethereum-attestation-service/eas-sdk": "^2.9.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"viem": "^2.0.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/node": "^22.0.0",
|
|
58
|
+
"tsx": "^4.20.3",
|
|
59
|
+
"typescript": "^5.9.2",
|
|
60
|
+
"viem": "^2.38.0"
|
|
61
|
+
}
|
|
62
|
+
}
|