@bitcoinunlimited/votepeerjs

VotePeer (voter.cash) javascript library. Blockchain protocol for on-chain voting with Bitcoin Cash.

Usage no npm install needed!

<script type="module">
  import bitcoinunlimitedVotepeerjs from 'https://cdn.skypack.dev/@bitcoinunlimited/votepeerjs';
</script>

README

votepeerjs - VotePeer Javascript Library

Notable features

Transparent Voting

A Bitcoin Cash smart contract and protocol for transparent on-chain voting.

"Two option vote" is a minimalistic and transparent voting protocol on top of Bitcoin Cash and similar blockchains. Participating, verifying and tallying does not require a full node, but is fully SPV client compatible. Votes are non-transferable.

This repository hosts the protocol/smart contract specification and a reference implementation in javascript.

Example

import {
  TwoOptionVote, TwoOptionVoteContract, tallyVotes, Blockchain,
  DEFAULT_CAST_TX_FEE, createSalt, derivePublicKey, getPublicKeyHash,
  generatePrivateKey, DEFAULT_DUST_THRESHOLD
} from 'two-option-vote';
const sleep = require('sleep');

// Initialize participants.
const alice = generatePrivateKey();
const bob = generatePrivateKey();

// Initialize an election
const votersPKH = [
  await getPublicKeyHash(await derivePublicKey(alice)),
  await getPublicKeyHash(await derivePublicKey(bob)),
];

const election: TwoOptionVote = {
  network: 'mainnet',
  salt: createSalt(),
  description: 'Pizza for lunch?',
  optionA: 'Yes',
  optionB: 'No',
  endHeight: 1_000_000,
  votersPKH,
};

// Setup contracts
const aliceContract = await TwoOptionVoteContract.make(election, alice);
const bobContract = await TwoOptionVoteContract.make(election, bob);

for (const contract of [aliceContract, bobContract]) {
  await contract.waitForBalance(DEFAULT_CAST_TX_FEE + DEFAULT_DUST_THRESHOLD, () => {
    console.log(`Too low balance in contract ${contract.getContractAddress()}`);
  });
}
const electrum = new Blockchain();
await electrum.connect();

// Alice casts vote for option A ("Yes") and bob for B ("No")
const aliceTxID = await aliceContract.castVote(await aliceContract.optionAHash());
const bobTxID = await bobContract.castVote(await bobContract.optionBHash());

console.log(`Alice voted in tx ${aliceTxID}`);
console.log(`Bob voted in tx ${bobTxID}`);

// Tally votes on election
sleep.sleep(5); // Wait for transactions to propagate before tallying.

const includeUnconfirmed = true;
const tally = await tallyVotes(electrum, election, includeUnconfirmed);
console.log(`Results: ${JSON.stringify(tally, null, 4)}`);

See this and more examples in the examples directory.

Developers

Tests vectors

See files with *.test.ts suffix.

Build project

npm run build
npm run test

Run the above example: node build/examples/readme-example.js

Building Fujisaki Ring signature dependency

For building the fujisaki ring signature dependency, you'll need to install wasm-pack and Rust.

When these dependencies are installed, run:

npm run build-ringsig

To use your new build, rm -rf node_modules/fujisaki-ringsig-wasm && npm install.

Other implementations

Contact

Join the Telegram channel