Skip to main content

sharesClient

Initialize with initializeFromShyConfig — see the Web SDK overview for the common setup pattern.

Non-standard options for this client: { operatorMode: true } to enable poll creation and admin methods.

Poll create authority

Any eligible holder may create a poll regardless of deployment model. poll_create_authority: "any_holder" is the only supported value.

poll_create_keys in the shyconfig is a list of known operator/board Ed25519 public keys used for tagging only. When the ABCI app sees a PollCreate signed by a listed key it emits creator_type: "authority" in the block event. All other PollCreate txs emit creator_type: "holder". The client exposes this as a creatorType field on the Proposal object so the frontend can badge official polls without restricting creation.

// Any holder — no special key needed
await client.createProposal({ ... })

// Board/operator — pass the authority key to get creator_type: "authority" badge
await client.createProposal({
...,
signingKey: boardPrivKey // optional — determines creatorType tag only
})

Membership and eligibility

// Build an account commitment for a wallet or DID subject
const { commitment } = await client.createAccountCommitment({
walletAddress: '0xabc...' // WalletVerifier deployments (shywire/shyshares)
// or:
subjectDID: 'did:prism:...' // IdentusVerifier deployments (shyshares custody)
})

// Current silo or token balance for this commitment
await client.getBalance(eligibilityAssetId, commitment)
// → { balance }

// Effective voting weight at the snapshot block for an active proposal
await client.getMembershipSnapshot(commitment, proposalId)
// → { weight, snapshotHeight }

Token or silo transfers after the snapshot block do not affect weight for that proposal.


Proposals

await client.listProposals(filters?)
// filters: { status, proposalClass }
// → Proposal[]

await client.getProposal(proposalId)
// → Proposal { id, class, question, options, snapshotBlock, status }

await client.getTally(proposalId)
// → Tally | null

Create a proposal (operator/board or any holder)

await client.createProposal({
class: 'parameter_change', // must be in governance.proposal_classes
question: 'Increase fee to 0.3%?',
options: ['yes', 'no'],
startTime: unixSeconds,
endTime: unixSeconds,
operatorSigningKey: key // required when poll_create_authority = operator_or_board
})

Custody proposal classes — custody_policy, warehouse_operator, accepted_sku_class:

await operatorClient.createProposal({
class: 'warehouse_operator',
question: 'Approve warehouse operator WH-NYC-2?',
options: ['approve', 'reject'],
startTime,
endTime,
operatorSigningKey: boardPrivKey
})

Close a proposal

await client.closeProposal(proposalId)

Weighted ballot

await client.submitWeightedBallot({
proposalId: 'proposal-42',
choice: 'yes',
accountCommitment: commitment,
identityInput: {
walletAddress: '0xabc...' // WalletVerifier
// or:
subjectDID: 'did:prism:...',
voterPrivKey: ephemeralPrivKey, // IdentusVerifier
issuerCredentialSig: credSig
}
})

Vote weight is read from the membership snapshot at the proposal's snapshot block. The List 1 record contains only the choice and a direction-free ballot ID — no identity, no wallet address, no DID. The List 2 record contains only the identity commitment — no choice, no weight.


Governance snapshot

snapshotModeWhen weight is fixed
proposal_creation_timeAt the block the proposal is created
voting_startAt the submission-period opening block
block_heightExplicit block height in the proposal record

Action queue (DAO model)

await client.listActions(filters?)
// → QueuedAction[]

await client.getAction(actionId)
// → QueuedAction { id, type, payload, proposalId, status, enqueueHeight }

await client.dispatchAction(actionId, {
adapter: 'shywire', // or 'byodao'
adapterPayload: { ... }
})

Actions are enqueued to canonical ledger state when a proposal crosses both quorum and approval thresholds. The canonical queue record is the authoritative governance result.

The custody consortium model (operator_or_board) does not use the action queue — policy changes are applied directly by the operator via the appropriate custody tx type after a passing vote.


Deployment guide

DAO governance (any_holder)

Any eligible token holder may create proposals. Voting weight is proportional to fungible token balance.

"governance": {
"poll_create_authority": "any_holder",
"membership_sources": ["token_balance"],
"proposal_classes": ["payout", "parameter_change", "role_change"],
"eligibility": { "asset_id": "gov-token", "min_balance": 1 },
"vote_weight": "token_quantity"
}

The shywire sub-state holds the anonymous holder registry; the shyvoting sub-state holds anonymous ballot state per proposal. Both run on one CometBFT chain with atomic app hash: sha256(voting_app_hash || wire_app_hash).

Custody consortium governance (operator_or_board)

Board or warehouse operators initiate polls. Holders vote anonymously on consortium policy, warehouse operator approvals, and accepted SKU classes.

"governance": {
"poll_create_authority": "operator_or_board",
"poll_create_keys": ["<operator-pubkey-hex>", "<board-pubkey-hex>"],
"membership_sources": ["token_balance"],
"proposal_classes": ["custody_policy", "warehouse_operator", "accepted_sku_class"],
"eligibility": { "asset_id": "silo", "min_balance": 1 },
"vote_weight": "token_quantity"
}

Polls are tagged by signer type at execution time (creator_type: "house" | "authority" | "holder"). No creation is blocked — tagging is informational.

House entity onboarding (KYB): the house creator type requires verified beneficial ownership via Persona KYB before the Ed25519 signing key is admitted to house_keys. Use the house-onboard CLI tool — see CLI reference.

Provisioning

Both models use the same binary — no per-deployment Go code:

shyware-abci --config shyconfig.json --db-path /opt/<deployment>/data --addr :26658
shyware-api --config shyconfig.json --port 8080
cd <deployment>/deploy/signing && terragrunt apply