@vocdoni/davinci-sdk 0.1.0 → 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 CHANGED
@@ -256,6 +256,55 @@ const process = await sdk.createProcess({
256
256
  });
257
257
  ```
258
258
 
259
+ #### OnchainCensus - Token-Based Voting
260
+
261
+ Use existing on-chain token contracts (ERC20, ERC721) for voting eligibility. Perfect for DAO governance where voting power comes from token holdings.
262
+
263
+ ```typescript
264
+ import { OnchainCensus } from '@vocdoni/davinci-sdk';
265
+
266
+ // Create census from token contract address with subgraph URI
267
+ const census = new OnchainCensus(
268
+ "0x1234567890123456789012345678901234567890", // Token contract address
269
+ "https://api.studio.thegraph.com/query/12345/token-holders/v1.0.0" // Subgraph endpoint
270
+ );
271
+
272
+ const process = await sdk.createProcess({
273
+ census: census,
274
+ maxVoters: 10000, // Required for onchain census
275
+ // ... rest of config
276
+ });
277
+ ```
278
+
279
+ **Key Features:**
280
+ - **No Publishing Required**: Uses existing on-chain data, no need to publish
281
+ - **Automatic Validation**: Contract address and URI validated on construction
282
+ - **Token Agnostic**: Works with any ERC20 or ERC721 contract
283
+ - **DAO Ready**: Perfect for token-based governance systems
284
+ - **Subgraph Integration**: URI should point to a subgraph or API endpoint for census data
285
+
286
+ **Technical Details:**
287
+ - `censusRoot` automatically set to 32-byte zero value (`0x0000...000`)
288
+ - `contractAddress` properly passed to smart contracts
289
+ - `uri` parameter is **required** and should point to a data source (e.g., subgraph)
290
+ - Census is immediately ready for process creation
291
+
292
+ **Example with different subgraph providers:**
293
+
294
+ ```typescript
295
+ // The Graph Studio
296
+ const census = new OnchainCensus(
297
+ "0xTokenAddress...",
298
+ "https://api.studio.thegraph.com/query/12345/my-token/v1.0.0"
299
+ );
300
+
301
+ // Custom subgraph deployment
302
+ const census = new OnchainCensus(
303
+ "0xTokenAddress...",
304
+ "https://subgraph.example.com/api/token-holders"
305
+ );
306
+ ```
307
+
259
308
  ### Auto-Publishing Feature
260
309
 
261
310
  The SDK automatically publishes unpublished censuses when creating a process:
@@ -390,7 +390,19 @@ interface BallotMode {
390
390
  interface CensusData {
391
391
  censusOrigin: CensusOrigin;
392
392
  censusRoot: string;
393
+ /**
394
+ * Contract address for onchain censuses (ERC20/ERC721 token contract).
395
+ * For offchain censuses, defaults to zero address.
396
+ * @default "0x0000000000000000000000000000000000000000"
397
+ */
398
+ contractAddress?: string;
393
399
  censusURI: string;
400
+ /**
401
+ * For onchain censuses, allows any valid Merkle root from the onchain source.
402
+ * For other census types, set to false to require the specific censusRoot.
403
+ * @default false
404
+ */
405
+ onchainAllowAnyValidRoot?: boolean;
394
406
  }
395
407
  interface EncryptionKey {
396
408
  x: string;
package/dist/index.d.ts CHANGED
@@ -402,9 +402,9 @@ declare class OnchainCensus extends Census {
402
402
  /**
403
403
  * Creates an OnchainCensus
404
404
  * @param contractAddress - The address of the smart contract (e.g., ERC20, ERC721)
405
- * @param uri - Optional URI with census information
405
+ * @param uri - The URI pointing to census data source (e.g., subgraph endpoint)
406
406
  */
407
- constructor(contractAddress: string, uri?: string);
407
+ constructor(contractAddress: string, uri: string);
408
408
  get contractAddress(): string;
409
409
  }
410
410
 
@@ -453,6 +453,7 @@ declare class CensusOrchestrator {
453
453
  type: CensusOrigin;
454
454
  root: string;
455
455
  uri: string;
456
+ contractAddress?: string;
456
457
  };
457
458
  }
458
459
 
@@ -469,7 +470,19 @@ interface BallotMode {
469
470
  interface CensusData {
470
471
  censusOrigin: CensusOrigin;
471
472
  censusRoot: string;
473
+ /**
474
+ * Contract address for onchain censuses (ERC20/ERC721 token contract).
475
+ * For offchain censuses, defaults to zero address.
476
+ * @default "0x0000000000000000000000000000000000000000"
477
+ */
478
+ contractAddress?: string;
472
479
  censusURI: string;
480
+ /**
481
+ * For onchain censuses, allows any valid Merkle root from the onchain source.
482
+ * For other census types, set to false to require the specific censusRoot.
483
+ * @default false
484
+ */
485
+ onchainAllowAnyValidRoot?: boolean;
473
486
  }
474
487
  interface EncryptionKey {
475
488
  x: string;
package/dist/index.js CHANGED
@@ -386,16 +386,19 @@ class OnchainCensus extends Census {
386
386
  /**
387
387
  * Creates an OnchainCensus
388
388
  * @param contractAddress - The address of the smart contract (e.g., ERC20, ERC721)
389
- * @param uri - Optional URI with census information
389
+ * @param uri - The URI pointing to census data source (e.g., subgraph endpoint)
390
390
  */
391
391
  constructor(contractAddress, uri) {
392
392
  super(CensusOrigin.Onchain);
393
393
  if (!/^(0x)?[0-9a-fA-F]{40}$/i.test(contractAddress)) {
394
394
  throw new Error("Contract address is missing or invalid");
395
395
  }
396
+ if (!uri || uri.trim() === "") {
397
+ throw new Error("URI is required for onchain census");
398
+ }
396
399
  this._contractAddress = contractAddress;
397
- this._censusRoot = contractAddress;
398
- this._censusURI = uri || `contract://${contractAddress}`;
400
+ this._censusRoot = "0x0000000000000000000000000000000000000000000000000000000000000000";
401
+ this._censusURI = uri;
399
402
  }
400
403
  get contractAddress() {
401
404
  return this._contractAddress;
@@ -475,10 +478,12 @@ class CensusOrchestrator {
475
478
  if (!census.censusRoot || !census.censusURI) {
476
479
  throw new Error("Census data is incomplete");
477
480
  }
481
+ const contractAddress = "contractAddress" in census ? census.contractAddress : void 0;
478
482
  return {
479
483
  type: census.censusOrigin,
480
484
  root: census.censusRoot,
481
- uri: census.censusURI
485
+ uri: census.censusURI,
486
+ contractAddress
482
487
  };
483
488
  }
484
489
  }
@@ -1002,7 +1007,9 @@ class ProcessRegistryService extends SmartContractService {
1002
1007
  const contractCensus = {
1003
1008
  censusOrigin: BigInt(census.censusOrigin),
1004
1009
  censusRoot: census.censusRoot,
1005
- censusURI: census.censusURI
1010
+ contractAddress: census.contractAddress ?? "0x0000000000000000000000000000000000000000",
1011
+ censusURI: census.censusURI,
1012
+ onchainAllowAnyValidRoot: census.onchainAllowAnyValidRoot ?? false
1006
1013
  };
1007
1014
  return this.sendTx(
1008
1015
  this.contract.newProcess(
@@ -1033,7 +1040,9 @@ class ProcessRegistryService extends SmartContractService {
1033
1040
  const contractCensus = {
1034
1041
  censusOrigin: BigInt(census.censusOrigin),
1035
1042
  censusRoot: census.censusRoot,
1036
- censusURI: census.censusURI
1043
+ contractAddress: census.contractAddress ?? "0x0000000000000000000000000000000000000000",
1044
+ censusURI: census.censusURI,
1045
+ onchainAllowAnyValidRoot: census.onchainAllowAnyValidRoot ?? false
1037
1046
  };
1038
1047
  return this.sendTx(
1039
1048
  this.contract.setProcessCensus(processID, contractCensus).catch((e) => {
@@ -1165,12 +1174,7 @@ class ProcessOrchestrationService {
1165
1174
  }
1166
1175
  await this.censusOrchestrator.publish(census);
1167
1176
  }
1168
- const censusData = this.censusOrchestrator.getCensusData(census);
1169
- return {
1170
- type: censusData.type,
1171
- root: censusData.root,
1172
- uri: censusData.uri
1173
- };
1177
+ return this.censusOrchestrator.getCensusData(census);
1174
1178
  }
1175
1179
  const { size, ...censusWithoutSize } = census;
1176
1180
  return censusWithoutSize;
@@ -1400,7 +1404,12 @@ class ProcessOrchestrationService {
1400
1404
  const census = {
1401
1405
  censusOrigin: censusConfig.type,
1402
1406
  censusRoot,
1403
- censusURI: censusConfig.uri
1407
+ contractAddress: censusConfig.contractAddress,
1408
+ // Only set for onchain censuses
1409
+ censusURI: censusConfig.uri,
1410
+ // For onchain censuses (ERC20 token snapshots), allow any valid merkle root
1411
+ // For other census types, require the specific censusRoot
1412
+ onchainAllowAnyValidRoot: censusConfig.type === CensusOrigin.Onchain
1404
1413
  };
1405
1414
  return {
1406
1415
  processId,