Skip to main content

Quickstart

Prerequisites

  • Node.js 18+ (web SDK)
  • Go 1.22+ (runtime / ABCI node)
  • No Docker required for local single-node dev — see below.

1. Start a local node

shyvoting-abci --addr :26658 --db-path /tmp/shyware-dev --identity-mode wallet &
cometbft init --home ~/.shyware-dev
cometbft start --home ~/.shyware-dev --proxy_app tcp://127.0.0.1:26658
shyvoting-api --cometbft-rpc http://127.0.0.1:26657 --port 8080

--identity-mode wallet needs no external IDV service — the identity commitment is an EVM address, so there's nothing to stand up for local dev. The other three modes (didit, zk, identus) each require a real verifier public key at startup (--didit-pubkey, --zk-vk-path, --identus-issuer-pubkey) and will refuse to start without one.

This is a native single-node CometBFT setup — no Docker daemon or container images needed. For a non-voting deployment (no Didit/IDV fields), the domain-agnostic embodiment ships the same shape as two binaries instead:

shygeneric-abci --addr :26658 --db-path /tmp/shygeneric-dev &
cometbft init --home ~/.shygeneric-dev
cometbft start --home ~/.shygeneric-dev --proxy_app tcp://127.0.0.1:26658
shygeneric-api --cometbft-rpc http://127.0.0.1:26657 --port 8080

shygeneric-api exposes POST /submissions, GET /submissions/{id}/count, and the other two-list operations directly — see Interfaces for the CometBFTLedgerInterface client that talks to it.

For a local multi-validator BFT testnet (four independent processes forming real consensus), use ShywareLLC/core/deploy/scripts/testnet-init-native.sh + testnet-start-native.sh — no Docker required there either. A Docker Compose variant of the same testnet exists as a secondary option when you specifically want container-level isolation between validators; see ShywareLLC/core/deploy/scripts/README.md.


2. Initialize a client

import { initializeFromShyConfig } from '@shyware/sdk/clients/voting'

const shyconfig = await fetch('/shyconfig.json').then(r => r.json())
const client = initializeFromShyConfig(shyconfig)

const summary = client.initialize()
// → { contractVersion: "shyvoting-v1", appId: "my-deployment", posture: "recoverable", ... }

3. Read submissions

const polls = await client.getAllSubmissions()
const poll = await client.getSubmission('polls', scopingId)
const tally = await client.getSubmissionTally('polls', scopingId)
const records = await client.getSubmissionRecords('polls', scopingId)

4. Cast a submission

const { submissionId, submissionNonce } = await client.voteSubmission({
scopingId: 'proposal-42',
payload: 'yes',
personId: 'didit-journey-id'
})
// submissionId — direction-free; publicly visible on-chain
// submissionNonce — private receipt; retain for post-close self-verification

The client derives identity_hash = H(identityCommitment || scopingId), generates submissionNonce, builds TxTypeBallotCast, POSTs to {api.base_url}/ballots, and persists the receipt to the configured store.


5. Verify the tally

const tally = await client.getSubmissionTally('polls', 'proposal-42')
// → { counts, totalVotes, confirmedCount, merkleRoot1, merkleRoot2, publicKey, signature }

Verify the KMS signature independently:

go run ShywareLLC/core/verify/cmd/verify --api http://localhost:8080 --poll proposal-42
# → Tally signature: VALID · Total: 42 · Confirmed: 39 / 42

6. Verify your own receipt

const records = await client.getSubmissionRecords('polls', 'proposal-42')
const verified = await client.verifyReceipt(submissionNonce, 'yes', records)
// → boolean — recomputes submissionId locally, no server contact

Other embodiments

// Weighted governance (shyshares)
import { initializeFromShyConfig } from '@shyware/sdk/clients/shares'
const client = initializeFromShyConfig(shyconfig)
await client.voteSubmission({ scopingId: proposalId, payload: 'yes', personId: commitment })

// Value transfer (shywire)
import { initializeFromShyConfig } from '@shyware/sdk/clients/wire'
const client = initializeFromShyConfig(shyconfig)
await client.wireSubmission({ scopingId: assetId, amount: 100, senderCommitment, recipientCommitment })

// Secret storage (shystore)
import { initializeFromShyConfig } from '@shyware/sdk/clients/store'
const client = initializeFromShyConfig(shyconfig, { getAuthHeaders, deriveSealerKey, signMessage })
await client.storeSubmission({ scopingId: bucketId, plaintext, category })

// Commodity custody (shycustody)
import { initializeFromShyConfig } from '@shyware/sdk/clients/custody'
const client = initializeFromShyConfig(shyconfig)
await client.buildRequestRedemption({ scopingId: assetId, amount: 5.0, redeemerCommitment })

// Revenue financing (shycontracts)
import { initializeFromShyConfig } from '@shyware/sdk/clients/contracts'
const client = initializeFromShyConfig(shyconfig)
await client.buildContractExecution({ contractId, partyCommitment, executionType: "remittance", sourceRef: "inv-001", amount: 12500 })

Next steps