Skip to content

feat(sdk): #17 typed @yieldstream/sdk TypeScript client and Merkle tooling - #20

Merged
CHASE3020 merged 1 commit into
mainfrom
feat/issue-17-typescript-sdk
Nov 6, 2026
Merged

CHASE3020 merged 1 commit into
mainfrom
feat/issue-17-typescript-sdk

Conversation

@CHASE3020

Copy link
Copy Markdown
Collaborator

Summary

Resolves #17.
Sibling SDK repository PR: yieldstream-org/yieldstream-sdk#7

Implements the official typed client wrapping the YieldStream distributor contract for web frontends (@stellar/stellar-sdk + Freighter):

  • Contract address binding & campaign creation (createCampaign / buildCreateCampaignTx)
  • generateTree & computeLeaf: Byte-identical JavaScript/TypeScript port of the contract's domain-separated Merkle leaf hashing including XDR ScVal encodings
  • Inclusion proof generation & lookup (getProof(wallet, distributionId, tree))
  • Transaction builders for claim and claimMany (Freighter and web app ready)
  • Event decoding helpers for contract lifecycle events (created, claimed, cancel, swept, upgrade)

Implementation Details

1. Merkle Engine (packages/sdk/src/merkle.ts)

  • Pinned RFC 6962 domain separation constants (LEAF_PREFIX = 0x00, NODE_PREFIX = 0x01).
  • Canonical leaf hashing matching merkle.rs byte-for-byte:
    20198\text{leaf} = \text{SHA-256}(0\text{x}00 \mathbin{\Vert} \text{XDR}(\text{distribution_id}) \mathbin{\Vert} \text{XDR}(\text{index}) \mathbin{\Vert} \text{XDR}(\text{recipient}) \mathbin{\Vert} \text{XDR}(\text{amount}))20198
  • Sorted sibling node hashing (RFC 6962 / OpenZeppelin pattern) to eliminate proof malleability:
    20198\text{parent} = \text{SHA-256}(0\text{x}01 \mathbin{\Vert} \min(a, b) \mathbin{\Vert} \max(a, b))20198
  • Power-of-two padding matching testutils by duplicating the terminal leaf.
  • High-level generateTree(distributionId, recipients) returning root, leaves, and per-claim inclusion proofs.
  • verifyProof(proof, root, leaf) for off-chain inclusion validation.

2. Typed Protocol Client (packages/sdk/src/client.ts)

  • YieldStreamClient configured with contractId, networkPassphrase, and rpcUrl.
  • Transaction builders:
    • buildCreateCampaignTx / createCampaign
    • buildClaimTx / claim
    • buildClaimManyTx / claimMany (batched claim operations)
    • buildCancelTx
    • buildSweepTx
    • buildUpgradeTx
  • View simulation helpers querying contract storage via Soroban RPC:
    • getDistribution(id)
    • isClaimed(id, index)
    • getDistributionCount()
    • getAdmin()
    • getVersion()

3. Cross-Language Conformance Test Suite (packages/sdk/src/conformance.test.ts)

  • Ran against canonical test vectors from test-vectors/merkle_v1.json.
  • Verifies:
    • Vector structure & domain separation constants
    • computeLeaf generates 100% byte-identical hashes for every single leaf in merkle_v1.json
    • buildTree reproduces roots and inclusion proofs matching the contract vectors
    • High-level generateTree reproduces all vector outputs
    • YieldStreamClient builds valid invokeHostFunction operations for createCampaign and claim

4. Documentation & Packaging (packages/sdk/README.md)

  • Complete copy-paste guide for campaign issuers and frontend claimers using @stellar/stellar-sdk and Freighter.
  • Publishable npm package configuration with source maps (tsconfig.json), declaration maps, and dual MIT/Apache-2.0 license.

Acceptance Criteria Verification

  • vitest suite proving JS leaf hashes == Rust leaves (conformance vs merkle_v1.json) — 9/9 tests pass
  • Copy-paste docs example in packages/sdk/README.md
  • Publishable package with license + source maps (declarationMap, sourceMap)
  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, and cargo test all pass

@CHASE3020
CHASE3020 merged commit a24936a into main Nov 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ecosystem: @yieldstream/sdk — TypeScript client for frontends

1 participant