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
- shyconfig manifest — full manifest reference
- Architecture — two-list state machine, identity tiers, count-match invariant
- Web SDK overview — uniform primitives, client module table
- ZK tier — high-assurance nullifier setup