Make sure you have Node.js 12 installed on your computer.
In an empty folder, create a package.json
file by running
$ npm init -yWrote to /home/user/dev/governance-as-a-service/package.json:{"name": "governance-as-a-service","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \\\\"Error: no test specified\\\\" && exit 1"},"keywords": [],"author": "","license": "ISC"}
Next, install the DVoteJS dependency and two dev dependencies to support TypeScript:
$ npm i dvote-js$ npm i -D typescript ts-node
Edit the scripts
section of package.json
and leave it like this:
"scripts": {"main": "ts-node index.ts"},
Then, let's create a file named index.ts
and create a function to generate the wallet of our new entity:
import { Wallet } from "ethers"function makeEntityWallet() {console.log("Creating entity wallet")const entityWallet = Wallet.createRandom()console.log("Entity address:", entityWallet.address)console.log("Entity private key:", entityWallet.privateKey)}makeEntityWallet()
To check that it works, let's run npm run main
:
$ npm run mainCreating entity walletEntity address: 0x1048d8cB20fE806389802ba48E2647dc85aB779aEntity private key: 0x6d88d78a4a76e42144b6867fdff89477f0a3b805d85b97cd46387a2f770f91f1
So here's our wallet, what's next?
In this example, we will be using an Ethereum testnet called Sokol. Write down your private key and and use the address to request some test coins from the faucet. You will need them to send some transactions.
Now, instead of creating a random wallet, we should use the one that received the test ether. In the lines above, replace this:
const entityWallet = Wallet.createRandom()
Into this:
// Use your private key hereconst entityWallet = new Wallet("0x6d88d78a4a76e42144b6867fdff89477f0a3b805d85b97cd46387a2f770f91f1")
Obviously, make sure to store any real private key nowhere within the source code or Git in general.
Now we need to get a pool of gateways and connect to one of them:
import { GatewayPool } from "dvote-js/dist/net/gateway-pool"let pool: GatewayPoolasync function connect() {// Get a pool of gateways to connect to the networkpool = await GatewayPool.discover({ networkId: NETWORK_ID, bootnodesContentUri: GATEWAY_BOOTNODE_URI })await pool.connect()}const disconnect = () => pool.disconnect()
Then, let's define the metadata of our Entity and make it available on IPFS and Ethereum. Add the following code to index.ts
:
import { EntityMetadata } from "dvote-js"import { updateEntity } from "dvote-js/dist/api/entity"async function registerEntity() {// Make a copy of the metadata template and customize itconst entityMetadata: EntityMetadata = Object.assign({}, Models.Entity.EntityMetadataTemplate)entityMetadata.name.default = "Vilafourier"entityMetadata.description.default = "Official communication and participation channel of the city council"entityMetadata.media = {avatar: 'https://my-organization.org/logo.png',header: 'https://my-organization.org/header.jpeg'}entityMetadata.actions = []const contentUri = await updateEntity(entityWallet.address, entityMetadata, entityWallet, pool)// Show stored valuesconsole.log("The entity has been defined")console.log(contentUri)}
And then:
$ npm run mainSetting the entity metadataWARNING: Multiple definitions for addrWARNING: Multiple definitions for setAddrThe entity has been definedipfs://QmdK5TnHDXPt4xozkuboyKP94RTrUxFr1z9Pkv5qhfahFG
Done!
This is what we just did:
We created JSON metadata containing the custom details of our entity
We pinned the JSON content on IPFS using a gateway from the pool
The hash of our metadata is QmdK5TnHDXPt4xozkuboyKP94RTrUxFr1z9Pkv5qhfahFG
and should be available from any IPFS peer
An Ethereum transaction was sent to the entities contract, defining the pointer to our new metadata.
The value on the smart contract can only be updated by our wallet, the blockchain ensures the integrity of our data and IPFS ensures its global availability.
Visualizer
To check that our entity is properly declared, we can check it on the visualizer: https://app.dev.vocdoni.net/entities/#/<entity-id>
This is the link in our case.
Note: Keep in mind that we're using a testnet and some of the data might be eventually disposed.