Skip to main content

Quickstart

Prerequisites

  • Node.js 18+ (web SDK)
  • Go 1.22+ (runtime / ABCI node)
  • Docker and Docker Compose (local node)

1. Start a local node

shyware-abci --config shyconfig.json --db-path /tmp/shyware-dev --addr :26658
shyware-api --config shyconfig.json --port 8080

Set identity.provider: "none" in your local shyconfig.json for development — the NoopVerifier skips IDV checks and derives a deterministic identity hash from the submitted public key.

For a full Docker Compose setup with CometBFT:

cd deploy/node/cometbft && docker compose up

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/community/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