@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 +94 -50
- package/package.json +2 -2
- package/dist/identity.d.ts +0 -38
- package/dist/identity.js +0 -61
- package/dist/identityNames.d.ts +0 -43
- package/dist/identityNames.js +0 -44
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -5
- package/dist/p2id.d.ts +0 -54
- package/dist/p2id.js +0 -82
- package/dist/p2idConstants.d.ts +0 -38
- package/dist/p2idConstants.js +0 -21
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({
|
|
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({
|
|
35
|
-
|
|
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(
|
|
49
|
-
|
|
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(
|
|
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(
|
|
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
|
-
[
|
|
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;
|
|
82
|
-
const ref = ethers.id('invoice-42');
|
|
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, {
|
|
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(
|
|
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
|
|
98
|
-
|
|
|
99
|
-
| `identityHash` | Recipient commitment from `identityHash(type, value)`
|
|
100
|
-
| `token`
|
|
101
|
-
| `amount`
|
|
102
|
-
| `constraint`
|
|
103
|
-
| `refundWindow` | Seconds before an unclaimed deposit becomes refundable
|
|
104
|
-
| `ref`
|
|
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(
|
|
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.`
|
|
140
|
-
|
|
|
141
|
-
| `Email`
|
|
142
|
-
| `Phone`
|
|
143
|
-
| `Google`
|
|
144
|
-
| `X` (alias `Twitter`) |
|
|
145
|
-
| `Discord`
|
|
146
|
-
| `Github`
|
|
147
|
-
| `Linkedin`
|
|
148
|
-
| `Apple`
|
|
149
|
-
| `Telegram`
|
|
150
|
-
| `Tiktok`
|
|
151
|
-
| `Instagram`
|
|
152
|
-
| `Farcaster`
|
|
153
|
-
| `Wallet`
|
|
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 {
|
|
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' });
|
|
213
|
+
p2idAddressForHash(hash, { environment: 'sandbox' }); // same result as p2idAddress(...)
|
|
172
214
|
|
|
173
|
-
P2ID_SCHEME;
|
|
174
|
-
p2idScheme();
|
|
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, {
|
|
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
|
|
232
|
-
|
|
|
233
|
-
| `p2idAddress(input)`
|
|
234
|
-
| `p2idAddressForHash(hash, opts?)`
|
|
235
|
-
| `identityHash(type, value, scheme?)`
|
|
236
|
-
| `P2ID_SCHEME`, `P2ID_SCHEMES`, `p2idScheme(name?)`
|
|
237
|
-
| `IdentityType`, `IdentityTypeName`, `IDENTITY_TYPE_BY_NAME`, `resolveIdentityType` | Identity type IDs and name mappings
|
|
238
|
-
| `normalizeIdentityValue`, `isCaseInsensitive`, `HASH_PREFIX`
|
|
239
|
-
| `checksumAddress`, `toHex`
|
|
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.
|
|
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
|
+
}
|
package/dist/identity.d.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/identityNames.d.ts
DELETED
|
@@ -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;
|
package/dist/identityNames.js
DELETED
|
@@ -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
|
-
}
|
package/dist/p2idConstants.d.ts
DELETED
|
@@ -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";
|
package/dist/p2idConstants.js
DELETED
|
@@ -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';
|