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