@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 +251 -42
- package/dist/contracts.d.ts +10 -54
- package/dist/index.d.ts +232 -151
- package/dist/index.js +558 -326
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +552 -320
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +3140 -2908
- package/dist/sequencer.d.ts +2 -2
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -215,6 +215,281 @@ function assertCSPCensusProof(proof) {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
var CensusType = /* @__PURE__ */ ((CensusType2) => {
|
|
219
|
+
CensusType2["PLAIN"] = "plain";
|
|
220
|
+
CensusType2["WEIGHTED"] = "weighted";
|
|
221
|
+
CensusType2["CSP"] = "csp";
|
|
222
|
+
return CensusType2;
|
|
223
|
+
})(CensusType || {});
|
|
224
|
+
class Census {
|
|
225
|
+
constructor(type) {
|
|
226
|
+
this._censusId = null;
|
|
227
|
+
this._censusRoot = null;
|
|
228
|
+
this._censusURI = null;
|
|
229
|
+
this._size = null;
|
|
230
|
+
this._type = type;
|
|
231
|
+
}
|
|
232
|
+
get censusId() {
|
|
233
|
+
return this._censusId;
|
|
234
|
+
}
|
|
235
|
+
get censusRoot() {
|
|
236
|
+
return this._censusRoot;
|
|
237
|
+
}
|
|
238
|
+
get censusURI() {
|
|
239
|
+
return this._censusURI;
|
|
240
|
+
}
|
|
241
|
+
get type() {
|
|
242
|
+
return this._type;
|
|
243
|
+
}
|
|
244
|
+
get size() {
|
|
245
|
+
return this._size;
|
|
246
|
+
}
|
|
247
|
+
get isPublished() {
|
|
248
|
+
return this._censusRoot !== null && this._censusURI !== null;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Convert CensusType to CensusOrigin enum for API compatibility
|
|
252
|
+
*/
|
|
253
|
+
get censusOrigin() {
|
|
254
|
+
switch (this._type) {
|
|
255
|
+
case "plain" /* PLAIN */:
|
|
256
|
+
case "weighted" /* WEIGHTED */:
|
|
257
|
+
return CensusOrigin.CensusOriginMerkleTree;
|
|
258
|
+
case "csp" /* CSP */:
|
|
259
|
+
return CensusOrigin.CensusOriginCSP;
|
|
260
|
+
default:
|
|
261
|
+
throw new Error(`Unknown census type: ${this._type}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
class PlainCensus extends Census {
|
|
267
|
+
constructor() {
|
|
268
|
+
super(CensusType.PLAIN);
|
|
269
|
+
this._participants = /* @__PURE__ */ new Set();
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Add participant(s) with automatic weight=1
|
|
273
|
+
* @param addresses - Single address or array of addresses
|
|
274
|
+
*/
|
|
275
|
+
add(addresses) {
|
|
276
|
+
const toAdd = Array.isArray(addresses) ? addresses : [addresses];
|
|
277
|
+
for (const address of toAdd) {
|
|
278
|
+
this.validateAddress(address);
|
|
279
|
+
this._participants.add(address.toLowerCase());
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Remove participant by address
|
|
284
|
+
*/
|
|
285
|
+
remove(address) {
|
|
286
|
+
this._participants.delete(address.toLowerCase());
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Get all participants as CensusParticipant array (for API)
|
|
290
|
+
* All participants have weight="1"
|
|
291
|
+
*/
|
|
292
|
+
get participants() {
|
|
293
|
+
return Array.from(this._participants).map((key) => ({
|
|
294
|
+
key,
|
|
295
|
+
weight: "1"
|
|
296
|
+
// Everyone has weight=1 in plain census
|
|
297
|
+
}));
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Get addresses only
|
|
301
|
+
*/
|
|
302
|
+
get addresses() {
|
|
303
|
+
return Array.from(this._participants);
|
|
304
|
+
}
|
|
305
|
+
validateAddress(address) {
|
|
306
|
+
if (!address || typeof address !== "string") {
|
|
307
|
+
throw new Error("Address is required and must be a string");
|
|
308
|
+
}
|
|
309
|
+
if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(address)) {
|
|
310
|
+
throw new Error(`Invalid Ethereum address format: ${address}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Internal method called after publishing
|
|
315
|
+
* @internal
|
|
316
|
+
*/
|
|
317
|
+
_setPublishedData(root, uri, size, censusId) {
|
|
318
|
+
this._censusRoot = root;
|
|
319
|
+
this._censusURI = uri;
|
|
320
|
+
this._size = size;
|
|
321
|
+
if (censusId) this._censusId = censusId;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
class WeightedCensus extends Census {
|
|
326
|
+
constructor() {
|
|
327
|
+
super(CensusType.WEIGHTED);
|
|
328
|
+
this._participants = /* @__PURE__ */ new Map();
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Add participant(s) with custom weights
|
|
332
|
+
* Weight can be provided as string, number, or bigint - will be converted to string internally
|
|
333
|
+
* @param participant - Single participant or array of participants with custom weights
|
|
334
|
+
*/
|
|
335
|
+
add(participant) {
|
|
336
|
+
const toAdd = Array.isArray(participant) ? participant : [participant];
|
|
337
|
+
for (const p of toAdd) {
|
|
338
|
+
this.validateParticipant(p);
|
|
339
|
+
const weightString = this.normalizeWeight(p.weight);
|
|
340
|
+
this._participants.set(p.key.toLowerCase(), weightString);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Remove participant by address
|
|
345
|
+
*/
|
|
346
|
+
remove(address) {
|
|
347
|
+
this._participants.delete(address.toLowerCase());
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Get all participants as CensusParticipant array
|
|
351
|
+
*/
|
|
352
|
+
get participants() {
|
|
353
|
+
return Array.from(this._participants.entries()).map(([key, weight]) => ({
|
|
354
|
+
key,
|
|
355
|
+
weight
|
|
356
|
+
}));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get participant addresses
|
|
360
|
+
*/
|
|
361
|
+
get addresses() {
|
|
362
|
+
return Array.from(this._participants.keys());
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Get weight for specific address
|
|
366
|
+
*/
|
|
367
|
+
getWeight(address) {
|
|
368
|
+
return this._participants.get(address.toLowerCase());
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Normalizes weight from string, number, or bigint to string
|
|
372
|
+
*/
|
|
373
|
+
normalizeWeight(weight) {
|
|
374
|
+
if (typeof weight === "string") {
|
|
375
|
+
if (!/^\d+$/.test(weight)) {
|
|
376
|
+
throw new Error(`Invalid weight format: ${weight}. Must be a positive integer.`);
|
|
377
|
+
}
|
|
378
|
+
return weight;
|
|
379
|
+
}
|
|
380
|
+
if (typeof weight === "number") {
|
|
381
|
+
if (!Number.isInteger(weight) || weight < 0) {
|
|
382
|
+
throw new Error(`Invalid weight: ${weight}. Must be a positive integer.`);
|
|
383
|
+
}
|
|
384
|
+
return weight.toString();
|
|
385
|
+
}
|
|
386
|
+
if (typeof weight === "bigint") {
|
|
387
|
+
if (weight < 0n) {
|
|
388
|
+
throw new Error(`Invalid weight: ${weight}. Must be a positive integer.`);
|
|
389
|
+
}
|
|
390
|
+
return weight.toString();
|
|
391
|
+
}
|
|
392
|
+
throw new Error(`Invalid weight type. Must be string, number, or bigint.`);
|
|
393
|
+
}
|
|
394
|
+
validateParticipant(participant) {
|
|
395
|
+
if (!participant.key || typeof participant.key !== "string") {
|
|
396
|
+
throw new Error("Participant key (address) is required");
|
|
397
|
+
}
|
|
398
|
+
if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(participant.key)) {
|
|
399
|
+
throw new Error(`Invalid Ethereum address format: ${participant.key}`);
|
|
400
|
+
}
|
|
401
|
+
if (participant.weight === void 0 || participant.weight === null) {
|
|
402
|
+
throw new Error("Participant weight is required");
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Internal method called after publishing
|
|
407
|
+
* @internal
|
|
408
|
+
*/
|
|
409
|
+
_setPublishedData(root, uri, size, censusId) {
|
|
410
|
+
this._censusRoot = root;
|
|
411
|
+
this._censusURI = uri;
|
|
412
|
+
this._size = size;
|
|
413
|
+
if (censusId) this._censusId = censusId;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
class CspCensus extends Census {
|
|
418
|
+
constructor(publicKey, cspURI, size) {
|
|
419
|
+
super(CensusType.CSP);
|
|
420
|
+
if (!/^(0x)?[0-9a-fA-F]+$/.test(publicKey)) {
|
|
421
|
+
throw new Error("Public key is missing or invalid");
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
new URL(cspURI);
|
|
425
|
+
} catch {
|
|
426
|
+
throw new Error("CSP URI is missing or invalid");
|
|
427
|
+
}
|
|
428
|
+
this._publicKey = publicKey;
|
|
429
|
+
this._cspURI = cspURI;
|
|
430
|
+
this._censusRoot = publicKey;
|
|
431
|
+
this._censusURI = cspURI;
|
|
432
|
+
this._size = size;
|
|
433
|
+
}
|
|
434
|
+
get publicKey() {
|
|
435
|
+
return this._publicKey;
|
|
436
|
+
}
|
|
437
|
+
get cspURI() {
|
|
438
|
+
return this._cspURI;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
class PublishedCensus extends Census {
|
|
443
|
+
constructor(type, root, uri, size) {
|
|
444
|
+
super(type);
|
|
445
|
+
this._censusRoot = root;
|
|
446
|
+
this._censusURI = uri;
|
|
447
|
+
this._size = size;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
class CensusOrchestrator {
|
|
452
|
+
constructor(censusService) {
|
|
453
|
+
this.censusService = censusService;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Publishes a PlainCensus or WeightedCensus
|
|
457
|
+
* Creates a working census, adds participants, and publishes it
|
|
458
|
+
*/
|
|
459
|
+
async publish(census) {
|
|
460
|
+
if (census.isPublished) {
|
|
461
|
+
throw new Error("Census is already published");
|
|
462
|
+
}
|
|
463
|
+
if (census.participants.length === 0) {
|
|
464
|
+
throw new Error("Cannot publish empty census");
|
|
465
|
+
}
|
|
466
|
+
const censusId = await this.censusService.createCensus();
|
|
467
|
+
await this.censusService.addParticipants(censusId, census.participants);
|
|
468
|
+
const publishResponse = await this.censusService.publishCensus(censusId);
|
|
469
|
+
census._setPublishedData(
|
|
470
|
+
publishResponse.root,
|
|
471
|
+
publishResponse.uri,
|
|
472
|
+
publishResponse.participantCount,
|
|
473
|
+
censusId
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Gets census data for process creation
|
|
478
|
+
* Throws if census is not published
|
|
479
|
+
*/
|
|
480
|
+
getCensusData(census) {
|
|
481
|
+
if (!census.isPublished) {
|
|
482
|
+
throw new Error("Census must be published before creating a process");
|
|
483
|
+
}
|
|
484
|
+
return {
|
|
485
|
+
type: census.censusOrigin,
|
|
486
|
+
root: census.censusRoot,
|
|
487
|
+
uri: census.censusURI,
|
|
488
|
+
size: census.size
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
218
493
|
function createProcessSignatureMessage(processId) {
|
|
219
494
|
const cleanProcessId = processId.replace(/^0x/, "").toLowerCase();
|
|
220
495
|
return `I am creating a new voting process for the davinci.vote protocol identified with id ${cleanProcessId}`;
|
|
@@ -305,11 +580,15 @@ class VocdoniSequencerService extends BaseService {
|
|
|
305
580
|
try {
|
|
306
581
|
const response = await fetch(hashOrUrl);
|
|
307
582
|
if (!response.ok) {
|
|
308
|
-
throw new Error(
|
|
583
|
+
throw new Error(
|
|
584
|
+
`Failed to fetch metadata from URL: ${response.status} ${response.statusText}`
|
|
585
|
+
);
|
|
309
586
|
}
|
|
310
587
|
return await response.json();
|
|
311
588
|
} catch (error) {
|
|
312
|
-
throw new Error(
|
|
589
|
+
throw new Error(
|
|
590
|
+
`Failed to fetch metadata from URL: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
591
|
+
);
|
|
313
592
|
}
|
|
314
593
|
}
|
|
315
594
|
if (!isHexString(hashOrUrl)) {
|
|
@@ -345,101 +624,6 @@ class VocdoniApiService {
|
|
|
345
624
|
}
|
|
346
625
|
}
|
|
347
626
|
|
|
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
627
|
var TxStatus = /* @__PURE__ */ ((TxStatus2) => {
|
|
444
628
|
TxStatus2["Pending"] = "pending";
|
|
445
629
|
TxStatus2["Completed"] = "completed";
|
|
@@ -458,19 +642,19 @@ class SmartContractService {
|
|
|
458
642
|
* Sends a transaction and yields status events during its lifecycle.
|
|
459
643
|
* This method handles the complete transaction flow from submission to completion,
|
|
460
644
|
* including error handling and status updates.
|
|
461
|
-
*
|
|
645
|
+
*
|
|
462
646
|
* @template T - The type of the successful response data
|
|
463
647
|
* @param txPromise - Promise resolving to the transaction response
|
|
464
648
|
* @param responseHandler - Function to process the successful transaction result
|
|
465
649
|
* @returns AsyncGenerator yielding transaction status events
|
|
466
|
-
*
|
|
650
|
+
*
|
|
467
651
|
* @example
|
|
468
652
|
* ```typescript
|
|
469
653
|
* const txStream = await this.sendTx(
|
|
470
654
|
* contract.someMethod(),
|
|
471
655
|
* async () => await contract.getUpdatedValue()
|
|
472
656
|
* );
|
|
473
|
-
*
|
|
657
|
+
*
|
|
474
658
|
* for await (const event of txStream) {
|
|
475
659
|
* switch (event.status) {
|
|
476
660
|
* case TxStatus.Pending:
|
|
@@ -507,12 +691,12 @@ class SmartContractService {
|
|
|
507
691
|
* Executes a transaction stream and returns the result or throws an error.
|
|
508
692
|
* This is a convenience method that processes a transaction stream and either
|
|
509
693
|
* returns the successful result or throws an appropriate error.
|
|
510
|
-
*
|
|
694
|
+
*
|
|
511
695
|
* @template T - The type of the successful response data
|
|
512
696
|
* @param stream - AsyncGenerator of transaction status events
|
|
513
697
|
* @returns Promise resolving to the successful response data
|
|
514
698
|
* @throws Error if the transaction fails or reverts
|
|
515
|
-
*
|
|
699
|
+
*
|
|
516
700
|
* @example
|
|
517
701
|
* ```typescript
|
|
518
702
|
* try {
|
|
@@ -542,11 +726,11 @@ class SmartContractService {
|
|
|
542
726
|
* Normalizes event listener arguments between different ethers.js versions.
|
|
543
727
|
* This helper method ensures consistent event argument handling regardless of
|
|
544
728
|
* whether the event payload follows ethers v5 or v6 format.
|
|
545
|
-
*
|
|
729
|
+
*
|
|
546
730
|
* @template Args - Tuple type representing the expected event arguments
|
|
547
731
|
* @param callback - The event callback function to normalize
|
|
548
732
|
* @returns Normalized event listener function
|
|
549
|
-
*
|
|
733
|
+
*
|
|
550
734
|
* @example
|
|
551
735
|
* ```typescript
|
|
552
736
|
* contract.on('Transfer', this.normalizeListener((from: string, to: string, amount: BigInt) => {
|
|
@@ -569,12 +753,12 @@ class SmartContractService {
|
|
|
569
753
|
* Sets up an event listener with automatic fallback for RPCs that don't support eth_newFilter.
|
|
570
754
|
* First attempts to use contract.on() which relies on eth_newFilter. If the RPC doesn't support
|
|
571
755
|
* this method (error code -32601), automatically falls back to polling with queryFilter.
|
|
572
|
-
*
|
|
756
|
+
*
|
|
573
757
|
* @template Args - Tuple type representing the event arguments
|
|
574
758
|
* @param contract - The contract instance to listen to
|
|
575
759
|
* @param eventFilter - The event filter to listen for
|
|
576
760
|
* @param callback - The callback function to invoke when the event occurs
|
|
577
|
-
*
|
|
761
|
+
*
|
|
578
762
|
* @example
|
|
579
763
|
* ```typescript
|
|
580
764
|
* this.setupEventListener(
|
|
@@ -600,13 +784,14 @@ class SmartContractService {
|
|
|
600
784
|
};
|
|
601
785
|
if ("send" in provider && typeof provider.send === "function") {
|
|
602
786
|
try {
|
|
603
|
-
await provider.send("eth_newFilter", [testFilter]);
|
|
787
|
+
const filterId = await provider.send("eth_newFilter", [testFilter]);
|
|
788
|
+
await provider.send("eth_getFilterChanges", [filterId]);
|
|
604
789
|
contract.on(eventFilter, normalizedCallback);
|
|
605
790
|
return;
|
|
606
791
|
} catch (error) {
|
|
607
792
|
if (this.isUnsupportedMethodError(error)) {
|
|
608
793
|
console.warn(
|
|
609
|
-
"RPC does not support eth_newFilter, falling back to polling for events. This may result in delayed event notifications."
|
|
794
|
+
"RPC does not fully support eth_newFilter/eth_getFilterChanges, falling back to polling for events. This may result in delayed event notifications."
|
|
610
795
|
);
|
|
611
796
|
this.setupPollingListener(contract, eventFilter, callback);
|
|
612
797
|
return;
|
|
@@ -631,18 +816,23 @@ class SmartContractService {
|
|
|
631
816
|
}
|
|
632
817
|
}
|
|
633
818
|
/**
|
|
634
|
-
* Checks if an error indicates that the RPC method is unsupported
|
|
635
|
-
*
|
|
819
|
+
* Checks if an error indicates that the RPC method is unsupported or filter operations are not working.
|
|
820
|
+
* This includes:
|
|
821
|
+
* - Method not found (-32601): RPC doesn't support eth_newFilter
|
|
822
|
+
* - Filter not found (-32000): RPC doesn't properly maintain filters
|
|
823
|
+
*
|
|
636
824
|
* @param error - The error to check
|
|
637
|
-
* @returns true if the error indicates unsupported
|
|
825
|
+
* @returns true if the error indicates unsupported or broken filter functionality
|
|
638
826
|
*/
|
|
639
827
|
isUnsupportedMethodError(error) {
|
|
640
|
-
|
|
828
|
+
const isMethodNotFound = error?.code === -32601 || error?.error?.code === -32601 || error?.data?.code === -32601 || typeof error?.message === "string" && error.message.includes("unsupported method");
|
|
829
|
+
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"));
|
|
830
|
+
return isMethodNotFound || isFilterNotFound;
|
|
641
831
|
}
|
|
642
832
|
/**
|
|
643
833
|
* Sets up a polling-based event listener as fallback when eth_newFilter is not supported.
|
|
644
834
|
* Periodically queries for new events and invokes the callback for each new event found.
|
|
645
|
-
*
|
|
835
|
+
*
|
|
646
836
|
* @template Args - Tuple type representing the event arguments
|
|
647
837
|
* @param contract - The contract instance to poll
|
|
648
838
|
* @param eventFilter - The event filter to poll for
|
|
@@ -694,7 +884,7 @@ class SmartContractService {
|
|
|
694
884
|
}
|
|
695
885
|
/**
|
|
696
886
|
* Sets the polling interval for event listeners using the fallback mechanism.
|
|
697
|
-
*
|
|
887
|
+
*
|
|
698
888
|
* @param intervalMs - Polling interval in milliseconds
|
|
699
889
|
*/
|
|
700
890
|
setEventPollingInterval(intervalMs) {
|
|
@@ -705,7 +895,7 @@ class SmartContractService {
|
|
|
705
895
|
class ContractServiceError extends Error {
|
|
706
896
|
/**
|
|
707
897
|
* Creates a new ContractServiceError instance.
|
|
708
|
-
*
|
|
898
|
+
*
|
|
709
899
|
* @param message - The error message describing what went wrong
|
|
710
900
|
* @param operation - The operation that was being performed when the error occurred
|
|
711
901
|
*/
|
|
@@ -858,7 +1048,7 @@ class ProcessRegistryService extends SmartContractService {
|
|
|
858
1048
|
}
|
|
859
1049
|
/**
|
|
860
1050
|
* Sets the results for a voting process.
|
|
861
|
-
*
|
|
1051
|
+
*
|
|
862
1052
|
* @param processID - The ID of the process to set results for
|
|
863
1053
|
* @param proof - Zero-knowledge proof validating the results
|
|
864
1054
|
* @param input - Input data for the proof verification
|
|
@@ -866,11 +1056,7 @@ class ProcessRegistryService extends SmartContractService {
|
|
|
866
1056
|
*/
|
|
867
1057
|
setProcessResults(processID, proof, input) {
|
|
868
1058
|
return this.sendTx(
|
|
869
|
-
this.contract.setProcessResults(
|
|
870
|
-
processID,
|
|
871
|
-
proof,
|
|
872
|
-
input
|
|
873
|
-
).catch((e) => {
|
|
1059
|
+
this.contract.setProcessResults(processID, proof, input).catch((e) => {
|
|
874
1060
|
throw new ProcessResultError(e.message, "setResults");
|
|
875
1061
|
}),
|
|
876
1062
|
async () => ({ success: true })
|
|
@@ -932,6 +1118,34 @@ class ProcessOrchestrationService {
|
|
|
932
1118
|
this.organizationRegistry = organizationRegistry;
|
|
933
1119
|
this.getCrypto = getCrypto;
|
|
934
1120
|
this.signer = signer;
|
|
1121
|
+
this.censusOrchestrator = new CensusOrchestrator(apiService.census);
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* Handles census - auto-publishes if needed and returns census config
|
|
1125
|
+
* @private
|
|
1126
|
+
*/
|
|
1127
|
+
async handleCensus(census) {
|
|
1128
|
+
if ("isPublished" in census) {
|
|
1129
|
+
if (census instanceof PlainCensus || census instanceof WeightedCensus) {
|
|
1130
|
+
if (!census.isPublished) {
|
|
1131
|
+
const censusBaseURL = this.apiService.census?.["axios"]?.defaults?.baseURL;
|
|
1132
|
+
if (!censusBaseURL || censusBaseURL === "" || censusBaseURL === "undefined") {
|
|
1133
|
+
throw new Error(
|
|
1134
|
+
'Census API URL is required to publish PlainCensus or WeightedCensus. Please provide "censusUrl" when initializing DavinciSDK, or use a pre-published census.'
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
await this.censusOrchestrator.publish(census);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
const censusData = this.censusOrchestrator.getCensusData(census);
|
|
1141
|
+
return {
|
|
1142
|
+
type: censusData.type,
|
|
1143
|
+
root: censusData.root,
|
|
1144
|
+
size: censusData.size,
|
|
1145
|
+
uri: censusData.uri
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
return census;
|
|
935
1149
|
}
|
|
936
1150
|
/**
|
|
937
1151
|
* Gets user-friendly process information by transforming raw contract data
|
|
@@ -1007,10 +1221,10 @@ class ProcessOrchestrationService {
|
|
|
1007
1221
|
/**
|
|
1008
1222
|
* Creates a complete voting process and returns an async generator that yields transaction status events.
|
|
1009
1223
|
* This method allows you to monitor the transaction progress in real-time.
|
|
1010
|
-
*
|
|
1224
|
+
*
|
|
1011
1225
|
* @param config - Process configuration
|
|
1012
1226
|
* @returns AsyncGenerator yielding transaction status events with ProcessCreationResult
|
|
1013
|
-
*
|
|
1227
|
+
*
|
|
1014
1228
|
* @example
|
|
1015
1229
|
* ```typescript
|
|
1016
1230
|
* const stream = sdk.createProcessStream({
|
|
@@ -1021,7 +1235,7 @@ class ProcessOrchestrationService {
|
|
|
1021
1235
|
* timing: { ... },
|
|
1022
1236
|
* questions: [ ... ]
|
|
1023
1237
|
* });
|
|
1024
|
-
*
|
|
1238
|
+
*
|
|
1025
1239
|
* for await (const event of stream) {
|
|
1026
1240
|
* switch (event.status) {
|
|
1027
1241
|
* case "pending":
|
|
@@ -1083,16 +1297,16 @@ class ProcessOrchestrationService {
|
|
|
1083
1297
|
/**
|
|
1084
1298
|
* Creates a complete voting process with minimal configuration.
|
|
1085
1299
|
* This is the ultra-easy method for end users that handles all the complex orchestration internally.
|
|
1086
|
-
*
|
|
1300
|
+
*
|
|
1087
1301
|
* For real-time transaction status updates, use createProcessStream() instead.
|
|
1088
|
-
*
|
|
1302
|
+
*
|
|
1089
1303
|
* The method automatically:
|
|
1090
1304
|
* - Gets encryption keys and initial state root from the sequencer
|
|
1091
1305
|
* - Handles process creation signatures
|
|
1092
1306
|
* - Coordinates between sequencer API and on-chain contract calls
|
|
1093
1307
|
* - Creates and pushes metadata
|
|
1094
1308
|
* - Submits the on-chain transaction
|
|
1095
|
-
*
|
|
1309
|
+
*
|
|
1096
1310
|
* @param config - Simplified process configuration
|
|
1097
1311
|
* @returns Promise resolving to the process creation result
|
|
1098
1312
|
*/
|
|
@@ -1116,7 +1330,8 @@ class ProcessOrchestrationService {
|
|
|
1116
1330
|
const { startTime, duration } = this.calculateTiming(config.timing);
|
|
1117
1331
|
const signerAddress = await this.signer.getAddress();
|
|
1118
1332
|
const processId = await this.processRegistry.getNextProcessId(signerAddress);
|
|
1119
|
-
const
|
|
1333
|
+
const censusConfig = await this.handleCensus(config.census);
|
|
1334
|
+
const censusRoot = censusConfig.root;
|
|
1120
1335
|
const ballotMode = config.ballot;
|
|
1121
1336
|
const metadata = this.createMetadata(config);
|
|
1122
1337
|
const metadataHash = await this.apiService.sequencer.pushMetadata(metadata);
|
|
@@ -1127,13 +1342,13 @@ class ProcessOrchestrationService {
|
|
|
1127
1342
|
censusRoot,
|
|
1128
1343
|
ballotMode,
|
|
1129
1344
|
signature,
|
|
1130
|
-
censusOrigin:
|
|
1345
|
+
censusOrigin: censusConfig.type
|
|
1131
1346
|
});
|
|
1132
1347
|
const census = {
|
|
1133
|
-
censusOrigin:
|
|
1134
|
-
maxVotes:
|
|
1348
|
+
censusOrigin: censusConfig.type,
|
|
1349
|
+
maxVotes: censusConfig.size.toString(),
|
|
1135
1350
|
censusRoot,
|
|
1136
|
-
censusURI:
|
|
1351
|
+
censusURI: censusConfig.uri
|
|
1137
1352
|
};
|
|
1138
1353
|
return {
|
|
1139
1354
|
processId,
|
|
@@ -1224,14 +1439,14 @@ class ProcessOrchestrationService {
|
|
|
1224
1439
|
/**
|
|
1225
1440
|
* Ends a voting process by setting its status to ENDED.
|
|
1226
1441
|
* Returns an async generator that yields transaction status events.
|
|
1227
|
-
*
|
|
1442
|
+
*
|
|
1228
1443
|
* @param processId - The process ID to end
|
|
1229
1444
|
* @returns AsyncGenerator yielding transaction status events
|
|
1230
|
-
*
|
|
1445
|
+
*
|
|
1231
1446
|
* @example
|
|
1232
1447
|
* ```typescript
|
|
1233
1448
|
* const stream = sdk.endProcessStream("0x1234567890abcdef...");
|
|
1234
|
-
*
|
|
1449
|
+
*
|
|
1235
1450
|
* for await (const event of stream) {
|
|
1236
1451
|
* switch (event.status) {
|
|
1237
1452
|
* case "pending":
|
|
@@ -1273,12 +1488,12 @@ class ProcessOrchestrationService {
|
|
|
1273
1488
|
/**
|
|
1274
1489
|
* Ends a voting process by setting its status to ENDED.
|
|
1275
1490
|
* This is a simplified method that waits for transaction completion.
|
|
1276
|
-
*
|
|
1491
|
+
*
|
|
1277
1492
|
* For real-time transaction status updates, use endProcessStream() instead.
|
|
1278
|
-
*
|
|
1493
|
+
*
|
|
1279
1494
|
* @param processId - The process ID to end
|
|
1280
1495
|
* @returns Promise resolving when the process is ended
|
|
1281
|
-
*
|
|
1496
|
+
*
|
|
1282
1497
|
* @example
|
|
1283
1498
|
* ```typescript
|
|
1284
1499
|
* await sdk.endProcess("0x1234567890abcdef...");
|
|
@@ -1300,14 +1515,14 @@ class ProcessOrchestrationService {
|
|
|
1300
1515
|
/**
|
|
1301
1516
|
* Pauses a voting process by setting its status to PAUSED.
|
|
1302
1517
|
* Returns an async generator that yields transaction status events.
|
|
1303
|
-
*
|
|
1518
|
+
*
|
|
1304
1519
|
* @param processId - The process ID to pause
|
|
1305
1520
|
* @returns AsyncGenerator yielding transaction status events
|
|
1306
|
-
*
|
|
1521
|
+
*
|
|
1307
1522
|
* @example
|
|
1308
1523
|
* ```typescript
|
|
1309
1524
|
* const stream = sdk.pauseProcessStream("0x1234567890abcdef...");
|
|
1310
|
-
*
|
|
1525
|
+
*
|
|
1311
1526
|
* for await (const event of stream) {
|
|
1312
1527
|
* switch (event.status) {
|
|
1313
1528
|
* case "pending":
|
|
@@ -1349,12 +1564,12 @@ class ProcessOrchestrationService {
|
|
|
1349
1564
|
/**
|
|
1350
1565
|
* Pauses a voting process by setting its status to PAUSED.
|
|
1351
1566
|
* This is a simplified method that waits for transaction completion.
|
|
1352
|
-
*
|
|
1567
|
+
*
|
|
1353
1568
|
* For real-time transaction status updates, use pauseProcessStream() instead.
|
|
1354
|
-
*
|
|
1569
|
+
*
|
|
1355
1570
|
* @param processId - The process ID to pause
|
|
1356
1571
|
* @returns Promise resolving when the process is paused
|
|
1357
|
-
*
|
|
1572
|
+
*
|
|
1358
1573
|
* @example
|
|
1359
1574
|
* ```typescript
|
|
1360
1575
|
* await sdk.pauseProcess("0x1234567890abcdef...");
|
|
@@ -1376,14 +1591,14 @@ class ProcessOrchestrationService {
|
|
|
1376
1591
|
/**
|
|
1377
1592
|
* Cancels a voting process by setting its status to CANCELED.
|
|
1378
1593
|
* Returns an async generator that yields transaction status events.
|
|
1379
|
-
*
|
|
1594
|
+
*
|
|
1380
1595
|
* @param processId - The process ID to cancel
|
|
1381
1596
|
* @returns AsyncGenerator yielding transaction status events
|
|
1382
|
-
*
|
|
1597
|
+
*
|
|
1383
1598
|
* @example
|
|
1384
1599
|
* ```typescript
|
|
1385
1600
|
* const stream = sdk.cancelProcessStream("0x1234567890abcdef...");
|
|
1386
|
-
*
|
|
1601
|
+
*
|
|
1387
1602
|
* for await (const event of stream) {
|
|
1388
1603
|
* switch (event.status) {
|
|
1389
1604
|
* case "pending":
|
|
@@ -1425,12 +1640,12 @@ class ProcessOrchestrationService {
|
|
|
1425
1640
|
/**
|
|
1426
1641
|
* Cancels a voting process by setting its status to CANCELED.
|
|
1427
1642
|
* This is a simplified method that waits for transaction completion.
|
|
1428
|
-
*
|
|
1643
|
+
*
|
|
1429
1644
|
* For real-time transaction status updates, use cancelProcessStream() instead.
|
|
1430
|
-
*
|
|
1645
|
+
*
|
|
1431
1646
|
* @param processId - The process ID to cancel
|
|
1432
1647
|
* @returns Promise resolving when the process is canceled
|
|
1433
|
-
*
|
|
1648
|
+
*
|
|
1434
1649
|
* @example
|
|
1435
1650
|
* ```typescript
|
|
1436
1651
|
* await sdk.cancelProcess("0x1234567890abcdef...");
|
|
@@ -1453,14 +1668,14 @@ class ProcessOrchestrationService {
|
|
|
1453
1668
|
* Resumes a voting process by setting its status to READY.
|
|
1454
1669
|
* This is typically used to resume a paused process.
|
|
1455
1670
|
* Returns an async generator that yields transaction status events.
|
|
1456
|
-
*
|
|
1671
|
+
*
|
|
1457
1672
|
* @param processId - The process ID to resume
|
|
1458
1673
|
* @returns AsyncGenerator yielding transaction status events
|
|
1459
|
-
*
|
|
1674
|
+
*
|
|
1460
1675
|
* @example
|
|
1461
1676
|
* ```typescript
|
|
1462
1677
|
* const stream = sdk.resumeProcessStream("0x1234567890abcdef...");
|
|
1463
|
-
*
|
|
1678
|
+
*
|
|
1464
1679
|
* for await (const event of stream) {
|
|
1465
1680
|
* switch (event.status) {
|
|
1466
1681
|
* case "pending":
|
|
@@ -1503,12 +1718,12 @@ class ProcessOrchestrationService {
|
|
|
1503
1718
|
* Resumes a voting process by setting its status to READY.
|
|
1504
1719
|
* This is typically used to resume a paused process.
|
|
1505
1720
|
* This is a simplified method that waits for transaction completion.
|
|
1506
|
-
*
|
|
1721
|
+
*
|
|
1507
1722
|
* For real-time transaction status updates, use resumeProcessStream() instead.
|
|
1508
|
-
*
|
|
1723
|
+
*
|
|
1509
1724
|
* @param processId - The process ID to resume
|
|
1510
1725
|
* @returns Promise resolving when the process is resumed
|
|
1511
|
-
*
|
|
1726
|
+
*
|
|
1512
1727
|
* @example
|
|
1513
1728
|
* ```typescript
|
|
1514
1729
|
* await sdk.resumeProcess("0x1234567890abcdef...");
|
|
@@ -1596,11 +1811,7 @@ class CircomProof {
|
|
|
1596
1811
|
}
|
|
1597
1812
|
this.zkeyCache.set(zkeyUrl, zkeyBin);
|
|
1598
1813
|
}
|
|
1599
|
-
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
|
1600
|
-
inputs,
|
|
1601
|
-
wasmBin,
|
|
1602
|
-
zkeyBin
|
|
1603
|
-
);
|
|
1814
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(inputs, wasmBin, zkeyBin);
|
|
1604
1815
|
return {
|
|
1605
1816
|
proof,
|
|
1606
1817
|
publicSignals
|
|
@@ -1635,11 +1846,13 @@ var VoteStatus = /* @__PURE__ */ ((VoteStatus2) => {
|
|
|
1635
1846
|
})(VoteStatus || {});
|
|
1636
1847
|
|
|
1637
1848
|
class VoteOrchestrationService {
|
|
1638
|
-
constructor(apiService, getCrypto, signer, censusProviders = {}) {
|
|
1849
|
+
constructor(apiService, getCrypto, signer, censusProviders = {}, config = {}) {
|
|
1639
1850
|
this.apiService = apiService;
|
|
1640
1851
|
this.getCrypto = getCrypto;
|
|
1641
1852
|
this.signer = signer;
|
|
1642
1853
|
this.censusProviders = censusProviders;
|
|
1854
|
+
this.verifyCircuitFiles = config.verifyCircuitFiles ?? true;
|
|
1855
|
+
this.verifyProof = config.verifyProof ?? true;
|
|
1643
1856
|
}
|
|
1644
1857
|
/**
|
|
1645
1858
|
* Submit a vote with simplified configuration
|
|
@@ -1648,7 +1861,7 @@ class VoteOrchestrationService {
|
|
|
1648
1861
|
* - Gets census proof (Merkle or CSP)
|
|
1649
1862
|
* - Generates cryptographic proofs
|
|
1650
1863
|
* - Signs and submits the vote
|
|
1651
|
-
*
|
|
1864
|
+
*
|
|
1652
1865
|
* @param config - Simplified vote configuration
|
|
1653
1866
|
* @returns Promise resolving to vote submission result
|
|
1654
1867
|
*/
|
|
@@ -1696,7 +1909,7 @@ class VoteOrchestrationService {
|
|
|
1696
1909
|
}
|
|
1697
1910
|
/**
|
|
1698
1911
|
* Get the status of a submitted vote
|
|
1699
|
-
*
|
|
1912
|
+
*
|
|
1700
1913
|
* @param processId - The process ID
|
|
1701
1914
|
* @param voteId - The vote ID
|
|
1702
1915
|
* @returns Promise resolving to vote status information
|
|
@@ -1711,7 +1924,7 @@ class VoteOrchestrationService {
|
|
|
1711
1924
|
}
|
|
1712
1925
|
/**
|
|
1713
1926
|
* Check if an address has voted in a process
|
|
1714
|
-
*
|
|
1927
|
+
*
|
|
1715
1928
|
* @param processId - The process ID
|
|
1716
1929
|
* @param address - The voter's address
|
|
1717
1930
|
* @returns Promise resolving to boolean indicating if the address has voted
|
|
@@ -1722,19 +1935,19 @@ class VoteOrchestrationService {
|
|
|
1722
1935
|
/**
|
|
1723
1936
|
* Watch vote status changes in real-time using an async generator.
|
|
1724
1937
|
* Yields each status change as it happens, allowing for reactive UI updates.
|
|
1725
|
-
*
|
|
1938
|
+
*
|
|
1726
1939
|
* @param processId - The process ID
|
|
1727
1940
|
* @param voteId - The vote ID
|
|
1728
1941
|
* @param options - Optional configuration
|
|
1729
1942
|
* @returns AsyncGenerator yielding vote status updates
|
|
1730
|
-
*
|
|
1943
|
+
*
|
|
1731
1944
|
* @example
|
|
1732
1945
|
* ```typescript
|
|
1733
1946
|
* const vote = await sdk.submitVote({ processId, choices: [1] });
|
|
1734
|
-
*
|
|
1947
|
+
*
|
|
1735
1948
|
* for await (const statusInfo of sdk.watchVoteStatus(vote.processId, vote.voteId)) {
|
|
1736
1949
|
* console.log(`Vote status: ${statusInfo.status}`);
|
|
1737
|
-
*
|
|
1950
|
+
*
|
|
1738
1951
|
* switch (statusInfo.status) {
|
|
1739
1952
|
* case VoteStatus.Pending:
|
|
1740
1953
|
* console.log("⏳ Processing...");
|
|
@@ -1771,7 +1984,7 @@ class VoteOrchestrationService {
|
|
|
1771
1984
|
/**
|
|
1772
1985
|
* Wait for a vote to reach a specific status.
|
|
1773
1986
|
* This is a simpler alternative to watchVoteStatus() that returns only the final status.
|
|
1774
|
-
*
|
|
1987
|
+
*
|
|
1775
1988
|
* @param processId - The process ID
|
|
1776
1989
|
* @param voteId - The vote ID
|
|
1777
1990
|
* @param targetStatus - The target status to wait for (default: "settled")
|
|
@@ -1874,12 +2087,20 @@ class VoteOrchestrationService {
|
|
|
1874
2087
|
const circomProof = new CircomProof({
|
|
1875
2088
|
wasmUrl: info.circuitUrl,
|
|
1876
2089
|
zkeyUrl: info.provingKeyUrl,
|
|
1877
|
-
vkeyUrl: info.verificationKeyUrl
|
|
2090
|
+
vkeyUrl: info.verificationKeyUrl,
|
|
2091
|
+
// Only pass hashes if verifyCircuitFiles is enabled
|
|
2092
|
+
...this.verifyCircuitFiles && {
|
|
2093
|
+
wasmHash: info.circuitHash,
|
|
2094
|
+
zkeyHash: info.provingKeyHash,
|
|
2095
|
+
vkeyHash: info.verificationKeyHash
|
|
2096
|
+
}
|
|
1878
2097
|
});
|
|
1879
2098
|
const { proof, publicSignals } = await circomProof.generate(circomInputs);
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
2099
|
+
if (this.verifyProof) {
|
|
2100
|
+
const isValid = await circomProof.verify(proof, publicSignals);
|
|
2101
|
+
if (!isValid) {
|
|
2102
|
+
throw new Error("Generated proof is invalid");
|
|
2103
|
+
}
|
|
1883
2104
|
}
|
|
1884
2105
|
return { proof, publicSignals };
|
|
1885
2106
|
}
|
|
@@ -1917,10 +2138,7 @@ class VoteOrchestrationService {
|
|
|
1917
2138
|
class OrganizationRegistryService extends SmartContractService {
|
|
1918
2139
|
constructor(contractAddress, runner) {
|
|
1919
2140
|
super();
|
|
1920
|
-
this.contract = davinciContracts.OrganizationRegistry__factory.connect(
|
|
1921
|
-
contractAddress,
|
|
1922
|
-
runner
|
|
1923
|
-
);
|
|
2141
|
+
this.contract = davinciContracts.OrganizationRegistry__factory.connect(contractAddress, runner);
|
|
1924
2142
|
}
|
|
1925
2143
|
// ─── READ OPERATIONS ───────────────────────────────────────────────────────
|
|
1926
2144
|
async getOrganization(id) {
|
|
@@ -2196,25 +2414,23 @@ class DavinciCrypto {
|
|
|
2196
2414
|
class DavinciSDK {
|
|
2197
2415
|
constructor(config) {
|
|
2198
2416
|
this.initialized = false;
|
|
2199
|
-
const
|
|
2200
|
-
environment: config.environment,
|
|
2201
|
-
customUrls: {
|
|
2202
|
-
sequencer: config.sequencerUrl,
|
|
2203
|
-
census: config.censusUrl
|
|
2204
|
-
},
|
|
2205
|
-
customChain: config.chain
|
|
2206
|
-
});
|
|
2417
|
+
const hasCustomAddresses = !!config.addresses && Object.keys(config.addresses).length > 0;
|
|
2207
2418
|
this.config = {
|
|
2208
2419
|
signer: config.signer,
|
|
2209
|
-
sequencerUrl: config.sequencerUrl
|
|
2210
|
-
censusUrl: config.censusUrl
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2420
|
+
sequencerUrl: config.sequencerUrl,
|
|
2421
|
+
censusUrl: config.censusUrl,
|
|
2422
|
+
customAddresses: config.addresses || {},
|
|
2423
|
+
fetchAddressesFromSequencer: !hasCustomAddresses,
|
|
2424
|
+
// Automatic: fetch if no custom addresses
|
|
2425
|
+
verifyCircuitFiles: config.verifyCircuitFiles ?? true,
|
|
2426
|
+
// Default to true for security
|
|
2427
|
+
verifyProof: config.verifyProof ?? true
|
|
2428
|
+
// Default to true for security
|
|
2214
2429
|
};
|
|
2215
2430
|
this.apiService = new VocdoniApiService({
|
|
2216
2431
|
sequencerURL: this.config.sequencerUrl,
|
|
2217
|
-
censusURL: this.config.censusUrl
|
|
2432
|
+
censusURL: this.config.censusUrl || ""
|
|
2433
|
+
// Use empty string if not provided
|
|
2218
2434
|
});
|
|
2219
2435
|
this.censusProviders = config.censusProviders || {};
|
|
2220
2436
|
}
|
|
@@ -2224,9 +2440,10 @@ class DavinciSDK {
|
|
|
2224
2440
|
*/
|
|
2225
2441
|
async init() {
|
|
2226
2442
|
if (this.initialized) return;
|
|
2227
|
-
if (this.config.
|
|
2228
|
-
await this.
|
|
2443
|
+
if (this.config.fetchAddressesFromSequencer) {
|
|
2444
|
+
await this.fetchContractAddressesFromSequencer();
|
|
2229
2445
|
}
|
|
2446
|
+
if (!this.config.censusUrl) ;
|
|
2230
2447
|
this.initialized = true;
|
|
2231
2448
|
}
|
|
2232
2449
|
/**
|
|
@@ -2238,28 +2455,34 @@ class DavinciSDK {
|
|
|
2238
2455
|
/**
|
|
2239
2456
|
* Get the process registry service for process management.
|
|
2240
2457
|
* Requires a signer with a provider for blockchain interactions.
|
|
2241
|
-
*
|
|
2458
|
+
*
|
|
2242
2459
|
* @throws Error if signer does not have a provider
|
|
2243
2460
|
*/
|
|
2244
2461
|
get processes() {
|
|
2245
2462
|
this.ensureProvider();
|
|
2246
2463
|
if (!this._processRegistry) {
|
|
2247
2464
|
const processRegistryAddress = this.resolveContractAddress("processRegistry");
|
|
2248
|
-
this._processRegistry = new ProcessRegistryService(
|
|
2465
|
+
this._processRegistry = new ProcessRegistryService(
|
|
2466
|
+
processRegistryAddress,
|
|
2467
|
+
this.config.signer
|
|
2468
|
+
);
|
|
2249
2469
|
}
|
|
2250
2470
|
return this._processRegistry;
|
|
2251
2471
|
}
|
|
2252
2472
|
/**
|
|
2253
2473
|
* Get the organization registry service for organization management.
|
|
2254
2474
|
* Requires a signer with a provider for blockchain interactions.
|
|
2255
|
-
*
|
|
2475
|
+
*
|
|
2256
2476
|
* @throws Error if signer does not have a provider
|
|
2257
2477
|
*/
|
|
2258
2478
|
get organizations() {
|
|
2259
2479
|
this.ensureProvider();
|
|
2260
2480
|
if (!this._organizationRegistry) {
|
|
2261
2481
|
const organizationRegistryAddress = this.resolveContractAddress("organizationRegistry");
|
|
2262
|
-
this._organizationRegistry = new OrganizationRegistryService(
|
|
2482
|
+
this._organizationRegistry = new OrganizationRegistryService(
|
|
2483
|
+
organizationRegistryAddress,
|
|
2484
|
+
this.config.signer
|
|
2485
|
+
);
|
|
2263
2486
|
}
|
|
2264
2487
|
return this._organizationRegistry;
|
|
2265
2488
|
}
|
|
@@ -2280,7 +2503,7 @@ class DavinciSDK {
|
|
|
2280
2503
|
/**
|
|
2281
2504
|
* Get the process orchestration service for simplified process creation.
|
|
2282
2505
|
* Requires a signer with a provider for blockchain interactions.
|
|
2283
|
-
*
|
|
2506
|
+
*
|
|
2284
2507
|
* @throws Error if signer does not have a provider
|
|
2285
2508
|
*/
|
|
2286
2509
|
get processOrchestrator() {
|
|
@@ -2305,7 +2528,11 @@ class DavinciSDK {
|
|
|
2305
2528
|
this.apiService,
|
|
2306
2529
|
() => this.getCrypto(),
|
|
2307
2530
|
this.config.signer,
|
|
2308
|
-
this.censusProviders
|
|
2531
|
+
this.censusProviders,
|
|
2532
|
+
{
|
|
2533
|
+
verifyCircuitFiles: this.config.verifyCircuitFiles,
|
|
2534
|
+
verifyProof: this.config.verifyProof
|
|
2535
|
+
}
|
|
2309
2536
|
);
|
|
2310
2537
|
}
|
|
2311
2538
|
return this._voteOrchestrator;
|
|
@@ -2314,24 +2541,24 @@ class DavinciSDK {
|
|
|
2314
2541
|
* Gets user-friendly process information from the blockchain.
|
|
2315
2542
|
* This method fetches raw contract data and transforms it into a user-friendly format
|
|
2316
2543
|
* that matches the ProcessConfig interface used for creation, plus additional runtime data.
|
|
2317
|
-
*
|
|
2544
|
+
*
|
|
2318
2545
|
* Requires a signer with a provider for blockchain interactions.
|
|
2319
|
-
*
|
|
2546
|
+
*
|
|
2320
2547
|
* @param processId - The process ID to fetch
|
|
2321
2548
|
* @returns Promise resolving to user-friendly process information
|
|
2322
2549
|
* @throws Error if signer does not have a provider
|
|
2323
|
-
*
|
|
2550
|
+
*
|
|
2324
2551
|
* @example
|
|
2325
2552
|
* ```typescript
|
|
2326
2553
|
* const processInfo = await sdk.getProcess("0x1234567890abcdef...");
|
|
2327
|
-
*
|
|
2554
|
+
*
|
|
2328
2555
|
* // Access the same fields as ProcessConfig
|
|
2329
2556
|
* console.log("Title:", processInfo.title);
|
|
2330
2557
|
* console.log("Description:", processInfo.description);
|
|
2331
2558
|
* console.log("Questions:", processInfo.questions);
|
|
2332
2559
|
* console.log("Census size:", processInfo.census.size);
|
|
2333
2560
|
* console.log("Ballot config:", processInfo.ballot);
|
|
2334
|
-
*
|
|
2561
|
+
*
|
|
2335
2562
|
* // Plus additional runtime information
|
|
2336
2563
|
* console.log("Status:", processInfo.status);
|
|
2337
2564
|
* console.log("Creator:", processInfo.creator);
|
|
@@ -2339,7 +2566,7 @@ class DavinciSDK {
|
|
|
2339
2566
|
* console.log("End date:", processInfo.endDate);
|
|
2340
2567
|
* console.log("Duration:", processInfo.duration, "seconds");
|
|
2341
2568
|
* console.log("Time remaining:", processInfo.timeRemaining, "seconds");
|
|
2342
|
-
*
|
|
2569
|
+
*
|
|
2343
2570
|
* // Access raw contract data if needed
|
|
2344
2571
|
* console.log("Raw data:", processInfo.raw);
|
|
2345
2572
|
* ```
|
|
@@ -2355,13 +2582,13 @@ class DavinciSDK {
|
|
|
2355
2582
|
* Creates a complete voting process and returns an async generator that yields transaction status events.
|
|
2356
2583
|
* This method allows you to monitor the transaction progress in real-time, including pending, completed,
|
|
2357
2584
|
* failed, and reverted states.
|
|
2358
|
-
*
|
|
2585
|
+
*
|
|
2359
2586
|
* Requires a signer with a provider for blockchain interactions.
|
|
2360
|
-
*
|
|
2587
|
+
*
|
|
2361
2588
|
* @param config - Simplified process configuration
|
|
2362
2589
|
* @returns AsyncGenerator yielding transaction status events
|
|
2363
2590
|
* @throws Error if signer does not have a provider
|
|
2364
|
-
*
|
|
2591
|
+
*
|
|
2365
2592
|
* @example
|
|
2366
2593
|
* ```typescript
|
|
2367
2594
|
* const stream = sdk.createProcessStream({
|
|
@@ -2397,7 +2624,7 @@ class DavinciSDK {
|
|
|
2397
2624
|
* }
|
|
2398
2625
|
* ]
|
|
2399
2626
|
* });
|
|
2400
|
-
*
|
|
2627
|
+
*
|
|
2401
2628
|
* // Monitor transaction progress
|
|
2402
2629
|
* for await (const event of stream) {
|
|
2403
2630
|
* switch (event.status) {
|
|
@@ -2432,22 +2659,22 @@ class DavinciSDK {
|
|
|
2432
2659
|
/**
|
|
2433
2660
|
* Creates a complete voting process with minimal configuration.
|
|
2434
2661
|
* This is the ultra-easy method for end users that handles all the complex orchestration internally.
|
|
2435
|
-
*
|
|
2662
|
+
*
|
|
2436
2663
|
* For real-time transaction status updates, use createProcessStream() instead.
|
|
2437
|
-
*
|
|
2664
|
+
*
|
|
2438
2665
|
* Requires a signer with a provider for blockchain interactions.
|
|
2439
|
-
*
|
|
2666
|
+
*
|
|
2440
2667
|
* The method automatically:
|
|
2441
2668
|
* - Gets encryption keys and initial state root from the sequencer
|
|
2442
2669
|
* - Handles process creation signatures
|
|
2443
2670
|
* - Coordinates between sequencer API and on-chain contract calls
|
|
2444
2671
|
* - Creates and pushes metadata
|
|
2445
2672
|
* - Submits the on-chain transaction
|
|
2446
|
-
*
|
|
2673
|
+
*
|
|
2447
2674
|
* @param config - Simplified process configuration
|
|
2448
2675
|
* @returns Promise resolving to the process creation result
|
|
2449
2676
|
* @throws Error if signer does not have a provider
|
|
2450
|
-
*
|
|
2677
|
+
*
|
|
2451
2678
|
* @example
|
|
2452
2679
|
* ```typescript
|
|
2453
2680
|
* // Option 1: Using duration (traditional approach)
|
|
@@ -2484,7 +2711,7 @@ class DavinciSDK {
|
|
|
2484
2711
|
* }
|
|
2485
2712
|
* ]
|
|
2486
2713
|
* });
|
|
2487
|
-
*
|
|
2714
|
+
*
|
|
2488
2715
|
* // Option 2: Using start and end dates
|
|
2489
2716
|
* const result2 = await sdk.createProcess({
|
|
2490
2717
|
* title: "Weekend Vote",
|
|
@@ -2505,18 +2732,20 @@ class DavinciSDK {
|
|
|
2505
2732
|
/**
|
|
2506
2733
|
* Submit a vote with simplified configuration.
|
|
2507
2734
|
* This is the ultra-easy method for end users that handles all the complex voting workflow internally.
|
|
2508
|
-
*
|
|
2735
|
+
*
|
|
2509
2736
|
* Does NOT require a provider - can be used with a bare Wallet for signing only.
|
|
2510
|
-
*
|
|
2737
|
+
* IMPORTANT: Requires censusUrl to be configured in the SDK for fetching census proofs (unless using custom census providers).
|
|
2738
|
+
*
|
|
2511
2739
|
* The method automatically:
|
|
2512
2740
|
* - Fetches process information and validates voting is allowed
|
|
2513
2741
|
* - Gets census proof (Merkle tree based)
|
|
2514
2742
|
* - Generates cryptographic proofs and encrypts the vote
|
|
2515
2743
|
* - Signs and submits the vote to the sequencer
|
|
2516
|
-
*
|
|
2744
|
+
*
|
|
2517
2745
|
* @param config - Simplified vote configuration
|
|
2518
2746
|
* @returns Promise resolving to vote submission result
|
|
2519
|
-
*
|
|
2747
|
+
* @throws Error if censusUrl is not configured (unless using custom census providers)
|
|
2748
|
+
*
|
|
2520
2749
|
* @example
|
|
2521
2750
|
* ```typescript
|
|
2522
2751
|
* // Submit a vote with voter's private key
|
|
@@ -2525,14 +2754,14 @@ class DavinciSDK {
|
|
|
2525
2754
|
* choices: [1, 0], // Vote for option 1 in question 1, option 0 in question 2
|
|
2526
2755
|
* voterKey: "0x1234567890abcdef..." // Voter's private key
|
|
2527
2756
|
* });
|
|
2528
|
-
*
|
|
2757
|
+
*
|
|
2529
2758
|
* console.log("Vote ID:", voteResult.voteId);
|
|
2530
2759
|
* console.log("Status:", voteResult.status);
|
|
2531
|
-
*
|
|
2760
|
+
*
|
|
2532
2761
|
* // Submit a vote with a Wallet instance
|
|
2533
2762
|
* import { Wallet } from "ethers";
|
|
2534
2763
|
* const voterWallet = new Wallet("0x...");
|
|
2535
|
-
*
|
|
2764
|
+
*
|
|
2536
2765
|
* const voteResult2 = await sdk.submitVote({
|
|
2537
2766
|
* processId: "0x1234567890abcdef...",
|
|
2538
2767
|
* choices: [2], // Single question vote
|
|
@@ -2544,17 +2773,22 @@ class DavinciSDK {
|
|
|
2544
2773
|
if (!this.initialized) {
|
|
2545
2774
|
throw new Error("SDK must be initialized before submitting votes. Call sdk.init() first.");
|
|
2546
2775
|
}
|
|
2776
|
+
if (!this.config.censusUrl && !this.censusProviders.merkle && !this.censusProviders.csp) {
|
|
2777
|
+
throw new Error(
|
|
2778
|
+
"Census URL is required for voting. Provide censusUrl in the SDK constructor config, or use custom census providers."
|
|
2779
|
+
);
|
|
2780
|
+
}
|
|
2547
2781
|
return this.voteOrchestrator.submitVote(config);
|
|
2548
2782
|
}
|
|
2549
2783
|
/**
|
|
2550
2784
|
* Get the status of a submitted vote.
|
|
2551
|
-
*
|
|
2785
|
+
*
|
|
2552
2786
|
* Does NOT require a provider - uses API calls only.
|
|
2553
|
-
*
|
|
2787
|
+
*
|
|
2554
2788
|
* @param processId - The process ID
|
|
2555
2789
|
* @param voteId - The vote ID returned from submitVote()
|
|
2556
2790
|
* @returns Promise resolving to vote status information
|
|
2557
|
-
*
|
|
2791
|
+
*
|
|
2558
2792
|
* @example
|
|
2559
2793
|
* ```typescript
|
|
2560
2794
|
* const statusInfo = await sdk.getVoteStatus(processId, voteId);
|
|
@@ -2570,13 +2804,13 @@ class DavinciSDK {
|
|
|
2570
2804
|
}
|
|
2571
2805
|
/**
|
|
2572
2806
|
* Check if an address has voted in a process.
|
|
2573
|
-
*
|
|
2807
|
+
*
|
|
2574
2808
|
* Does NOT require a provider - uses API calls only.
|
|
2575
|
-
*
|
|
2809
|
+
*
|
|
2576
2810
|
* @param processId - The process ID
|
|
2577
2811
|
* @param address - The voter's address
|
|
2578
2812
|
* @returns Promise resolving to boolean indicating if the address has voted
|
|
2579
|
-
*
|
|
2813
|
+
*
|
|
2580
2814
|
* @example
|
|
2581
2815
|
* ```typescript
|
|
2582
2816
|
* const hasVoted = await sdk.hasAddressVoted(processId, "0x1234567890abcdef...");
|
|
@@ -2587,22 +2821,24 @@ class DavinciSDK {
|
|
|
2587
2821
|
*/
|
|
2588
2822
|
async hasAddressVoted(processId, address) {
|
|
2589
2823
|
if (!this.initialized) {
|
|
2590
|
-
throw new Error(
|
|
2824
|
+
throw new Error(
|
|
2825
|
+
"SDK must be initialized before checking vote status. Call sdk.init() first."
|
|
2826
|
+
);
|
|
2591
2827
|
}
|
|
2592
2828
|
return this.voteOrchestrator.hasAddressVoted(processId, address);
|
|
2593
2829
|
}
|
|
2594
2830
|
/**
|
|
2595
2831
|
* Watch vote status changes in real-time using an async generator.
|
|
2596
|
-
* This method yields each status change as it happens, perfect for showing
|
|
2832
|
+
* This method yields each status change as it happens, perfect for showing
|
|
2597
2833
|
* progress indicators in UI applications.
|
|
2598
|
-
*
|
|
2834
|
+
*
|
|
2599
2835
|
* Does NOT require a provider - uses API calls only.
|
|
2600
|
-
*
|
|
2836
|
+
*
|
|
2601
2837
|
* @param processId - The process ID
|
|
2602
2838
|
* @param voteId - The vote ID
|
|
2603
2839
|
* @param options - Optional configuration
|
|
2604
2840
|
* @returns AsyncGenerator yielding vote status updates
|
|
2605
|
-
*
|
|
2841
|
+
*
|
|
2606
2842
|
* @example
|
|
2607
2843
|
* ```typescript
|
|
2608
2844
|
* // Submit vote
|
|
@@ -2610,11 +2846,11 @@ class DavinciSDK {
|
|
|
2610
2846
|
* processId: "0x1234567890abcdef...",
|
|
2611
2847
|
* choices: [1]
|
|
2612
2848
|
* });
|
|
2613
|
-
*
|
|
2849
|
+
*
|
|
2614
2850
|
* // Watch status changes in real-time
|
|
2615
2851
|
* for await (const statusInfo of sdk.watchVoteStatus(voteResult.processId, voteResult.voteId)) {
|
|
2616
2852
|
* console.log(`Vote status: ${statusInfo.status}`);
|
|
2617
|
-
*
|
|
2853
|
+
*
|
|
2618
2854
|
* switch (statusInfo.status) {
|
|
2619
2855
|
* case VoteStatus.Pending:
|
|
2620
2856
|
* console.log("⏳ Processing...");
|
|
@@ -2634,7 +2870,9 @@ class DavinciSDK {
|
|
|
2634
2870
|
*/
|
|
2635
2871
|
watchVoteStatus(processId, voteId, options) {
|
|
2636
2872
|
if (!this.initialized) {
|
|
2637
|
-
throw new Error(
|
|
2873
|
+
throw new Error(
|
|
2874
|
+
"SDK must be initialized before watching vote status. Call sdk.init() first."
|
|
2875
|
+
);
|
|
2638
2876
|
}
|
|
2639
2877
|
return this.voteOrchestrator.watchVoteStatus(processId, voteId, options);
|
|
2640
2878
|
}
|
|
@@ -2642,16 +2880,16 @@ class DavinciSDK {
|
|
|
2642
2880
|
* Wait for a vote to reach a specific status.
|
|
2643
2881
|
* This is a simpler alternative to watchVoteStatus() that returns only the final status.
|
|
2644
2882
|
* Useful for waiting for vote confirmation and processing without needing to handle each intermediate status.
|
|
2645
|
-
*
|
|
2883
|
+
*
|
|
2646
2884
|
* Does NOT require a provider - uses API calls only.
|
|
2647
|
-
*
|
|
2885
|
+
*
|
|
2648
2886
|
* @param processId - The process ID
|
|
2649
2887
|
* @param voteId - The vote ID
|
|
2650
2888
|
* @param targetStatus - The target status to wait for (default: "settled")
|
|
2651
2889
|
* @param timeoutMs - Maximum time to wait in milliseconds (default: 300000 = 5 minutes)
|
|
2652
2890
|
* @param pollIntervalMs - Polling interval in milliseconds (default: 5000 = 5 seconds)
|
|
2653
2891
|
* @returns Promise resolving to final vote status
|
|
2654
|
-
*
|
|
2892
|
+
*
|
|
2655
2893
|
* @example
|
|
2656
2894
|
* ```typescript
|
|
2657
2895
|
* // Submit vote and wait for it to be settled
|
|
@@ -2659,7 +2897,7 @@ class DavinciSDK {
|
|
|
2659
2897
|
* processId: "0x1234567890abcdef...",
|
|
2660
2898
|
* choices: [1]
|
|
2661
2899
|
* });
|
|
2662
|
-
*
|
|
2900
|
+
*
|
|
2663
2901
|
* // Wait for the vote to be fully processed
|
|
2664
2902
|
* const finalStatus = await sdk.waitForVoteStatus(
|
|
2665
2903
|
* voteResult.processId,
|
|
@@ -2668,31 +2906,39 @@ class DavinciSDK {
|
|
|
2668
2906
|
* 300000, // 5 minute timeout
|
|
2669
2907
|
* 5000 // Check every 5 seconds
|
|
2670
2908
|
* );
|
|
2671
|
-
*
|
|
2909
|
+
*
|
|
2672
2910
|
* console.log("Vote final status:", finalStatus.status);
|
|
2673
2911
|
* ```
|
|
2674
2912
|
*/
|
|
2675
2913
|
async waitForVoteStatus(processId, voteId, targetStatus = VoteStatus.Settled, timeoutMs = 3e5, pollIntervalMs = 5e3) {
|
|
2676
2914
|
if (!this.initialized) {
|
|
2677
|
-
throw new Error(
|
|
2915
|
+
throw new Error(
|
|
2916
|
+
"SDK must be initialized before waiting for vote status. Call sdk.init() first."
|
|
2917
|
+
);
|
|
2678
2918
|
}
|
|
2679
|
-
return this.voteOrchestrator.waitForVoteStatus(
|
|
2919
|
+
return this.voteOrchestrator.waitForVoteStatus(
|
|
2920
|
+
processId,
|
|
2921
|
+
voteId,
|
|
2922
|
+
targetStatus,
|
|
2923
|
+
timeoutMs,
|
|
2924
|
+
pollIntervalMs
|
|
2925
|
+
);
|
|
2680
2926
|
}
|
|
2681
2927
|
/**
|
|
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
|
|
2928
|
+
* Ends a voting process by setting its status to ENDED and returns an async generator
|
|
2929
|
+
* that yields transaction status events. This method allows you to monitor the
|
|
2684
2930
|
* transaction progress in real-time.
|
|
2685
|
-
*
|
|
2931
|
+
*
|
|
2686
2932
|
* Requires a signer with a provider for blockchain interactions.
|
|
2687
|
-
*
|
|
2933
|
+
*
|
|
2688
2934
|
* @param processId - The process ID to end
|
|
2689
2935
|
* @returns AsyncGenerator yielding transaction status events
|
|
2690
2936
|
* @throws Error if signer does not have a provider
|
|
2691
|
-
*
|
|
2937
|
+
*
|
|
2692
2938
|
* @example
|
|
2693
2939
|
* ```typescript
|
|
2694
2940
|
* const stream = sdk.endProcessStream("0x1234567890abcdef...");
|
|
2695
|
-
*
|
|
2941
|
+
*
|
|
2696
2942
|
* for await (const event of stream) {
|
|
2697
2943
|
* switch (event.status) {
|
|
2698
2944
|
* case TxStatus.Pending:
|
|
@@ -2721,15 +2967,15 @@ class DavinciSDK {
|
|
|
2721
2967
|
/**
|
|
2722
2968
|
* Ends a voting process by setting its status to ENDED.
|
|
2723
2969
|
* This is the simplified method that waits for transaction completion.
|
|
2724
|
-
*
|
|
2970
|
+
*
|
|
2725
2971
|
* For real-time transaction status updates, use endProcessStream() instead.
|
|
2726
|
-
*
|
|
2972
|
+
*
|
|
2727
2973
|
* Requires a signer with a provider for blockchain interactions.
|
|
2728
|
-
*
|
|
2974
|
+
*
|
|
2729
2975
|
* @param processId - The process ID to end
|
|
2730
2976
|
* @returns Promise resolving when the process is ended
|
|
2731
2977
|
* @throws Error if signer does not have a provider
|
|
2732
|
-
*
|
|
2978
|
+
*
|
|
2733
2979
|
* @example
|
|
2734
2980
|
* ```typescript
|
|
2735
2981
|
* await sdk.endProcess("0x1234567890abcdef...");
|
|
@@ -2744,20 +2990,20 @@ class DavinciSDK {
|
|
|
2744
2990
|
return this.processOrchestrator.endProcess(processId);
|
|
2745
2991
|
}
|
|
2746
2992
|
/**
|
|
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
|
|
2993
|
+
* Pauses a voting process by setting its status to PAUSED and returns an async generator
|
|
2994
|
+
* that yields transaction status events. This method allows you to monitor the
|
|
2749
2995
|
* transaction progress in real-time.
|
|
2750
|
-
*
|
|
2996
|
+
*
|
|
2751
2997
|
* Requires a signer with a provider for blockchain interactions.
|
|
2752
|
-
*
|
|
2998
|
+
*
|
|
2753
2999
|
* @param processId - The process ID to pause
|
|
2754
3000
|
* @returns AsyncGenerator yielding transaction status events
|
|
2755
3001
|
* @throws Error if signer does not have a provider
|
|
2756
|
-
*
|
|
3002
|
+
*
|
|
2757
3003
|
* @example
|
|
2758
3004
|
* ```typescript
|
|
2759
3005
|
* const stream = sdk.pauseProcessStream("0x1234567890abcdef...");
|
|
2760
|
-
*
|
|
3006
|
+
*
|
|
2761
3007
|
* for await (const event of stream) {
|
|
2762
3008
|
* switch (event.status) {
|
|
2763
3009
|
* case TxStatus.Pending:
|
|
@@ -2786,15 +3032,15 @@ class DavinciSDK {
|
|
|
2786
3032
|
/**
|
|
2787
3033
|
* Pauses a voting process by setting its status to PAUSED.
|
|
2788
3034
|
* This is the simplified method that waits for transaction completion.
|
|
2789
|
-
*
|
|
3035
|
+
*
|
|
2790
3036
|
* For real-time transaction status updates, use pauseProcessStream() instead.
|
|
2791
|
-
*
|
|
3037
|
+
*
|
|
2792
3038
|
* Requires a signer with a provider for blockchain interactions.
|
|
2793
|
-
*
|
|
3039
|
+
*
|
|
2794
3040
|
* @param processId - The process ID to pause
|
|
2795
3041
|
* @returns Promise resolving when the process is paused
|
|
2796
3042
|
* @throws Error if signer does not have a provider
|
|
2797
|
-
*
|
|
3043
|
+
*
|
|
2798
3044
|
* @example
|
|
2799
3045
|
* ```typescript
|
|
2800
3046
|
* await sdk.pauseProcess("0x1234567890abcdef...");
|
|
@@ -2809,20 +3055,20 @@ class DavinciSDK {
|
|
|
2809
3055
|
return this.processOrchestrator.pauseProcess(processId);
|
|
2810
3056
|
}
|
|
2811
3057
|
/**
|
|
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
|
|
3058
|
+
* Cancels a voting process by setting its status to CANCELED and returns an async generator
|
|
3059
|
+
* that yields transaction status events. This method allows you to monitor the
|
|
2814
3060
|
* transaction progress in real-time.
|
|
2815
|
-
*
|
|
3061
|
+
*
|
|
2816
3062
|
* Requires a signer with a provider for blockchain interactions.
|
|
2817
|
-
*
|
|
3063
|
+
*
|
|
2818
3064
|
* @param processId - The process ID to cancel
|
|
2819
3065
|
* @returns AsyncGenerator yielding transaction status events
|
|
2820
3066
|
* @throws Error if signer does not have a provider
|
|
2821
|
-
*
|
|
3067
|
+
*
|
|
2822
3068
|
* @example
|
|
2823
3069
|
* ```typescript
|
|
2824
3070
|
* const stream = sdk.cancelProcessStream("0x1234567890abcdef...");
|
|
2825
|
-
*
|
|
3071
|
+
*
|
|
2826
3072
|
* for await (const event of stream) {
|
|
2827
3073
|
* switch (event.status) {
|
|
2828
3074
|
* case TxStatus.Pending:
|
|
@@ -2851,15 +3097,15 @@ class DavinciSDK {
|
|
|
2851
3097
|
/**
|
|
2852
3098
|
* Cancels a voting process by setting its status to CANCELED.
|
|
2853
3099
|
* This is the simplified method that waits for transaction completion.
|
|
2854
|
-
*
|
|
3100
|
+
*
|
|
2855
3101
|
* For real-time transaction status updates, use cancelProcessStream() instead.
|
|
2856
|
-
*
|
|
3102
|
+
*
|
|
2857
3103
|
* Requires a signer with a provider for blockchain interactions.
|
|
2858
|
-
*
|
|
3104
|
+
*
|
|
2859
3105
|
* @param processId - The process ID to cancel
|
|
2860
3106
|
* @returns Promise resolving when the process is canceled
|
|
2861
3107
|
* @throws Error if signer does not have a provider
|
|
2862
|
-
*
|
|
3108
|
+
*
|
|
2863
3109
|
* @example
|
|
2864
3110
|
* ```typescript
|
|
2865
3111
|
* await sdk.cancelProcess("0x1234567890abcdef...");
|
|
@@ -2874,19 +3120,19 @@ class DavinciSDK {
|
|
|
2874
3120
|
return this.processOrchestrator.cancelProcess(processId);
|
|
2875
3121
|
}
|
|
2876
3122
|
/**
|
|
2877
|
-
* Resumes a voting process by setting its status to READY and returns an async generator
|
|
3123
|
+
* Resumes a voting process by setting its status to READY and returns an async generator
|
|
2878
3124
|
* that yields transaction status events. This is typically used to resume a paused process.
|
|
2879
|
-
*
|
|
3125
|
+
*
|
|
2880
3126
|
* Requires a signer with a provider for blockchain interactions.
|
|
2881
|
-
*
|
|
3127
|
+
*
|
|
2882
3128
|
* @param processId - The process ID to resume
|
|
2883
3129
|
* @returns AsyncGenerator yielding transaction status events
|
|
2884
3130
|
* @throws Error if signer does not have a provider
|
|
2885
|
-
*
|
|
3131
|
+
*
|
|
2886
3132
|
* @example
|
|
2887
3133
|
* ```typescript
|
|
2888
3134
|
* const stream = sdk.resumeProcessStream("0x1234567890abcdef...");
|
|
2889
|
-
*
|
|
3135
|
+
*
|
|
2890
3136
|
* for await (const event of stream) {
|
|
2891
3137
|
* switch (event.status) {
|
|
2892
3138
|
* case TxStatus.Pending:
|
|
@@ -2916,15 +3162,15 @@ class DavinciSDK {
|
|
|
2916
3162
|
* Resumes a voting process by setting its status to READY.
|
|
2917
3163
|
* This is typically used to resume a paused process.
|
|
2918
3164
|
* This is the simplified method that waits for transaction completion.
|
|
2919
|
-
*
|
|
3165
|
+
*
|
|
2920
3166
|
* For real-time transaction status updates, use resumeProcessStream() instead.
|
|
2921
|
-
*
|
|
3167
|
+
*
|
|
2922
3168
|
* Requires a signer with a provider for blockchain interactions.
|
|
2923
|
-
*
|
|
3169
|
+
*
|
|
2924
3170
|
* @param processId - The process ID to resume
|
|
2925
3171
|
* @returns Promise resolving when the process is resumed
|
|
2926
3172
|
* @throws Error if signer does not have a provider
|
|
2927
|
-
*
|
|
3173
|
+
*
|
|
2928
3174
|
* @example
|
|
2929
3175
|
* ```typescript
|
|
2930
3176
|
* await sdk.resumeProcess("0x1234567890abcdef...");
|
|
@@ -2940,64 +3186,50 @@ class DavinciSDK {
|
|
|
2940
3186
|
}
|
|
2941
3187
|
/**
|
|
2942
3188
|
* Resolve contract address based on configuration priority:
|
|
2943
|
-
* 1.
|
|
2944
|
-
* 2.
|
|
2945
|
-
* 3. Default deployed addresses from npm package
|
|
3189
|
+
* 1. Custom addresses from user config (if provided)
|
|
3190
|
+
* 2. Addresses from sequencer (fetched during init if no custom addresses provided)
|
|
2946
3191
|
*/
|
|
2947
3192
|
resolveContractAddress(contractName) {
|
|
2948
|
-
|
|
2949
|
-
return this.getDefaultContractAddress(contractName);
|
|
2950
|
-
}
|
|
2951
|
-
const customAddress = this.config.contractAddresses[contractName];
|
|
3193
|
+
const customAddress = this.config.customAddresses[contractName];
|
|
2952
3194
|
if (customAddress) {
|
|
2953
3195
|
return customAddress;
|
|
2954
3196
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
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}`);
|
|
3197
|
+
if (!this.config.customAddresses[contractName]) {
|
|
3198
|
+
throw new Error(
|
|
3199
|
+
`Contract address for '${contractName}' not found. Make sure SDK is initialized with sdk.init() or provide custom addresses in config.`
|
|
3200
|
+
);
|
|
2975
3201
|
}
|
|
3202
|
+
return this.config.customAddresses[contractName];
|
|
2976
3203
|
}
|
|
2977
3204
|
/**
|
|
2978
|
-
*
|
|
2979
|
-
*
|
|
3205
|
+
* Fetch contract addresses from sequencer info
|
|
3206
|
+
* This is called during init() if custom addresses are not provided
|
|
2980
3207
|
*/
|
|
2981
|
-
async
|
|
3208
|
+
async fetchContractAddressesFromSequencer() {
|
|
2982
3209
|
try {
|
|
2983
3210
|
const info = await this.apiService.sequencer.getInfo();
|
|
2984
3211
|
const contracts = info.contracts;
|
|
2985
3212
|
if (contracts.process) {
|
|
3213
|
+
this.config.customAddresses.processRegistry = contracts.process;
|
|
2986
3214
|
this._processRegistry = new ProcessRegistryService(contracts.process, this.config.signer);
|
|
2987
|
-
this.config.contractAddresses.processRegistry = contracts.process;
|
|
2988
3215
|
}
|
|
2989
3216
|
if (contracts.organization) {
|
|
2990
|
-
this.
|
|
2991
|
-
this.
|
|
3217
|
+
this.config.customAddresses.organizationRegistry = contracts.organization;
|
|
3218
|
+
this._organizationRegistry = new OrganizationRegistryService(
|
|
3219
|
+
contracts.organization,
|
|
3220
|
+
this.config.signer
|
|
3221
|
+
);
|
|
2992
3222
|
}
|
|
2993
3223
|
if (contracts.stateTransitionVerifier) {
|
|
2994
|
-
this.config.
|
|
3224
|
+
this.config.customAddresses.stateTransitionVerifier = contracts.stateTransitionVerifier;
|
|
2995
3225
|
}
|
|
2996
3226
|
if (contracts.resultsVerifier) {
|
|
2997
|
-
this.config.
|
|
3227
|
+
this.config.customAddresses.resultsVerifier = contracts.resultsVerifier;
|
|
2998
3228
|
}
|
|
2999
3229
|
} catch (error) {
|
|
3000
|
-
|
|
3230
|
+
throw new Error(
|
|
3231
|
+
`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.`
|
|
3232
|
+
);
|
|
3001
3233
|
}
|
|
3002
3234
|
}
|
|
3003
3235
|
/**
|
|
@@ -3027,10 +3259,13 @@ class DavinciSDK {
|
|
|
3027
3259
|
}
|
|
3028
3260
|
|
|
3029
3261
|
exports.BaseService = BaseService;
|
|
3262
|
+
exports.Census = Census;
|
|
3263
|
+
exports.CensusOrchestrator = CensusOrchestrator;
|
|
3030
3264
|
exports.CensusOrigin = CensusOrigin;
|
|
3265
|
+
exports.CensusType = CensusType;
|
|
3031
3266
|
exports.CircomProof = CircomProof;
|
|
3032
3267
|
exports.ContractServiceError = ContractServiceError;
|
|
3033
|
-
exports.
|
|
3268
|
+
exports.CspCensus = CspCensus;
|
|
3034
3269
|
exports.DavinciCrypto = DavinciCrypto;
|
|
3035
3270
|
exports.DavinciSDK = DavinciSDK;
|
|
3036
3271
|
exports.ElectionMetadataTemplate = ElectionMetadataTemplate;
|
|
@@ -3040,6 +3275,7 @@ exports.OrganizationCreateError = OrganizationCreateError;
|
|
|
3040
3275
|
exports.OrganizationDeleteError = OrganizationDeleteError;
|
|
3041
3276
|
exports.OrganizationRegistryService = OrganizationRegistryService;
|
|
3042
3277
|
exports.OrganizationUpdateError = OrganizationUpdateError;
|
|
3278
|
+
exports.PlainCensus = PlainCensus;
|
|
3043
3279
|
exports.ProcessCensusError = ProcessCensusError;
|
|
3044
3280
|
exports.ProcessCreateError = ProcessCreateError;
|
|
3045
3281
|
exports.ProcessDurationError = ProcessDurationError;
|
|
@@ -3049,6 +3285,7 @@ exports.ProcessResultError = ProcessResultError;
|
|
|
3049
3285
|
exports.ProcessStateTransitionError = ProcessStateTransitionError;
|
|
3050
3286
|
exports.ProcessStatus = ProcessStatus;
|
|
3051
3287
|
exports.ProcessStatusError = ProcessStatusError;
|
|
3288
|
+
exports.PublishedCensus = PublishedCensus;
|
|
3052
3289
|
exports.SmartContractService = SmartContractService;
|
|
3053
3290
|
exports.TxStatus = TxStatus;
|
|
3054
3291
|
exports.VocdoniApiService = VocdoniApiService;
|
|
@@ -3056,18 +3293,13 @@ exports.VocdoniCensusService = VocdoniCensusService;
|
|
|
3056
3293
|
exports.VocdoniSequencerService = VocdoniSequencerService;
|
|
3057
3294
|
exports.VoteOrchestrationService = VoteOrchestrationService;
|
|
3058
3295
|
exports.VoteStatus = VoteStatus;
|
|
3296
|
+
exports.WeightedCensus = WeightedCensus;
|
|
3059
3297
|
exports.assertCSPCensusProof = assertCSPCensusProof;
|
|
3060
3298
|
exports.assertMerkleCensusProof = assertMerkleCensusProof;
|
|
3061
3299
|
exports.createProcessSignatureMessage = createProcessSignatureMessage;
|
|
3062
|
-
exports.deployedAddresses = deployedAddresses;
|
|
3063
3300
|
exports.getElectionMetadataTemplate = getElectionMetadataTemplate;
|
|
3064
|
-
exports.getEnvironmentChain = getEnvironmentChain;
|
|
3065
|
-
exports.getEnvironmentConfig = getEnvironmentConfig;
|
|
3066
|
-
exports.getEnvironmentUrls = getEnvironmentUrls;
|
|
3067
3301
|
exports.isCSPCensusProof = isCSPCensusProof;
|
|
3068
3302
|
exports.isMerkleCensusProof = isMerkleCensusProof;
|
|
3069
|
-
exports.resolveConfiguration = resolveConfiguration;
|
|
3070
|
-
exports.resolveUrls = resolveUrls;
|
|
3071
3303
|
exports.signProcessCreation = signProcessCreation;
|
|
3072
3304
|
exports.validateProcessId = validateProcessId;
|
|
3073
3305
|
//# sourceMappingURL=index.js.map
|