@kynesyslabs/demosdk 2.6.0 → 2.7.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.
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ /**
3
+ * IPFS Operations for Demos Network SDK
4
+ *
5
+ * Provides payload creators for IPFS transactions and helper utilities.
6
+ * Works with the Demos transaction system for add, pin, and unpin operations.
7
+ *
8
+ * @fileoverview IPFS operations module for SDK
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { ipfs } from '@kynesyslabs/demosdk'
13
+ *
14
+ * // Create add payload for transaction
15
+ * const addPayload = ipfs.IPFSOperations.createAddPayload(
16
+ * Buffer.from('Hello IPFS!'),
17
+ * 'hello.txt'
18
+ * )
19
+ *
20
+ * // Create pin payload for existing CID
21
+ * const pinPayload = ipfs.IPFSOperations.createPinPayload(
22
+ * 'QmExampleCID...'
23
+ * )
24
+ *
25
+ * // Create unpin payload
26
+ * const unpinPayload = ipfs.IPFSOperations.createUnpinPayload(
27
+ * 'QmExampleCID...'
28
+ * )
29
+ * ```
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.IPFSOperations = exports.IPFS_CONSTANTS = void 0;
33
+ // REVIEW: IPFS Operations class for Demos Network SDK
34
+ // ============================================================================
35
+ // Constants
36
+ // ============================================================================
37
+ /**
38
+ * IPFS configuration constants
39
+ */
40
+ exports.IPFS_CONSTANTS = {
41
+ /** Maximum content size for direct upload (1GB) */
42
+ MAX_CONTENT_SIZE: 1024 * 1024 * 1024,
43
+ /** CIDv0 pattern (Qm followed by base58 characters) */
44
+ CID_V0_PATTERN: /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/,
45
+ /** CIDv1 patterns (bafy or bafk prefix with base32 characters) */
46
+ CID_V1_PATTERN: /^(bafy|bafk|bafz|bafb)[a-z2-7]{50,}$/i,
47
+ };
48
+ // ============================================================================
49
+ // Main Class
50
+ // ============================================================================
51
+ /**
52
+ * IPFS Operations class for creating payloads and utility functions
53
+ *
54
+ * This class provides static methods to create transaction payloads for IPFS operations.
55
+ * The payloads can be used with the Demos transaction system.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { ipfs, websdk } from '@kynesyslabs/demosdk'
60
+ *
61
+ * // Initialize Demos client
62
+ * const demos = new websdk.Demos({ rpcUrl: 'https://rpc.demos.network' })
63
+ *
64
+ * // Create add payload
65
+ * const addPayload = ipfs.IPFSOperations.createAddPayload(
66
+ * Buffer.from('My content'),
67
+ * 'myfile.txt'
68
+ * )
69
+ *
70
+ * // Build and send transaction (pseudocode - actual tx flow depends on integration)
71
+ * // The payload goes in transaction.content.data as ['ipfs', payload]
72
+ * ```
73
+ */
74
+ class IPFSOperations {
75
+ // ========================================================================
76
+ // Payload Creators (for transactions)
77
+ // ========================================================================
78
+ /**
79
+ * Create a payload for IPFS_ADD operation
80
+ *
81
+ * Uploads content to IPFS and automatically pins it to the sender's account.
82
+ *
83
+ * @param content - Content to upload (Buffer, Uint8Array, or string)
84
+ * @param options - Optional filename and metadata
85
+ * @returns IPFSAddPayload for transaction creation
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * // Simple text upload
90
+ * const payload = IPFSOperations.createAddPayload(
91
+ * 'Hello, IPFS!',
92
+ * { filename: 'hello.txt' }
93
+ * )
94
+ *
95
+ * // Binary content
96
+ * const imageBuffer = fs.readFileSync('image.png')
97
+ * const imagePayload = IPFSOperations.createAddPayload(
98
+ * imageBuffer,
99
+ * { filename: 'image.png', metadata: { type: 'image/png' } }
100
+ * )
101
+ * ```
102
+ */
103
+ static createAddPayload(content, options = {}) {
104
+ // Convert content to base64
105
+ let base64Content;
106
+ if (typeof content === "string") {
107
+ base64Content = Buffer.from(content).toString("base64");
108
+ }
109
+ else {
110
+ // Both Buffer and Uint8Array can be converted via Buffer.from
111
+ base64Content = Buffer.from(content).toString("base64");
112
+ }
113
+ return {
114
+ operation: "IPFS_ADD",
115
+ content: base64Content,
116
+ filename: options.filename,
117
+ metadata: options.metadata,
118
+ };
119
+ }
120
+ /**
121
+ * Create a payload for IPFS_PIN operation
122
+ *
123
+ * Pins an existing CID to the sender's account.
124
+ *
125
+ * @param cid - Content Identifier to pin
126
+ * @param options - Optional duration and metadata
127
+ * @returns IPFSPinPayload for transaction creation
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * // Pin indefinitely
132
+ * const payload = IPFSOperations.createPinPayload('QmExample...')
133
+ *
134
+ * // Pin with duration (blocks)
135
+ * const timedPayload = IPFSOperations.createPinPayload('QmExample...', {
136
+ * duration: 1000000, // ~30 days at 2.5s blocks
137
+ * metadata: { source: 'user-upload' }
138
+ * })
139
+ * ```
140
+ */
141
+ static createPinPayload(cid, options = {}) {
142
+ // Validate CID format
143
+ if (!this.isValidCID(cid)) {
144
+ throw new Error(`Invalid CID format: ${cid}`);
145
+ }
146
+ return {
147
+ operation: "IPFS_PIN",
148
+ cid,
149
+ duration: options.duration,
150
+ metadata: options.metadata,
151
+ };
152
+ }
153
+ /**
154
+ * Create a payload for IPFS_UNPIN operation
155
+ *
156
+ * Removes a pin from the sender's account.
157
+ *
158
+ * @param cid - Content Identifier to unpin
159
+ * @returns IPFSUnpinPayload for transaction creation
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const payload = IPFSOperations.createUnpinPayload('QmExample...')
164
+ * ```
165
+ */
166
+ static createUnpinPayload(cid) {
167
+ // Validate CID format
168
+ if (!this.isValidCID(cid)) {
169
+ throw new Error(`Invalid CID format: ${cid}`);
170
+ }
171
+ return {
172
+ operation: "IPFS_UNPIN",
173
+ cid,
174
+ };
175
+ }
176
+ // ========================================================================
177
+ // Validation Utilities
178
+ // ========================================================================
179
+ /**
180
+ * Validate a CID format
181
+ *
182
+ * Supports both CIDv0 (Qm...) and CIDv1 (bafy.../bafk...) formats.
183
+ *
184
+ * @param cid - Content Identifier to validate
185
+ * @returns true if CID is valid format
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * IPFSOperations.isValidCID('QmExample...') // true for valid CIDv0
190
+ * IPFSOperations.isValidCID('bafyExample...') // true for valid CIDv1
191
+ * IPFSOperations.isValidCID('invalid') // false
192
+ * ```
193
+ */
194
+ static isValidCID(cid) {
195
+ if (!cid || typeof cid !== "string") {
196
+ return false;
197
+ }
198
+ return (exports.IPFS_CONSTANTS.CID_V0_PATTERN.test(cid) ||
199
+ exports.IPFS_CONSTANTS.CID_V1_PATTERN.test(cid));
200
+ }
201
+ /**
202
+ * Validate content size
203
+ *
204
+ * @param content - Content to validate
205
+ * @returns true if content size is within limit
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const largeBuffer = Buffer.alloc(2 * 1024 * 1024 * 1024) // 2GB
210
+ * IPFSOperations.isValidContentSize(largeBuffer) // false
211
+ * ```
212
+ */
213
+ static isValidContentSize(content) {
214
+ let size;
215
+ if (typeof content === "string") {
216
+ size = Buffer.byteLength(content);
217
+ }
218
+ else {
219
+ size = content.length;
220
+ }
221
+ return size <= exports.IPFS_CONSTANTS.MAX_CONTENT_SIZE;
222
+ }
223
+ /**
224
+ * Get content size in bytes
225
+ *
226
+ * @param content - Content to measure
227
+ * @returns Size in bytes
228
+ */
229
+ static getContentSize(content) {
230
+ if (typeof content === "string") {
231
+ return Buffer.byteLength(content);
232
+ }
233
+ return content.length;
234
+ }
235
+ // ========================================================================
236
+ // Content Encoding Utilities
237
+ // ========================================================================
238
+ /**
239
+ * Encode content to base64
240
+ *
241
+ * @param content - Content to encode
242
+ * @returns Base64 encoded string
243
+ */
244
+ static encodeContent(content) {
245
+ if (typeof content === "string") {
246
+ return Buffer.from(content).toString("base64");
247
+ }
248
+ // Both Buffer and Uint8Array can be converted via Buffer.from
249
+ return Buffer.from(content).toString("base64");
250
+ }
251
+ /**
252
+ * Decode base64 content to Buffer
253
+ *
254
+ * @param base64Content - Base64 encoded content
255
+ * @returns Decoded Buffer
256
+ */
257
+ static decodeContent(base64Content) {
258
+ return Buffer.from(base64Content, "base64");
259
+ }
260
+ /**
261
+ * Decode base64 content to string
262
+ *
263
+ * @param base64Content - Base64 encoded content
264
+ * @param encoding - Text encoding (default: 'utf-8')
265
+ * @returns Decoded string
266
+ */
267
+ static decodeContentAsString(base64Content, encoding = "utf-8") {
268
+ return Buffer.from(base64Content, "base64").toString(encoding);
269
+ }
270
+ // ========================================================================
271
+ // Type Guards
272
+ // ========================================================================
273
+ /**
274
+ * Check if payload is an add operation
275
+ */
276
+ static isAddPayload(payload) {
277
+ return payload.operation === "IPFS_ADD";
278
+ }
279
+ /**
280
+ * Check if payload is a pin operation
281
+ */
282
+ static isPinPayload(payload) {
283
+ return payload.operation === "IPFS_PIN";
284
+ }
285
+ /**
286
+ * Check if payload is an unpin operation
287
+ */
288
+ static isUnpinPayload(payload) {
289
+ return payload.operation === "IPFS_UNPIN";
290
+ }
291
+ }
292
+ exports.IPFSOperations = IPFSOperations;
293
+ //# sourceMappingURL=IPFSOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IPFSOperations.js","sourceRoot":"","sources":["../../../src/ipfs/IPFSOperations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { IPFSOperations, IPFS_CONSTANTS } from "./IPFSOperations";
2
+ export type { AddOptions, PinOptions, IPFSStatusResponse, IPFSAddResponse, IPFSGetResponse, PinInfo, IPFSPinsResponse, } from "./IPFSOperations";
3
+ export type { IPFSOperationType, IPFSAddPayload, IPFSPinPayload, IPFSUnpinPayload, IPFSPayload, } from "../types/blockchain/TransactionSubtypes/IPFSTransaction";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IPFS_CONSTANTS = exports.IPFSOperations = void 0;
4
+ var IPFSOperations_1 = require("./IPFSOperations");
5
+ Object.defineProperty(exports, "IPFSOperations", { enumerable: true, get: function () { return IPFSOperations_1.IPFSOperations; } });
6
+ Object.defineProperty(exports, "IPFS_CONSTANTS", { enumerable: true, get: function () { return IPFSOperations_1.IPFS_CONSTANTS; } });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ipfs/index.ts"],"names":[],"mappings":";;;AAAA,mDAAiE;AAAxD,gHAAA,cAAc,OAAA;AAAE,gHAAA,cAAc,OAAA"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Key Server Client
3
+ *
4
+ * Client for interacting with Key Server OAuth endpoints.
5
+ * Enables dApps to verify user ownership of GitHub/Discord accounts
6
+ * with DAHR attestation.
7
+ */
8
+ import type { KeyServerClientConfig, OAuthService, OAuthInitOptions, OAuthInitResult, OAuthPollResult, OAuthVerifyOptions, OAuthVerificationResult } from "./types";
9
+ export declare class KeyServerClient {
10
+ private readonly endpoint;
11
+ private readonly nodePubKey;
12
+ constructor(config: KeyServerClientConfig);
13
+ /**
14
+ * Get list of available OAuth providers
15
+ *
16
+ * @returns Array of available provider names
17
+ * @throws OAuthError if request fails
18
+ */
19
+ getProviders(): Promise<OAuthService[]>;
20
+ /**
21
+ * Initiate an OAuth verification flow
22
+ *
23
+ * @param service - OAuth provider ("github" or "discord")
24
+ * @param options - Optional configuration
25
+ * @returns OAuth flow initiation result with authUrl and state
26
+ * @throws OAuthError if initiation fails
27
+ */
28
+ initiateOAuth(service: OAuthService, options?: OAuthInitOptions): Promise<OAuthInitResult>;
29
+ /**
30
+ * Poll for OAuth verification result
31
+ *
32
+ * @param state - State identifier from initiateOAuth
33
+ * @returns Current status of the OAuth flow
34
+ * @throws OAuthError if polling fails
35
+ */
36
+ pollOAuth(state: string): Promise<OAuthPollResult>;
37
+ /**
38
+ * Convenience method: initiate OAuth and wait for completion
39
+ *
40
+ * This method handles the full OAuth flow:
41
+ * 1. Initiates the OAuth flow
42
+ * 2. Calls onAuthUrl callback for dApp to display the URL
43
+ * 3. Polls until completion, timeout, or failure
44
+ * 4. Returns the verified user info and attestation
45
+ *
46
+ * @param service - OAuth provider ("github" or "discord")
47
+ * @param options - Configuration including callbacks
48
+ * @returns Final verification result
49
+ * @throws OAuthError if verification fails or times out
50
+ */
51
+ verifyOAuth(service: OAuthService, options?: OAuthVerifyOptions): Promise<OAuthVerificationResult>;
52
+ /**
53
+ * Internal fetch wrapper with error handling
54
+ */
55
+ private fetch;
56
+ /**
57
+ * Sleep utility for polling
58
+ */
59
+ private sleep;
60
+ }
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ /**
3
+ * Key Server Client
4
+ *
5
+ * Client for interacting with Key Server OAuth endpoints.
6
+ * Enables dApps to verify user ownership of GitHub/Discord accounts
7
+ * with DAHR attestation.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.KeyServerClient = void 0;
11
+ const errors_1 = require("./errors");
12
+ const DEFAULT_TIMEOUT = 600000; // 10 minutes
13
+ const DEFAULT_POLL_INTERVAL = 2000; // 2 seconds
14
+ class KeyServerClient {
15
+ constructor(config) {
16
+ // Normalize endpoint (remove trailing slash)
17
+ this.endpoint = config.endpoint.replace(/\/$/, "");
18
+ this.nodePubKey = config.nodePubKey;
19
+ }
20
+ /**
21
+ * Get list of available OAuth providers
22
+ *
23
+ * @returns Array of available provider names
24
+ * @throws OAuthError if request fails
25
+ */
26
+ async getProviders() {
27
+ const response = await this.fetch("/oauth/providers", { method: "GET" });
28
+ if (!response.success || !response.providers) {
29
+ throw new errors_1.OAuthError("OAUTH_NOT_AVAILABLE", response.error?.message || "Failed to get providers");
30
+ }
31
+ return response.providers;
32
+ }
33
+ /**
34
+ * Initiate an OAuth verification flow
35
+ *
36
+ * @param service - OAuth provider ("github" or "discord")
37
+ * @param options - Optional configuration
38
+ * @returns OAuth flow initiation result with authUrl and state
39
+ * @throws OAuthError if initiation fails
40
+ */
41
+ async initiateOAuth(service, options) {
42
+ const response = await this.fetch("/oauth/init", {
43
+ method: "POST",
44
+ body: JSON.stringify({
45
+ service,
46
+ nodePubKey: this.nodePubKey,
47
+ scopes: options?.scopes,
48
+ }),
49
+ });
50
+ if (!response.success) {
51
+ throw errors_1.OAuthError.fromResponse(response.error || { code: "INTERNAL_ERROR", message: "Unknown error" });
52
+ }
53
+ return {
54
+ success: true,
55
+ authUrl: response.authUrl,
56
+ state: response.state,
57
+ expiresAt: response.expiresAt,
58
+ };
59
+ }
60
+ /**
61
+ * Poll for OAuth verification result
62
+ *
63
+ * @param state - State identifier from initiateOAuth
64
+ * @returns Current status of the OAuth flow
65
+ * @throws OAuthError if polling fails
66
+ */
67
+ async pollOAuth(state) {
68
+ const response = await this.fetch("/oauth/poll", {
69
+ method: "POST",
70
+ body: JSON.stringify({
71
+ state,
72
+ nodePubKey: this.nodePubKey,
73
+ }),
74
+ });
75
+ return response;
76
+ }
77
+ /**
78
+ * Convenience method: initiate OAuth and wait for completion
79
+ *
80
+ * This method handles the full OAuth flow:
81
+ * 1. Initiates the OAuth flow
82
+ * 2. Calls onAuthUrl callback for dApp to display the URL
83
+ * 3. Polls until completion, timeout, or failure
84
+ * 4. Returns the verified user info and attestation
85
+ *
86
+ * @param service - OAuth provider ("github" or "discord")
87
+ * @param options - Configuration including callbacks
88
+ * @returns Final verification result
89
+ * @throws OAuthError if verification fails or times out
90
+ */
91
+ async verifyOAuth(service, options) {
92
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
93
+ const pollInterval = options?.pollInterval ?? DEFAULT_POLL_INTERVAL;
94
+ // Step 1: Initiate OAuth flow
95
+ const initResult = await this.initiateOAuth(service, {
96
+ scopes: options?.scopes,
97
+ timeout,
98
+ });
99
+ // Step 2: Notify dApp of auth URL
100
+ if (options?.onAuthUrl) {
101
+ options.onAuthUrl(initResult.authUrl, initResult.state);
102
+ }
103
+ // Step 3: Poll for result
104
+ const startTime = Date.now();
105
+ let attempt = 0;
106
+ while (Date.now() - startTime < timeout) {
107
+ attempt++;
108
+ // Wait before polling (except first attempt)
109
+ if (attempt > 1) {
110
+ await this.sleep(pollInterval);
111
+ }
112
+ const pollResult = await this.pollOAuth(initResult.state);
113
+ // Notify dApp of poll status
114
+ if (options?.onPoll) {
115
+ options.onPoll(attempt, pollResult.status);
116
+ }
117
+ // Check for terminal states
118
+ switch (pollResult.status) {
119
+ case "completed":
120
+ if (!pollResult.result || !pollResult.attestation) {
121
+ throw new errors_1.OAuthError("INTERNAL_ERROR", "Completed but missing result or attestation");
122
+ }
123
+ return {
124
+ success: true,
125
+ user: pollResult.result,
126
+ attestation: pollResult.attestation,
127
+ };
128
+ case "failed":
129
+ throw errors_1.OAuthError.fromResponse(pollResult.error || { code: "OAUTH_PROVIDER_ERROR", message: "Verification failed" });
130
+ case "expired":
131
+ throw new errors_1.OAuthError("OAUTH_EXPIRED", "OAuth flow expired");
132
+ case "pending":
133
+ // Continue polling
134
+ break;
135
+ }
136
+ }
137
+ // Timeout reached
138
+ throw new errors_1.OAuthError("OAUTH_TIMEOUT", `OAuth verification timed out after ${timeout}ms`);
139
+ }
140
+ /**
141
+ * Internal fetch wrapper with error handling
142
+ */
143
+ async fetch(path, options) {
144
+ const url = `${this.endpoint}${path}`;
145
+ try {
146
+ const response = await fetch(url, {
147
+ ...options,
148
+ headers: {
149
+ "Content-Type": "application/json",
150
+ ...options.headers,
151
+ },
152
+ });
153
+ const data = await response.json();
154
+ return data;
155
+ }
156
+ catch (error) {
157
+ if (error instanceof errors_1.OAuthError) {
158
+ throw error;
159
+ }
160
+ throw new errors_1.OAuthError("NETWORK_ERROR", `Failed to connect to Key Server: ${error.message}`, { url, originalError: String(error) });
161
+ }
162
+ }
163
+ /**
164
+ * Sleep utility for polling
165
+ */
166
+ sleep(ms) {
167
+ return new Promise((resolve) => setTimeout(resolve, ms));
168
+ }
169
+ }
170
+ exports.KeyServerClient = KeyServerClient;
171
+ //# sourceMappingURL=KeyServerClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyServerClient.js","sourceRoot":"","sources":["../../../src/keyserver/KeyServerClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Key Server OAuth Errors
3
+ */
4
+ /**
5
+ * Error codes for OAuth operations
6
+ */
7
+ export type OAuthErrorCode = "OAUTH_INVALID_SERVICE" | "OAUTH_NOT_CONFIGURED" | "OAUTH_NOT_AVAILABLE" | "OAUTH_DENIED" | "OAUTH_EXPIRED" | "OAUTH_PROVIDER_ERROR" | "OAUTH_STATE_NOT_FOUND" | "OAUTH_STATE_MISMATCH" | "OAUTH_TIMEOUT" | "NETWORK_ERROR" | "INTERNAL_ERROR";
8
+ /**
9
+ * OAuth-specific error class
10
+ */
11
+ export declare class OAuthError extends Error {
12
+ readonly code: OAuthErrorCode;
13
+ readonly details?: Record<string, unknown>;
14
+ constructor(code: OAuthErrorCode, message: string, details?: Record<string, unknown>);
15
+ /**
16
+ * Create error from Key Server error response
17
+ */
18
+ static fromResponse(error: {
19
+ code: string;
20
+ message: string;
21
+ }): OAuthError;
22
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * Key Server OAuth Errors
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OAuthError = void 0;
7
+ /**
8
+ * OAuth-specific error class
9
+ */
10
+ class OAuthError extends Error {
11
+ constructor(code, message, details) {
12
+ super(message);
13
+ this.name = "OAuthError";
14
+ this.code = code;
15
+ this.details = details;
16
+ // Maintains proper stack trace in V8 environments
17
+ if (Error.captureStackTrace) {
18
+ Error.captureStackTrace(this, OAuthError);
19
+ }
20
+ }
21
+ /**
22
+ * Create error from Key Server error response
23
+ */
24
+ static fromResponse(error) {
25
+ return new OAuthError(error.code, error.message);
26
+ }
27
+ }
28
+ exports.OAuthError = OAuthError;
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/keyserver/errors.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAkBH;;GAEG;AACH,MAAa,UAAW,SAAQ,KAAK;IAIjC,YACI,IAAoB,EACpB,OAAe,EACf,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,kDAAkD;QAClD,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,KAGnB;QACG,OAAO,IAAI,UAAU,CACjB,KAAK,CAAC,IAAsB,EAC5B,KAAK,CAAC,OAAO,CAChB,CAAC;IACN,CAAC;CACJ;AAhCD,gCAgCC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Key Server Module
3
+ *
4
+ * Client for Key Server OAuth verification with DAHR attestation.
5
+ * Enables dApps to verify user ownership of GitHub/Discord accounts.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { KeyServerClient } from "@kynesyslabs/demosdk/keyserver";
10
+ *
11
+ * const client = new KeyServerClient({
12
+ * endpoint: "http://localhost:3030",
13
+ * nodePubKey: nodePublicKey,
14
+ * });
15
+ *
16
+ * // Full verification flow
17
+ * const result = await client.verifyOAuth("github", {
18
+ * onAuthUrl: (url) => window.open(url),
19
+ * onPoll: (attempt, status) => console.log(`Poll ${attempt}: ${status}`),
20
+ * });
21
+ *
22
+ * console.log("Verified user:", result.user.username);
23
+ * console.log("Attestation:", result.attestation);
24
+ * ```
25
+ */
26
+ export { KeyServerClient } from "./KeyServerClient";
27
+ export { OAuthError } from "./errors";
28
+ export { verifyAttestation, verifyOAuthAttestation } from "./verification";
29
+ export type { OAuthErrorCode } from "./errors";
30
+ export type { VerifyAttestationOptions, AttestationVerificationResult, } from "./verification";
31
+ export type { KeyServerClientConfig, OAuthService, OAuthInitOptions, OAuthInitResult, OAuthPollResult, OAuthVerifyOptions, OAuthVerificationResult, OAuthStatus, OAuthUserInfo, DAHRAttestation, OAuthProvidersResponse, } from "./types";