@vocdoni/davinci-sdk 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Vocdoni DaVinci SDK
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40vocdoni%2Fdavinci-sdk.svg)](https://badge.fury.io/js/%40vocdoni%2Fdavinci-sdk)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
6
  [![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](#)
7
7
 
@@ -20,44 +20,32 @@ yarn add @vocdoni/davinci-sdk
20
20
  ### Basic Usage
21
21
 
22
22
  ```typescript
23
- import { DavinciSDK, CensusOrigin } from '@vocdoni/davinci-sdk';
23
+ import { DavinciSDK, PlainCensus, WeightedCensus } from '@vocdoni/davinci-sdk';
24
24
  import { Wallet } from 'ethers';
25
25
 
26
26
  // Initialize the SDK
27
27
  const wallet = new Wallet('your-private-key');
28
28
  const sdk = new DavinciSDK({
29
29
  signer: wallet,
30
- environment: 'dev' // or 'stg', 'prod'
30
+ sequencerUrl: 'https://sequencer-dev.davinci.vote',
31
+ censusUrl: 'https://c3-dev.davinci.vote'
31
32
  });
32
33
 
33
34
  await sdk.init();
34
35
 
35
36
  // 1. Create a census with eligible voters
36
- const censusId = await sdk.api.census.createCensus();
37
-
38
- // Add participants to the census
39
- const participants = [
40
- { key: "0x1234567890123456789012345678901234567890", weight: "1" },
41
- { key: "0x2345678901234567890123456789012345678901", weight: "1" },
42
- { key: "0x3456789012345678901234567890123456789012", weight: "2" } // Higher weight
43
- ];
44
-
45
- await sdk.api.census.addParticipants(censusId, participants);
46
-
47
- // Publish the census to get the root
48
- const publishResult = await sdk.api.census.publishCensus(censusId);
49
- const censusSize = await sdk.api.census.getCensusSize(publishResult.root);
37
+ const census = new PlainCensus(); // or WeightedCensus for custom voting power
38
+ census.add([
39
+ '0x1234567890123456789012345678901234567890',
40
+ '0x2345678901234567890123456789012345678901',
41
+ '0x3456789012345678901234567890123456789012'
42
+ ]);
50
43
 
51
44
  // 2. Create a voting process
52
45
  const process = await sdk.createProcess({
53
46
  title: "Community Decision",
54
47
  description: "Vote on our next community initiative",
55
- census: {
56
- type: CensusOrigin.CensusOriginMerkleTree,
57
- root: publishResult.root,
58
- size: censusSize,
59
- uri: publishResult.uri
60
- },
48
+ census: census,
61
49
  timing: {
62
50
  startDate: new Date("2024-12-01T10:00:00Z"),
63
51
  duration: 86400 // 24 hours in seconds
@@ -76,7 +64,8 @@ const process = await sdk.createProcess({
76
64
  const voterWallet = new Wallet('voter-private-key'); // Must be one of the census participants
77
65
  const voterSdk = new DavinciSDK({
78
66
  signer: voterWallet,
79
- environment: 'dev'
67
+ sequencerUrl: 'https://sequencer-dev.davinci.vote'
68
+ // No censusUrl needed for voting-only operations
80
69
  });
81
70
  await voterSdk.init();
82
71
 
@@ -157,6 +146,190 @@ pnpm add @vocdoni/davinci-sdk ethers
157
146
  - **Process**: Container for all voting parameters and metadata
158
147
  - **Proof**: Cryptographic evidence that a vote is valid
159
148
 
149
+ ## 📋 Census Management
150
+
151
+ The SDK provides simple-to-use census classes that make voter management easy. Census objects are **automatically published** when creating a process - no manual steps required!
152
+
153
+ ### Census Types
154
+
155
+ #### PlainCensus - Equal Voting Power
156
+
157
+ Everyone gets the same voting weight (weight = 1).
158
+
159
+ ```typescript
160
+ import { PlainCensus } from '@vocdoni/davinci-sdk';
161
+
162
+ const census = new PlainCensus();
163
+ census.add([
164
+ '0x1234567890123456789012345678901234567890',
165
+ '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
166
+ '0x9876543210987654321098765432109876543210'
167
+ ]);
168
+
169
+ // Use directly in process creation - SDK auto-publishes!
170
+ const process = await sdk.createProcess({
171
+ census: census, // ✨ Auto-published!
172
+ // ... rest of config
173
+ });
174
+ ```
175
+
176
+ #### WeightedCensus - Custom Voting Power
177
+
178
+ Assign different voting weights to participants. Supports flexible weight types: **string**, **number**, or **bigint**.
179
+
180
+ ```typescript
181
+ import { WeightedCensus } from '@vocdoni/davinci-sdk';
182
+
183
+ const census = new WeightedCensus();
184
+
185
+ census.add([
186
+ { key: '0x123...', weight: "1" }, // string
187
+ { key: '0x456...', weight: 5 }, // number
188
+ { key: '0x789...', weight: 100n }, // bigint
189
+ ]);
190
+
191
+ // Auto-published when creating process
192
+ const process = await sdk.createProcess({
193
+ census: census,
194
+ // ... rest of config
195
+ });
196
+ ```
197
+
198
+ #### CspCensus - Certificate Service Provider
199
+
200
+ For external authentication systems.
201
+
202
+ ```typescript
203
+ import { CspCensus } from '@vocdoni/davinci-sdk';
204
+
205
+ const census = new CspCensus(
206
+ "0x1234567890abcdef", // Root hash (public key)
207
+ "https://csp-server.com", // CSP URL
208
+ 1000 // Expected number of voters
209
+ );
210
+
211
+ const process = await sdk.createProcess({
212
+ census: census,
213
+ // ... rest of config
214
+ });
215
+ ```
216
+
217
+ #### PublishedCensus - Use Pre-Published Census
218
+
219
+ For censuses already published to the network.
220
+
221
+ ```typescript
222
+ import { PublishedCensus, CensusType } from '@vocdoni/davinci-sdk';
223
+
224
+ const census = new PublishedCensus(
225
+ CensusType.WEIGHTED,
226
+ "0xroot...",
227
+ "ipfs://uri...",
228
+ 100 // size
229
+ );
230
+
231
+ const process = await sdk.createProcess({
232
+ census: census,
233
+ // ... rest of config
234
+ });
235
+ ```
236
+
237
+ ### Auto-Publishing Feature
238
+
239
+ The SDK automatically publishes unpublished censuses when creating a process:
240
+
241
+ ```typescript
242
+ const census = new PlainCensus();
243
+ census.add(['0x123...', '0x456...']);
244
+
245
+ console.log(census.isPublished); // false
246
+
247
+ // SDK automatically publishes during process creation
248
+ const process = await sdk.createProcess({
249
+ census: census,
250
+ // ... config
251
+ });
252
+
253
+ console.log(census.isPublished); // true ✅
254
+ console.log(census.censusRoot); // Published root hash
255
+ console.log(census.censusURI); // Published URI
256
+ ```
257
+
258
+ ### Flexible Weight Types
259
+
260
+ WeightedCensus accepts weights as strings, numbers, or bigints for maximum flexibility:
261
+
262
+ ```typescript
263
+ const census = new WeightedCensus();
264
+
265
+ // String weights (recommended for very large numbers)
266
+ census.add({ key: '0x123...', weight: "999999999999" });
267
+
268
+ // Number weights (easy to use, good for reasonable values)
269
+ census.add({ key: '0x456...', weight: 100 });
270
+
271
+ // BigInt weights (for JavaScript bigint support)
272
+ census.add({ key: '0x789...', weight: 1000000n });
273
+
274
+ // Mix them all!
275
+ census.add([
276
+ { key: '0xaaa...', weight: "1" },
277
+ { key: '0xbbb...', weight: 5 },
278
+ { key: '0xccc...', weight: 10n }
279
+ ]);
280
+ ```
281
+
282
+ ### Census Operations
283
+
284
+ ```typescript
285
+ const census = new WeightedCensus();
286
+
287
+ // Add single participant
288
+ census.add({ key: '0x123...', weight: 5 });
289
+
290
+ // Add multiple participants
291
+ census.add([
292
+ { key: '0x456...', weight: 10 },
293
+ { key: '0x789...', weight: 15 }
294
+ ]);
295
+
296
+ // Remove participant
297
+ census.remove('0x123...');
298
+
299
+ // Get participant weight
300
+ const weight = census.getWeight('0x456...'); // Returns: "10"
301
+
302
+ // Get all addresses
303
+ const addresses = census.addresses; // ['0x456...', '0x789...']
304
+
305
+ // Get all participants with weights
306
+ const participants = census.participants;
307
+ // [{ key: '0x456...', weight: '10' }, { key: '0x789...', weight: '15' }]
308
+
309
+ // Check if published
310
+ if (census.isPublished) {
311
+ console.log('Root:', census.censusRoot);
312
+ console.log('URI:', census.censusURI);
313
+ console.log('Size:', census.size);
314
+ }
315
+ ```
316
+
317
+ ### Manual Census Configuration (Advanced)
318
+
319
+ For advanced use cases, you can still provide census data manually:
320
+
321
+ ```typescript
322
+ const process = await sdk.createProcess({
323
+ census: {
324
+ type: CensusOrigin.CensusOriginMerkleTree,
325
+ root: "0xabc...",
326
+ size: 100,
327
+ uri: "ipfs://..."
328
+ },
329
+ // ... rest of config
330
+ });
331
+ ```
332
+
160
333
  ## 📖 API Reference
161
334
 
162
335
  ### SDK Initialization
@@ -166,33 +339,62 @@ pnpm add @vocdoni/davinci-sdk ethers
166
339
  ```typescript
167
340
  interface DavinciSDKConfig {
168
341
  signer: Signer; // Ethereum signer (required)
169
- environment?: 'dev' | 'stg' | 'prod'; // Environment (default: 'prod')
170
- sequencerUrl?: string; // Custom sequencer URL
171
- censusUrl?: string; // Custom census API URL
172
- chain?: 'sepolia' | 'mainnet'; // Blockchain network
173
- contractAddresses?: { // Custom contract addresses
342
+ sequencerUrl: string; // Sequencer API URL (required)
343
+ censusUrl?: string; // Census API URL (optional, only needed for census creation)
344
+ addresses?: { // Custom contract addresses (optional)
174
345
  processRegistry?: string;
175
346
  organizationRegistry?: string;
176
- // ... other contracts
347
+ stateTransitionVerifier?: string;
348
+ resultsVerifier?: string;
349
+ sequencerRegistry?: string;
177
350
  };
178
- useSequencerAddresses?: boolean; // Use addresses from sequencer
351
+ censusProviders?: CensusProviders; // Custom census proof providers (optional)
352
+ verifyCircuitFiles?: boolean; // Verify downloaded circuit files (default: true)
353
+ verifyProof?: boolean; // Verify generated proof before submission (default: true)
179
354
  }
180
355
  ```
181
356
 
357
+ **Key Points:**
358
+
359
+ - **`sequencerUrl`** (required): The Vocdoni sequencer API endpoint
360
+ - Dev: `https://sequencer-dev.davinci.vote`
361
+ - Staging: `https://sequencer1.davinci.vote`
362
+ - Production: (check latest docs)
363
+
364
+ - **`censusUrl`** (optional): Only required if you're creating censuses from scratch. Not needed for voting-only operations.
365
+
366
+ - **Contract Addresses**: If not provided, the SDK automatically fetches them from the sequencer's `/info` endpoint during initialization. This is the recommended approach.
367
+
182
368
  #### Basic Initialization
183
369
 
184
370
  ```typescript
185
371
  import { DavinciSDK } from '@vocdoni/davinci-sdk';
186
372
  import { Wallet } from 'ethers';
187
373
 
374
+ // Development environment
188
375
  const sdk = new DavinciSDK({
189
376
  signer: new Wallet('your-private-key'),
190
- environment: 'dev'
377
+ sequencerUrl: 'https://sequencer-dev.davinci.vote',
378
+ censusUrl: 'https://c3-dev.davinci.vote'
191
379
  });
192
380
 
193
381
  await sdk.init();
194
382
  ```
195
383
 
384
+ **Automatic Contract Address Fetching:**
385
+
386
+ The SDK automatically fetches contract addresses from the sequencer during `init()`:
387
+
388
+ ```typescript
389
+ const sdk = new DavinciSDK({
390
+ signer: wallet,
391
+ sequencerUrl: 'https://sequencer-dev.davinci.vote'
392
+ // Contract addresses will be fetched automatically from sequencer
393
+ });
394
+
395
+ await sdk.init(); // Fetches and stores contract addresses
396
+ ```
397
+
196
398
  ### Process Management
197
399
 
198
400
  #### Creating a Process (Simple)
@@ -360,7 +562,8 @@ async function completeVotingExample() {
360
562
  const organizerWallet = new Wallet('organizer-private-key');
361
563
  const sdk = new DavinciSDK({
362
564
  signer: organizerWallet,
363
- environment: 'dev'
565
+ sequencerUrl: 'https://sequencer-dev.davinci.vote',
566
+ censusUrl: 'https://c3-dev.davinci.vote'
364
567
  });
365
568
  await sdk.init();
366
569
 
@@ -415,7 +618,8 @@ async function completeVotingExample() {
415
618
  const voterWallet = voters[0]; // Use first voter from census
416
619
  const voterSdk = new DavinciSDK({
417
620
  signer: voterWallet,
418
- environment: 'dev'
621
+ sequencerUrl: 'https://sequencer-dev.davinci.vote'
622
+ // No censusUrl needed for voting-only operations
419
623
  });
420
624
  await voterSdk.init();
421
625
 
@@ -459,7 +663,7 @@ async function browserVotingExample() {
459
663
  // Initialize SDK
460
664
  const sdk = new DavinciSDK({
461
665
  signer,
462
- environment: 'prod'
666
+ sequencerUrl: 'https://sequencer.davinci.vote' // Production URL
463
667
  });
464
668
  await sdk.init();
465
669
 
@@ -483,10 +687,9 @@ async function browserVotingExample() {
483
687
  ```typescript
484
688
  const sdk = new DavinciSDK({
485
689
  signer: wallet,
486
- chain: 'sepolia',
487
690
  sequencerUrl: 'https://your-custom-sequencer.com',
488
691
  censusUrl: 'https://your-custom-census.com',
489
- contractAddresses: {
692
+ addresses: {
490
693
  processRegistry: '0x...',
491
694
  organizationRegistry: '0x...',
492
695
  stateTransitionVerifier: '0x...',
@@ -495,14 +698,18 @@ const sdk = new DavinciSDK({
495
698
  });
496
699
  ```
497
700
 
498
- ### Using Sequencer-Provided Addresses
701
+ ### Automatic Contract Address Fetching (Default Behavior)
702
+
703
+ By default, the SDK automatically fetches contract addresses from the sequencer's `/info` endpoint:
499
704
 
500
705
  ```typescript
501
706
  const sdk = new DavinciSDK({
502
707
  signer: wallet,
503
- environment: 'dev',
504
- useSequencerAddresses: true // Fetch contract addresses from sequencer
708
+ sequencerUrl: 'https://sequencer-dev.davinci.vote'
709
+ // Contract addresses fetched automatically during init()
505
710
  });
711
+
712
+ await sdk.init(); // Fetches addresses from sequencer
506
713
  ```
507
714
 
508
715
  ### Custom Vote Randomness
@@ -511,7 +718,7 @@ const sdk = new DavinciSDK({
511
718
  const vote = await sdk.submitVote({
512
719
  processId: "0x...",
513
720
  choices: [1],
514
- randomness: "your-custom-randomness-hex" // For deterministic testing
721
+ randomness: "your-custom-randomness-hex"
515
722
  });
516
723
  ```
517
724
 
@@ -645,7 +852,9 @@ yarn format
645
852
 
646
853
  ## 📄 License
647
854
 
648
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
855
+ This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) - see the [LICENSE](LICENSE) file for details.
856
+
857
+ The AGPL-3.0 is a copyleft license that requires anyone who distributes your code or a derivative work to make the source available under the same terms. If your application is a web service, users interacting with it remotely must also be able to access the source code.
649
858
 
650
859
  ## 🆘 Support
651
860
 
@@ -1,53 +1,6 @@
1
1
  import { ContractTransactionResponse, BaseContract, ContractEventName, EventFilter, ContractRunner } from 'ethers';
2
2
  import * as _vocdoni_davinci_contracts_dist_src_ProcessRegistry from '@vocdoni/davinci-contracts/dist/src/ProcessRegistry';
3
3
 
4
- /**
5
- * Interface defining the structure of deployed contract addresses across different networks.
6
- * Each contract has addresses for both Sepolia testnet and Ethereum mainnet.
7
- */
8
- interface DeployedAddresses {
9
- /** Process Registry contract addresses */
10
- processRegistry: {
11
- /** Sepolia testnet address */
12
- sepolia: string;
13
- /** Ethereum mainnet address */
14
- mainnet: string;
15
- };
16
- /** Organization Registry contract addresses */
17
- organizationRegistry: {
18
- /** Sepolia testnet address */
19
- sepolia: string;
20
- /** Ethereum mainnet address */
21
- mainnet: string;
22
- };
23
- /** State Transition Verifier contract addresses */
24
- stateTransitionVerifierGroth16: {
25
- /** Sepolia testnet address */
26
- sepolia: string;
27
- /** Ethereum mainnet address */
28
- mainnet: string;
29
- };
30
- /** Results Verifier contract addresses */
31
- resultsVerifierGroth16: {
32
- /** Sepolia testnet address */
33
- sepolia: string;
34
- /** Ethereum mainnet address */
35
- mainnet: string;
36
- };
37
- /** Sequencer Registry contract addresses */
38
- sequencerRegistry: {
39
- /** Sepolia testnet address */
40
- sepolia: string;
41
- /** Ethereum mainnet address */
42
- mainnet: string;
43
- };
44
- }
45
- /**
46
- * Deployed contract addresses imported from @vocdoni/davinci-contracts package.
47
- * These addresses are used to interact with the Vocdoni voting protocol contracts
48
- * on different networks.
49
- */
50
- declare const deployedAddresses: DeployedAddresses;
51
4
  /**
52
5
  * Enum representing the possible states of a transaction during its lifecycle.
53
6
  * Used to track and report transaction status in the event stream.
@@ -184,10 +137,13 @@ declare abstract class SmartContractService {
184
137
  */
185
138
  protected setupEventListener<Args extends any[]>(contract: BaseContract, eventFilter: ContractEventName | EventFilter, callback: (...args: Args) => void): Promise<void>;
186
139
  /**
187
- * Checks if an error indicates that the RPC method is unsupported (eth_newFilter).
140
+ * Checks if an error indicates that the RPC method is unsupported or filter operations are not working.
141
+ * This includes:
142
+ * - Method not found (-32601): RPC doesn't support eth_newFilter
143
+ * - Filter not found (-32000): RPC doesn't properly maintain filters
188
144
  *
189
145
  * @param error - The error to check
190
- * @returns true if the error indicates unsupported method
146
+ * @returns true if the error indicates unsupported or broken filter functionality
191
147
  */
192
148
  private isUnsupportedMethodError;
193
149
  /**
@@ -414,7 +370,7 @@ interface BallotMode {
414
370
  maxValueSum: string;
415
371
  minValueSum: string;
416
372
  }
417
- interface Census {
373
+ interface CensusData {
418
374
  censusOrigin: CensusOrigin;
419
375
  maxVotes: string;
420
376
  censusRoot: string;
@@ -525,13 +481,13 @@ declare class ProcessRegistryService extends SmartContractService {
525
481
  }>;
526
482
  getRVerifier(): Promise<string>;
527
483
  getSTVerifier(): Promise<string>;
528
- newProcess(status: ProcessStatus, startTime: number, duration: number, ballotMode: BallotMode, census: Census, metadata: string, encryptionKey: EncryptionKey, initStateRoot: bigint): AsyncGenerator<TxStatusEvent<{
484
+ newProcess(status: ProcessStatus, startTime: number, duration: number, ballotMode: BallotMode, census: CensusData, metadata: string, encryptionKey: EncryptionKey, initStateRoot: bigint): AsyncGenerator<TxStatusEvent<{
529
485
  success: boolean;
530
486
  }>, void, unknown>;
531
487
  setProcessStatus(processID: string, newStatus: ProcessStatus): AsyncGenerator<TxStatusEvent<{
532
488
  success: boolean;
533
489
  }>, void, unknown>;
534
- setProcessCensus(processID: string, census: Census): AsyncGenerator<TxStatusEvent<{
490
+ setProcessCensus(processID: string, census: CensusData): AsyncGenerator<TxStatusEvent<{
535
491
  success: boolean;
536
492
  }>, void, unknown>;
537
493
  setProcessDuration(processID: string, duration: number): AsyncGenerator<TxStatusEvent<{
@@ -563,5 +519,5 @@ declare class ProcessRegistryService extends SmartContractService {
563
519
  removeAllListeners(): void;
564
520
  }
565
521
 
566
- export { ContractServiceError, OrganizationAdministratorError, OrganizationCreateError, OrganizationDeleteError, OrganizationRegistryService, OrganizationUpdateError, ProcessCensusError, ProcessCreateError, ProcessDurationError, ProcessRegistryService, ProcessResultError, ProcessStateTransitionError, ProcessStatus, ProcessStatusError, SmartContractService, TxStatus, deployedAddresses };
567
- export type { DeployedAddresses, EntityCallback, OrganizationAdministratorAddedCallback, OrganizationAdministratorRemovedCallback, OrganizationCreatedCallback, OrganizationInfo, OrganizationUpdatedCallback, ProcessCensusUpdatedCallback, ProcessCreatedCallback, ProcessDurationChangedCallback, ProcessResultsSetCallback, ProcessStateRootUpdatedCallback, ProcessStatusChangedCallback, TxStatusEvent };
522
+ export { ContractServiceError, OrganizationAdministratorError, OrganizationCreateError, OrganizationDeleteError, OrganizationRegistryService, OrganizationUpdateError, ProcessCensusError, ProcessCreateError, ProcessDurationError, ProcessRegistryService, ProcessResultError, ProcessStateTransitionError, ProcessStatus, ProcessStatusError, SmartContractService, TxStatus };
523
+ export type { EntityCallback, OrganizationAdministratorAddedCallback, OrganizationAdministratorRemovedCallback, OrganizationCreatedCallback, OrganizationInfo, OrganizationUpdatedCallback, ProcessCensusUpdatedCallback, ProcessCreatedCallback, ProcessDurationChangedCallback, ProcessResultsSetCallback, ProcessStateRootUpdatedCallback, ProcessStatusChangedCallback, TxStatusEvent };