@vocdoni/davinci-sdk 0.0.2 → 0.0.4

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/dist/index.js CHANGED
@@ -89,12 +89,12 @@ class VocdoniCensusService extends BaseService {
89
89
  super(baseURL);
90
90
  }
91
91
  /**
92
- * Constructs the URI for accessing a census by its root
93
- * @param censusRoot - The census root (hex-prefixed)
92
+ * Constructs the URI for accessing a census
93
+ * @param relativePath - The relative path
94
94
  * @returns The constructed URI for the census
95
95
  */
96
- getCensusUri(censusRoot) {
97
- return `${this.axios.defaults.baseURL}/censuses/${censusRoot}`;
96
+ getCensusUri(relativePath) {
97
+ return `${this.axios.defaults.baseURL}${relativePath}`;
98
98
  }
99
99
  createCensus() {
100
100
  return this.request({
@@ -163,10 +163,13 @@ class VocdoniCensusService extends BaseService {
163
163
  return this.request({
164
164
  method: "POST",
165
165
  url: `/censuses/${censusId}/publish`
166
- }).then((response) => ({
167
- ...response,
168
- uri: this.getCensusUri(response.root)
169
- }));
166
+ }).then((apiResponse) => {
167
+ const { censusUri, ...responseWithoutCensusUri } = apiResponse;
168
+ return {
169
+ ...responseWithoutCensusUri,
170
+ uri: this.getCensusUri(censusUri)
171
+ };
172
+ });
170
173
  }
171
174
  // BigQuery endpoints
172
175
  getSnapshots(params) {
@@ -196,13 +199,13 @@ var CensusOrigin = /* @__PURE__ */ ((CensusOrigin2) => {
196
199
  return CensusOrigin2;
197
200
  })(CensusOrigin || {});
198
201
  function isBaseCensusProof(proof) {
199
- return !!proof && typeof proof.root === "string" && typeof proof.address === "string" && typeof proof.weight === "string" && typeof proof.censusOrigin === "number" && Object.values(CensusOrigin).includes(proof.censusOrigin);
202
+ return !!proof && typeof proof.root === "string" && typeof proof.address === "string" && typeof proof.censusOrigin === "number" && Object.values(CensusOrigin).includes(proof.censusOrigin);
200
203
  }
201
204
  function isMerkleCensusProof(proof) {
202
- return isBaseCensusProof(proof) && proof.censusOrigin === 1 /* CensusOriginMerkleTree */ && typeof proof.value === "string" && typeof proof.siblings === "string";
205
+ return isBaseCensusProof(proof) && proof.censusOrigin === 1 /* CensusOriginMerkleTree */ && typeof proof.weight === "string" && typeof proof.value === "string" && typeof proof.siblings === "string";
203
206
  }
204
207
  function isCSPCensusProof(proof) {
205
- return isBaseCensusProof(proof) && proof.censusOrigin === 2 /* CensusOriginCSP */ && typeof proof.processId === "string" && typeof proof.publicKey === "string" && typeof proof.signature === "string";
208
+ return isBaseCensusProof(proof) && proof.censusOrigin === 2 /* CensusOriginCSP */ && typeof proof.weight === "string" && typeof proof.processId === "string" && typeof proof.publicKey === "string" && typeof proof.signature === "string";
206
209
  }
207
210
  function assertMerkleCensusProof(proof) {
208
211
  if (!isMerkleCensusProof(proof)) {
@@ -215,6 +218,281 @@ function assertCSPCensusProof(proof) {
215
218
  }
216
219
  }
217
220
 
221
+ var CensusType = /* @__PURE__ */ ((CensusType2) => {
222
+ CensusType2["PLAIN"] = "plain";
223
+ CensusType2["WEIGHTED"] = "weighted";
224
+ CensusType2["CSP"] = "csp";
225
+ return CensusType2;
226
+ })(CensusType || {});
227
+ class Census {
228
+ constructor(type) {
229
+ this._censusId = null;
230
+ this._censusRoot = null;
231
+ this._censusURI = null;
232
+ this._size = null;
233
+ this._type = type;
234
+ }
235
+ get censusId() {
236
+ return this._censusId;
237
+ }
238
+ get censusRoot() {
239
+ return this._censusRoot;
240
+ }
241
+ get censusURI() {
242
+ return this._censusURI;
243
+ }
244
+ get type() {
245
+ return this._type;
246
+ }
247
+ get size() {
248
+ return this._size;
249
+ }
250
+ get isPublished() {
251
+ return this._censusRoot !== null && this._censusURI !== null;
252
+ }
253
+ /**
254
+ * Convert CensusType to CensusOrigin enum for API compatibility
255
+ */
256
+ get censusOrigin() {
257
+ switch (this._type) {
258
+ case "plain" /* PLAIN */:
259
+ case "weighted" /* WEIGHTED */:
260
+ return CensusOrigin.CensusOriginMerkleTree;
261
+ case "csp" /* CSP */:
262
+ return CensusOrigin.CensusOriginCSP;
263
+ default:
264
+ throw new Error(`Unknown census type: ${this._type}`);
265
+ }
266
+ }
267
+ }
268
+
269
+ class PlainCensus extends Census {
270
+ constructor() {
271
+ super(CensusType.PLAIN);
272
+ this._participants = /* @__PURE__ */ new Set();
273
+ }
274
+ /**
275
+ * Add participant(s) with automatic weight=1
276
+ * @param addresses - Single address or array of addresses
277
+ */
278
+ add(addresses) {
279
+ const toAdd = Array.isArray(addresses) ? addresses : [addresses];
280
+ for (const address of toAdd) {
281
+ this.validateAddress(address);
282
+ this._participants.add(address.toLowerCase());
283
+ }
284
+ }
285
+ /**
286
+ * Remove participant by address
287
+ */
288
+ remove(address) {
289
+ this._participants.delete(address.toLowerCase());
290
+ }
291
+ /**
292
+ * Get all participants as CensusParticipant array (for API)
293
+ * All participants have weight="1"
294
+ */
295
+ get participants() {
296
+ return Array.from(this._participants).map((key) => ({
297
+ key,
298
+ weight: "1"
299
+ // Everyone has weight=1 in plain census
300
+ }));
301
+ }
302
+ /**
303
+ * Get addresses only
304
+ */
305
+ get addresses() {
306
+ return Array.from(this._participants);
307
+ }
308
+ validateAddress(address) {
309
+ if (!address || typeof address !== "string") {
310
+ throw new Error("Address is required and must be a string");
311
+ }
312
+ if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(address)) {
313
+ throw new Error(`Invalid Ethereum address format: ${address}`);
314
+ }
315
+ }
316
+ /**
317
+ * Internal method called after publishing
318
+ * @internal
319
+ */
320
+ _setPublishedData(root, uri, size, censusId) {
321
+ this._censusRoot = root;
322
+ this._censusURI = uri;
323
+ this._size = size;
324
+ if (censusId) this._censusId = censusId;
325
+ }
326
+ }
327
+
328
+ class WeightedCensus extends Census {
329
+ constructor() {
330
+ super(CensusType.WEIGHTED);
331
+ this._participants = /* @__PURE__ */ new Map();
332
+ }
333
+ /**
334
+ * Add participant(s) with custom weights
335
+ * Weight can be provided as string, number, or bigint - will be converted to string internally
336
+ * @param participant - Single participant or array of participants with custom weights
337
+ */
338
+ add(participant) {
339
+ const toAdd = Array.isArray(participant) ? participant : [participant];
340
+ for (const p of toAdd) {
341
+ this.validateParticipant(p);
342
+ const weightString = this.normalizeWeight(p.weight);
343
+ this._participants.set(p.key.toLowerCase(), weightString);
344
+ }
345
+ }
346
+ /**
347
+ * Remove participant by address
348
+ */
349
+ remove(address) {
350
+ this._participants.delete(address.toLowerCase());
351
+ }
352
+ /**
353
+ * Get all participants as CensusParticipant array
354
+ */
355
+ get participants() {
356
+ return Array.from(this._participants.entries()).map(([key, weight]) => ({
357
+ key,
358
+ weight
359
+ }));
360
+ }
361
+ /**
362
+ * Get participant addresses
363
+ */
364
+ get addresses() {
365
+ return Array.from(this._participants.keys());
366
+ }
367
+ /**
368
+ * Get weight for specific address
369
+ */
370
+ getWeight(address) {
371
+ return this._participants.get(address.toLowerCase());
372
+ }
373
+ /**
374
+ * Normalizes weight from string, number, or bigint to string
375
+ */
376
+ normalizeWeight(weight) {
377
+ if (typeof weight === "string") {
378
+ if (!/^\d+$/.test(weight)) {
379
+ throw new Error(`Invalid weight format: ${weight}. Must be a positive integer.`);
380
+ }
381
+ return weight;
382
+ }
383
+ if (typeof weight === "number") {
384
+ if (!Number.isInteger(weight) || weight < 0) {
385
+ throw new Error(`Invalid weight: ${weight}. Must be a positive integer.`);
386
+ }
387
+ return weight.toString();
388
+ }
389
+ if (typeof weight === "bigint") {
390
+ if (weight < 0n) {
391
+ throw new Error(`Invalid weight: ${weight}. Must be a positive integer.`);
392
+ }
393
+ return weight.toString();
394
+ }
395
+ throw new Error(`Invalid weight type. Must be string, number, or bigint.`);
396
+ }
397
+ validateParticipant(participant) {
398
+ if (!participant.key || typeof participant.key !== "string") {
399
+ throw new Error("Participant key (address) is required");
400
+ }
401
+ if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(participant.key)) {
402
+ throw new Error(`Invalid Ethereum address format: ${participant.key}`);
403
+ }
404
+ if (participant.weight === void 0 || participant.weight === null) {
405
+ throw new Error("Participant weight is required");
406
+ }
407
+ }
408
+ /**
409
+ * Internal method called after publishing
410
+ * @internal
411
+ */
412
+ _setPublishedData(root, uri, size, censusId) {
413
+ this._censusRoot = root;
414
+ this._censusURI = uri;
415
+ this._size = size;
416
+ if (censusId) this._censusId = censusId;
417
+ }
418
+ }
419
+
420
+ class CspCensus extends Census {
421
+ constructor(publicKey, cspURI, size) {
422
+ super(CensusType.CSP);
423
+ if (!/^(0x)?[0-9a-fA-F]+$/.test(publicKey)) {
424
+ throw new Error("Public key is missing or invalid");
425
+ }
426
+ try {
427
+ new URL(cspURI);
428
+ } catch {
429
+ throw new Error("CSP URI is missing or invalid");
430
+ }
431
+ this._publicKey = publicKey;
432
+ this._cspURI = cspURI;
433
+ this._censusRoot = publicKey;
434
+ this._censusURI = cspURI;
435
+ this._size = size;
436
+ }
437
+ get publicKey() {
438
+ return this._publicKey;
439
+ }
440
+ get cspURI() {
441
+ return this._cspURI;
442
+ }
443
+ }
444
+
445
+ class PublishedCensus extends Census {
446
+ constructor(type, root, uri, size) {
447
+ super(type);
448
+ this._censusRoot = root;
449
+ this._censusURI = uri;
450
+ this._size = size;
451
+ }
452
+ }
453
+
454
+ class CensusOrchestrator {
455
+ constructor(censusService) {
456
+ this.censusService = censusService;
457
+ }
458
+ /**
459
+ * Publishes a PlainCensus or WeightedCensus
460
+ * Creates a working census, adds participants, and publishes it
461
+ */
462
+ async publish(census) {
463
+ if (census.isPublished) {
464
+ throw new Error("Census is already published");
465
+ }
466
+ if (census.participants.length === 0) {
467
+ throw new Error("Cannot publish empty census");
468
+ }
469
+ const censusId = await this.censusService.createCensus();
470
+ await this.censusService.addParticipants(censusId, census.participants);
471
+ const publishResponse = await this.censusService.publishCensus(censusId);
472
+ census._setPublishedData(
473
+ publishResponse.root,
474
+ publishResponse.uri,
475
+ publishResponse.participantCount,
476
+ censusId
477
+ );
478
+ }
479
+ /**
480
+ * Gets census data for process creation
481
+ * Throws if census is not published
482
+ */
483
+ getCensusData(census) {
484
+ if (!census.isPublished) {
485
+ throw new Error("Census must be published before creating a process");
486
+ }
487
+ return {
488
+ type: census.censusOrigin,
489
+ root: census.censusRoot,
490
+ uri: census.censusURI,
491
+ size: census.size
492
+ };
493
+ }
494
+ }
495
+
218
496
  function createProcessSignatureMessage(processId) {
219
497
  const cleanProcessId = processId.replace(/^0x/, "").toLowerCase();
220
498
  return `I am creating a new voting process for the davinci.vote protocol identified with id ${cleanProcessId}`;
@@ -287,6 +565,12 @@ class VocdoniSequencerService extends BaseService {
287
565
  throw error;
288
566
  }
289
567
  }
568
+ isAddressAbleToVote(processId, address) {
569
+ return this.request({
570
+ method: "GET",
571
+ url: `/processes/${processId}/participants/${address}`
572
+ });
573
+ }
290
574
  getInfo() {
291
575
  return this.request({
292
576
  method: "GET",
@@ -305,11 +589,15 @@ class VocdoniSequencerService extends BaseService {
305
589
  try {
306
590
  const response = await fetch(hashOrUrl);
307
591
  if (!response.ok) {
308
- throw new Error(`Failed to fetch metadata from URL: ${response.status} ${response.statusText}`);
592
+ throw new Error(
593
+ `Failed to fetch metadata from URL: ${response.status} ${response.statusText}`
594
+ );
309
595
  }
310
596
  return await response.json();
311
597
  } catch (error) {
312
- throw new Error(`Failed to fetch metadata from URL: ${error instanceof Error ? error.message : "Unknown error"}`);
598
+ throw new Error(
599
+ `Failed to fetch metadata from URL: ${error instanceof Error ? error.message : "Unknown error"}`
600
+ );
313
601
  }
314
602
  }
315
603
  if (!isHexString(hashOrUrl)) {
@@ -345,101 +633,6 @@ class VocdoniApiService {
345
633
  }
346
634
  }
347
635
 
348
- const DEFAULT_ENVIRONMENT_URLS = {
349
- dev: {
350
- sequencer: "https://sequencer-dev.davinci.vote",
351
- census: "https://c3-dev.davinci.vote",
352
- chain: "sepolia"
353
- },
354
- stg: {
355
- sequencer: "https://sequencer1.davinci.vote",
356
- census: "https://c3.davinci.vote",
357
- chain: "sepolia"
358
- },
359
- prod: {
360
- // TODO: Add production URLs when available
361
- sequencer: "",
362
- census: "",
363
- chain: "mainnet"
364
- }
365
- };
366
- function getEnvironmentConfig(environment) {
367
- return DEFAULT_ENVIRONMENT_URLS[environment];
368
- }
369
- function getEnvironmentUrls(environment) {
370
- const config = DEFAULT_ENVIRONMENT_URLS[environment];
371
- return {
372
- sequencer: config.sequencer,
373
- census: config.census
374
- };
375
- }
376
- function getEnvironmentChain(environment) {
377
- return DEFAULT_ENVIRONMENT_URLS[environment].chain;
378
- }
379
- function resolveConfiguration(options = {}) {
380
- const environment = options.environment || "prod";
381
- const defaultConfig = getEnvironmentConfig(environment);
382
- const resolvedConfig = { ...defaultConfig };
383
- if (options.customUrls) {
384
- if (options.customUrls.sequencer !== void 0) {
385
- resolvedConfig.sequencer = options.customUrls.sequencer;
386
- }
387
- if (options.customUrls.census !== void 0) {
388
- resolvedConfig.census = options.customUrls.census;
389
- }
390
- }
391
- if (options.customChain) {
392
- resolvedConfig.chain = options.customChain;
393
- }
394
- return resolvedConfig;
395
- }
396
- function resolveUrls(options = {}) {
397
- const config = resolveConfiguration(options);
398
- return {
399
- sequencer: config.sequencer,
400
- census: config.census
401
- };
402
- }
403
-
404
- var processRegistry = {
405
- sepolia: "0x50CA6A350f3A9C7B8a82eE7a4D5F0f21C54D68e3",
406
- uzh: "0x69B16f67Bd2fB18bD720379E9C1Ef5EaD3872d67",
407
- mainnet: "0x0",
408
- celo: "0xDda6c75d32c375946C8ae9be41B2F3539dB1118A"
409
- };
410
- var organizationRegistry = {
411
- sepolia: "0xF30678f579Fd89b86295503dC179d5d3aed47a98",
412
- uzh: "0xf7BCE4546805547bE526Ca864d6722Ed193E51Aa",
413
- mainnet: "0x0",
414
- celo: "0xE17D701EA8f34022F97fC2Ec68c73D42bF99D0BD"
415
- };
416
- var stateTransitionVerifierGroth16 = {
417
- sepolia: "0x96EcBbD6aB5fDC063E0fC426F2700290DeeAFE4E",
418
- uzh: "0x5e4673CD378F05cc3Ae25804539c91E711548741",
419
- mainnet: "0x0",
420
- celo: "0x2DaF913D423128258b2F378E320F9D9D3Be5eCf5"
421
- };
422
- var resultsVerifierGroth16 = {
423
- sepolia: "0x3ab37C40f7d0649f7a15BA3230f14AB29B51eDCC",
424
- uzh: "0x00c7F87731346F592197E49A90Ad6EC236Ad9985",
425
- mainnet: "0x0",
426
- celo: "0x808276962217AD1ED3af7D51bFc791903CAd9389"
427
- };
428
- var sequencerRegistry = {
429
- sepolia: "0x0",
430
- uzh: "0x0",
431
- mainnet: "0x0",
432
- celo: "0x0"
433
- };
434
- var addressesJson = {
435
- processRegistry: processRegistry,
436
- organizationRegistry: organizationRegistry,
437
- stateTransitionVerifierGroth16: stateTransitionVerifierGroth16,
438
- resultsVerifierGroth16: resultsVerifierGroth16,
439
- sequencerRegistry: sequencerRegistry
440
- };
441
-
442
- const deployedAddresses = addressesJson;
443
636
  var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
444
637
  TxStatus2["Pending"] = "pending";
445
638
  TxStatus2["Completed"] = "completed";
@@ -458,19 +651,19 @@ class SmartContractService {
458
651
  * Sends a transaction and yields status events during its lifecycle.
459
652
  * This method handles the complete transaction flow from submission to completion,
460
653
  * including error handling and status updates.
461
- *
654
+ *
462
655
  * @template T - The type of the successful response data
463
656
  * @param txPromise - Promise resolving to the transaction response
464
657
  * @param responseHandler - Function to process the successful transaction result
465
658
  * @returns AsyncGenerator yielding transaction status events
466
- *
659
+ *
467
660
  * @example
468
661
  * ```typescript
469
662
  * const txStream = await this.sendTx(
470
663
  * contract.someMethod(),
471
664
  * async () => await contract.getUpdatedValue()
472
665
  * );
473
- *
666
+ *
474
667
  * for await (const event of txStream) {
475
668
  * switch (event.status) {
476
669
  * case TxStatus.Pending:
@@ -507,12 +700,12 @@ class SmartContractService {
507
700
  * Executes a transaction stream and returns the result or throws an error.
508
701
  * This is a convenience method that processes a transaction stream and either
509
702
  * returns the successful result or throws an appropriate error.
510
- *
703
+ *
511
704
  * @template T - The type of the successful response data
512
705
  * @param stream - AsyncGenerator of transaction status events
513
706
  * @returns Promise resolving to the successful response data
514
707
  * @throws Error if the transaction fails or reverts
515
- *
708
+ *
516
709
  * @example
517
710
  * ```typescript
518
711
  * try {
@@ -542,11 +735,11 @@ class SmartContractService {
542
735
  * Normalizes event listener arguments between different ethers.js versions.
543
736
  * This helper method ensures consistent event argument handling regardless of
544
737
  * whether the event payload follows ethers v5 or v6 format.
545
- *
738
+ *
546
739
  * @template Args - Tuple type representing the expected event arguments
547
740
  * @param callback - The event callback function to normalize
548
741
  * @returns Normalized event listener function
549
- *
742
+ *
550
743
  * @example
551
744
  * ```typescript
552
745
  * contract.on('Transfer', this.normalizeListener((from: string, to: string, amount: BigInt) => {
@@ -569,12 +762,12 @@ class SmartContractService {
569
762
  * Sets up an event listener with automatic fallback for RPCs that don't support eth_newFilter.
570
763
  * First attempts to use contract.on() which relies on eth_newFilter. If the RPC doesn't support
571
764
  * this method (error code -32601), automatically falls back to polling with queryFilter.
572
- *
765
+ *
573
766
  * @template Args - Tuple type representing the event arguments
574
767
  * @param contract - The contract instance to listen to
575
768
  * @param eventFilter - The event filter to listen for
576
769
  * @param callback - The callback function to invoke when the event occurs
577
- *
770
+ *
578
771
  * @example
579
772
  * ```typescript
580
773
  * this.setupEventListener(
@@ -600,13 +793,14 @@ class SmartContractService {
600
793
  };
601
794
  if ("send" in provider && typeof provider.send === "function") {
602
795
  try {
603
- await provider.send("eth_newFilter", [testFilter]);
796
+ const filterId = await provider.send("eth_newFilter", [testFilter]);
797
+ await provider.send("eth_getFilterChanges", [filterId]);
604
798
  contract.on(eventFilter, normalizedCallback);
605
799
  return;
606
800
  } catch (error) {
607
801
  if (this.isUnsupportedMethodError(error)) {
608
802
  console.warn(
609
- "RPC does not support eth_newFilter, falling back to polling for events. This may result in delayed event notifications."
803
+ "RPC does not fully support eth_newFilter/eth_getFilterChanges, falling back to polling for events. This may result in delayed event notifications."
610
804
  );
611
805
  this.setupPollingListener(contract, eventFilter, callback);
612
806
  return;
@@ -631,18 +825,23 @@ class SmartContractService {
631
825
  }
632
826
  }
633
827
  /**
634
- * Checks if an error indicates that the RPC method is unsupported (eth_newFilter).
635
- *
828
+ * Checks if an error indicates that the RPC method is unsupported or filter operations are not working.
829
+ * This includes:
830
+ * - Method not found (-32601): RPC doesn't support eth_newFilter
831
+ * - Filter not found (-32000): RPC doesn't properly maintain filters
832
+ *
636
833
  * @param error - The error to check
637
- * @returns true if the error indicates unsupported method
834
+ * @returns true if the error indicates unsupported or broken filter functionality
638
835
  */
639
836
  isUnsupportedMethodError(error) {
640
- return error?.code === -32601 || error?.error?.code === -32601 || error?.data?.code === -32601 || typeof error?.message === "string" && error.message.includes("unsupported method");
837
+ const isMethodNotFound = error?.code === -32601 || error?.error?.code === -32601 || error?.data?.code === -32601 || typeof error?.message === "string" && error.message.includes("unsupported method");
838
+ const isFilterNotFound = (error?.code === -32e3 || error?.error?.code === -32e3 || error?.code === "UNKNOWN_ERROR" && error?.error?.code === -32e3) && (error?.message?.includes("filter not found") || error?.error?.message?.includes("filter not found"));
839
+ return isMethodNotFound || isFilterNotFound;
641
840
  }
642
841
  /**
643
842
  * Sets up a polling-based event listener as fallback when eth_newFilter is not supported.
644
843
  * Periodically queries for new events and invokes the callback for each new event found.
645
- *
844
+ *
646
845
  * @template Args - Tuple type representing the event arguments
647
846
  * @param contract - The contract instance to poll
648
847
  * @param eventFilter - The event filter to poll for
@@ -694,7 +893,7 @@ class SmartContractService {
694
893
  }
695
894
  /**
696
895
  * Sets the polling interval for event listeners using the fallback mechanism.
697
- *
896
+ *
698
897
  * @param intervalMs - Polling interval in milliseconds
699
898
  */
700
899
  setEventPollingInterval(intervalMs) {
@@ -705,7 +904,7 @@ class SmartContractService {
705
904
  class ContractServiceError extends Error {
706
905
  /**
707
906
  * Creates a new ContractServiceError instance.
708
- *
907
+ *
709
908
  * @param message - The error message describing what went wrong
710
909
  * @param operation - The operation that was being performed when the error occurred
711
910
  */
@@ -795,7 +994,6 @@ class ProcessRegistryService extends SmartContractService {
795
994
  newProcess(status, startTime, duration, ballotMode, census, metadata, encryptionKey, initStateRoot) {
796
995
  const contractCensus = {
797
996
  censusOrigin: BigInt(census.censusOrigin),
798
- maxVotes: BigInt(census.maxVotes),
799
997
  censusRoot: census.censusRoot,
800
998
  censusURI: census.censusURI
801
999
  };
@@ -826,7 +1024,6 @@ class ProcessRegistryService extends SmartContractService {
826
1024
  setProcessCensus(processID, census) {
827
1025
  const contractCensus = {
828
1026
  censusOrigin: BigInt(census.censusOrigin),
829
- maxVotes: BigInt(census.maxVotes),
830
1027
  censusRoot: census.censusRoot,
831
1028
  censusURI: census.censusURI
832
1029
  };
@@ -858,7 +1055,7 @@ class ProcessRegistryService extends SmartContractService {
858
1055
  }
859
1056
  /**
860
1057
  * Sets the results for a voting process.
861
- *
1058
+ *
862
1059
  * @param processID - The ID of the process to set results for
863
1060
  * @param proof - Zero-knowledge proof validating the results
864
1061
  * @param input - Input data for the proof verification
@@ -866,11 +1063,7 @@ class ProcessRegistryService extends SmartContractService {
866
1063
  */
867
1064
  setProcessResults(processID, proof, input) {
868
1065
  return this.sendTx(
869
- this.contract.setProcessResults(
870
- processID,
871
- proof,
872
- input
873
- ).catch((e) => {
1066
+ this.contract.setProcessResults(processID, proof, input).catch((e) => {
874
1067
  throw new ProcessResultError(e.message, "setResults");
875
1068
  }),
876
1069
  async () => ({ success: true })
@@ -932,6 +1125,34 @@ class ProcessOrchestrationService {
932
1125
  this.organizationRegistry = organizationRegistry;
933
1126
  this.getCrypto = getCrypto;
934
1127
  this.signer = signer;
1128
+ this.censusOrchestrator = new CensusOrchestrator(apiService.census);
1129
+ }
1130
+ /**
1131
+ * Handles census - auto-publishes if needed and returns census config
1132
+ * @private
1133
+ */
1134
+ async handleCensus(census) {
1135
+ if ("isPublished" in census) {
1136
+ if (census instanceof PlainCensus || census instanceof WeightedCensus) {
1137
+ if (!census.isPublished) {
1138
+ const censusBaseURL = this.apiService.census?.["axios"]?.defaults?.baseURL;
1139
+ if (!censusBaseURL || censusBaseURL === "" || censusBaseURL === "undefined") {
1140
+ throw new Error(
1141
+ 'Census API URL is required to publish PlainCensus or WeightedCensus. Please provide "censusUrl" when initializing DavinciSDK, or use a pre-published census.'
1142
+ );
1143
+ }
1144
+ await this.censusOrchestrator.publish(census);
1145
+ }
1146
+ }
1147
+ const censusData = this.censusOrchestrator.getCensusData(census);
1148
+ return {
1149
+ type: censusData.type,
1150
+ root: censusData.root,
1151
+ size: censusData.size,
1152
+ uri: censusData.uri
1153
+ };
1154
+ }
1155
+ return census;
935
1156
  }
936
1157
  /**
937
1158
  * Gets user-friendly process information by transforming raw contract data
@@ -971,7 +1192,6 @@ class ProcessOrchestrationService {
971
1192
  const census = {
972
1193
  type: Number(rawProcess.census.censusOrigin),
973
1194
  root: rawProcess.census.censusRoot,
974
- size: Number(rawProcess.census.maxVotes),
975
1195
  uri: rawProcess.census.censusURI || ""
976
1196
  };
977
1197
  const ballot = {
@@ -986,11 +1206,11 @@ class ProcessOrchestrationService {
986
1206
  };
987
1207
  return {
988
1208
  processId,
989
- title,
1209
+ title: title || "",
990
1210
  description,
991
1211
  census,
992
1212
  ballot,
993
- questions,
1213
+ questions: questions || [],
994
1214
  status: Number(rawProcess.status),
995
1215
  creator: rawProcess.organizationId,
996
1216
  startDate: new Date(startTime * 1e3),
@@ -1007,10 +1227,10 @@ class ProcessOrchestrationService {
1007
1227
  /**
1008
1228
  * Creates a complete voting process and returns an async generator that yields transaction status events.
1009
1229
  * This method allows you to monitor the transaction progress in real-time.
1010
- *
1230
+ *
1011
1231
  * @param config - Process configuration
1012
1232
  * @returns AsyncGenerator yielding transaction status events with ProcessCreationResult
1013
- *
1233
+ *
1014
1234
  * @example
1015
1235
  * ```typescript
1016
1236
  * const stream = sdk.createProcessStream({
@@ -1021,7 +1241,7 @@ class ProcessOrchestrationService {
1021
1241
  * timing: { ... },
1022
1242
  * questions: [ ... ]
1023
1243
  * });
1024
- *
1244
+ *
1025
1245
  * for await (const event of stream) {
1026
1246
  * switch (event.status) {
1027
1247
  * case "pending":
@@ -1083,16 +1303,16 @@ class ProcessOrchestrationService {
1083
1303
  /**
1084
1304
  * Creates a complete voting process with minimal configuration.
1085
1305
  * This is the ultra-easy method for end users that handles all the complex orchestration internally.
1086
- *
1306
+ *
1087
1307
  * For real-time transaction status updates, use createProcessStream() instead.
1088
- *
1308
+ *
1089
1309
  * The method automatically:
1090
1310
  * - Gets encryption keys and initial state root from the sequencer
1091
1311
  * - Handles process creation signatures
1092
1312
  * - Coordinates between sequencer API and on-chain contract calls
1093
1313
  * - Creates and pushes metadata
1094
1314
  * - Submits the on-chain transaction
1095
- *
1315
+ *
1096
1316
  * @param config - Simplified process configuration
1097
1317
  * @returns Promise resolving to the process creation result
1098
1318
  */
@@ -1116,24 +1336,32 @@ class ProcessOrchestrationService {
1116
1336
  const { startTime, duration } = this.calculateTiming(config.timing);
1117
1337
  const signerAddress = await this.signer.getAddress();
1118
1338
  const processId = await this.processRegistry.getNextProcessId(signerAddress);
1119
- const censusRoot = config.census.root;
1339
+ const censusConfig = await this.handleCensus(config.census);
1340
+ const censusRoot = censusConfig.root;
1120
1341
  const ballotMode = config.ballot;
1121
- const metadata = this.createMetadata(config);
1122
- const metadataHash = await this.apiService.sequencer.pushMetadata(metadata);
1123
- const metadataUri = this.apiService.sequencer.getMetadataUrl(metadataHash);
1342
+ let metadataUri;
1343
+ if ("metadataUri" in config) {
1344
+ metadataUri = config.metadataUri;
1345
+ } else {
1346
+ const metadata = this.createMetadata(config);
1347
+ const metadataHash = await this.apiService.sequencer.pushMetadata(metadata);
1348
+ metadataUri = this.apiService.sequencer.getMetadataUrl(metadataHash);
1349
+ }
1124
1350
  const signature = await signProcessCreation(processId, this.signer);
1125
1351
  const sequencerResult = await this.apiService.sequencer.createProcess({
1126
1352
  processId,
1127
- censusRoot,
1353
+ census: {
1354
+ censusOrigin: censusConfig.type,
1355
+ censusRoot,
1356
+ censusURI: censusConfig.uri
1357
+ },
1128
1358
  ballotMode,
1129
- signature,
1130
- censusOrigin: config.census.type
1359
+ signature
1131
1360
  });
1132
1361
  const census = {
1133
- censusOrigin: config.census.type,
1134
- maxVotes: config.census.size.toString(),
1362
+ censusOrigin: censusConfig.type,
1135
1363
  censusRoot,
1136
- censusURI: config.census.uri
1364
+ censusURI: censusConfig.uri
1137
1365
  };
1138
1366
  return {
1139
1367
  processId,
@@ -1200,15 +1428,13 @@ class ProcessOrchestrationService {
1200
1428
  throw new Error("Invalid date format. Use Date object, ISO string, or Unix timestamp.");
1201
1429
  }
1202
1430
  /**
1203
- * Creates metadata from the simplified configuration
1431
+ * Creates metadata from the configuration with metadata fields
1432
+ * This method should only be called with ProcessConfigWithMetadata
1204
1433
  */
1205
1434
  createMetadata(config) {
1206
1435
  const metadata = getElectionMetadataTemplate();
1207
1436
  metadata.title.default = config.title;
1208
1437
  metadata.description.default = config.description || "";
1209
- if (!config.questions || config.questions.length === 0) {
1210
- throw new Error("Questions are required. Please provide at least one question with choices.");
1211
- }
1212
1438
  metadata.questions = config.questions.map((q) => ({
1213
1439
  title: { default: q.title },
1214
1440
  description: { default: q.description || "" },
@@ -1224,14 +1450,14 @@ class ProcessOrchestrationService {
1224
1450
  /**
1225
1451
  * Ends a voting process by setting its status to ENDED.
1226
1452
  * Returns an async generator that yields transaction status events.
1227
- *
1453
+ *
1228
1454
  * @param processId - The process ID to end
1229
1455
  * @returns AsyncGenerator yielding transaction status events
1230
- *
1456
+ *
1231
1457
  * @example
1232
1458
  * ```typescript
1233
1459
  * const stream = sdk.endProcessStream("0x1234567890abcdef...");
1234
- *
1460
+ *
1235
1461
  * for await (const event of stream) {
1236
1462
  * switch (event.status) {
1237
1463
  * case "pending":
@@ -1273,12 +1499,12 @@ class ProcessOrchestrationService {
1273
1499
  /**
1274
1500
  * Ends a voting process by setting its status to ENDED.
1275
1501
  * This is a simplified method that waits for transaction completion.
1276
- *
1502
+ *
1277
1503
  * For real-time transaction status updates, use endProcessStream() instead.
1278
- *
1504
+ *
1279
1505
  * @param processId - The process ID to end
1280
1506
  * @returns Promise resolving when the process is ended
1281
- *
1507
+ *
1282
1508
  * @example
1283
1509
  * ```typescript
1284
1510
  * await sdk.endProcess("0x1234567890abcdef...");
@@ -1300,14 +1526,14 @@ class ProcessOrchestrationService {
1300
1526
  /**
1301
1527
  * Pauses a voting process by setting its status to PAUSED.
1302
1528
  * Returns an async generator that yields transaction status events.
1303
- *
1529
+ *
1304
1530
  * @param processId - The process ID to pause
1305
1531
  * @returns AsyncGenerator yielding transaction status events
1306
- *
1532
+ *
1307
1533
  * @example
1308
1534
  * ```typescript
1309
1535
  * const stream = sdk.pauseProcessStream("0x1234567890abcdef...");
1310
- *
1536
+ *
1311
1537
  * for await (const event of stream) {
1312
1538
  * switch (event.status) {
1313
1539
  * case "pending":
@@ -1349,12 +1575,12 @@ class ProcessOrchestrationService {
1349
1575
  /**
1350
1576
  * Pauses a voting process by setting its status to PAUSED.
1351
1577
  * This is a simplified method that waits for transaction completion.
1352
- *
1578
+ *
1353
1579
  * For real-time transaction status updates, use pauseProcessStream() instead.
1354
- *
1580
+ *
1355
1581
  * @param processId - The process ID to pause
1356
1582
  * @returns Promise resolving when the process is paused
1357
- *
1583
+ *
1358
1584
  * @example
1359
1585
  * ```typescript
1360
1586
  * await sdk.pauseProcess("0x1234567890abcdef...");
@@ -1376,14 +1602,14 @@ class ProcessOrchestrationService {
1376
1602
  /**
1377
1603
  * Cancels a voting process by setting its status to CANCELED.
1378
1604
  * Returns an async generator that yields transaction status events.
1379
- *
1605
+ *
1380
1606
  * @param processId - The process ID to cancel
1381
1607
  * @returns AsyncGenerator yielding transaction status events
1382
- *
1608
+ *
1383
1609
  * @example
1384
1610
  * ```typescript
1385
1611
  * const stream = sdk.cancelProcessStream("0x1234567890abcdef...");
1386
- *
1612
+ *
1387
1613
  * for await (const event of stream) {
1388
1614
  * switch (event.status) {
1389
1615
  * case "pending":
@@ -1425,12 +1651,12 @@ class ProcessOrchestrationService {
1425
1651
  /**
1426
1652
  * Cancels a voting process by setting its status to CANCELED.
1427
1653
  * This is a simplified method that waits for transaction completion.
1428
- *
1654
+ *
1429
1655
  * For real-time transaction status updates, use cancelProcessStream() instead.
1430
- *
1656
+ *
1431
1657
  * @param processId - The process ID to cancel
1432
1658
  * @returns Promise resolving when the process is canceled
1433
- *
1659
+ *
1434
1660
  * @example
1435
1661
  * ```typescript
1436
1662
  * await sdk.cancelProcess("0x1234567890abcdef...");
@@ -1453,14 +1679,14 @@ class ProcessOrchestrationService {
1453
1679
  * Resumes a voting process by setting its status to READY.
1454
1680
  * This is typically used to resume a paused process.
1455
1681
  * Returns an async generator that yields transaction status events.
1456
- *
1682
+ *
1457
1683
  * @param processId - The process ID to resume
1458
1684
  * @returns AsyncGenerator yielding transaction status events
1459
- *
1685
+ *
1460
1686
  * @example
1461
1687
  * ```typescript
1462
1688
  * const stream = sdk.resumeProcessStream("0x1234567890abcdef...");
1463
- *
1689
+ *
1464
1690
  * for await (const event of stream) {
1465
1691
  * switch (event.status) {
1466
1692
  * case "pending":
@@ -1503,12 +1729,12 @@ class ProcessOrchestrationService {
1503
1729
  * Resumes a voting process by setting its status to READY.
1504
1730
  * This is typically used to resume a paused process.
1505
1731
  * This is a simplified method that waits for transaction completion.
1506
- *
1732
+ *
1507
1733
  * For real-time transaction status updates, use resumeProcessStream() instead.
1508
- *
1734
+ *
1509
1735
  * @param processId - The process ID to resume
1510
1736
  * @returns Promise resolving when the process is resumed
1511
- *
1737
+ *
1512
1738
  * @example
1513
1739
  * ```typescript
1514
1740
  * await sdk.resumeProcess("0x1234567890abcdef...");
@@ -1596,11 +1822,7 @@ class CircomProof {
1596
1822
  }
1597
1823
  this.zkeyCache.set(zkeyUrl, zkeyBin);
1598
1824
  }
1599
- const { proof, publicSignals } = await snarkjs.groth16.fullProve(
1600
- inputs,
1601
- wasmBin,
1602
- zkeyBin
1603
- );
1825
+ const { proof, publicSignals } = await snarkjs.groth16.fullProve(inputs, wasmBin, zkeyBin);
1604
1826
  return {
1605
1827
  proof,
1606
1828
  publicSignals
@@ -1635,11 +1857,13 @@ var VoteStatus = /* @__PURE__ */ ((VoteStatus2) => {
1635
1857
  })(VoteStatus || {});
1636
1858
 
1637
1859
  class VoteOrchestrationService {
1638
- constructor(apiService, getCrypto, signer, censusProviders = {}) {
1860
+ constructor(apiService, getCrypto, signer, censusProviders = {}, config = {}) {
1639
1861
  this.apiService = apiService;
1640
1862
  this.getCrypto = getCrypto;
1641
1863
  this.signer = signer;
1642
1864
  this.censusProviders = censusProviders;
1865
+ this.verifyCircuitFiles = config.verifyCircuitFiles ?? true;
1866
+ this.verifyProof = config.verifyProof ?? true;
1643
1867
  }
1644
1868
  /**
1645
1869
  * Submit a vote with simplified configuration
@@ -1648,7 +1872,7 @@ class VoteOrchestrationService {
1648
1872
  * - Gets census proof (Merkle or CSP)
1649
1873
  * - Generates cryptographic proofs
1650
1874
  * - Signs and submits the vote
1651
- *
1875
+ *
1652
1876
  * @param config - Simplified vote configuration
1653
1877
  * @returns Promise resolving to vote submission result
1654
1878
  */
@@ -1675,16 +1899,19 @@ class VoteOrchestrationService {
1675
1899
  );
1676
1900
  const { proof } = await this.generateZkProof(circomInputs);
1677
1901
  const signature = await this.signVote(voteId);
1678
- await this.submitVoteRequest({
1902
+ const voteRequest = {
1679
1903
  processId: config.processId,
1680
- censusProof,
1681
1904
  ballot: cryptoOutput.ballot,
1682
1905
  ballotProof: proof,
1683
1906
  ballotInputsHash: cryptoOutput.ballotInputsHash,
1684
1907
  address: voterAddress,
1685
1908
  signature,
1686
1909
  voteId
1687
- });
1910
+ };
1911
+ if (process.census.censusOrigin === CensusOrigin.CensusOriginCSP) {
1912
+ voteRequest.censusProof = censusProof;
1913
+ }
1914
+ await this.submitVoteRequest(voteRequest);
1688
1915
  const status = await this.apiService.sequencer.getVoteStatus(config.processId, voteId);
1689
1916
  return {
1690
1917
  voteId,
@@ -1696,7 +1923,7 @@ class VoteOrchestrationService {
1696
1923
  }
1697
1924
  /**
1698
1925
  * Get the status of a submitted vote
1699
- *
1926
+ *
1700
1927
  * @param processId - The process ID
1701
1928
  * @param voteId - The vote ID
1702
1929
  * @returns Promise resolving to vote status information
@@ -1711,7 +1938,7 @@ class VoteOrchestrationService {
1711
1938
  }
1712
1939
  /**
1713
1940
  * Check if an address has voted in a process
1714
- *
1941
+ *
1715
1942
  * @param processId - The process ID
1716
1943
  * @param address - The voter's address
1717
1944
  * @returns Promise resolving to boolean indicating if the address has voted
@@ -1722,19 +1949,19 @@ class VoteOrchestrationService {
1722
1949
  /**
1723
1950
  * Watch vote status changes in real-time using an async generator.
1724
1951
  * Yields each status change as it happens, allowing for reactive UI updates.
1725
- *
1952
+ *
1726
1953
  * @param processId - The process ID
1727
1954
  * @param voteId - The vote ID
1728
1955
  * @param options - Optional configuration
1729
1956
  * @returns AsyncGenerator yielding vote status updates
1730
- *
1957
+ *
1731
1958
  * @example
1732
1959
  * ```typescript
1733
1960
  * const vote = await sdk.submitVote({ processId, choices: [1] });
1734
- *
1961
+ *
1735
1962
  * for await (const statusInfo of sdk.watchVoteStatus(vote.processId, vote.voteId)) {
1736
1963
  * console.log(`Vote status: ${statusInfo.status}`);
1737
- *
1964
+ *
1738
1965
  * switch (statusInfo.status) {
1739
1966
  * case VoteStatus.Pending:
1740
1967
  * console.log("⏳ Processing...");
@@ -1771,7 +1998,7 @@ class VoteOrchestrationService {
1771
1998
  /**
1772
1999
  * Wait for a vote to reach a specific status.
1773
2000
  * This is a simpler alternative to watchVoteStatus() that returns only the final status.
1774
- *
2001
+ *
1775
2002
  * @param processId - The process ID
1776
2003
  * @param voteId - The vote ID
1777
2004
  * @param targetStatus - The target status to wait for (default: "settled")
@@ -1874,12 +2101,20 @@ class VoteOrchestrationService {
1874
2101
  const circomProof = new CircomProof({
1875
2102
  wasmUrl: info.circuitUrl,
1876
2103
  zkeyUrl: info.provingKeyUrl,
1877
- vkeyUrl: info.verificationKeyUrl
2104
+ vkeyUrl: info.verificationKeyUrl,
2105
+ // Only pass hashes if verifyCircuitFiles is enabled
2106
+ ...this.verifyCircuitFiles && {
2107
+ wasmHash: info.circuitHash,
2108
+ zkeyHash: info.provingKeyHash,
2109
+ vkeyHash: info.verificationKeyHash
2110
+ }
1878
2111
  });
1879
2112
  const { proof, publicSignals } = await circomProof.generate(circomInputs);
1880
- const isValid = await circomProof.verify(proof, publicSignals);
1881
- if (!isValid) {
1882
- throw new Error("Generated proof is invalid");
2113
+ if (this.verifyProof) {
2114
+ const isValid = await circomProof.verify(proof, publicSignals);
2115
+ if (!isValid) {
2116
+ throw new Error("Generated proof is invalid");
2117
+ }
1883
2118
  }
1884
2119
  return { proof, publicSignals };
1885
2120
  }
@@ -1917,10 +2152,7 @@ class VoteOrchestrationService {
1917
2152
  class OrganizationRegistryService extends SmartContractService {
1918
2153
  constructor(contractAddress, runner) {
1919
2154
  super();
1920
- this.contract = davinciContracts.OrganizationRegistry__factory.connect(
1921
- contractAddress,
1922
- runner
1923
- );
2155
+ this.contract = davinciContracts.OrganizationRegistry__factory.connect(contractAddress, runner);
1924
2156
  }
1925
2157
  // ─── READ OPERATIONS ───────────────────────────────────────────────────────
1926
2158
  async getOrganization(id) {
@@ -2123,14 +2355,15 @@ class DavinciCrypto {
2123
2355
  * @param privKey - The private key in hex format
2124
2356
  * @param processId - The process ID in hex format
2125
2357
  * @param address - The address in hex format
2358
+ * @param weight - The vote weight as a decimal string
2126
2359
  * @returns The CSP proof as a parsed JSON object
2127
2360
  * @throws if called before `await init()`, or if Go returns an error
2128
2361
  */
2129
- async cspSign(censusOrigin, privKey, processId, address) {
2362
+ async cspSign(censusOrigin, privKey, processId, address, weight) {
2130
2363
  if (!this.initialized) {
2131
2364
  throw new Error("DavinciCrypto not initialized \u2014 call `await init()` first");
2132
2365
  }
2133
- const raw = globalThis.DavinciCrypto.cspSign(censusOrigin, privKey, processId, address);
2366
+ const raw = globalThis.DavinciCrypto.cspSign(censusOrigin, privKey, processId, address, weight);
2134
2367
  if (raw.error) {
2135
2368
  throw new Error(`Go/WASM cspSign error: ${raw.error}`);
2136
2369
  }
@@ -2144,13 +2377,14 @@ class DavinciCrypto {
2144
2377
  * @param censusOrigin - The census origin type (e.g., CensusOrigin.CensusOriginCSP)
2145
2378
  * @param root - The census root
2146
2379
  * @param address - The address
2380
+ * @param weight - The vote weight as a decimal string
2147
2381
  * @param processId - The process ID
2148
2382
  * @param publicKey - The public key
2149
2383
  * @param signature - The signature
2150
2384
  * @returns The verification result
2151
2385
  * @throws if called before `await init()`, or if Go returns an error
2152
2386
  */
2153
- async cspVerify(censusOrigin, root, address, processId, publicKey, signature) {
2387
+ async cspVerify(censusOrigin, root, address, weight, processId, publicKey, signature) {
2154
2388
  if (!this.initialized) {
2155
2389
  throw new Error("DavinciCrypto not initialized \u2014 call `await init()` first");
2156
2390
  }
@@ -2158,6 +2392,7 @@ class DavinciCrypto {
2158
2392
  censusOrigin,
2159
2393
  root,
2160
2394
  address,
2395
+ weight,
2161
2396
  processId,
2162
2397
  publicKey,
2163
2398
  signature
@@ -2196,25 +2431,23 @@ class DavinciCrypto {
2196
2431
  class DavinciSDK {
2197
2432
  constructor(config) {
2198
2433
  this.initialized = false;
2199
- const resolvedConfig = resolveConfiguration({
2200
- environment: config.environment,
2201
- customUrls: {
2202
- sequencer: config.sequencerUrl,
2203
- census: config.censusUrl
2204
- },
2205
- customChain: config.chain
2206
- });
2434
+ const hasCustomAddresses = !!config.addresses && Object.keys(config.addresses).length > 0;
2207
2435
  this.config = {
2208
2436
  signer: config.signer,
2209
- sequencerUrl: config.sequencerUrl ?? resolvedConfig.sequencer,
2210
- censusUrl: config.censusUrl ?? resolvedConfig.census,
2211
- chain: config.chain ?? resolvedConfig.chain,
2212
- contractAddresses: config.contractAddresses || {},
2213
- useSequencerAddresses: config.useSequencerAddresses || false
2437
+ sequencerUrl: config.sequencerUrl,
2438
+ censusUrl: config.censusUrl,
2439
+ customAddresses: config.addresses || {},
2440
+ fetchAddressesFromSequencer: !hasCustomAddresses,
2441
+ // Automatic: fetch if no custom addresses
2442
+ verifyCircuitFiles: config.verifyCircuitFiles ?? true,
2443
+ // Default to true for security
2444
+ verifyProof: config.verifyProof ?? true
2445
+ // Default to true for security
2214
2446
  };
2215
2447
  this.apiService = new VocdoniApiService({
2216
2448
  sequencerURL: this.config.sequencerUrl,
2217
- censusURL: this.config.censusUrl
2449
+ censusURL: this.config.censusUrl || ""
2450
+ // Use empty string if not provided
2218
2451
  });
2219
2452
  this.censusProviders = config.censusProviders || {};
2220
2453
  }
@@ -2224,9 +2457,10 @@ class DavinciSDK {
2224
2457
  */
2225
2458
  async init() {
2226
2459
  if (this.initialized) return;
2227
- if (this.config.useSequencerAddresses) {
2228
- await this.updateContractAddressesFromSequencer();
2460
+ if (this.config.fetchAddressesFromSequencer) {
2461
+ await this.fetchContractAddressesFromSequencer();
2229
2462
  }
2463
+ if (!this.config.censusUrl) ;
2230
2464
  this.initialized = true;
2231
2465
  }
2232
2466
  /**
@@ -2238,28 +2472,34 @@ class DavinciSDK {
2238
2472
  /**
2239
2473
  * Get the process registry service for process management.
2240
2474
  * Requires a signer with a provider for blockchain interactions.
2241
- *
2475
+ *
2242
2476
  * @throws Error if signer does not have a provider
2243
2477
  */
2244
2478
  get processes() {
2245
2479
  this.ensureProvider();
2246
2480
  if (!this._processRegistry) {
2247
2481
  const processRegistryAddress = this.resolveContractAddress("processRegistry");
2248
- this._processRegistry = new ProcessRegistryService(processRegistryAddress, this.config.signer);
2482
+ this._processRegistry = new ProcessRegistryService(
2483
+ processRegistryAddress,
2484
+ this.config.signer
2485
+ );
2249
2486
  }
2250
2487
  return this._processRegistry;
2251
2488
  }
2252
2489
  /**
2253
2490
  * Get the organization registry service for organization management.
2254
2491
  * Requires a signer with a provider for blockchain interactions.
2255
- *
2492
+ *
2256
2493
  * @throws Error if signer does not have a provider
2257
2494
  */
2258
2495
  get organizations() {
2259
2496
  this.ensureProvider();
2260
2497
  if (!this._organizationRegistry) {
2261
2498
  const organizationRegistryAddress = this.resolveContractAddress("organizationRegistry");
2262
- this._organizationRegistry = new OrganizationRegistryService(organizationRegistryAddress, this.config.signer);
2499
+ this._organizationRegistry = new OrganizationRegistryService(
2500
+ organizationRegistryAddress,
2501
+ this.config.signer
2502
+ );
2263
2503
  }
2264
2504
  return this._organizationRegistry;
2265
2505
  }
@@ -2280,7 +2520,7 @@ class DavinciSDK {
2280
2520
  /**
2281
2521
  * Get the process orchestration service for simplified process creation.
2282
2522
  * Requires a signer with a provider for blockchain interactions.
2283
- *
2523
+ *
2284
2524
  * @throws Error if signer does not have a provider
2285
2525
  */
2286
2526
  get processOrchestrator() {
@@ -2305,7 +2545,11 @@ class DavinciSDK {
2305
2545
  this.apiService,
2306
2546
  () => this.getCrypto(),
2307
2547
  this.config.signer,
2308
- this.censusProviders
2548
+ this.censusProviders,
2549
+ {
2550
+ verifyCircuitFiles: this.config.verifyCircuitFiles,
2551
+ verifyProof: this.config.verifyProof
2552
+ }
2309
2553
  );
2310
2554
  }
2311
2555
  return this._voteOrchestrator;
@@ -2314,24 +2558,24 @@ class DavinciSDK {
2314
2558
  * Gets user-friendly process information from the blockchain.
2315
2559
  * This method fetches raw contract data and transforms it into a user-friendly format
2316
2560
  * that matches the ProcessConfig interface used for creation, plus additional runtime data.
2317
- *
2561
+ *
2318
2562
  * Requires a signer with a provider for blockchain interactions.
2319
- *
2563
+ *
2320
2564
  * @param processId - The process ID to fetch
2321
2565
  * @returns Promise resolving to user-friendly process information
2322
2566
  * @throws Error if signer does not have a provider
2323
- *
2567
+ *
2324
2568
  * @example
2325
2569
  * ```typescript
2326
2570
  * const processInfo = await sdk.getProcess("0x1234567890abcdef...");
2327
- *
2571
+ *
2328
2572
  * // Access the same fields as ProcessConfig
2329
2573
  * console.log("Title:", processInfo.title);
2330
2574
  * console.log("Description:", processInfo.description);
2331
2575
  * console.log("Questions:", processInfo.questions);
2332
2576
  * console.log("Census size:", processInfo.census.size);
2333
2577
  * console.log("Ballot config:", processInfo.ballot);
2334
- *
2578
+ *
2335
2579
  * // Plus additional runtime information
2336
2580
  * console.log("Status:", processInfo.status);
2337
2581
  * console.log("Creator:", processInfo.creator);
@@ -2339,7 +2583,7 @@ class DavinciSDK {
2339
2583
  * console.log("End date:", processInfo.endDate);
2340
2584
  * console.log("Duration:", processInfo.duration, "seconds");
2341
2585
  * console.log("Time remaining:", processInfo.timeRemaining, "seconds");
2342
- *
2586
+ *
2343
2587
  * // Access raw contract data if needed
2344
2588
  * console.log("Raw data:", processInfo.raw);
2345
2589
  * ```
@@ -2355,13 +2599,13 @@ class DavinciSDK {
2355
2599
  * Creates a complete voting process and returns an async generator that yields transaction status events.
2356
2600
  * This method allows you to monitor the transaction progress in real-time, including pending, completed,
2357
2601
  * failed, and reverted states.
2358
- *
2602
+ *
2359
2603
  * Requires a signer with a provider for blockchain interactions.
2360
- *
2604
+ *
2361
2605
  * @param config - Simplified process configuration
2362
2606
  * @returns AsyncGenerator yielding transaction status events
2363
2607
  * @throws Error if signer does not have a provider
2364
- *
2608
+ *
2365
2609
  * @example
2366
2610
  * ```typescript
2367
2611
  * const stream = sdk.createProcessStream({
@@ -2397,7 +2641,7 @@ class DavinciSDK {
2397
2641
  * }
2398
2642
  * ]
2399
2643
  * });
2400
- *
2644
+ *
2401
2645
  * // Monitor transaction progress
2402
2646
  * for await (const event of stream) {
2403
2647
  * switch (event.status) {
@@ -2432,22 +2676,22 @@ class DavinciSDK {
2432
2676
  /**
2433
2677
  * Creates a complete voting process with minimal configuration.
2434
2678
  * This is the ultra-easy method for end users that handles all the complex orchestration internally.
2435
- *
2679
+ *
2436
2680
  * For real-time transaction status updates, use createProcessStream() instead.
2437
- *
2681
+ *
2438
2682
  * Requires a signer with a provider for blockchain interactions.
2439
- *
2683
+ *
2440
2684
  * The method automatically:
2441
2685
  * - Gets encryption keys and initial state root from the sequencer
2442
2686
  * - Handles process creation signatures
2443
2687
  * - Coordinates between sequencer API and on-chain contract calls
2444
2688
  * - Creates and pushes metadata
2445
2689
  * - Submits the on-chain transaction
2446
- *
2690
+ *
2447
2691
  * @param config - Simplified process configuration
2448
2692
  * @returns Promise resolving to the process creation result
2449
2693
  * @throws Error if signer does not have a provider
2450
- *
2694
+ *
2451
2695
  * @example
2452
2696
  * ```typescript
2453
2697
  * // Option 1: Using duration (traditional approach)
@@ -2484,7 +2728,7 @@ class DavinciSDK {
2484
2728
  * }
2485
2729
  * ]
2486
2730
  * });
2487
- *
2731
+ *
2488
2732
  * // Option 2: Using start and end dates
2489
2733
  * const result2 = await sdk.createProcess({
2490
2734
  * title: "Weekend Vote",
@@ -2505,18 +2749,20 @@ class DavinciSDK {
2505
2749
  /**
2506
2750
  * Submit a vote with simplified configuration.
2507
2751
  * This is the ultra-easy method for end users that handles all the complex voting workflow internally.
2508
- *
2752
+ *
2509
2753
  * Does NOT require a provider - can be used with a bare Wallet for signing only.
2510
- *
2754
+ * IMPORTANT: Requires censusUrl to be configured in the SDK for fetching census proofs (unless using custom census providers).
2755
+ *
2511
2756
  * The method automatically:
2512
2757
  * - Fetches process information and validates voting is allowed
2513
2758
  * - Gets census proof (Merkle tree based)
2514
2759
  * - Generates cryptographic proofs and encrypts the vote
2515
2760
  * - Signs and submits the vote to the sequencer
2516
- *
2761
+ *
2517
2762
  * @param config - Simplified vote configuration
2518
2763
  * @returns Promise resolving to vote submission result
2519
- *
2764
+ * @throws Error if censusUrl is not configured (unless using custom census providers)
2765
+ *
2520
2766
  * @example
2521
2767
  * ```typescript
2522
2768
  * // Submit a vote with voter's private key
@@ -2525,14 +2771,14 @@ class DavinciSDK {
2525
2771
  * choices: [1, 0], // Vote for option 1 in question 1, option 0 in question 2
2526
2772
  * voterKey: "0x1234567890abcdef..." // Voter's private key
2527
2773
  * });
2528
- *
2774
+ *
2529
2775
  * console.log("Vote ID:", voteResult.voteId);
2530
2776
  * console.log("Status:", voteResult.status);
2531
- *
2777
+ *
2532
2778
  * // Submit a vote with a Wallet instance
2533
2779
  * import { Wallet } from "ethers";
2534
2780
  * const voterWallet = new Wallet("0x...");
2535
- *
2781
+ *
2536
2782
  * const voteResult2 = await sdk.submitVote({
2537
2783
  * processId: "0x1234567890abcdef...",
2538
2784
  * choices: [2], // Single question vote
@@ -2544,17 +2790,22 @@ class DavinciSDK {
2544
2790
  if (!this.initialized) {
2545
2791
  throw new Error("SDK must be initialized before submitting votes. Call sdk.init() first.");
2546
2792
  }
2793
+ if (!this.config.censusUrl && !this.censusProviders.merkle && !this.censusProviders.csp) {
2794
+ throw new Error(
2795
+ "Census URL is required for voting. Provide censusUrl in the SDK constructor config, or use custom census providers."
2796
+ );
2797
+ }
2547
2798
  return this.voteOrchestrator.submitVote(config);
2548
2799
  }
2549
2800
  /**
2550
2801
  * Get the status of a submitted vote.
2551
- *
2802
+ *
2552
2803
  * Does NOT require a provider - uses API calls only.
2553
- *
2804
+ *
2554
2805
  * @param processId - The process ID
2555
2806
  * @param voteId - The vote ID returned from submitVote()
2556
2807
  * @returns Promise resolving to vote status information
2557
- *
2808
+ *
2558
2809
  * @example
2559
2810
  * ```typescript
2560
2811
  * const statusInfo = await sdk.getVoteStatus(processId, voteId);
@@ -2570,13 +2821,13 @@ class DavinciSDK {
2570
2821
  }
2571
2822
  /**
2572
2823
  * Check if an address has voted in a process.
2573
- *
2824
+ *
2574
2825
  * Does NOT require a provider - uses API calls only.
2575
- *
2826
+ *
2576
2827
  * @param processId - The process ID
2577
2828
  * @param address - The voter's address
2578
2829
  * @returns Promise resolving to boolean indicating if the address has voted
2579
- *
2830
+ *
2580
2831
  * @example
2581
2832
  * ```typescript
2582
2833
  * const hasVoted = await sdk.hasAddressVoted(processId, "0x1234567890abcdef...");
@@ -2587,22 +2838,48 @@ class DavinciSDK {
2587
2838
  */
2588
2839
  async hasAddressVoted(processId, address) {
2589
2840
  if (!this.initialized) {
2590
- throw new Error("SDK must be initialized before checking vote status. Call sdk.init() first.");
2841
+ throw new Error(
2842
+ "SDK must be initialized before checking vote status. Call sdk.init() first."
2843
+ );
2591
2844
  }
2592
2845
  return this.voteOrchestrator.hasAddressVoted(processId, address);
2593
2846
  }
2847
+ /**
2848
+ * Check if an address is able to vote in a process and get participant information.
2849
+ *
2850
+ * Does NOT require a provider - uses API calls only.
2851
+ *
2852
+ * @param processId - The process ID
2853
+ * @param address - The voter's address
2854
+ * @returns Promise resolving to participant information (key and weight)
2855
+ *
2856
+ * @example
2857
+ * ```typescript
2858
+ * const participantInfo = await sdk.isAddressAbleToVote(processId, "0x1234567890abcdef...");
2859
+ * console.log("Address:", participantInfo.key);
2860
+ * console.log("Weight:", participantInfo.weight);
2861
+ * ```
2862
+ */
2863
+ async isAddressAbleToVote(processId, address) {
2864
+ if (!this.initialized) {
2865
+ throw new Error(
2866
+ "SDK must be initialized before checking participant info. Call sdk.init() first."
2867
+ );
2868
+ }
2869
+ return this.apiService.sequencer.isAddressAbleToVote(processId, address);
2870
+ }
2594
2871
  /**
2595
2872
  * Watch vote status changes in real-time using an async generator.
2596
- * This method yields each status change as it happens, perfect for showing
2873
+ * This method yields each status change as it happens, perfect for showing
2597
2874
  * progress indicators in UI applications.
2598
- *
2875
+ *
2599
2876
  * Does NOT require a provider - uses API calls only.
2600
- *
2877
+ *
2601
2878
  * @param processId - The process ID
2602
2879
  * @param voteId - The vote ID
2603
2880
  * @param options - Optional configuration
2604
2881
  * @returns AsyncGenerator yielding vote status updates
2605
- *
2882
+ *
2606
2883
  * @example
2607
2884
  * ```typescript
2608
2885
  * // Submit vote
@@ -2610,11 +2887,11 @@ class DavinciSDK {
2610
2887
  * processId: "0x1234567890abcdef...",
2611
2888
  * choices: [1]
2612
2889
  * });
2613
- *
2890
+ *
2614
2891
  * // Watch status changes in real-time
2615
2892
  * for await (const statusInfo of sdk.watchVoteStatus(voteResult.processId, voteResult.voteId)) {
2616
2893
  * console.log(`Vote status: ${statusInfo.status}`);
2617
- *
2894
+ *
2618
2895
  * switch (statusInfo.status) {
2619
2896
  * case VoteStatus.Pending:
2620
2897
  * console.log("⏳ Processing...");
@@ -2634,7 +2911,9 @@ class DavinciSDK {
2634
2911
  */
2635
2912
  watchVoteStatus(processId, voteId, options) {
2636
2913
  if (!this.initialized) {
2637
- throw new Error("SDK must be initialized before watching vote status. Call sdk.init() first.");
2914
+ throw new Error(
2915
+ "SDK must be initialized before watching vote status. Call sdk.init() first."
2916
+ );
2638
2917
  }
2639
2918
  return this.voteOrchestrator.watchVoteStatus(processId, voteId, options);
2640
2919
  }
@@ -2642,16 +2921,16 @@ class DavinciSDK {
2642
2921
  * Wait for a vote to reach a specific status.
2643
2922
  * This is a simpler alternative to watchVoteStatus() that returns only the final status.
2644
2923
  * Useful for waiting for vote confirmation and processing without needing to handle each intermediate status.
2645
- *
2924
+ *
2646
2925
  * Does NOT require a provider - uses API calls only.
2647
- *
2926
+ *
2648
2927
  * @param processId - The process ID
2649
2928
  * @param voteId - The vote ID
2650
2929
  * @param targetStatus - The target status to wait for (default: "settled")
2651
2930
  * @param timeoutMs - Maximum time to wait in milliseconds (default: 300000 = 5 minutes)
2652
2931
  * @param pollIntervalMs - Polling interval in milliseconds (default: 5000 = 5 seconds)
2653
2932
  * @returns Promise resolving to final vote status
2654
- *
2933
+ *
2655
2934
  * @example
2656
2935
  * ```typescript
2657
2936
  * // Submit vote and wait for it to be settled
@@ -2659,7 +2938,7 @@ class DavinciSDK {
2659
2938
  * processId: "0x1234567890abcdef...",
2660
2939
  * choices: [1]
2661
2940
  * });
2662
- *
2941
+ *
2663
2942
  * // Wait for the vote to be fully processed
2664
2943
  * const finalStatus = await sdk.waitForVoteStatus(
2665
2944
  * voteResult.processId,
@@ -2668,31 +2947,39 @@ class DavinciSDK {
2668
2947
  * 300000, // 5 minute timeout
2669
2948
  * 5000 // Check every 5 seconds
2670
2949
  * );
2671
- *
2950
+ *
2672
2951
  * console.log("Vote final status:", finalStatus.status);
2673
2952
  * ```
2674
2953
  */
2675
2954
  async waitForVoteStatus(processId, voteId, targetStatus = VoteStatus.Settled, timeoutMs = 3e5, pollIntervalMs = 5e3) {
2676
2955
  if (!this.initialized) {
2677
- throw new Error("SDK must be initialized before waiting for vote status. Call sdk.init() first.");
2956
+ throw new Error(
2957
+ "SDK must be initialized before waiting for vote status. Call sdk.init() first."
2958
+ );
2678
2959
  }
2679
- return this.voteOrchestrator.waitForVoteStatus(processId, voteId, targetStatus, timeoutMs, pollIntervalMs);
2960
+ return this.voteOrchestrator.waitForVoteStatus(
2961
+ processId,
2962
+ voteId,
2963
+ targetStatus,
2964
+ timeoutMs,
2965
+ pollIntervalMs
2966
+ );
2680
2967
  }
2681
2968
  /**
2682
- * Ends a voting process by setting its status to ENDED and returns an async generator
2683
- * that yields transaction status events. This method allows you to monitor the
2969
+ * Ends a voting process by setting its status to ENDED and returns an async generator
2970
+ * that yields transaction status events. This method allows you to monitor the
2684
2971
  * transaction progress in real-time.
2685
- *
2972
+ *
2686
2973
  * Requires a signer with a provider for blockchain interactions.
2687
- *
2974
+ *
2688
2975
  * @param processId - The process ID to end
2689
2976
  * @returns AsyncGenerator yielding transaction status events
2690
2977
  * @throws Error if signer does not have a provider
2691
- *
2978
+ *
2692
2979
  * @example
2693
2980
  * ```typescript
2694
2981
  * const stream = sdk.endProcessStream("0x1234567890abcdef...");
2695
- *
2982
+ *
2696
2983
  * for await (const event of stream) {
2697
2984
  * switch (event.status) {
2698
2985
  * case TxStatus.Pending:
@@ -2721,15 +3008,15 @@ class DavinciSDK {
2721
3008
  /**
2722
3009
  * Ends a voting process by setting its status to ENDED.
2723
3010
  * This is the simplified method that waits for transaction completion.
2724
- *
3011
+ *
2725
3012
  * For real-time transaction status updates, use endProcessStream() instead.
2726
- *
3013
+ *
2727
3014
  * Requires a signer with a provider for blockchain interactions.
2728
- *
3015
+ *
2729
3016
  * @param processId - The process ID to end
2730
3017
  * @returns Promise resolving when the process is ended
2731
3018
  * @throws Error if signer does not have a provider
2732
- *
3019
+ *
2733
3020
  * @example
2734
3021
  * ```typescript
2735
3022
  * await sdk.endProcess("0x1234567890abcdef...");
@@ -2744,20 +3031,20 @@ class DavinciSDK {
2744
3031
  return this.processOrchestrator.endProcess(processId);
2745
3032
  }
2746
3033
  /**
2747
- * Pauses a voting process by setting its status to PAUSED and returns an async generator
2748
- * that yields transaction status events. This method allows you to monitor the
3034
+ * Pauses a voting process by setting its status to PAUSED and returns an async generator
3035
+ * that yields transaction status events. This method allows you to monitor the
2749
3036
  * transaction progress in real-time.
2750
- *
3037
+ *
2751
3038
  * Requires a signer with a provider for blockchain interactions.
2752
- *
3039
+ *
2753
3040
  * @param processId - The process ID to pause
2754
3041
  * @returns AsyncGenerator yielding transaction status events
2755
3042
  * @throws Error if signer does not have a provider
2756
- *
3043
+ *
2757
3044
  * @example
2758
3045
  * ```typescript
2759
3046
  * const stream = sdk.pauseProcessStream("0x1234567890abcdef...");
2760
- *
3047
+ *
2761
3048
  * for await (const event of stream) {
2762
3049
  * switch (event.status) {
2763
3050
  * case TxStatus.Pending:
@@ -2786,15 +3073,15 @@ class DavinciSDK {
2786
3073
  /**
2787
3074
  * Pauses a voting process by setting its status to PAUSED.
2788
3075
  * This is the simplified method that waits for transaction completion.
2789
- *
3076
+ *
2790
3077
  * For real-time transaction status updates, use pauseProcessStream() instead.
2791
- *
3078
+ *
2792
3079
  * Requires a signer with a provider for blockchain interactions.
2793
- *
3080
+ *
2794
3081
  * @param processId - The process ID to pause
2795
3082
  * @returns Promise resolving when the process is paused
2796
3083
  * @throws Error if signer does not have a provider
2797
- *
3084
+ *
2798
3085
  * @example
2799
3086
  * ```typescript
2800
3087
  * await sdk.pauseProcess("0x1234567890abcdef...");
@@ -2809,20 +3096,20 @@ class DavinciSDK {
2809
3096
  return this.processOrchestrator.pauseProcess(processId);
2810
3097
  }
2811
3098
  /**
2812
- * Cancels a voting process by setting its status to CANCELED and returns an async generator
2813
- * that yields transaction status events. This method allows you to monitor the
3099
+ * Cancels a voting process by setting its status to CANCELED and returns an async generator
3100
+ * that yields transaction status events. This method allows you to monitor the
2814
3101
  * transaction progress in real-time.
2815
- *
3102
+ *
2816
3103
  * Requires a signer with a provider for blockchain interactions.
2817
- *
3104
+ *
2818
3105
  * @param processId - The process ID to cancel
2819
3106
  * @returns AsyncGenerator yielding transaction status events
2820
3107
  * @throws Error if signer does not have a provider
2821
- *
3108
+ *
2822
3109
  * @example
2823
3110
  * ```typescript
2824
3111
  * const stream = sdk.cancelProcessStream("0x1234567890abcdef...");
2825
- *
3112
+ *
2826
3113
  * for await (const event of stream) {
2827
3114
  * switch (event.status) {
2828
3115
  * case TxStatus.Pending:
@@ -2851,15 +3138,15 @@ class DavinciSDK {
2851
3138
  /**
2852
3139
  * Cancels a voting process by setting its status to CANCELED.
2853
3140
  * This is the simplified method that waits for transaction completion.
2854
- *
3141
+ *
2855
3142
  * For real-time transaction status updates, use cancelProcessStream() instead.
2856
- *
3143
+ *
2857
3144
  * Requires a signer with a provider for blockchain interactions.
2858
- *
3145
+ *
2859
3146
  * @param processId - The process ID to cancel
2860
3147
  * @returns Promise resolving when the process is canceled
2861
3148
  * @throws Error if signer does not have a provider
2862
- *
3149
+ *
2863
3150
  * @example
2864
3151
  * ```typescript
2865
3152
  * await sdk.cancelProcess("0x1234567890abcdef...");
@@ -2874,19 +3161,19 @@ class DavinciSDK {
2874
3161
  return this.processOrchestrator.cancelProcess(processId);
2875
3162
  }
2876
3163
  /**
2877
- * Resumes a voting process by setting its status to READY and returns an async generator
3164
+ * Resumes a voting process by setting its status to READY and returns an async generator
2878
3165
  * that yields transaction status events. This is typically used to resume a paused process.
2879
- *
3166
+ *
2880
3167
  * Requires a signer with a provider for blockchain interactions.
2881
- *
3168
+ *
2882
3169
  * @param processId - The process ID to resume
2883
3170
  * @returns AsyncGenerator yielding transaction status events
2884
3171
  * @throws Error if signer does not have a provider
2885
- *
3172
+ *
2886
3173
  * @example
2887
3174
  * ```typescript
2888
3175
  * const stream = sdk.resumeProcessStream("0x1234567890abcdef...");
2889
- *
3176
+ *
2890
3177
  * for await (const event of stream) {
2891
3178
  * switch (event.status) {
2892
3179
  * case TxStatus.Pending:
@@ -2916,15 +3203,15 @@ class DavinciSDK {
2916
3203
  * Resumes a voting process by setting its status to READY.
2917
3204
  * This is typically used to resume a paused process.
2918
3205
  * This is the simplified method that waits for transaction completion.
2919
- *
3206
+ *
2920
3207
  * For real-time transaction status updates, use resumeProcessStream() instead.
2921
- *
3208
+ *
2922
3209
  * Requires a signer with a provider for blockchain interactions.
2923
- *
3210
+ *
2924
3211
  * @param processId - The process ID to resume
2925
3212
  * @returns Promise resolving when the process is resumed
2926
3213
  * @throws Error if signer does not have a provider
2927
- *
3214
+ *
2928
3215
  * @example
2929
3216
  * ```typescript
2930
3217
  * await sdk.resumeProcess("0x1234567890abcdef...");
@@ -2940,64 +3227,50 @@ class DavinciSDK {
2940
3227
  }
2941
3228
  /**
2942
3229
  * Resolve contract address based on configuration priority:
2943
- * 1. If useSequencerAddresses is true: addresses from sequencer (highest priority)
2944
- * 2. Custom addresses from config (if provided by user)
2945
- * 3. Default deployed addresses from npm package
3230
+ * 1. Custom addresses from user config (if provided)
3231
+ * 2. Addresses from sequencer (fetched during init if no custom addresses provided)
2946
3232
  */
2947
3233
  resolveContractAddress(contractName) {
2948
- if (this.config.useSequencerAddresses) {
2949
- return this.getDefaultContractAddress(contractName);
2950
- }
2951
- const customAddress = this.config.contractAddresses[contractName];
3234
+ const customAddress = this.config.customAddresses[contractName];
2952
3235
  if (customAddress) {
2953
3236
  return customAddress;
2954
3237
  }
2955
- return this.getDefaultContractAddress(contractName);
2956
- }
2957
- /**
2958
- * Get default contract address from deployed addresses
2959
- */
2960
- getDefaultContractAddress(contractName) {
2961
- const chain = this.config.chain;
2962
- switch (contractName) {
2963
- case "processRegistry":
2964
- return deployedAddresses.processRegistry[chain];
2965
- case "organizationRegistry":
2966
- return deployedAddresses.organizationRegistry[chain];
2967
- case "stateTransitionVerifier":
2968
- return deployedAddresses.stateTransitionVerifierGroth16[chain];
2969
- case "resultsVerifier":
2970
- return deployedAddresses.resultsVerifierGroth16[chain];
2971
- case "sequencerRegistry":
2972
- return deployedAddresses.sequencerRegistry[chain];
2973
- default:
2974
- throw new Error(`Unknown contract: ${contractName}`);
3238
+ if (!this.config.customAddresses[contractName]) {
3239
+ throw new Error(
3240
+ `Contract address for '${contractName}' not found. Make sure SDK is initialized with sdk.init() or provide custom addresses in config.`
3241
+ );
2975
3242
  }
3243
+ return this.config.customAddresses[contractName];
2976
3244
  }
2977
3245
  /**
2978
- * Update contract addresses from sequencer info if useSequencerAddresses is enabled
2979
- * Sequencer addresses have priority over user-provided addresses
3246
+ * Fetch contract addresses from sequencer info
3247
+ * This is called during init() if custom addresses are not provided
2980
3248
  */
2981
- async updateContractAddressesFromSequencer() {
3249
+ async fetchContractAddressesFromSequencer() {
2982
3250
  try {
2983
3251
  const info = await this.apiService.sequencer.getInfo();
2984
3252
  const contracts = info.contracts;
2985
3253
  if (contracts.process) {
3254
+ this.config.customAddresses.processRegistry = contracts.process;
2986
3255
  this._processRegistry = new ProcessRegistryService(contracts.process, this.config.signer);
2987
- this.config.contractAddresses.processRegistry = contracts.process;
2988
3256
  }
2989
3257
  if (contracts.organization) {
2990
- this._organizationRegistry = new OrganizationRegistryService(contracts.organization, this.config.signer);
2991
- this.config.contractAddresses.organizationRegistry = contracts.organization;
3258
+ this.config.customAddresses.organizationRegistry = contracts.organization;
3259
+ this._organizationRegistry = new OrganizationRegistryService(
3260
+ contracts.organization,
3261
+ this.config.signer
3262
+ );
2992
3263
  }
2993
3264
  if (contracts.stateTransitionVerifier) {
2994
- this.config.contractAddresses.stateTransitionVerifier = contracts.stateTransitionVerifier;
3265
+ this.config.customAddresses.stateTransitionVerifier = contracts.stateTransitionVerifier;
2995
3266
  }
2996
3267
  if (contracts.resultsVerifier) {
2997
- this.config.contractAddresses.resultsVerifier = contracts.resultsVerifier;
3268
+ this.config.customAddresses.resultsVerifier = contracts.resultsVerifier;
2998
3269
  }
2999
3270
  } catch (error) {
3000
- console.warn("Failed to fetch contract addresses from sequencer, using defaults:", error);
3271
+ throw new Error(
3272
+ `Failed to fetch contract addresses from sequencer: ${error instanceof Error ? error.message : String(error)}. You can provide custom addresses in the SDK config to avoid this error.`
3273
+ );
3001
3274
  }
3002
3275
  }
3003
3276
  /**
@@ -3027,10 +3300,13 @@ class DavinciSDK {
3027
3300
  }
3028
3301
 
3029
3302
  exports.BaseService = BaseService;
3303
+ exports.Census = Census;
3304
+ exports.CensusOrchestrator = CensusOrchestrator;
3030
3305
  exports.CensusOrigin = CensusOrigin;
3306
+ exports.CensusType = CensusType;
3031
3307
  exports.CircomProof = CircomProof;
3032
3308
  exports.ContractServiceError = ContractServiceError;
3033
- exports.DEFAULT_ENVIRONMENT_URLS = DEFAULT_ENVIRONMENT_URLS;
3309
+ exports.CspCensus = CspCensus;
3034
3310
  exports.DavinciCrypto = DavinciCrypto;
3035
3311
  exports.DavinciSDK = DavinciSDK;
3036
3312
  exports.ElectionMetadataTemplate = ElectionMetadataTemplate;
@@ -3040,6 +3316,7 @@ exports.OrganizationCreateError = OrganizationCreateError;
3040
3316
  exports.OrganizationDeleteError = OrganizationDeleteError;
3041
3317
  exports.OrganizationRegistryService = OrganizationRegistryService;
3042
3318
  exports.OrganizationUpdateError = OrganizationUpdateError;
3319
+ exports.PlainCensus = PlainCensus;
3043
3320
  exports.ProcessCensusError = ProcessCensusError;
3044
3321
  exports.ProcessCreateError = ProcessCreateError;
3045
3322
  exports.ProcessDurationError = ProcessDurationError;
@@ -3049,6 +3326,7 @@ exports.ProcessResultError = ProcessResultError;
3049
3326
  exports.ProcessStateTransitionError = ProcessStateTransitionError;
3050
3327
  exports.ProcessStatus = ProcessStatus;
3051
3328
  exports.ProcessStatusError = ProcessStatusError;
3329
+ exports.PublishedCensus = PublishedCensus;
3052
3330
  exports.SmartContractService = SmartContractService;
3053
3331
  exports.TxStatus = TxStatus;
3054
3332
  exports.VocdoniApiService = VocdoniApiService;
@@ -3056,18 +3334,13 @@ exports.VocdoniCensusService = VocdoniCensusService;
3056
3334
  exports.VocdoniSequencerService = VocdoniSequencerService;
3057
3335
  exports.VoteOrchestrationService = VoteOrchestrationService;
3058
3336
  exports.VoteStatus = VoteStatus;
3337
+ exports.WeightedCensus = WeightedCensus;
3059
3338
  exports.assertCSPCensusProof = assertCSPCensusProof;
3060
3339
  exports.assertMerkleCensusProof = assertMerkleCensusProof;
3061
3340
  exports.createProcessSignatureMessage = createProcessSignatureMessage;
3062
- exports.deployedAddresses = deployedAddresses;
3063
3341
  exports.getElectionMetadataTemplate = getElectionMetadataTemplate;
3064
- exports.getEnvironmentChain = getEnvironmentChain;
3065
- exports.getEnvironmentConfig = getEnvironmentConfig;
3066
- exports.getEnvironmentUrls = getEnvironmentUrls;
3067
3342
  exports.isCSPCensusProof = isCSPCensusProof;
3068
3343
  exports.isMerkleCensusProof = isMerkleCensusProof;
3069
- exports.resolveConfiguration = resolveConfiguration;
3070
- exports.resolveUrls = resolveUrls;
3071
3344
  exports.signProcessCreation = signProcessCreation;
3072
3345
  exports.validateProcessId = validateProcessId;
3073
3346
  //# sourceMappingURL=index.js.map