@vocdoni/davinci-sdk 0.0.7 → 0.1.1
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 +97 -28
- package/dist/contracts.d.ts +12 -0
- package/dist/index.d.ts +91 -88
- package/dist/index.js +142 -154
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -152
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +142 -154
- package/dist/sequencer.d.ts +12 -0
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -218,34 +218,12 @@ function assertCSPCensusProof(proof) {
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
var CensusType = /* @__PURE__ */ ((CensusType2) => {
|
|
222
|
-
CensusType2["PLAIN"] = "plain";
|
|
223
|
-
CensusType2["WEIGHTED"] = "weighted";
|
|
224
|
-
CensusType2["CSP"] = "csp";
|
|
225
|
-
return CensusType2;
|
|
226
|
-
})(CensusType || {});
|
|
227
221
|
class Census {
|
|
228
|
-
constructor(
|
|
222
|
+
constructor(censusOrigin) {
|
|
229
223
|
this._censusId = null;
|
|
230
224
|
this._censusRoot = null;
|
|
231
225
|
this._censusURI = null;
|
|
232
|
-
this.
|
|
233
|
-
this._type = type;
|
|
234
|
-
if (censusOrigin !== void 0) {
|
|
235
|
-
this._censusOrigin = censusOrigin;
|
|
236
|
-
} else {
|
|
237
|
-
switch (type) {
|
|
238
|
-
case "plain" /* PLAIN */:
|
|
239
|
-
case "weighted" /* WEIGHTED */:
|
|
240
|
-
this._censusOrigin = CensusOrigin.OffchainStatic;
|
|
241
|
-
break;
|
|
242
|
-
case "csp" /* CSP */:
|
|
243
|
-
this._censusOrigin = CensusOrigin.CSP;
|
|
244
|
-
break;
|
|
245
|
-
default:
|
|
246
|
-
throw new Error(`Unknown census type: ${type}`);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
226
|
+
this._censusOrigin = censusOrigin;
|
|
249
227
|
}
|
|
250
228
|
get censusId() {
|
|
251
229
|
return this._censusId;
|
|
@@ -256,12 +234,6 @@ class Census {
|
|
|
256
234
|
get censusURI() {
|
|
257
235
|
return this._censusURI;
|
|
258
236
|
}
|
|
259
|
-
get type() {
|
|
260
|
-
return this._type;
|
|
261
|
-
}
|
|
262
|
-
get size() {
|
|
263
|
-
return this._size;
|
|
264
|
-
}
|
|
265
237
|
get isPublished() {
|
|
266
238
|
return this._censusRoot !== null && this._censusURI !== null;
|
|
267
239
|
}
|
|
@@ -271,91 +243,41 @@ class Census {
|
|
|
271
243
|
get censusOrigin() {
|
|
272
244
|
return this._censusOrigin;
|
|
273
245
|
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
class PlainCensus extends Census {
|
|
277
|
-
/**
|
|
278
|
-
* Creates a new PlainCensus
|
|
279
|
-
* @param censusOrigin - The census origin (defaults to OffchainStatic for backward compatibility)
|
|
280
|
-
*/
|
|
281
|
-
constructor(censusOrigin) {
|
|
282
|
-
super(CensusType.PLAIN, censusOrigin);
|
|
283
|
-
this._participants = /* @__PURE__ */ new Set();
|
|
284
|
-
}
|
|
285
246
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
247
|
+
* Check if this census requires publishing via the Census API
|
|
248
|
+
* Merkle censuses (OffchainStatic, OffchainDynamic) need to be published
|
|
249
|
+
* Onchain and CSP censuses are ready immediately upon construction
|
|
288
250
|
*/
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
for (const address of toAdd) {
|
|
292
|
-
this.validateAddress(address);
|
|
293
|
-
this._participants.add(address.toLowerCase());
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Remove participant by address
|
|
298
|
-
*/
|
|
299
|
-
remove(address) {
|
|
300
|
-
this._participants.delete(address.toLowerCase());
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Get all participants as CensusParticipant array (for API)
|
|
304
|
-
* All participants have weight="1"
|
|
305
|
-
*/
|
|
306
|
-
get participants() {
|
|
307
|
-
return Array.from(this._participants).map((key) => ({
|
|
308
|
-
key,
|
|
309
|
-
weight: "1"
|
|
310
|
-
// Everyone has weight=1 in plain census
|
|
311
|
-
}));
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Get addresses only
|
|
315
|
-
*/
|
|
316
|
-
get addresses() {
|
|
317
|
-
return Array.from(this._participants);
|
|
318
|
-
}
|
|
319
|
-
validateAddress(address) {
|
|
320
|
-
if (!address || typeof address !== "string") {
|
|
321
|
-
throw new Error("Address is required and must be a string");
|
|
322
|
-
}
|
|
323
|
-
if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(address)) {
|
|
324
|
-
throw new Error(`Invalid Ethereum address format: ${address}`);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Internal method called after publishing
|
|
329
|
-
* @internal
|
|
330
|
-
*/
|
|
331
|
-
_setPublishedData(root, uri, size, censusId) {
|
|
332
|
-
this._censusRoot = root;
|
|
333
|
-
this._censusURI = uri;
|
|
334
|
-
this._size = size;
|
|
335
|
-
if (censusId) this._censusId = censusId;
|
|
251
|
+
get requiresPublishing() {
|
|
252
|
+
return this._censusOrigin === CensusOrigin.OffchainStatic || this._censusOrigin === CensusOrigin.OffchainDynamic;
|
|
336
253
|
}
|
|
337
254
|
}
|
|
338
255
|
|
|
339
|
-
class
|
|
340
|
-
/**
|
|
341
|
-
* Creates a new WeightedCensus
|
|
342
|
-
* @param censusOrigin - The census origin (defaults to OffchainStatic for backward compatibility)
|
|
343
|
-
*/
|
|
256
|
+
class MerkleCensus extends Census {
|
|
344
257
|
constructor(censusOrigin) {
|
|
345
|
-
super(
|
|
258
|
+
super(censusOrigin);
|
|
346
259
|
this._participants = /* @__PURE__ */ new Map();
|
|
347
260
|
}
|
|
348
261
|
/**
|
|
349
|
-
* Add participant(s)
|
|
350
|
-
*
|
|
351
|
-
*
|
|
262
|
+
* Add participant(s) - supports both plain addresses and weighted participants
|
|
263
|
+
* @param data - Can be:
|
|
264
|
+
* - string: single address (weight=1)
|
|
265
|
+
* - string[]: array of addresses (weight=1 for all)
|
|
266
|
+
* - {key: string, weight: string|number|bigint}: single weighted participant
|
|
267
|
+
* - Array of weighted participants
|
|
352
268
|
*/
|
|
353
|
-
add(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
269
|
+
add(data) {
|
|
270
|
+
if (typeof data === "string") {
|
|
271
|
+
this.addAddress(data, "1");
|
|
272
|
+
} else if (Array.isArray(data)) {
|
|
273
|
+
if (data.length === 0) return;
|
|
274
|
+
if (typeof data[0] === "string") {
|
|
275
|
+
data.forEach((addr) => this.addAddress(addr, "1"));
|
|
276
|
+
} else {
|
|
277
|
+
data.forEach((p) => this.addParticipant(p));
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
this.addParticipant(data);
|
|
359
281
|
}
|
|
360
282
|
}
|
|
361
283
|
/**
|
|
@@ -385,6 +307,21 @@ class WeightedCensus extends Census {
|
|
|
385
307
|
getWeight(address) {
|
|
386
308
|
return this._participants.get(address.toLowerCase());
|
|
387
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Internal method to add a plain address with a given weight
|
|
312
|
+
*/
|
|
313
|
+
addAddress(address, weight) {
|
|
314
|
+
this.validateAddress(address);
|
|
315
|
+
this._participants.set(address.toLowerCase(), weight);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Internal method to add a weighted participant
|
|
319
|
+
*/
|
|
320
|
+
addParticipant(participant) {
|
|
321
|
+
this.validateAddress(participant.key);
|
|
322
|
+
const weight = this.normalizeWeight(participant.weight);
|
|
323
|
+
this._participants.set(participant.key.toLowerCase(), weight);
|
|
324
|
+
}
|
|
388
325
|
/**
|
|
389
326
|
* Normalizes weight from string, number, or bigint to string
|
|
390
327
|
*/
|
|
@@ -409,32 +346,66 @@ class WeightedCensus extends Census {
|
|
|
409
346
|
}
|
|
410
347
|
throw new Error(`Invalid weight type. Must be string, number, or bigint.`);
|
|
411
348
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (
|
|
417
|
-
throw new Error(
|
|
349
|
+
/**
|
|
350
|
+
* Validates Ethereum address format
|
|
351
|
+
*/
|
|
352
|
+
validateAddress(address) {
|
|
353
|
+
if (!address || typeof address !== "string") {
|
|
354
|
+
throw new Error("Address is required and must be a string");
|
|
418
355
|
}
|
|
419
|
-
if (
|
|
420
|
-
throw new Error(
|
|
356
|
+
if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(address)) {
|
|
357
|
+
throw new Error(`Invalid Ethereum address format: ${address}`);
|
|
421
358
|
}
|
|
422
359
|
}
|
|
423
360
|
/**
|
|
424
361
|
* Internal method called after publishing
|
|
425
362
|
* @internal
|
|
426
363
|
*/
|
|
427
|
-
_setPublishedData(root, uri,
|
|
364
|
+
_setPublishedData(root, uri, censusId) {
|
|
428
365
|
this._censusRoot = root;
|
|
429
366
|
this._censusURI = uri;
|
|
430
|
-
this._size = size;
|
|
431
367
|
if (censusId) this._censusId = censusId;
|
|
432
368
|
}
|
|
433
369
|
}
|
|
434
370
|
|
|
371
|
+
class OffchainCensus extends MerkleCensus {
|
|
372
|
+
constructor() {
|
|
373
|
+
super(CensusOrigin.OffchainStatic);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
class OffchainDynamicCensus extends MerkleCensus {
|
|
378
|
+
constructor() {
|
|
379
|
+
super(CensusOrigin.OffchainDynamic);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
class OnchainCensus extends Census {
|
|
384
|
+
/**
|
|
385
|
+
* Creates an OnchainCensus
|
|
386
|
+
* @param contractAddress - The address of the smart contract (e.g., ERC20, ERC721)
|
|
387
|
+
* @param uri - The URI pointing to census data source (e.g., subgraph endpoint)
|
|
388
|
+
*/
|
|
389
|
+
constructor(contractAddress, uri) {
|
|
390
|
+
super(CensusOrigin.Onchain);
|
|
391
|
+
if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(contractAddress)) {
|
|
392
|
+
throw new Error("Contract address is missing or invalid");
|
|
393
|
+
}
|
|
394
|
+
if (!uri || uri.trim() === "") {
|
|
395
|
+
throw new Error("URI is required for onchain census");
|
|
396
|
+
}
|
|
397
|
+
this._contractAddress = contractAddress;
|
|
398
|
+
this._censusRoot = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
399
|
+
this._censusURI = uri;
|
|
400
|
+
}
|
|
401
|
+
get contractAddress() {
|
|
402
|
+
return this._contractAddress;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
435
406
|
class CspCensus extends Census {
|
|
436
|
-
constructor(publicKey, cspURI
|
|
437
|
-
super(
|
|
407
|
+
constructor(publicKey, cspURI) {
|
|
408
|
+
super(CensusOrigin.CSP);
|
|
438
409
|
if (!/^(0x)?[0-9a-fA-F]+$/.test(publicKey)) {
|
|
439
410
|
throw new Error("Public key is missing or invalid");
|
|
440
411
|
}
|
|
@@ -447,7 +418,6 @@ class CspCensus extends Census {
|
|
|
447
418
|
this._cspURI = cspURI;
|
|
448
419
|
this._censusRoot = publicKey;
|
|
449
420
|
this._censusURI = cspURI;
|
|
450
|
-
this._size = size;
|
|
451
421
|
}
|
|
452
422
|
get publicKey() {
|
|
453
423
|
return this._publicKey;
|
|
@@ -460,17 +430,14 @@ class CspCensus extends Census {
|
|
|
460
430
|
class PublishedCensus extends Census {
|
|
461
431
|
/**
|
|
462
432
|
* Creates a PublishedCensus from existing census data
|
|
463
|
-
* @param
|
|
433
|
+
* @param censusOrigin - The census origin (OffchainStatic, OffchainDynamic, Onchain, or CSP)
|
|
464
434
|
* @param root - The census root
|
|
465
435
|
* @param uri - The census URI
|
|
466
|
-
* @param size - The census size (number of participants)
|
|
467
|
-
* @param censusOrigin - The census origin (optional - defaults based on type if not provided)
|
|
468
436
|
*/
|
|
469
|
-
constructor(
|
|
470
|
-
super(
|
|
437
|
+
constructor(censusOrigin, root, uri) {
|
|
438
|
+
super(censusOrigin);
|
|
471
439
|
this._censusRoot = root;
|
|
472
440
|
this._censusURI = uri;
|
|
473
|
-
this._size = size;
|
|
474
441
|
}
|
|
475
442
|
}
|
|
476
443
|
|
|
@@ -479,7 +446,7 @@ class CensusOrchestrator {
|
|
|
479
446
|
this.censusService = censusService;
|
|
480
447
|
}
|
|
481
448
|
/**
|
|
482
|
-
* Publishes a
|
|
449
|
+
* Publishes a MerkleCensus (OffchainCensus, OffchainDynamicCensus, or OnchainCensus)
|
|
483
450
|
* Creates a working census, adds participants, and publishes it
|
|
484
451
|
*/
|
|
485
452
|
async publish(census) {
|
|
@@ -495,23 +462,26 @@ class CensusOrchestrator {
|
|
|
495
462
|
census._setPublishedData(
|
|
496
463
|
publishResponse.root,
|
|
497
464
|
publishResponse.uri,
|
|
498
|
-
publishResponse.participantCount,
|
|
499
465
|
censusId
|
|
500
466
|
);
|
|
501
467
|
}
|
|
502
468
|
/**
|
|
503
469
|
* Gets census data for process creation
|
|
504
|
-
* Throws if census is not published
|
|
470
|
+
* Throws if census is not ready (published for Merkle/CSP, or constructed for Onchain)
|
|
505
471
|
*/
|
|
506
472
|
getCensusData(census) {
|
|
507
|
-
if (!census.isPublished) {
|
|
508
|
-
throw new Error("
|
|
473
|
+
if (census.requiresPublishing && !census.isPublished) {
|
|
474
|
+
throw new Error("Merkle census must be published before creating a process");
|
|
509
475
|
}
|
|
476
|
+
if (!census.censusRoot || !census.censusURI) {
|
|
477
|
+
throw new Error("Census data is incomplete");
|
|
478
|
+
}
|
|
479
|
+
const contractAddress = "contractAddress" in census ? census.contractAddress : void 0;
|
|
510
480
|
return {
|
|
511
481
|
type: census.censusOrigin,
|
|
512
482
|
root: census.censusRoot,
|
|
513
483
|
uri: census.censusURI,
|
|
514
|
-
|
|
484
|
+
contractAddress
|
|
515
485
|
};
|
|
516
486
|
}
|
|
517
487
|
}
|
|
@@ -1035,7 +1005,9 @@ class ProcessRegistryService extends SmartContractService {
|
|
|
1035
1005
|
const contractCensus = {
|
|
1036
1006
|
censusOrigin: BigInt(census.censusOrigin),
|
|
1037
1007
|
censusRoot: census.censusRoot,
|
|
1038
|
-
|
|
1008
|
+
contractAddress: census.contractAddress ?? "0x0000000000000000000000000000000000000000",
|
|
1009
|
+
censusURI: census.censusURI,
|
|
1010
|
+
onchainAllowAnyValidRoot: census.onchainAllowAnyValidRoot ?? false
|
|
1039
1011
|
};
|
|
1040
1012
|
return this.sendTx(
|
|
1041
1013
|
this.contract.newProcess(
|
|
@@ -1066,7 +1038,9 @@ class ProcessRegistryService extends SmartContractService {
|
|
|
1066
1038
|
const contractCensus = {
|
|
1067
1039
|
censusOrigin: BigInt(census.censusOrigin),
|
|
1068
1040
|
censusRoot: census.censusRoot,
|
|
1069
|
-
|
|
1041
|
+
contractAddress: census.contractAddress ?? "0x0000000000000000000000000000000000000000",
|
|
1042
|
+
censusURI: census.censusURI,
|
|
1043
|
+
onchainAllowAnyValidRoot: census.onchainAllowAnyValidRoot ?? false
|
|
1070
1044
|
};
|
|
1071
1045
|
return this.sendTx(
|
|
1072
1046
|
this.contract.setProcessCensus(processID, contractCensus).catch((e) => {
|
|
@@ -1189,26 +1163,19 @@ class ProcessOrchestrationService {
|
|
|
1189
1163
|
*/
|
|
1190
1164
|
async handleCensus(census) {
|
|
1191
1165
|
if ("isPublished" in census) {
|
|
1192
|
-
if (census
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
);
|
|
1199
|
-
}
|
|
1200
|
-
await this.censusOrchestrator.publish(census);
|
|
1166
|
+
if (census.requiresPublishing && !census.isPublished) {
|
|
1167
|
+
const censusBaseURL = this.apiService.census?.["axios"]?.defaults?.baseURL;
|
|
1168
|
+
if (!censusBaseURL || censusBaseURL === "" || censusBaseURL === "undefined") {
|
|
1169
|
+
throw new Error(
|
|
1170
|
+
'Census API URL is required to publish Merkle censuses (OffchainCensus, OffchainDynamicCensus). Please provide "censusUrl" when initializing DavinciSDK, or use a pre-published census.'
|
|
1171
|
+
);
|
|
1201
1172
|
}
|
|
1173
|
+
await this.censusOrchestrator.publish(census);
|
|
1202
1174
|
}
|
|
1203
|
-
|
|
1204
|
-
return {
|
|
1205
|
-
type: censusData.type,
|
|
1206
|
-
root: censusData.root,
|
|
1207
|
-
size: censusData.size,
|
|
1208
|
-
uri: censusData.uri
|
|
1209
|
-
};
|
|
1175
|
+
return this.censusOrchestrator.getCensusData(census);
|
|
1210
1176
|
}
|
|
1211
|
-
|
|
1177
|
+
const { size, ...censusWithoutSize } = census;
|
|
1178
|
+
return censusWithoutSize;
|
|
1212
1179
|
}
|
|
1213
1180
|
/**
|
|
1214
1181
|
* Gets user-friendly process information by transforming raw contract data
|
|
@@ -1416,11 +1383,31 @@ class ProcessOrchestrationService {
|
|
|
1416
1383
|
ballotMode,
|
|
1417
1384
|
signature
|
|
1418
1385
|
});
|
|
1419
|
-
|
|
1386
|
+
let maxVoters;
|
|
1387
|
+
if (config.maxVoters !== void 0) {
|
|
1388
|
+
maxVoters = config.maxVoters;
|
|
1389
|
+
} else if ("isPublished" in config.census && config.census.isPublished) {
|
|
1390
|
+
if ("participants" in config.census) {
|
|
1391
|
+
maxVoters = config.census.participants.length;
|
|
1392
|
+
} else {
|
|
1393
|
+
throw new Error(
|
|
1394
|
+
"maxVoters is required when using OnchainCensus, CspCensus, or PublishedCensus. It can only be auto-calculated for published MerkleCensus (OffchainCensus/OffchainDynamicCensus)."
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
} else {
|
|
1398
|
+
throw new Error(
|
|
1399
|
+
"maxVoters is required. It can only be omitted when using a published MerkleCensus (OffchainCensus/OffchainDynamicCensus), in which case it defaults to the participant count."
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1420
1402
|
const census = {
|
|
1421
1403
|
censusOrigin: censusConfig.type,
|
|
1422
1404
|
censusRoot,
|
|
1423
|
-
|
|
1405
|
+
contractAddress: censusConfig.contractAddress,
|
|
1406
|
+
// Only set for onchain censuses
|
|
1407
|
+
censusURI: censusConfig.uri,
|
|
1408
|
+
// For onchain censuses (ERC20 token snapshots), allow any valid merkle root
|
|
1409
|
+
// For other census types, require the specific censusRoot
|
|
1410
|
+
onchainAllowAnyValidRoot: censusConfig.type === CensusOrigin.Onchain
|
|
1424
1411
|
};
|
|
1425
1412
|
return {
|
|
1426
1413
|
processId,
|
|
@@ -3540,5 +3527,5 @@ class DavinciSDK {
|
|
|
3540
3527
|
}
|
|
3541
3528
|
}
|
|
3542
3529
|
|
|
3543
|
-
export { BaseService, Census, CensusNotUpdatable, CensusOrchestrator, CensusOrigin,
|
|
3530
|
+
export { BaseService, Census, CensusNotUpdatable, CensusOrchestrator, CensusOrigin, CircomProof, ContractServiceError, CspCensus, DavinciCrypto, DavinciSDK, ElectionMetadataTemplate, ElectionResultsTypeNames, MerkleCensus, OffchainCensus, OffchainDynamicCensus, OnchainCensus, OrganizationAdministratorError, OrganizationCreateError, OrganizationDeleteError, OrganizationRegistryService, OrganizationUpdateError, ProcessCensusError, ProcessCreateError, ProcessDurationError, ProcessOrchestrationService, ProcessRegistryService, ProcessResultError, ProcessStateTransitionError, ProcessStatus, ProcessStatusError, PublishedCensus, SmartContractService, TxStatus, VocdoniApiService, VocdoniCensusService, VocdoniSequencerService, VoteOrchestrationService, VoteStatus, assertCSPCensusProof, assertMerkleCensusProof, createProcessSignatureMessage, getElectionMetadataTemplate, isCSPCensusProof, isMerkleCensusProof, signProcessCreation, validateProcessId };
|
|
3544
3531
|
//# sourceMappingURL=index.mjs.map
|