@pvium/p2id-core 0.1.0 → 0.1.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/README.md CHANGED
@@ -21,7 +21,10 @@ Requires Node.js 20+ or a browser with Web Crypto support.
21
21
  ```ts
22
22
  import { p2idAddress, IdentityType } from '@pvium/p2id-core';
23
23
 
24
- const to = p2idAddress({ identityType: IdentityType.Email, identityValue: 'you@example.com' });
24
+ const to = p2idAddress({
25
+ identityType: IdentityType.Email,
26
+ identityValue: 'you@example.com',
27
+ });
25
28
  // Checksummed vault address for native coin or supported ERC-20 transfers.
26
29
  ```
27
30
 
@@ -31,8 +34,16 @@ Email addresses are case-insensitive: `You@Example.com` derives the same address
31
34
  Production is the default environment. Use `sandbox` on testnets or pass a custom factory address:
32
35
 
33
36
  ```ts
34
- p2idAddress({ identityType: IdentityType.X, identityValue: 'jack', environment: 'sandbox' });
35
- p2idAddress({ identityType: IdentityType.Github, identityValue: 'octocat', factory: '0xYourFactory…' });
37
+ p2idAddress({
38
+ identityType: IdentityType.X,
39
+ identityValue: 'jack',
40
+ environment: 'sandbox',
41
+ });
42
+ p2idAddress({
43
+ identityType: IdentityType.Github,
44
+ identityValue: 'octocat',
45
+ factory: '0xYourFactory…',
46
+ });
36
47
  ```
37
48
 
38
49
  Derivation requires a recorded factory for the selected environment or an explicit `factory`.
@@ -45,15 +56,25 @@ Using [ethers](https://docs.ethers.org) v6:
45
56
  import { ethers } from 'ethers';
46
57
  import { p2idAddress, IdentityType } from '@pvium/p2id-core';
47
58
 
48
- const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, new ethers.JsonRpcProvider(process.env.RPC_URL));
49
- const to = p2idAddress({ identityType: IdentityType.Telegram, identityValue: 'durov' });
59
+ const signer = new ethers.Wallet(
60
+ process.env.PRIVATE_KEY!,
61
+ new ethers.JsonRpcProvider(process.env.RPC_URL),
62
+ );
63
+ const to = p2idAddress({
64
+ identityType: IdentityType.Telegram,
65
+ identityValue: 'durov',
66
+ });
50
67
 
51
68
  // the native coin (BNB on BNB Chain, ETH on Base)
52
69
  await signer.sendTransaction({ to, value: ethers.parseEther('0.1') });
53
70
 
54
71
  // an ERC-20
55
72
  const USDC = '0x…'; // the token's contract address on the chain you are paying on
56
- const usdc = new ethers.Contract(USDC, ['function transfer(address to, uint256 amount) returns (bool)'], signer);
73
+ const usdc = new ethers.Contract(
74
+ USDC,
75
+ ['function transfer(address to, uint256 amount) returns (bool)'],
76
+ signer,
77
+ );
57
78
  await usdc.transfer(to, 25_000_000n); // 25 USDC (6 decimals)
58
79
  ```
59
80
 
@@ -69,39 +90,50 @@ deposit after that window elapses.
69
90
  import { ethers } from 'ethers';
70
91
  import { identityHash, p2idScheme, IdentityType } from '@pvium/p2id-core';
71
92
 
72
- const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, new ethers.JsonRpcProvider(process.env.RPC_URL));
93
+ const signer = new ethers.Wallet(
94
+ process.env.PRIVATE_KEY!,
95
+ new ethers.JsonRpcProvider(process.env.RPC_URL),
96
+ );
73
97
  const factory = new ethers.Contract(
74
98
  p2idScheme().factories.production!, // or .sandbox on testnets
75
- ['function fund(bytes32 identityHash, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) payable returns (address vault, uint256 depositId)'],
99
+ [
100
+ 'function fund(bytes32 identityHash, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) payable returns (address vault, uint256 depositId)',
101
+ ],
76
102
  signer,
77
103
  );
78
104
 
79
105
  const id = identityHash(IdentityType.Email, 'you@example.com');
80
106
  const NO_CONSTRAINT = ethers.ZeroHash; // no additional claim requirement
81
- const WEEK = 7 * 24 * 3600; // refund window in seconds
82
- const ref = ethers.id('invoice-42'); // application-defined bytes32; ethers.ZeroHash for none
107
+ const WEEK = 7 * 24 * 3600; // refund window in seconds
108
+ const ref = ethers.id('invoice-42'); // application-defined bytes32; ethers.ZeroHash for none
83
109
 
84
110
  // Native coin: use the zero address for `token` and send `amount` as transaction value.
85
111
  const amount = ethers.parseEther('0.1');
86
- await factory.fund(id, ethers.ZeroAddress, amount, NO_CONSTRAINT, WEEK, ref, { value: amount });
112
+ await factory.fund(id, ethers.ZeroAddress, amount, NO_CONSTRAINT, WEEK, ref, {
113
+ value: amount,
114
+ });
87
115
 
88
116
  // an ERC-20: approve the factory, then fund
89
117
  const USDC = '0x…'; // the token's contract address
90
- const usdc = new ethers.Contract(USDC, ['function approve(address spender, uint256 amount) returns (bool)'], signer);
118
+ const usdc = new ethers.Contract(
119
+ USDC,
120
+ ['function approve(address spender, uint256 amount) returns (bool)'],
121
+ signer,
122
+ );
91
123
  await usdc.approve(await factory.getAddress(), 25_000_000n);
92
124
  await factory.fund(id, USDC, 25_000_000n, NO_CONSTRAINT, WEEK, ref);
93
125
  ```
94
126
 
95
127
  `fund` accepts the same arguments for native coin and ERC-20 deposits:
96
128
 
97
- | Argument | Meaning |
98
- | --- | --- |
99
- | `identityHash` | Recipient commitment from `identityHash(type, value)` |
100
- | `token` | ERC-20 contract address, or the zero address for native coin |
101
- | `amount` | Amount in the asset's smallest unit |
102
- | `constraint` | A 32-byte commitment to an additional claim requirement; zero for none |
103
- | `refundWindow` | Seconds before an unclaimed deposit becomes refundable |
104
- | `ref` | Application-defined 32-byte reference, emitted in `Funded`; zero for none |
129
+ | Argument | Meaning |
130
+ | -------------- | ------------------------------------------------------------------------- |
131
+ | `identityHash` | Recipient commitment from `identityHash(type, value)` |
132
+ | `token` | ERC-20 contract address, or the zero address for native coin |
133
+ | `amount` | Amount in the asset's smallest unit |
134
+ | `constraint` | A 32-byte commitment to an additional claim requirement; zero for none |
135
+ | `refundWindow` | Seconds before an unclaimed deposit becomes refundable |
136
+ | `ref` | Application-defined 32-byte reference, emitted in `Funded`; zero for none |
105
137
 
106
138
  The window must fall within the factory's configured limits. After it elapses, the funder calls
107
139
  `refund(depositId)` on the vault. Contract interfaces are included; see [Solidity](#solidity).
@@ -123,7 +155,11 @@ Read native coin and ERC-20 balances at the derived address:
123
155
  const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
124
156
  await provider.getBalance(to); // native coin
125
157
 
126
- const token = new ethers.Contract(USDC, ['function balanceOf(address) view returns (uint256)'], provider);
158
+ const token = new ethers.Contract(
159
+ USDC,
160
+ ['function balanceOf(address) view returns (uint256)'],
161
+ provider,
162
+ );
127
163
  await token.balanceOf(to); // ERC-20
128
164
  ```
129
165
 
@@ -136,21 +172,21 @@ identity provider: it does not accept provider-specific account types (e.g. Priv
136
172
  these to the numeric IDs used in identity hashes, and `identityTypeName` gives the P2ID name of an
137
173
  ID. The type table is append-only.
138
174
 
139
- | `IdentityType.` | Id | Value | Example | Lowercased |
140
- | --- | ---: | --- | --- | :---: |
141
- | `Email` | 0 | address | `you@example.com` | yes |
142
- | `Phone` | 1 | E.164 number | `+15551234567` | no |
143
- | `Google` | 2 | email | `you@gmail.com` | yes |
144
- | `X` (alias `Twitter`) | 3 | username, no `@` | `jack` | yes |
145
- | `Discord` | 4 | username | `wumpus` | yes |
146
- | `Github` | 5 | username | `octocat` | yes |
147
- | `Linkedin` | 6 | email | `you@example.com` | yes |
148
- | `Apple` | 7 | email | `you@icloud.com` | yes |
149
- | `Telegram` | 8 | username | `durov` | yes |
150
- | `Tiktok` | 9 | username | `charlidamelio` | yes |
151
- | `Instagram` | 10 | username | `instagram` | yes |
152
- | `Farcaster` | 11 | username | `dwr` | yes |
153
- | `Wallet` | 12 | address | `0xA01b…0f98` or base58 | only `0x…` |
175
+ | `IdentityType.` | Id | Value | Example | Lowercased |
176
+ | --------------------- | --: | ---------------- | ----------------------- | :--------: |
177
+ | `Email` | 0 | address | `you@example.com` | yes |
178
+ | `Phone` | 1 | E.164 number | `+15551234567` | no |
179
+ | `Google` | 2 | email | `you@gmail.com` | yes |
180
+ | `X` (alias `Twitter`) | 3 | username, no `@` | `jack` | yes |
181
+ | `Discord` | 4 | username | `wumpus` | yes |
182
+ | `Github` | 5 | username | `octocat` | yes |
183
+ | `Linkedin` | 6 | email | `you@example.com` | yes |
184
+ | `Apple` | 7 | email | `you@icloud.com` | yes |
185
+ | `Telegram` | 8 | username | `durov` | yes |
186
+ | `Tiktok` | 9 | username | `charlidamelio` | yes |
187
+ | `Instagram` | 10 | username | `instagram` | yes |
188
+ | `Farcaster` | 11 | username | `dwr` | yes |
189
+ | `Wallet` | 12 | address | `0xA01b…0f98` or base58 | only `0x…` |
154
190
 
155
191
  The same email produces different addresses under `Email`, `Google`, `Linkedin` and `Apple`.
156
192
  Select the type the recipient will use to authenticate.
@@ -165,13 +201,19 @@ p2id = keccak256( 0xff ‖ factory ‖ identityHash ‖ vaultInitCodeHas
165
201
  ```
166
202
 
167
203
  ```ts
168
- import { identityHash, p2idAddressForHash, p2idScheme, P2ID_SCHEME, IdentityType } from '@pvium/p2id-core';
204
+ import {
205
+ identityHash,
206
+ p2idAddressForHash,
207
+ p2idScheme,
208
+ P2ID_SCHEME,
209
+ IdentityType,
210
+ } from '@pvium/p2id-core';
169
211
 
170
212
  const hash = identityHash(IdentityType.Email, 'you@example.com'); // identity commitment and vault salt
171
- p2idAddressForHash(hash, { environment: 'sandbox' }); // same result as p2idAddress(...)
213
+ p2idAddressForHash(hash, { environment: 'sandbox' }); // same result as p2idAddress(...)
172
214
 
173
- P2ID_SCHEME; // 'pvium.vault.v1', the current address scheme
174
- p2idScheme(); // { identityDomain, vaultInitCodeHash, factories: { production, sandbox } }
215
+ P2ID_SCHEME; // 'pvium.vault.v1', the current address scheme
216
+ p2idScheme(); // { identityDomain, vaultInitCodeHash, factories: { production, sandbox } }
175
217
  ```
176
218
 
177
219
  The formula excludes the chain ID. Addresses match across chains with standard CREATE2 semantics
@@ -215,7 +257,9 @@ For a base64-encoded attestation proof:
215
257
  ```ts
216
258
  const hash = identityHash(IdentityType.Email, 'you@example.com');
217
259
  const proof = ethers.decodeBase64(attestation.proof);
218
- await payByEmail.pay(proof, publicInputFields, hash, attestation.wallet, { value });
260
+ await payByEmail.pay(proof, publicInputFields, hash, attestation.wallet, {
261
+ value,
262
+ });
219
263
  ```
220
264
 
221
265
  `verifyIdentity` checks the identity type, identity hash and wallet hash against the proof.
@@ -228,12 +272,12 @@ For a wallet on another chain, such as a base58 Solana address, pass
228
272
 
229
273
  ## Exports
230
274
 
231
- | Export | Purpose |
232
- | --- | --- |
233
- | `p2idAddress(input)` | Derive a vault address from `{ identityType, identityValue, environment?, scheme?, factory? }` |
234
- | `p2idAddressForHash(hash, opts?)` | Derive a vault address from an identity hash |
235
- | `identityHash(type, value, scheme?)` | Compute the identity commitment used as the vault salt |
236
- | `P2ID_SCHEME`, `P2ID_SCHEMES`, `p2idScheme(name?)` | Read address-scheme constants |
237
- | `IdentityType`, `IdentityTypeName`, `IDENTITY_TYPE_BY_NAME`, `resolveIdentityType` | Identity type IDs and name mappings |
238
- | `normalizeIdentityValue`, `isCaseInsensitive`, `HASH_PREFIX` | Identity normalisation rules and hash prefix |
239
- | `checksumAddress`, `toHex` | Address checksum and hexadecimal encoding |
275
+ | Export | Purpose |
276
+ | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
277
+ | `p2idAddress(input)` | Derive a vault address from `{ identityType, identityValue, environment?, scheme?, factory? }` |
278
+ | `p2idAddressForHash(hash, opts?)` | Derive a vault address from an identity hash |
279
+ | `identityHash(type, value, scheme?)` | Compute the identity commitment used as the vault salt |
280
+ | `P2ID_SCHEME`, `P2ID_SCHEMES`, `p2idScheme(name?)` | Read address-scheme constants |
281
+ | `IdentityType`, `IdentityTypeName`, `IDENTITY_TYPE_BY_NAME`, `resolveIdentityType` | Identity type IDs and name mappings |
282
+ | `normalizeIdentityValue`, `isCaseInsensitive`, `HASH_PREFIX` | Identity normalisation rules and hash prefix |
283
+ | `checksumAddress`, `toHex` | Address checksum and hexadecimal encoding |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pvium/p2id-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "P2ID protocol core: identity types and hashing, chain-agnostic P2ID address derivation, and the Solidity sources",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,4 +41,4 @@
41
41
  "engines": {
42
42
  "node": ">=20"
43
43
  }
44
- }
44
+ }
@@ -1,38 +0,0 @@
1
- /**
2
- * Identity types. The numeric value is the protocol's type id (it is what gets hashed), so it
3
- * must match circuit/src/identity.nr and never change.
4
- */
5
- export declare enum IdentityType {
6
- Email = 0,
7
- Phone = 1,
8
- Google = 2,
9
- Twitter = 3,
10
- /** Alias of `Twitter`: the platform's current name. Same id, same addresses. */
11
- X = 3,
12
- Discord = 4,
13
- Github = 5,
14
- Linkedin = 6,
15
- Apple = 7,
16
- Telegram = 8,
17
- Tiktok = 9,
18
- Instagram = 10,
19
- Farcaster = 11,
20
- Wallet = 12
21
- }
22
- /** Domain-separation prefix baked into the circuit's identity hash. */
23
- export declare const HASH_PREFIX = "p2id.identity.v1";
24
- /** Types whose value is ASCII-lowercased before hashing: everything except phone numbers and
25
- * wallet addresses (matches CASE_INSENSITIVE in circuit/src/identity.nr). */
26
- export declare function isCaseInsensitive(type: IdentityType): boolean;
27
- /**
28
- * Apply the circuit's normalisation to an identity value: ASCII-lowercase for case-insensitive
29
- * types and for EVM (`0x…`) wallet addresses; base58 (Solana) addresses are left untouched.
30
- */
31
- export declare function normalizeIdentityValue(type: IdentityType, value: string): string;
32
- /**
33
- * `sha256(HASH_PREFIX || type || normalize(value))`, exactly as the circuit computes it.
34
- * This is the routing salt a payer uses to address an identity, and the value a proof's
35
- * `identityHash` output is compared against.
36
- */
37
- export declare function identityHash(type: IdentityType, value: string, domain?: string): `0x${string}`;
38
- export declare function toHex(bytes: Uint8Array): `0x${string}`;
package/dist/identity.js DELETED
@@ -1,61 +0,0 @@
1
- import { sha256 } from '@noble/hashes/sha256';
2
- /**
3
- * Identity types. The numeric value is the protocol's type id (it is what gets hashed), so it
4
- * must match circuit/src/identity.nr and never change.
5
- */
6
- export var IdentityType;
7
- (function (IdentityType) {
8
- IdentityType[IdentityType["Email"] = 0] = "Email";
9
- IdentityType[IdentityType["Phone"] = 1] = "Phone";
10
- IdentityType[IdentityType["Google"] = 2] = "Google";
11
- IdentityType[IdentityType["Twitter"] = 3] = "Twitter";
12
- /** Alias of `Twitter`: the platform's current name. Same id, same addresses. */
13
- IdentityType[IdentityType["X"] = 3] = "X";
14
- IdentityType[IdentityType["Discord"] = 4] = "Discord";
15
- IdentityType[IdentityType["Github"] = 5] = "Github";
16
- IdentityType[IdentityType["Linkedin"] = 6] = "Linkedin";
17
- IdentityType[IdentityType["Apple"] = 7] = "Apple";
18
- IdentityType[IdentityType["Telegram"] = 8] = "Telegram";
19
- IdentityType[IdentityType["Tiktok"] = 9] = "Tiktok";
20
- IdentityType[IdentityType["Instagram"] = 10] = "Instagram";
21
- IdentityType[IdentityType["Farcaster"] = 11] = "Farcaster";
22
- IdentityType[IdentityType["Wallet"] = 12] = "Wallet";
23
- })(IdentityType || (IdentityType = {}));
24
- /** Domain-separation prefix baked into the circuit's identity hash. */
25
- export const HASH_PREFIX = 'p2id.identity.v1';
26
- /** Types whose value is ASCII-lowercased before hashing: everything except phone numbers and
27
- * wallet addresses (matches CASE_INSENSITIVE in circuit/src/identity.nr). */
28
- export function isCaseInsensitive(type) {
29
- return type !== IdentityType.Wallet && type !== IdentityType.Phone;
30
- }
31
- /**
32
- * Apply the circuit's normalisation to an identity value: ASCII-lowercase for case-insensitive
33
- * types and for EVM (`0x…`) wallet addresses; base58 (Solana) addresses are left untouched.
34
- */
35
- export function normalizeIdentityValue(type, value) {
36
- const lower = isCaseInsensitive(type) || (type === IdentityType.Wallet && value.startsWith('0x'));
37
- return lower ? value.replace(/[A-Z]/g, (c) => c.toLowerCase()) : value;
38
- }
39
- /**
40
- * `sha256(HASH_PREFIX || type || normalize(value))`, exactly as the circuit computes it.
41
- * This is the routing salt a payer uses to address an identity, and the value a proof's
42
- * `identityHash` output is compared against.
43
- */
44
- export function identityHash(type, value, domain = HASH_PREFIX) {
45
- const enc = new TextEncoder();
46
- const prefix = enc.encode(domain);
47
- const body = enc.encode(normalizeIdentityValue(type, value));
48
- if (body.length < 1 || body.length > 128)
49
- throw new Error('identity value must be 1..128 bytes');
50
- const preimage = new Uint8Array(prefix.length + 1 + body.length);
51
- preimage.set(prefix, 0);
52
- preimage[prefix.length] = type;
53
- preimage.set(body, prefix.length + 1);
54
- return toHex(sha256(preimage));
55
- }
56
- export function toHex(bytes) {
57
- let s = '';
58
- for (const b of bytes)
59
- s += b.toString(16).padStart(2, '0');
60
- return `0x${s}`;
61
- }
@@ -1,43 +0,0 @@
1
- import { IdentityType } from './identity.js';
2
- /** P2ID type names (the URI names in P2ID.md). */
3
- export declare const P2ID_TYPE_NAMES: {
4
- readonly email: IdentityType.Email;
5
- readonly phone: IdentityType.Phone;
6
- readonly google: IdentityType.Google;
7
- readonly x: IdentityType.Twitter;
8
- readonly discord: IdentityType.Discord;
9
- readonly github: IdentityType.Github;
10
- readonly linkedin: IdentityType.Linkedin;
11
- readonly apple: IdentityType.Apple;
12
- readonly telegram: IdentityType.Telegram;
13
- readonly tiktok: IdentityType.Tiktok;
14
- readonly instagram: IdentityType.Instagram;
15
- readonly farcaster: IdentityType.Farcaster;
16
- readonly wallet: IdentityType.Wallet;
17
- };
18
- /**
19
- * Every accepted name: the canonical P2ID names plus `twitter` (an alias of `x`). P2ID core is
20
- * agnostic of any identity provider — it does not know Privy (or any other verifier's) account
21
- * types. Callers map their provider's account types to these names themselves.
22
- */
23
- export declare const IDENTITY_TYPE_BY_NAME: {
24
- readonly twitter: IdentityType.Twitter;
25
- readonly email: IdentityType.Email;
26
- readonly phone: IdentityType.Phone;
27
- readonly google: IdentityType.Google;
28
- readonly x: IdentityType.Twitter;
29
- readonly discord: IdentityType.Discord;
30
- readonly github: IdentityType.Github;
31
- readonly linkedin: IdentityType.Linkedin;
32
- readonly apple: IdentityType.Apple;
33
- readonly telegram: IdentityType.Telegram;
34
- readonly tiktok: IdentityType.Tiktok;
35
- readonly instagram: IdentityType.Instagram;
36
- readonly farcaster: IdentityType.Farcaster;
37
- readonly wallet: IdentityType.Wallet;
38
- };
39
- export type P2IDTypeName = keyof typeof P2ID_TYPE_NAMES;
40
- /** The P2ID name of a type, e.g. IdentityType.Twitter -> "x". */
41
- export declare function identityTypeName(type: IdentityType): P2IDTypeName;
42
- export type IdentityTypeName = keyof typeof IDENTITY_TYPE_BY_NAME;
43
- export declare function resolveIdentityType(t: IdentityType | IdentityTypeName): IdentityType;
@@ -1,44 +0,0 @@
1
- import { IdentityType } from './identity.js';
2
- /** P2ID type names (the URI names in P2ID.md). */
3
- export const P2ID_TYPE_NAMES = {
4
- email: IdentityType.Email,
5
- phone: IdentityType.Phone,
6
- google: IdentityType.Google,
7
- x: IdentityType.X,
8
- discord: IdentityType.Discord,
9
- github: IdentityType.Github,
10
- linkedin: IdentityType.Linkedin,
11
- apple: IdentityType.Apple,
12
- telegram: IdentityType.Telegram,
13
- tiktok: IdentityType.Tiktok,
14
- instagram: IdentityType.Instagram,
15
- farcaster: IdentityType.Farcaster,
16
- wallet: IdentityType.Wallet,
17
- };
18
- /**
19
- * Every accepted name: the canonical P2ID names plus `twitter` (an alias of `x`). P2ID core is
20
- * agnostic of any identity provider — it does not know Privy (or any other verifier's) account
21
- * types. Callers map their provider's account types to these names themselves.
22
- */
23
- export const IDENTITY_TYPE_BY_NAME = {
24
- ...P2ID_TYPE_NAMES,
25
- twitter: IdentityType.Twitter,
26
- };
27
- /** The P2ID name of a type, e.g. IdentityType.Twitter -> "x". */
28
- export function identityTypeName(type) {
29
- const entry = Object.entries(P2ID_TYPE_NAMES).find(([, id]) => id === type);
30
- if (!entry)
31
- throw new Error(`unknown identity type id ${type}`);
32
- return entry[0];
33
- }
34
- export function resolveIdentityType(t) {
35
- if (typeof t === 'number') {
36
- if (!Object.values(IDENTITY_TYPE_BY_NAME).includes(t))
37
- throw new Error(`unknown identity type id ${t}`);
38
- return t;
39
- }
40
- const id = IDENTITY_TYPE_BY_NAME[t];
41
- if (id === undefined)
42
- throw new Error(`unknown identity type "${t}"`);
43
- return id;
44
- }
package/dist/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export { IdentityType, HASH_PREFIX, isCaseInsensitive, normalizeIdentityValue, toHex } from './identity.js';
2
- export { IDENTITY_TYPE_BY_NAME, P2ID_TYPE_NAMES, identityTypeName, resolveIdentityType } from './identityNames.js';
3
- export type { IdentityTypeName, P2IDTypeName } from './identityNames.js';
4
- export { identityHash, p2idAddress, p2idAddressForHash, p2idScheme, checksumAddress, P2ID_SCHEME, P2ID_SCHEMES } from './p2id.js';
5
- export type { P2IDAddressInput, P2IDEnvironment, P2IDScheme, P2IDSchemeName } from './p2id.js';
package/dist/index.js DELETED
@@ -1,5 +0,0 @@
1
- // P2ID protocol core: no proof verification here, and no heavy dependencies, so it is safe in
2
- // browsers. Verifying attestations lives in @pvium/p2id-verifier.
3
- export { IdentityType, HASH_PREFIX, isCaseInsensitive, normalizeIdentityValue, toHex } from './identity.js';
4
- export { IDENTITY_TYPE_BY_NAME, P2ID_TYPE_NAMES, identityTypeName, resolveIdentityType } from './identityNames.js';
5
- export { identityHash, p2idAddress, p2idAddressForHash, p2idScheme, checksumAddress, P2ID_SCHEME, P2ID_SCHEMES } from './p2id.js';
package/dist/p2id.d.ts DELETED
@@ -1,54 +0,0 @@
1
- import { IdentityType } from './identity.js';
2
- import { type IdentityTypeName } from './identityNames.js';
3
- import { P2ID_SCHEME, P2ID_SCHEMES, type P2IDScheme, type P2IDSchemeName } from './p2idConstants.js';
4
- export { P2ID_SCHEME, P2ID_SCHEMES };
5
- export type { P2IDScheme, P2IDSchemeName };
6
- /** A Pvium environment: `production` (mainnets) or `sandbox` (testnets). Each has its own factory. */
7
- export type P2IDEnvironment = 'production' | 'sandbox';
8
- /**
9
- * P2ID address derivation.
10
- *
11
- * identityHash = sha256(identityDomain ‖ byte(typeId) ‖ normalize(value))
12
- * p2id = keccak256(0xff ‖ factory ‖ identityHash ‖ vaultInitCodeHash)[12..]
13
- *
14
- * `normalize` ASCII-lowercases every type except phone and wallet, and lowercases `0x…` wallet
15
- * addresses. A *scheme* (`p2id.vault.vN`) fixes the three constants: the identity domain, the
16
- * vault creation-code hash and the factory. The factory is deployed through the deterministic
17
- * deployment proxy, so it is at the same address on every EVM chain: a P2ID address is
18
- * chain-agnostic, like any wallet address. (The vault contract still has to be deployed on each
19
- * chain where it is claimed; anyone can do that, and funds sent before then are claimable once
20
- * it is.)
21
- *
22
- * Each Pvium environment is its own stack: `production` (mainnets, the production Privy app) and
23
- * `sandbox` (testnets, the sandbox Privy app) have different factories, so the same identity has
24
- * a different address in each. Production is the default.
25
- *
26
- * Schemes are history. A change to the vault bytecode moves every address, so it ships as the
27
- * next scheme and becomes `P2ID_SCHEME`; earlier schemes stay in `P2ID_SCHEMES` so addresses
28
- * people were already given can be derived, and claimed, forever.
29
- */
30
- /** Constants of a scheme; defaults to the current one. */
31
- export declare function p2idScheme(name?: P2IDSchemeName | string): P2IDScheme;
32
- /** The identity commitment: the CREATE2 salt of the identity's vault and the value proofs bind. */
33
- export declare function identityHash(type: IdentityType | IdentityTypeName, value: string, scheme?: P2IDSchemeName | string): `0x${string}`;
34
- export interface P2IDAddressInput {
35
- identityType: IdentityType | IdentityTypeName;
36
- /** The identity as the user linked it, e.g. "you@example.com". Case does not matter. */
37
- identityValue: string;
38
- /** Address scheme; defaults to the current one (`P2ID_SCHEME`). Pass an older one to find an address issued under it. */
39
- scheme?: P2IDSchemeName | string;
40
- /** Pvium environment; defaults to `production`. Use `sandbox` on testnets. */
41
- environment?: P2IDEnvironment;
42
- /** Derive against another factory than the scheme's (e.g. a test deployment). */
43
- factory?: `0x${string}`;
44
- }
45
- /** The P2ID address for an identity: where to pay it, on any EVM chain, deployed or not. Checksummed. */
46
- export declare function p2idAddress(input: P2IDAddressInput): `0x${string}`;
47
- /** Same, from an identity hash you already have (e.g. from an attestation's claim). */
48
- export declare function p2idAddressForHash(identityHash: `0x${string}`, opts?: {
49
- scheme?: P2IDSchemeName | string;
50
- environment?: P2IDEnvironment;
51
- factory?: `0x${string}`;
52
- }): `0x${string}`;
53
- /** EIP-55 checksum. */
54
- export declare function checksumAddress(address: `0x${string}`): `0x${string}`;
package/dist/p2id.js DELETED
@@ -1,82 +0,0 @@
1
- import { keccak_256 } from '@noble/hashes/sha3';
2
- import { identityHash as hashIdentity, toHex } from './identity.js';
3
- import { resolveIdentityType } from './identityNames.js';
4
- import { P2ID_SCHEME, P2ID_SCHEMES } from './p2idConstants.js';
5
- export { P2ID_SCHEME, P2ID_SCHEMES };
6
- /**
7
- * P2ID address derivation.
8
- *
9
- * identityHash = sha256(identityDomain ‖ byte(typeId) ‖ normalize(value))
10
- * p2id = keccak256(0xff ‖ factory ‖ identityHash ‖ vaultInitCodeHash)[12..]
11
- *
12
- * `normalize` ASCII-lowercases every type except phone and wallet, and lowercases `0x…` wallet
13
- * addresses. A *scheme* (`p2id.vault.vN`) fixes the three constants: the identity domain, the
14
- * vault creation-code hash and the factory. The factory is deployed through the deterministic
15
- * deployment proxy, so it is at the same address on every EVM chain: a P2ID address is
16
- * chain-agnostic, like any wallet address. (The vault contract still has to be deployed on each
17
- * chain where it is claimed; anyone can do that, and funds sent before then are claimable once
18
- * it is.)
19
- *
20
- * Each Pvium environment is its own stack: `production` (mainnets, the production Privy app) and
21
- * `sandbox` (testnets, the sandbox Privy app) have different factories, so the same identity has
22
- * a different address in each. Production is the default.
23
- *
24
- * Schemes are history. A change to the vault bytecode moves every address, so it ships as the
25
- * next scheme and becomes `P2ID_SCHEME`; earlier schemes stay in `P2ID_SCHEMES` so addresses
26
- * people were already given can be derived, and claimed, forever.
27
- */
28
- /** Constants of a scheme; defaults to the current one. */
29
- export function p2idScheme(name = P2ID_SCHEME) {
30
- const s = P2ID_SCHEMES[name];
31
- if (!s)
32
- throw new Error(`unknown P2ID scheme "${name}" (known: ${Object.keys(P2ID_SCHEMES).join(', ')})`);
33
- return s;
34
- }
35
- /** The identity commitment: the CREATE2 salt of the identity's vault and the value proofs bind. */
36
- export function identityHash(type, value, scheme = P2ID_SCHEME) {
37
- return hashIdentity(resolveIdentityType(type), value, p2idScheme(scheme).identityDomain);
38
- }
39
- /** The P2ID address for an identity: where to pay it, on any EVM chain, deployed or not. Checksummed. */
40
- export function p2idAddress(input) {
41
- const salt = identityHash(input.identityType, input.identityValue, input.scheme);
42
- return p2idAddressForHash(salt, { scheme: input.scheme, environment: input.environment, factory: input.factory });
43
- }
44
- /** Same, from an identity hash you already have (e.g. from an attestation's claim). */
45
- export function p2idAddressForHash(identityHash, opts = {}) {
46
- const scheme = p2idScheme(opts.scheme);
47
- const environment = opts.environment ?? 'production';
48
- if (environment !== 'production' && environment !== 'sandbox')
49
- throw new Error(`unknown environment "${environment}"`);
50
- const factory = opts.factory ?? scheme.factories[environment];
51
- if (!factory) {
52
- throw new Error(`scheme ${opts.scheme ?? P2ID_SCHEME} has no ${environment} factory address in this release yet; pass \`factory\` explicitly`);
53
- }
54
- if (!/^0x[0-9a-fA-F]{40}$/.test(factory))
55
- throw new Error(`bad factory address ${factory}`);
56
- const preimage = new Uint8Array(1 + 20 + 32 + 32);
57
- preimage[0] = 0xff;
58
- preimage.set(hexToBytes(factory, 20), 1);
59
- preimage.set(hexToBytes(identityHash, 32), 21);
60
- preimage.set(hexToBytes(scheme.vaultInitCodeHash, 32), 53);
61
- return checksumAddress(toHex(keccak_256(preimage).subarray(12)));
62
- }
63
- /** EIP-55 checksum. */
64
- export function checksumAddress(address) {
65
- const lower = address.slice(2).toLowerCase();
66
- const hash = keccak_256(new TextEncoder().encode(lower));
67
- let out = '0x';
68
- for (let i = 0; i < 40; i++) {
69
- const nibble = (hash[i >> 1] >> (i % 2 === 0 ? 4 : 0)) & 0xf;
70
- out += nibble >= 8 ? lower[i].toUpperCase() : lower[i];
71
- }
72
- return out;
73
- }
74
- function hexToBytes(hex, length) {
75
- const h = hex.startsWith('0x') ? hex.slice(2) : hex;
76
- if (h.length !== length * 2 || !/^[0-9a-fA-F]*$/.test(h))
77
- throw new Error(`expected ${length}-byte hex, got ${hex}`);
78
- const out = new Uint8Array(length);
79
- for (let i = 0; i < length; i++)
80
- out[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
81
- return out;
82
- }
@@ -1,38 +0,0 @@
1
- export interface P2IDScheme {
2
- /** Domain prefix of the identity hash this scheme salts vaults with, e.g. "p2id.identity.v1". */
3
- identityDomain: string;
4
- /** keccak256 of the P2IDVault creation code; with the factory address it fixes every vault address. */
5
- vaultInitCodeHash: `0x${string}`;
6
- /**
7
- * The PviumP2IdVaultFactory per Pvium environment. Deployed through the deterministic deployment
8
- * proxy, so within an environment it has one address on every EVM chain. "production" is the
9
- * mainnet stack, "sandbox" the testnet stack (a different Privy app and key set). Null until
10
- * that environment's first deployment is recorded.
11
- */
12
- factories: {
13
- production: `0x${string}` | null;
14
- sandbox: `0x${string}` | null;
15
- };
16
- }
17
- /** Every P2ID address scheme this release can derive, keyed by domain. Older schemes stay forever. */
18
- export declare const P2ID_SCHEMES: {
19
- readonly "p2id.vault.v1": {
20
- readonly identityDomain: "p2id.identity.v1";
21
- readonly vaultInitCodeHash: "0xe6b8d636ef647cfda0770fa7f2a8c93b886399c3d9405ffcb35ef946083a0802";
22
- readonly factories: {
23
- readonly production: null;
24
- readonly sandbox: "0x21859137b4979B101079742942c741224529eE6D";
25
- };
26
- };
27
- readonly "p2id.vault.v2": {
28
- readonly identityDomain: "p2id.identity.v1";
29
- readonly vaultInitCodeHash: "0xd98f76cb96350f1064d0358ba2d449e80533e26ba3900b7fba5d7570888f3699";
30
- readonly factories: {
31
- readonly production: null;
32
- readonly sandbox: "0x85463cD0FC3CcB9d0891E2ac3124322349A23a86";
33
- };
34
- };
35
- };
36
- export type P2IDSchemeName = keyof typeof P2ID_SCHEMES;
37
- /** The scheme new payments should use. */
38
- export declare const P2ID_SCHEME: "p2id.vault.v2";
@@ -1,21 +0,0 @@
1
- /** Every P2ID address scheme this release can derive, keyed by domain. Older schemes stay forever. */
2
- export const P2ID_SCHEMES = {
3
- "p2id.vault.v1": {
4
- "identityDomain": "p2id.identity.v1",
5
- "vaultInitCodeHash": "0xe6b8d636ef647cfda0770fa7f2a8c93b886399c3d9405ffcb35ef946083a0802",
6
- "factories": {
7
- "production": null,
8
- "sandbox": "0x21859137b4979B101079742942c741224529eE6D"
9
- }
10
- },
11
- "p2id.vault.v2": {
12
- "identityDomain": "p2id.identity.v1",
13
- "vaultInitCodeHash": "0xd98f76cb96350f1064d0358ba2d449e80533e26ba3900b7fba5d7570888f3699",
14
- "factories": {
15
- "production": null,
16
- "sandbox": "0x85463cD0FC3CcB9d0891E2ac3124322349A23a86"
17
- }
18
- }
19
- };
20
- /** The scheme new payments should use. */
21
- export const P2ID_SCHEME = 'p2id.vault.v2';