@proofchain/sdk 1.2.0 → 2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 ProofChain / MegaWatts Solutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,144 +1,284 @@
1
- # @attestation/sdk
1
+ # ProofChain JavaScript/TypeScript SDK
2
2
 
3
- TypeScript SDK for the Attestation Service API.
3
+ Official JavaScript/TypeScript SDK for [ProofChain](https://proofchain.co.za) - blockchain-anchored document attestation.
4
+
5
+ Works in Node.js and browsers.
4
6
 
5
7
  ## Installation
6
8
 
7
9
  ```bash
8
- npm install @attestation/sdk ethers
10
+ npm install @proofchain/sdk
11
+ # or
12
+ yarn add @proofchain/sdk
13
+ # or
14
+ pnpm add @proofchain/sdk
9
15
  ```
10
16
 
11
17
  ## Quick Start
12
18
 
13
19
  ```typescript
14
- import { AttestationClient, AttestationRegistryContract } from '@attestation/sdk';
15
- import { ethers } from 'ethers';
20
+ import { ProofChain } from '@proofchain/sdk';
21
+
22
+ // Create client
23
+ const client = new ProofChain({ apiKey: 'your-api-key' });
16
24
 
17
- // Create API client
18
- const client = new AttestationClient({
19
- baseUrl: 'http://localhost:8000',
25
+ // Attest a document
26
+ const result = await client.documents.attest({
27
+ file: myFile, // File, Blob, or Buffer
28
+ userId: 'user@example.com',
29
+ eventType: 'contract_signed',
20
30
  });
21
31
 
22
- // Health check
23
- const health = await client.health();
24
- console.log(health.status); // 'healthy'
32
+ console.log('IPFS Hash:', result.ipfsHash);
33
+ console.log('Verify URL:', result.verifyUrl);
34
+
35
+ // Verify
36
+ const verification = await client.verify(result.ipfsHash);
37
+ console.log('Valid:', verification.valid);
38
+ ```
39
+
40
+ ## High-Performance Ingestion
25
41
 
26
- // Web3 Authentication
27
- const challenge = await client.requestChallenge('0x742d35...');
28
- // Sign the challenge.message with your wallet
29
- const auth = await client.verifySignature(
30
- '0x742d35...',
31
- signature,
32
- challenge.message
33
- );
34
- // Token is automatically set on the client
42
+ For maximum throughput, use the dedicated `IngestionClient` which connects directly to the Rust ingestion API:
43
+
44
+ ```typescript
45
+ import { IngestionClient } from '@proofchain/sdk';
46
+
47
+ const ingestion = new IngestionClient({ apiKey: 'your-api-key' });
48
+
49
+ // Single event (immediate attestation)
50
+ const result = await ingestion.ingest({
51
+ userId: 'user-123',
52
+ eventType: 'purchase',
53
+ data: { amount: 99.99, product: 'widget' },
54
+ });
55
+
56
+ console.log('Event ID:', result.eventId);
57
+ console.log('Certificate:', result.certificateId);
58
+
59
+ // Batch events (up to 1000 per request)
60
+ const batchResult = await ingestion.ingestBatch({
61
+ events: [
62
+ { userId: 'user-1', eventType: 'click', data: { page: '/home' } },
63
+ { userId: 'user-2', eventType: 'click', data: { page: '/products' } },
64
+ // ... up to 1000 events
65
+ ],
66
+ });
67
+
68
+ console.log('Queued:', batchResult.queued);
69
+ console.log('Failed:', batchResult.failed);
70
+ ```
71
+
72
+ ## State Channels (High-Volume Streaming)
73
+
74
+ For high-throughput scenarios (100K+ events/sec):
75
+
76
+ ```typescript
77
+ import { ProofChain } from '@proofchain/sdk';
35
78
 
79
+ const client = new ProofChain({ apiKey: 'your-api-key' });
80
+
81
+ // Create a state channel
82
+ const channel = await client.channels.create({ name: 'iot-sensors' });
83
+
84
+ // Stream events
85
+ for (const reading of sensorReadings) {
86
+ await client.channels.stream(channel.channelId, {
87
+ eventType: 'sensor_reading',
88
+ userId: reading.deviceId,
89
+ data: { temperature: reading.temp, humidity: reading.humidity },
90
+ });
91
+ }
92
+
93
+ // Settle on-chain
94
+ const settlement = await client.channels.settle(channel.channelId);
95
+ console.log('TX Hash:', settlement.txHash);
96
+ ```
97
+
98
+ ## Features
99
+
100
+ ### Documents
101
+
102
+ ```typescript
103
+ // Attest a file (Node.js)
104
+ import { readFileSync } from 'fs';
105
+
106
+ const result = await client.documents.attest({
107
+ file: readFileSync('contract.pdf'),
108
+ filename: 'contract.pdf',
109
+ userId: 'user@example.com',
110
+ eventType: 'document_uploaded',
111
+ metadata: { department: 'legal' },
112
+ });
113
+
114
+ // Attest a file (Browser)
115
+ const fileInput = document.querySelector('input[type="file"]');
116
+ const result = await client.documents.attest({
117
+ file: fileInput.files[0],
118
+ userId: 'user@example.com',
119
+ });
120
+
121
+ // Get document by hash
122
+ const doc = await client.documents.get('Qm...');
123
+ ```
124
+
125
+ ### Events
126
+
127
+ ```typescript
36
128
  // Create an event
37
- const event = await client.createEvent({
38
- user_id: 'user123',
39
- event_type: 'document_signed',
40
- data: { documentId: 'doc-456', hash: '0xabc...' },
129
+ const event = await client.events.create({
130
+ eventType: 'user_action',
131
+ userId: 'user123',
132
+ data: { action: 'login', ip: '192.168.1.1' },
133
+ });
134
+
135
+ // List events
136
+ const events = await client.events.list({
137
+ userId: 'user123',
138
+ eventType: 'user_action',
139
+ limit: 100,
140
+ });
141
+
142
+ // Search events
143
+ const results = await client.events.search({
144
+ query: 'login',
145
+ startDate: '2024-01-01',
146
+ endDate: '2024-12-31',
41
147
  });
42
- console.log(event.ipfs_hash);
43
-
44
- // Get Merkle proof
45
- await client.rebuildMerkleTree('user123');
46
- const proof = await client.getMerkleProof('user123', event.ipfs_hash);
47
- console.log(proof.root, proof.proof);
48
-
49
- // Verify proof off-chain
50
- const isValid = await client.verifyMerkleProof(
51
- proof.leaf,
52
- proof.proof,
53
- proof.root
54
- );
55
- console.log(isValid.valid); // true
56
148
  ```
57
149
 
58
- ## On-Chain Verification
150
+ ### Verification
59
151
 
60
152
  ```typescript
61
- import { AttestationRegistryContract } from '@attestation/sdk';
62
- import { ethers } from 'ethers';
63
-
64
- // Connect to contract
65
- const provider = new ethers.JsonRpcProvider('https://rpc.example.com');
66
- const signer = new ethers.Wallet(privateKey, provider);
67
- const contract = new AttestationRegistryContract(
68
- '0xContractAddress...',
69
- signer
70
- );
71
-
72
- // Get on-chain root
73
- const root = await contract.getRoot('0xWalletAddress...');
74
- console.log(root.merkleRoot, root.eventCount);
75
-
76
- // Verify attestation on-chain
77
- const isValid = await contract.verifyAttestation(
78
- '0xWalletAddress...',
79
- proof.leaf,
80
- proof.proof
81
- );
82
-
83
- // Update root (requires authorization)
84
- const tx = await contract.updateRoot(
85
- '0xWalletAddress...',
86
- proof.root,
87
- 3201,
88
- 'QmLatestIpfsHash...'
89
- );
90
- await tx.wait();
91
-
92
- // Off-chain verification (no RPC needed)
93
- const validOffchain = AttestationRegistryContract.verifyProofOffchain(
94
- proof.leaf,
95
- proof.proof,
96
- proof.root
97
- );
153
+ // Verify by IPFS hash
154
+ const result = await client.verify('Qm...');
155
+
156
+ if (result.valid) {
157
+ console.log('Timestamp:', result.timestamp);
158
+ console.log('Blockchain TX:', result.blockchainTx);
159
+ console.log('Certificate ID:', result.certificateId);
160
+ }
98
161
  ```
99
162
 
100
- ## API Reference
101
-
102
- ### AttestationClient
103
-
104
- | Method | Description |
105
- |--------|-------------|
106
- | `health()` | Check API health |
107
- | `requestChallenge(wallet)` | Get auth challenge |
108
- | `verifySignature(wallet, sig, msg)` | Verify and get JWT |
109
- | `createEvent(event)` | Create new event |
110
- | `getEvents(userId, options)` | List user events |
111
- | `queryEvents(userId, query)` | Query with filters |
112
- | `rebuildMerkleTree(userId)` | Rebuild Merkle tree |
113
- | `getMerkleRoot(userId)` | Get current root |
114
- | `getMerkleProof(userId, ipfsHash)` | Get proof for event |
115
- | `verifyMerkleProof(leaf, proof, root)` | Verify proof |
116
- | `linkWallet(request)` | Link wallet to user |
117
- | `getWalletStatus(userId)` | Get wallet status |
118
-
119
- ### AttestationRegistryContract
120
-
121
- | Method | Description |
122
- |--------|-------------|
123
- | `getRoot(wallet)` | Get on-chain root |
124
- | `getHistoryCount(wallet)` | Get history count |
125
- | `getHistoricalRoot(wallet, index)` | Get historical root |
126
- | `verifyAttestation(wallet, leaf, proof)` | Verify on-chain |
127
- | `computeLeaf(ipfs, type, timestamp)` | Compute leaf hash |
128
- | `updateRoot(wallet, root, count, ipfs)` | Update root |
129
- | `batchUpdateRoots(...)` | Batch update |
130
- | `setAuthorizedUpdater(addr, auth)` | Manage updaters |
131
-
132
- ### Static Methods
163
+ ### Certificates
133
164
 
134
165
  ```typescript
135
- // Compute leaf without RPC
136
- AttestationRegistryContract.computeLeafOffchain(ipfsHash, eventType, timestamp);
166
+ // Issue a certificate
167
+ const cert = await client.certificates.issue({
168
+ recipientName: 'John Doe',
169
+ recipientEmail: 'john@example.com',
170
+ title: 'Course Completion',
171
+ description: 'Completed JavaScript Fundamentals',
172
+ metadata: { courseId: 'JS101', score: 95 },
173
+ });
137
174
 
138
- // Verify proof without RPC
139
- AttestationRegistryContract.verifyProofOffchain(leaf, proof, root);
175
+ console.log('Certificate ID:', cert.certificateId);
176
+ console.log('QR Code:', cert.qrCodeUrl);
177
+
178
+ // Revoke
179
+ await client.certificates.revoke(cert.certificateId, 'Issued in error');
180
+ ```
181
+
182
+ ### Webhooks
183
+
184
+ ```typescript
185
+ // Register a webhook
186
+ const webhook = await client.webhooks.create({
187
+ url: 'https://your-app.com/webhook',
188
+ events: ['document.attested', 'channel.settled'],
189
+ secret: 'your-secret',
190
+ });
191
+
192
+ // List webhooks
193
+ const webhooks = await client.webhooks.list();
194
+
195
+ // Delete
196
+ await client.webhooks.delete(webhook.id);
197
+ ```
198
+
199
+ ## Error Handling
200
+
201
+ ```typescript
202
+ import { ProofChain, ProofChainError, AuthenticationError, RateLimitError } from '@proofchain/sdk';
203
+
204
+ try {
205
+ const result = await client.documents.attest(req);
206
+ } catch (error) {
207
+ if (error instanceof AuthenticationError) {
208
+ console.error('Invalid API key');
209
+ } else if (error instanceof RateLimitError) {
210
+ console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
211
+ } else if (error instanceof ProofChainError) {
212
+ console.error(`API error: ${error.message}`);
213
+ }
214
+ }
215
+ ```
216
+
217
+ ## Configuration
218
+
219
+ ```typescript
220
+ import { ProofChain } from '@proofchain/sdk';
221
+
222
+ // Full configuration
223
+ const client = new ProofChain({
224
+ apiKey: 'your-api-key',
225
+ baseUrl: 'https://ingest.proofchain.co.za', // Ingestion API (Rust)
226
+ mgmtUrl: 'https://api.proofchain.co.za', // Management API (Python)
227
+ timeout: 30000, // 30 seconds
228
+ maxRetries: 3,
229
+ });
230
+
231
+ // From environment variable (Node.js)
232
+ // Set PROOFCHAIN_API_KEY
233
+ const client = ProofChain.fromEnv();
234
+ ```
235
+
236
+ ## TypeScript Support
237
+
238
+ Full TypeScript support with exported types:
239
+
240
+ ```typescript
241
+ import type {
242
+ AttestationResult,
243
+ Event,
244
+ Channel,
245
+ ChannelStatus,
246
+ Settlement,
247
+ Certificate,
248
+ Webhook,
249
+ VerificationResult,
250
+ SearchResult,
251
+ } from '@proofchain/sdk';
252
+ ```
253
+
254
+ ## Browser Usage
255
+
256
+ The SDK works in browsers with no additional configuration:
257
+
258
+ ```html
259
+ <script type="module">
260
+ import { ProofChain } from 'https://esm.sh/@proofchain/sdk';
261
+
262
+ const client = new ProofChain({ apiKey: 'your-api-key' });
263
+
264
+ // Use with file input
265
+ document.querySelector('#upload').addEventListener('change', async (e) => {
266
+ const file = e.target.files[0];
267
+ const result = await client.documents.attest({
268
+ file,
269
+ userId: 'user@example.com',
270
+ });
271
+ console.log('Attested:', result.ipfsHash);
272
+ });
273
+ </script>
140
274
  ```
141
275
 
142
276
  ## License
143
277
 
144
- MIT
278
+ MIT License - see [LICENSE](LICENSE) for details.
279
+
280
+ ## Support
281
+
282
+ - Documentation: https://proofchain.co.za/docs
283
+ - Email: support@proofchain.co.za
284
+ - GitHub Issues: https://github.com/proofchain/proofchain-js/issues