@collectorcrypt/vrf-client 0.1.0
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/addresses.d.ts +34 -0
- package/dist/addresses.d.ts.map +1 -0
- package/dist/addresses.js +87 -0
- package/dist/addresses.js.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +15 -0
- package/dist/constants.js.map +1 -0
- package/dist/idl/cc_vrf.json +1024 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/light.d.ts +98 -0
- package/dist/light.d.ts.map +1 -0
- package/dist/light.js +182 -0
- package/dist/light.js.map +1 -0
- package/dist/operations.d.ts +172 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +417 -0
- package/dist/operations.js.map +1 -0
- package/dist/program.d.ts +9 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +21 -0
- package/dist/program.js.map +1 -0
- package/dist/verifyEndToEnd.d.ts +124 -0
- package/dist/verifyEndToEnd.d.ts.map +1 -0
- package/dist/verifyEndToEnd.js +150 -0
- package/dist/verifyEndToEnd.js.map +1 -0
- package/package.json +49 -0
- package/src/addresses.ts +105 -0
- package/src/constants.ts +16 -0
- package/src/idl/cc_vrf.json +1024 -0
- package/src/index.ts +80 -0
- package/src/light.ts +259 -0
- package/src/operations.ts +655 -0
- package/src/program.ts +17 -0
- package/src/verifyEndToEnd.ts +305 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @collectorcrypt/vrf-client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript SDK for the cc-vrf on-chain VRF program. Wraps the Anchor IDL,
|
|
5
|
+
* Light Protocol compressed-PDA plumbing, and the RFC 9381 ECVRF library so
|
|
6
|
+
* consumers can publish, commit, and verify VRF proofs with one import.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Re-export the ECVRF primitives so consumers don't need a second import.
|
|
10
|
+
export {
|
|
11
|
+
generateKeyPair,
|
|
12
|
+
publicKeyFromSeed,
|
|
13
|
+
proveVRF,
|
|
14
|
+
verifyVRF,
|
|
15
|
+
vrfProofToHash,
|
|
16
|
+
bytesToHex,
|
|
17
|
+
hexToBytes,
|
|
18
|
+
} from "@collectorcrypt/ecvrf";
|
|
19
|
+
|
|
20
|
+
export { CC_VRF_PROGRAM_ID, SUITE_EDWARDS25519_SHA512_TAI } from "./constants";
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
deriveAuthorityAddress,
|
|
24
|
+
deriveProofCommitAddress,
|
|
25
|
+
deriveProofCommitWithBetaAddress,
|
|
26
|
+
memoHash,
|
|
27
|
+
alphaHash,
|
|
28
|
+
proofHash,
|
|
29
|
+
encodeLabel,
|
|
30
|
+
} from "./addresses";
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
forceLightV2,
|
|
34
|
+
buildCreateContext,
|
|
35
|
+
buildCommitProofContext,
|
|
36
|
+
buildReadOnlyAuthorityContext,
|
|
37
|
+
buildMutateContext,
|
|
38
|
+
} from "./light";
|
|
39
|
+
|
|
40
|
+
export { getProgram } from "./program";
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
buildInitAuthorityIx,
|
|
44
|
+
buildFreezeAuthorityIx,
|
|
45
|
+
buildRevokeAuthorityIx,
|
|
46
|
+
buildCommitProofIx,
|
|
47
|
+
buildCommitProofEventIx,
|
|
48
|
+
buildCommitProofWithBetaIx,
|
|
49
|
+
fetchAuthority,
|
|
50
|
+
fetchProofCommit,
|
|
51
|
+
fetchProofCommitWithBeta,
|
|
52
|
+
fetchProofCommitEvents,
|
|
53
|
+
decodeAuthority,
|
|
54
|
+
decodeProofCommit,
|
|
55
|
+
decodeProofCommitWithBeta,
|
|
56
|
+
asTx,
|
|
57
|
+
} from "./operations";
|
|
58
|
+
|
|
59
|
+
export type {
|
|
60
|
+
InitAuthorityInput,
|
|
61
|
+
FreezeAuthorityInput,
|
|
62
|
+
CommitProofInput,
|
|
63
|
+
ProofCommitEvent,
|
|
64
|
+
} from "./operations";
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
verifyEndToEnd,
|
|
68
|
+
verifyAuthorityCommitEndToEnd,
|
|
69
|
+
pickCanonicalCommit,
|
|
70
|
+
} from "./verifyEndToEnd";
|
|
71
|
+
|
|
72
|
+
export type {
|
|
73
|
+
OnChainAuthority,
|
|
74
|
+
OnChainCommit,
|
|
75
|
+
VerifyAuthorityCommitEndToEndInput,
|
|
76
|
+
VerifyAuthorityCommitEndToEndResult,
|
|
77
|
+
VerifyEndToEndInput,
|
|
78
|
+
VerifyEndToEndResult,
|
|
79
|
+
PickCanonicalResult,
|
|
80
|
+
} from "./verifyEndToEnd";
|
package/src/light.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
batchAddressTree,
|
|
4
|
+
bn,
|
|
5
|
+
CompressedAccountWithMerkleContext,
|
|
6
|
+
featureFlags,
|
|
7
|
+
PackedAccounts,
|
|
8
|
+
Rpc,
|
|
9
|
+
selectStateTreeInfo,
|
|
10
|
+
SystemAccountMetaConfig,
|
|
11
|
+
VERSION,
|
|
12
|
+
} from "@lightprotocol/stateless.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Force the SDK into V2 mode so our address derivations + state-tree usage
|
|
16
|
+
* match the on-chain program's ADDRESS_TREE_V2 expectation.
|
|
17
|
+
*/
|
|
18
|
+
export function forceLightV2() {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
(featureFlags as any).version = VERSION.V2;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* For CREATE flows (init_authority, commit_proof): builds the validity-proof
|
|
25
|
+
* bundle + packed remaining-accounts list needed to mint a new compressed
|
|
26
|
+
* PDA at the given address.
|
|
27
|
+
*/
|
|
28
|
+
export async function buildCreateContext(
|
|
29
|
+
rpc: Rpc,
|
|
30
|
+
programId: PublicKey,
|
|
31
|
+
newCompressedAddress: PublicKey,
|
|
32
|
+
existingInputs: {
|
|
33
|
+
hash: Uint8Array;
|
|
34
|
+
tree: PublicKey;
|
|
35
|
+
queue: PublicKey;
|
|
36
|
+
}[] = [],
|
|
37
|
+
) {
|
|
38
|
+
forceLightV2();
|
|
39
|
+
const addressTree = new PublicKey(batchAddressTree);
|
|
40
|
+
const proofRes = await rpc.getValidityProofV0(
|
|
41
|
+
existingInputs.map((i) => ({
|
|
42
|
+
hash: bn(i.hash),
|
|
43
|
+
tree: i.tree,
|
|
44
|
+
queue: i.queue,
|
|
45
|
+
})),
|
|
46
|
+
[
|
|
47
|
+
{
|
|
48
|
+
tree: addressTree,
|
|
49
|
+
queue: addressTree,
|
|
50
|
+
address: bn(newCompressedAddress.toBytes()),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const stateTreeInfos = await rpc.getStateTreeInfos();
|
|
56
|
+
const stateTreeInfo = selectStateTreeInfo(stateTreeInfos);
|
|
57
|
+
|
|
58
|
+
const systemAccountConfig = SystemAccountMetaConfig.new(programId);
|
|
59
|
+
const remainingAccounts =
|
|
60
|
+
PackedAccounts.newWithSystemAccountsV2(systemAccountConfig);
|
|
61
|
+
const addressMtIdx = remainingAccounts.insertOrGet(addressTree);
|
|
62
|
+
const outputStIdx = remainingAccounts.insertOrGet(stateTreeInfo.queue);
|
|
63
|
+
|
|
64
|
+
const packedAddressTreeInfo = {
|
|
65
|
+
rootIndex: proofRes.rootIndices[proofRes.rootIndices.length - 1],
|
|
66
|
+
addressMerkleTreePubkeyIndex: addressMtIdx,
|
|
67
|
+
addressQueuePubkeyIndex: addressMtIdx,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
proof: { 0: proofRes.compressedProof },
|
|
72
|
+
packedAddressTreeInfo,
|
|
73
|
+
outputStateTreeIndex: outputStIdx,
|
|
74
|
+
remainingAccountMetas: remainingAccounts.toAccountMetas().remainingAccounts,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* For commit_proof specifically: one input (the existing authority, treated
|
|
80
|
+
* as read-only on chain) + one new address (the commit). Both indices come
|
|
81
|
+
* from the same getValidityProofV0 call so they reference the same proof
|
|
82
|
+
* and the same packed-accounts list.
|
|
83
|
+
*/
|
|
84
|
+
export async function buildCommitProofContext(
|
|
85
|
+
rpc: Rpc,
|
|
86
|
+
programId: PublicKey,
|
|
87
|
+
authorityExisting: CompressedAccountWithMerkleContext,
|
|
88
|
+
newCommitAddress: PublicKey,
|
|
89
|
+
) {
|
|
90
|
+
forceLightV2();
|
|
91
|
+
const addressTree = new PublicKey(batchAddressTree);
|
|
92
|
+
|
|
93
|
+
const proofRes = await rpc.getValidityProofV0(
|
|
94
|
+
[
|
|
95
|
+
{
|
|
96
|
+
hash: authorityExisting.hash,
|
|
97
|
+
tree: authorityExisting.treeInfo.tree,
|
|
98
|
+
queue: authorityExisting.treeInfo.queue,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
{
|
|
103
|
+
tree: addressTree,
|
|
104
|
+
queue: addressTree,
|
|
105
|
+
address: bn(newCommitAddress.toBytes()),
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const stateTreeInfos = await rpc.getStateTreeInfos();
|
|
111
|
+
const stateTreeInfo = selectStateTreeInfo(stateTreeInfos);
|
|
112
|
+
|
|
113
|
+
const systemAccountConfig = SystemAccountMetaConfig.new(programId);
|
|
114
|
+
const remainingAccounts =
|
|
115
|
+
PackedAccounts.newWithSystemAccountsV2(systemAccountConfig);
|
|
116
|
+
|
|
117
|
+
// Order matters: insert in the order the program will reference them via
|
|
118
|
+
// packed indices. Both the authority's tree and the address tree are
|
|
119
|
+
// shared in V2 (batched merkle tree), but we still pack the auth's tree
|
|
120
|
+
// first since the authority meta is constructed first below.
|
|
121
|
+
const authMerkleTreePubkeyIndex = remainingAccounts.insertOrGet(
|
|
122
|
+
authorityExisting.treeInfo.tree,
|
|
123
|
+
);
|
|
124
|
+
const authQueuePubkeyIndex = remainingAccounts.insertOrGet(
|
|
125
|
+
authorityExisting.treeInfo.queue,
|
|
126
|
+
);
|
|
127
|
+
const addressMtIdx = remainingAccounts.insertOrGet(addressTree);
|
|
128
|
+
const outputStIdx = remainingAccounts.insertOrGet(stateTreeInfo.queue);
|
|
129
|
+
|
|
130
|
+
const authorityReadOnlyMeta = {
|
|
131
|
+
treeInfo: {
|
|
132
|
+
rootIndex: proofRes.rootIndices[0],
|
|
133
|
+
proveByIndex: true,
|
|
134
|
+
merkleTreePubkeyIndex: authMerkleTreePubkeyIndex,
|
|
135
|
+
queuePubkeyIndex: authQueuePubkeyIndex,
|
|
136
|
+
leafIndex: authorityExisting.leafIndex,
|
|
137
|
+
},
|
|
138
|
+
address: authorityExisting.address,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const packedAddressTreeInfo = {
|
|
142
|
+
rootIndex: proofRes.rootIndices[proofRes.rootIndices.length - 1],
|
|
143
|
+
addressMerkleTreePubkeyIndex: addressMtIdx,
|
|
144
|
+
addressQueuePubkeyIndex: addressMtIdx,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
proof: { 0: proofRes.compressedProof },
|
|
149
|
+
authorityReadOnlyMeta,
|
|
150
|
+
packedAddressTreeInfo,
|
|
151
|
+
outputStateTreeIndex: outputStIdx,
|
|
152
|
+
remainingAccountMetas: remainingAccounts.toAccountMetas().remainingAccounts,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* For event-mode commits: builds a validity-proof bundle for an existing
|
|
158
|
+
* authority treated as read-only. No new compressed address is created.
|
|
159
|
+
*/
|
|
160
|
+
export async function buildReadOnlyAuthorityContext(
|
|
161
|
+
rpc: Rpc,
|
|
162
|
+
programId: PublicKey,
|
|
163
|
+
authorityExisting: CompressedAccountWithMerkleContext,
|
|
164
|
+
) {
|
|
165
|
+
forceLightV2();
|
|
166
|
+
const proofRes = await rpc.getValidityProofV0(
|
|
167
|
+
[
|
|
168
|
+
{
|
|
169
|
+
hash: authorityExisting.hash,
|
|
170
|
+
tree: authorityExisting.treeInfo.tree,
|
|
171
|
+
queue: authorityExisting.treeInfo.queue,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
[],
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const systemAccountConfig = SystemAccountMetaConfig.new(programId);
|
|
178
|
+
const remainingAccounts =
|
|
179
|
+
PackedAccounts.newWithSystemAccountsV2(systemAccountConfig);
|
|
180
|
+
const authMerkleTreePubkeyIndex = remainingAccounts.insertOrGet(
|
|
181
|
+
authorityExisting.treeInfo.tree,
|
|
182
|
+
);
|
|
183
|
+
const authQueuePubkeyIndex = remainingAccounts.insertOrGet(
|
|
184
|
+
authorityExisting.treeInfo.queue,
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const authorityReadOnlyMeta = {
|
|
188
|
+
treeInfo: {
|
|
189
|
+
rootIndex: proofRes.rootIndices[0],
|
|
190
|
+
proveByIndex: true,
|
|
191
|
+
merkleTreePubkeyIndex: authMerkleTreePubkeyIndex,
|
|
192
|
+
queuePubkeyIndex: authQueuePubkeyIndex,
|
|
193
|
+
leafIndex: authorityExisting.leafIndex,
|
|
194
|
+
},
|
|
195
|
+
address: authorityExisting.address,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
proof: { 0: proofRes.compressedProof },
|
|
200
|
+
authorityReadOnlyMeta,
|
|
201
|
+
remainingAccountMetas: remainingAccounts.toAccountMetas().remainingAccounts,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* For MUTATE flows (freeze_authority, revoke_authority): builds the
|
|
207
|
+
* validity-proof bundle + account meta for an existing compressed PDA.
|
|
208
|
+
*/
|
|
209
|
+
export async function buildMutateContext(
|
|
210
|
+
rpc: Rpc,
|
|
211
|
+
programId: PublicKey,
|
|
212
|
+
existing: CompressedAccountWithMerkleContext,
|
|
213
|
+
) {
|
|
214
|
+
forceLightV2();
|
|
215
|
+
const proofRes = await rpc.getValidityProofV0(
|
|
216
|
+
[
|
|
217
|
+
{
|
|
218
|
+
hash: existing.hash,
|
|
219
|
+
tree: existing.treeInfo.tree,
|
|
220
|
+
queue: existing.treeInfo.queue,
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
[],
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const stateTreeInfos = await rpc.getStateTreeInfos();
|
|
227
|
+
const stateTreeInfo = selectStateTreeInfo(stateTreeInfos);
|
|
228
|
+
|
|
229
|
+
const systemAccountConfig = SystemAccountMetaConfig.new(programId);
|
|
230
|
+
const remainingAccounts =
|
|
231
|
+
PackedAccounts.newWithSystemAccountsV2(systemAccountConfig);
|
|
232
|
+
const merkleTreePubkeyIndex = remainingAccounts.insertOrGet(
|
|
233
|
+
existing.treeInfo.tree,
|
|
234
|
+
);
|
|
235
|
+
const queuePubkeyIndex = remainingAccounts.insertOrGet(
|
|
236
|
+
existing.treeInfo.queue,
|
|
237
|
+
);
|
|
238
|
+
const outputStateTreeIndex = remainingAccounts.insertOrGet(
|
|
239
|
+
stateTreeInfo.queue,
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const accountMeta = {
|
|
243
|
+
treeInfo: {
|
|
244
|
+
rootIndex: proofRes.rootIndices[0],
|
|
245
|
+
proveByIndex: true,
|
|
246
|
+
merkleTreePubkeyIndex,
|
|
247
|
+
queuePubkeyIndex,
|
|
248
|
+
leafIndex: existing.leafIndex,
|
|
249
|
+
},
|
|
250
|
+
address: existing.address,
|
|
251
|
+
outputStateTreeIndex,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
proof: { 0: proofRes.compressedProof },
|
|
256
|
+
accountMeta,
|
|
257
|
+
remainingAccountMetas: remainingAccounts.toAccountMetas().remainingAccounts,
|
|
258
|
+
};
|
|
259
|
+
}
|