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