@brainai/satp-client 0.1.0-rc.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/src/v3-pda.js ADDED
@@ -0,0 +1,281 @@
1
+ const { PublicKey } = require('@solana/web3.js');
2
+ const crypto = require('crypto');
3
+
4
+ // ═══════════════════════════════════════════════════
5
+ // SATP V3 Program IDs — Devnet
6
+ // ═══════════════════════════════════════════════════
7
+
8
+ const V3_DEVNET_PROGRAM_IDS = {
9
+ IDENTITY: new PublicKey('GTppU4E44BqXTQgbqMZ68ozFzhP1TLty3EGnzzjtNZfG'),
10
+ REVIEWS: new PublicKey('r9XX4frcqxxAZ6Au9V5PA3EAxs1zoNckqLLmoSRcNr4'),
11
+ REPUTATION: new PublicKey('2Lz7KzMvKdrGeAuS8WPHu7jK2yScrnKVgacpYVEuDjkJ'),
12
+ ATTESTATIONS: new PublicKey('6Xd1dAQJPvQRJ4Ntr6LtPTjDjPUZ8nfnmYLZaZ2DtrdD'),
13
+ VALIDATION: new PublicKey('6rYRiCYidJYV7QvKrzKGgNu4oMh6BAvynked69R7xMbV'),
14
+ ESCROW: new PublicKey('HXCUWKR2NvRcZ7rNAJHwPcH6QAAWaLR4bRFbfyuDND6C'),
15
+ };
16
+
17
+ const V3_MAINNET_PROGRAM_IDS = null;
18
+
19
+ // ═══════════════════════════════════════════════════
20
+ // V3 PDA Seeds — must match on-chain programs
21
+ // ═══════════════════════════════════════════════════
22
+
23
+ const V3_SEEDS = {
24
+ GENESIS: 'genesis',
25
+ REPUTATION_AUTHORITY: 'reputation_v3_authority',
26
+ VALIDATION_AUTHORITY: 'validation_v3_authority',
27
+ MINT_TRACKER: 'mint_tracker',
28
+ NAME_REGISTRY: 'name_registry',
29
+ LINKED_WALLET: 'linked_wallet',
30
+ REVIEW: 'review_v3',
31
+ REVIEW_COUNTER: 'review_counter_v3',
32
+ ATTESTATION: 'attestation_v3',
33
+ ESCROW_V3: 'escrow_v3',
34
+ };
35
+
36
+ // ═══════════════════════════════════════════════════
37
+ // V3 Program ID Getter
38
+ // ═══════════════════════════════════════════════════
39
+
40
+ function getV3ProgramIds(network = 'devnet') {
41
+ if (network !== 'devnet' && network !== 'mainnet') {
42
+ throw new Error('Invalid network: expected devnet or mainnet');
43
+ }
44
+ if (network === 'mainnet') {
45
+ throw new Error('SATP V3 mainnet program IDs are not configured; use devnet or provide an approved mainnet decision packet before enabling mainnet');
46
+ }
47
+ return V3_DEVNET_PROGRAM_IDS;
48
+ }
49
+
50
+ // ═══════════════════════════════════════════════════
51
+ // Utility: Hash agent_id to 32-byte seed
52
+ // ═══════════════════════════════════════════════════
53
+
54
+ /**
55
+ * Hash an agent_id string to 32-byte SHA-256 (matches on-chain solana_program::hash::hash).
56
+ * @param {string} agentId - Agent identifier string
57
+ * @returns {Buffer} 32-byte hash
58
+ */
59
+ function hashAgentId(agentId) {
60
+ return crypto.createHash('sha256').update(agentId, 'utf8').digest();
61
+ }
62
+
63
+ /**
64
+ * Hash a name (lowercased) for name registry PDA.
65
+ * @param {string} name
66
+ * @returns {Buffer} 32-byte SHA-256 hash
67
+ */
68
+ function hashName(name) {
69
+ return crypto.createHash('sha256').update(name.toLowerCase(), 'utf8').digest();
70
+ }
71
+
72
+ // ═══════════════════════════════════════════════════
73
+ // V3 PDA Derivation Functions
74
+ // ═══════════════════════════════════════════════════
75
+
76
+ /**
77
+ * Derive Genesis Record PDA.
78
+ * Seeds: ["genesis", agent_id_hash]
79
+ * @param {string|Buffer} agentIdOrHash - agent_id string or 32-byte hash
80
+ * @param {'mainnet'|'devnet'} network
81
+ * @returns {[PublicKey, number]} [pda, bump]
82
+ */
83
+ function getGenesisPDA(agentIdOrHash, network = 'devnet') {
84
+ const hash = typeof agentIdOrHash === 'string'
85
+ ? hashAgentId(agentIdOrHash)
86
+ : Buffer.from(agentIdOrHash);
87
+ const programIds = getV3ProgramIds(network);
88
+ return PublicKey.findProgramAddressSync(
89
+ [Buffer.from(V3_SEEDS.GENESIS), hash],
90
+ programIds.IDENTITY
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Derive Reputation V3 Authority PDA (CPI signer).
96
+ * Seeds: ["reputation_v3_authority"]
97
+ * @param {'mainnet'|'devnet'} network
98
+ * @returns {[PublicKey, number]}
99
+ */
100
+ function getV3ReputationAuthorityPDA(network = 'devnet') {
101
+ const programIds = getV3ProgramIds(network);
102
+ return PublicKey.findProgramAddressSync(
103
+ [Buffer.from(V3_SEEDS.REPUTATION_AUTHORITY)],
104
+ programIds.REPUTATION
105
+ );
106
+ }
107
+
108
+ /**
109
+ * Derive Validation V3 Authority PDA (CPI signer).
110
+ * Seeds: ["validation_v3_authority"]
111
+ * @param {'mainnet'|'devnet'} network
112
+ * @returns {[PublicKey, number]}
113
+ */
114
+ function getV3ValidationAuthorityPDA(network = 'devnet') {
115
+ const programIds = getV3ProgramIds(network);
116
+ return PublicKey.findProgramAddressSync(
117
+ [Buffer.from(V3_SEEDS.VALIDATION_AUTHORITY)],
118
+ programIds.VALIDATION
119
+ );
120
+ }
121
+
122
+ /**
123
+ * Derive MintTracker PDA.
124
+ * Seeds: ["mint_tracker", genesis_pda]
125
+ * @param {PublicKey|string} genesisPDA
126
+ * @param {'mainnet'|'devnet'} network
127
+ * @returns {[PublicKey, number]}
128
+ */
129
+ function getV3MintTrackerPDA(genesisPDA, network = 'devnet') {
130
+ const genesisKey = new PublicKey(genesisPDA);
131
+ const programIds = getV3ProgramIds(network);
132
+ return PublicKey.findProgramAddressSync(
133
+ [Buffer.from(V3_SEEDS.MINT_TRACKER), genesisKey.toBuffer()],
134
+ programIds.IDENTITY
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Derive Name Registry PDA.
140
+ * Seeds: ["name_registry", name_hash]
141
+ * @param {string|Buffer} nameOrHash - Display name string or 32-byte hash
142
+ * @param {'mainnet'|'devnet'} network
143
+ * @returns {[PublicKey, number]}
144
+ */
145
+ function getNameRegistryPDA(nameOrHash, network = 'devnet') {
146
+ const hash = typeof nameOrHash === 'string'
147
+ ? hashName(nameOrHash)
148
+ : Buffer.from(nameOrHash);
149
+ const programIds = getV3ProgramIds(network);
150
+ return PublicKey.findProgramAddressSync(
151
+ [Buffer.from(V3_SEEDS.NAME_REGISTRY), hash],
152
+ programIds.IDENTITY
153
+ );
154
+ }
155
+
156
+ /**
157
+ * Derive Linked Wallet PDA.
158
+ * Seeds: ["linked_wallet", genesis_pda, wallet]
159
+ * @param {PublicKey|string} genesisPDA
160
+ * @param {PublicKey|string} wallet
161
+ * @param {'mainnet'|'devnet'} network
162
+ * @returns {[PublicKey, number]}
163
+ */
164
+ function getLinkedWalletPDA(genesisPDA, wallet, network = 'devnet') {
165
+ const genesisKey = new PublicKey(genesisPDA);
166
+ const walletKey = new PublicKey(wallet);
167
+ const programIds = getV3ProgramIds(network);
168
+ return PublicKey.findProgramAddressSync(
169
+ [Buffer.from(V3_SEEDS.LINKED_WALLET), genesisKey.toBuffer(), walletKey.toBuffer()],
170
+ programIds.IDENTITY
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Derive V3 Review PDA (agent-scoped).
176
+ * Seeds: ["review_v3", SHA256(agent_id), reviewer]
177
+ * @param {string|Buffer} agentIdOrHash - agent_id string or 32-byte hash
178
+ * @param {PublicKey|string} reviewer
179
+ * @param {'mainnet'|'devnet'} network
180
+ * @returns {[PublicKey, number]}
181
+ */
182
+ function getV3ReviewPDA(agentIdOrHash, reviewer, network = 'devnet') {
183
+ const hash = typeof agentIdOrHash === 'string'
184
+ ? hashAgentId(agentIdOrHash)
185
+ : Buffer.from(agentIdOrHash);
186
+ const reviewerKey = new PublicKey(reviewer);
187
+ const programIds = getV3ProgramIds(network);
188
+ return PublicKey.findProgramAddressSync(
189
+ [Buffer.from(V3_SEEDS.REVIEW), hash, reviewerKey.toBuffer()],
190
+ programIds.REVIEWS
191
+ );
192
+ }
193
+
194
+ /**
195
+ * Derive V3 Review Counter PDA.
196
+ * Seeds: ["review_counter_v3", SHA256(agent_id)]
197
+ * @param {string|Buffer} agentIdOrHash - agent_id string or 32-byte hash
198
+ * @param {'mainnet'|'devnet'} network
199
+ * @returns {[PublicKey, number]}
200
+ */
201
+ function getV3ReviewCounterPDA(agentIdOrHash, network = 'devnet') {
202
+ const hash = typeof agentIdOrHash === 'string'
203
+ ? hashAgentId(agentIdOrHash)
204
+ : Buffer.from(agentIdOrHash);
205
+ const programIds = getV3ProgramIds(network);
206
+ return PublicKey.findProgramAddressSync(
207
+ [Buffer.from(V3_SEEDS.REVIEW_COUNTER), hash],
208
+ programIds.REVIEWS
209
+ );
210
+ }
211
+
212
+ /**
213
+ * Derive V3 Attestation PDA.
214
+ * Seeds: ["attestation", agent_id_hash, attester, attestation_type]
215
+ * @param {string|Buffer} agentIdOrHash
216
+ * @param {PublicKey|string} attester
217
+ * @param {string} attestationType
218
+ * @param {'mainnet'|'devnet'} network
219
+ * @returns {[PublicKey, number]}
220
+ */
221
+ function getV3AttestationPDA(agentIdOrHash, attester, attestationType, network = 'devnet') {
222
+ const hash = typeof agentIdOrHash === 'string'
223
+ ? hashAgentId(agentIdOrHash)
224
+ : Buffer.from(agentIdOrHash);
225
+ const attesterKey = new PublicKey(attester);
226
+ const programIds = getV3ProgramIds(network);
227
+ return PublicKey.findProgramAddressSync(
228
+ [
229
+ Buffer.from(V3_SEEDS.ATTESTATION),
230
+ hash,
231
+ attesterKey.toBuffer(),
232
+ Buffer.from(attestationType, 'utf8'),
233
+ ],
234
+ programIds.ATTESTATIONS
235
+ );
236
+ }
237
+
238
+ /**
239
+ * Derive Escrow V3 PDA.
240
+ * Seeds: ["escrow_v3", client, description_hash, nonce_le_bytes]
241
+ * @param {PublicKey|string} client - Client wallet
242
+ * @param {Buffer} descriptionHash - 32-byte SHA-256 of job description
243
+ * @param {number|bigint} nonce - Unique nonce (u64)
244
+ * @param {'mainnet'|'devnet'} network
245
+ * @returns {[PublicKey, number]}
246
+ */
247
+ function getV3EscrowPDA(client, descriptionHash, nonce, network = 'devnet') {
248
+ const clientKey = new PublicKey(client);
249
+ const hashBuf = Buffer.isBuffer(descriptionHash) ? descriptionHash : Buffer.from(descriptionHash);
250
+ const nonceBuf = Buffer.alloc(8);
251
+ nonceBuf.writeBigUInt64LE(BigInt(nonce));
252
+ const programIds = getV3ProgramIds(network);
253
+ return PublicKey.findProgramAddressSync(
254
+ [Buffer.from(V3_SEEDS.ESCROW_V3), clientKey.toBuffer(), hashBuf, nonceBuf],
255
+ programIds.ESCROW
256
+ );
257
+ }
258
+
259
+ module.exports = {
260
+ // Program IDs
261
+ V3_DEVNET_PROGRAM_IDS,
262
+ V3_MAINNET_PROGRAM_IDS,
263
+ getV3ProgramIds,
264
+ V3_SEEDS,
265
+
266
+ // Utilities
267
+ hashAgentId,
268
+ hashName,
269
+
270
+ // PDA derivation
271
+ getGenesisPDA,
272
+ getV3ReputationAuthorityPDA,
273
+ getV3ValidationAuthorityPDA,
274
+ getV3MintTrackerPDA,
275
+ getNameRegistryPDA,
276
+ getLinkedWalletPDA,
277
+ getV3ReviewPDA,
278
+ getV3ReviewCounterPDA,
279
+ getV3AttestationPDA,
280
+ getV3EscrowPDA,
281
+ };