@grapenpm/gpass-sdk 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/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@grapenpm/gpass-sdk",
3
+ "version": "0.1.0",
4
+ "description": "SDK for the Grape Gating Protocol (GPASS) - composable access control for Solana DAOs",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "src"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup src/index.ts --format cjs,esm --dts",
14
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
15
+ "test": "jest",
16
+ "lint": "eslint src --ext .ts",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "solana",
21
+ "anchor",
22
+ "grape",
23
+ "gating",
24
+ "dao",
25
+ "web3",
26
+ "reputation",
27
+ "verification"
28
+ ],
29
+ "author": "Grape Protocol",
30
+ "license": "MIT",
31
+ "peerDependencies": {
32
+ "@coral-xyz/anchor": "^0.29.0",
33
+ "@solana/web3.js": "^1.87.0"
34
+ },
35
+ "devDependencies": {
36
+ "@coral-xyz/anchor": "^0.29.0",
37
+ "@solana/web3.js": "^1.87.0",
38
+ "@types/jest": "^29.5.0",
39
+ "@types/node": "^20.0.0",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5.0.0"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/Grape-Labs/grape-gating-protocol"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ }
50
+ }
package/src/bn-js.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ declare module "bn.js" {
2
+ class BN {
3
+ constructor(
4
+ value?:
5
+ | number
6
+ | string
7
+ | number[]
8
+ | Uint8Array
9
+ | Buffer
10
+ | BN,
11
+ base?: number | "hex",
12
+ endian?: "le" | "be"
13
+ );
14
+ toNumber(): number;
15
+ toString(base?: number | "hex", length?: number): string;
16
+ }
17
+ export default BN;
18
+ }
package/src/client.ts ADDED
@@ -0,0 +1,349 @@
1
+ import {
2
+ AnchorProvider,
3
+ Program,
4
+ BN,
5
+ } from "@coral-xyz/anchor";
6
+ import {
7
+ PublicKey,
8
+ SystemProgram,
9
+ TransactionInstruction,
10
+ Transaction,
11
+ SendTransactionError,
12
+ } from "@solana/web3.js";
13
+ import { IDL, GrapeGatingProtocol } from "./idl";
14
+ import {
15
+ GPASS_PROGRAM_ID,
16
+ Gate,
17
+ GateCheckRecord,
18
+ GateCriteria,
19
+ GateType,
20
+ GateTypeFactory,
21
+ InitializeGateParams,
22
+ CheckGateParams,
23
+ UpdateGateCriteriaParams,
24
+ SetGateActiveParams,
25
+ CloseGateParams,
26
+ } from "./types";
27
+ import {
28
+ findGatePda,
29
+ findCheckRecordPda,
30
+ } from "./pda";
31
+
32
+ export class GpassClient {
33
+ public readonly program: Program<GrapeGatingProtocol>;
34
+ public readonly provider: AnchorProvider;
35
+
36
+ constructor(provider: AnchorProvider, programId: PublicKey = GPASS_PROGRAM_ID) {
37
+ this.provider = provider;
38
+ this.program = new Program<GrapeGatingProtocol>(IDL, programId, provider);
39
+ }
40
+
41
+ // ─────────────────────────────────────────────────────
42
+ // INITIALIZE GATE
43
+ // ─────────────────────────────────────────────────────
44
+
45
+ /**
46
+ * Create a new gate with the given criteria.
47
+ *
48
+ * @example
49
+ * const { tx, gate } = await client.initializeGate({
50
+ * gateId: Keypair.generate().publicKey,
51
+ * criteria: GateCriteriaFactory.combined({
52
+ * vineConfig,
53
+ * minPoints: 500,
54
+ * season: 1,
55
+ * grapeSpace,
56
+ * platforms: [VerificationPlatform.Discord],
57
+ * requireWalletLink: true,
58
+ * }),
59
+ * gateType: GateTypeFactory.reusable(),
60
+ * });
61
+ */
62
+ async initializeGate(params: InitializeGateParams): Promise<{
63
+ tx: string;
64
+ gate: PublicKey;
65
+ }> {
66
+ const authority = params.authority ?? this.provider.wallet.publicKey;
67
+ const [gatePda] = await findGatePda(params.gateId);
68
+
69
+ const tx = await this.program.methods
70
+ .initializeGate(params.gateId, params.criteria as any, params.gateType as any)
71
+ .accounts({
72
+ gate: gatePda,
73
+ authority,
74
+ payer: this.provider.wallet.publicKey,
75
+ systemProgram: SystemProgram.programId,
76
+ })
77
+ .rpc();
78
+
79
+ return { tx, gate: gatePda };
80
+ }
81
+
82
+ // ─────────────────────────────────────────────────────
83
+ // CHECK GATE
84
+ // ─────────────────────────────────────────────────────
85
+
86
+ /**
87
+ * Check whether a user passes a gate's criteria.
88
+ * Throws GateCheckFailed (6002) if the user does not pass.
89
+ *
90
+ * @example
91
+ * await client.checkGate({
92
+ * gateId,
93
+ * user: walletPublicKey,
94
+ * reputationAccount: vineRepPda,
95
+ * identityAccount: grapeIdentityPda,
96
+ * storeRecord: true,
97
+ * });
98
+ */
99
+ async checkGate(params: CheckGateParams): Promise<string> {
100
+ const [gatePda] = await findGatePda(params.gateId);
101
+ const [checkRecordPda] = params.storeRecord
102
+ ? await findCheckRecordPda(gatePda, params.user)
103
+ : [null];
104
+
105
+ const tx = await this.program.methods
106
+ .checkGate(params.gateId)
107
+ .accounts({
108
+ gate: gatePda,
109
+ user: params.user,
110
+ reputationAccount: params.reputationAccount ?? null,
111
+ identityAccount: params.identityAccount ?? null,
112
+ linkAccount: params.linkAccount ?? null,
113
+ tokenAccount: params.tokenAccount ?? null,
114
+ checkRecord: checkRecordPda ?? null,
115
+ payer: this.provider.wallet.publicKey,
116
+ systemProgram: SystemProgram.programId,
117
+ })
118
+ .rpc();
119
+
120
+ return tx;
121
+ }
122
+
123
+ /**
124
+ * Simulate a gate check without submitting a transaction.
125
+ * Returns true if the user would pass, false otherwise.
126
+ * Does NOT throw — use this for UI gating.
127
+ */
128
+ async simulateCheckGate(params: CheckGateParams): Promise<boolean> {
129
+ try {
130
+ const [gatePda] = await findGatePda(params.gateId);
131
+ const [checkRecordPda] = params.storeRecord
132
+ ? await findCheckRecordPda(gatePda, params.user)
133
+ : [null];
134
+
135
+ await this.program.methods
136
+ .checkGate(params.gateId)
137
+ .accounts({
138
+ gate: gatePda,
139
+ user: params.user,
140
+ reputationAccount: params.reputationAccount ?? null,
141
+ identityAccount: params.identityAccount ?? null,
142
+ linkAccount: params.linkAccount ?? null,
143
+ tokenAccount: params.tokenAccount ?? null,
144
+ checkRecord: checkRecordPda ?? null,
145
+ payer: this.provider.wallet.publicKey,
146
+ systemProgram: SystemProgram.programId,
147
+ })
148
+ .simulate();
149
+
150
+ return true;
151
+ } catch {
152
+ return false;
153
+ }
154
+ }
155
+
156
+ // ─────────────────────────────────────────────────────
157
+ // UPDATE GATE
158
+ // ─────────────────────────────────────────────────────
159
+
160
+ /**
161
+ * Update the criteria for an existing gate.
162
+ */
163
+ async updateGateCriteria(params: UpdateGateCriteriaParams): Promise<string> {
164
+ const [gatePda] = await findGatePda(params.gateId);
165
+
166
+ return this.program.methods
167
+ .updateGateCriteria(params.gateId, params.newCriteria as any)
168
+ .accounts({
169
+ gate: gatePda,
170
+ authority: this.provider.wallet.publicKey,
171
+ })
172
+ .rpc();
173
+ }
174
+
175
+ /**
176
+ * Enable or disable a gate.
177
+ */
178
+ async setGateActive(params: SetGateActiveParams): Promise<string> {
179
+ const [gatePda] = await findGatePda(params.gateId);
180
+
181
+ return this.program.methods
182
+ .setGateActive(params.gateId, params.isActive)
183
+ .accounts({
184
+ gate: gatePda,
185
+ authority: this.provider.wallet.publicKey,
186
+ })
187
+ .rpc();
188
+ }
189
+
190
+ /**
191
+ * Transfer gate authority to a new public key.
192
+ */
193
+ async setGateAuthority(params: {
194
+ gateId: PublicKey;
195
+ newAuthority: PublicKey;
196
+ }): Promise<string> {
197
+ const [gatePda] = await findGatePda(params.gateId);
198
+
199
+ return this.program.methods
200
+ .setGateAuthority(params.gateId, params.newAuthority)
201
+ .accounts({
202
+ gate: gatePda,
203
+ authority: this.provider.wallet.publicKey,
204
+ })
205
+ .rpc();
206
+ }
207
+
208
+ // ─────────────────────────────────────────────────────
209
+ // CLOSE
210
+ // ─────────────────────────────────────────────────────
211
+
212
+ /**
213
+ * Close a gate and reclaim rent.
214
+ */
215
+ async closeGate(params: CloseGateParams): Promise<string> {
216
+ const [gatePda] = await findGatePda(params.gateId);
217
+ const recipient = params.recipient ?? this.provider.wallet.publicKey;
218
+
219
+ return this.program.methods
220
+ .closeGate(params.gateId)
221
+ .accounts({
222
+ gate: gatePda,
223
+ authority: this.provider.wallet.publicKey,
224
+ recipient,
225
+ })
226
+ .rpc();
227
+ }
228
+
229
+ /**
230
+ * Close a check record and reclaim rent.
231
+ */
232
+ async closeCheckRecord(params: {
233
+ gateId: PublicKey;
234
+ user: PublicKey;
235
+ recipient?: PublicKey;
236
+ }): Promise<string> {
237
+ const [gatePda] = await findGatePda(params.gateId);
238
+ const [checkRecordPda] = await findCheckRecordPda(gatePda, params.user);
239
+ const recipient = params.recipient ?? this.provider.wallet.publicKey;
240
+
241
+ return this.program.methods
242
+ .closeCheckRecord(params.gateId)
243
+ .accounts({
244
+ gate: gatePda,
245
+ user: params.user,
246
+ checkRecord: checkRecordPda,
247
+ authority: this.provider.wallet.publicKey,
248
+ recipient,
249
+ })
250
+ .rpc();
251
+ }
252
+
253
+ // ─────────────────────────────────────────────────────
254
+ // FETCH ACCOUNTS
255
+ // ─────────────────────────────────────────────────────
256
+
257
+ /**
258
+ * Fetch a Gate account.
259
+ */
260
+ async fetchGate(gateId: PublicKey): Promise<Gate | null> {
261
+ const [gatePda] = await findGatePda(gateId);
262
+ try {
263
+ return (await this.program.account.Gate.fetch(gatePda)) as unknown as Gate;
264
+ } catch {
265
+ return null;
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Fetch a GateCheckRecord for a user.
271
+ */
272
+ async fetchCheckRecord(
273
+ gateId: PublicKey,
274
+ user: PublicKey
275
+ ): Promise<GateCheckRecord | null> {
276
+ const [gatePda] = await findGatePda(gateId);
277
+ const [checkRecordPda] = await findCheckRecordPda(gatePda, user);
278
+ try {
279
+ return (await this.program.account.GateCheckRecord.fetch(
280
+ checkRecordPda
281
+ )) as unknown as GateCheckRecord;
282
+ } catch {
283
+ return null;
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Fetch all gates owned by a specific authority.
289
+ */
290
+ async fetchGatesByAuthority(authority: PublicKey): Promise<
291
+ { publicKey: PublicKey; account: Gate }[]
292
+ > {
293
+ const accounts = await this.program.account.Gate.all([
294
+ {
295
+ memcmp: {
296
+ offset: 8 + 1 + 32, // discriminator + version + gateId
297
+ bytes: authority.toBase58(),
298
+ },
299
+ },
300
+ ]);
301
+ return accounts as unknown as { publicKey: PublicKey; account: Gate }[];
302
+ }
303
+
304
+ // ─────────────────────────────────────────────────────
305
+ // INSTRUCTION BUILDERS (for composing with other txns)
306
+ // ─────────────────────────────────────────────────────
307
+
308
+ /**
309
+ * Returns the raw instruction for checkGate — useful for
310
+ * bundling into a larger transaction (e.g., CPI-style on client side).
311
+ */
312
+ async buildCheckGateInstruction(
313
+ params: CheckGateParams
314
+ ): Promise<TransactionInstruction> {
315
+ const [gatePda] = await findGatePda(params.gateId);
316
+ const [checkRecordPda] = params.storeRecord
317
+ ? await findCheckRecordPda(gatePda, params.user)
318
+ : [null];
319
+
320
+ return this.program.methods
321
+ .checkGate(params.gateId)
322
+ .accounts({
323
+ gate: gatePda,
324
+ user: params.user,
325
+ reputationAccount: params.reputationAccount ?? null,
326
+ identityAccount: params.identityAccount ?? null,
327
+ linkAccount: params.linkAccount ?? null,
328
+ tokenAccount: params.tokenAccount ?? null,
329
+ checkRecord: checkRecordPda ?? null,
330
+ payer: this.provider.wallet.publicKey,
331
+ systemProgram: SystemProgram.programId,
332
+ })
333
+ .instruction();
334
+ }
335
+
336
+ /**
337
+ * Build a full transaction that checks a gate and then executes
338
+ * additional instructions (e.g., mint, vote, transfer).
339
+ */
340
+ async buildGatedTransaction(
341
+ checkParams: CheckGateParams,
342
+ ...additionalInstructions: TransactionInstruction[]
343
+ ): Promise<Transaction> {
344
+ const checkIx = await this.buildCheckGateInstruction(checkParams);
345
+ const tx = new Transaction();
346
+ tx.add(checkIx, ...additionalInstructions);
347
+ return tx;
348
+ }
349
+ }