Skip to content

sdk/revdist: add multi-language revenue distribution SDK#2774

Closed
snormore wants to merge 32 commits intomainfrom
snor/revdist-go-sdk
Closed

sdk/revdist: add multi-language revenue distribution SDK#2774
snormore wants to merge 32 commits intomainfrom
snor/revdist-go-sdk

Conversation

@snormore
Copy link
Contributor

@snormore snormore commented Jan 31, 2026

Summary

  • Add read-only revenue distribution SDK in Go, Python, and TypeScript at sdk/revdist/
  • All three languages support deserialization of Solana on-chain accounts (ProgramConfig, Distribution, SolanaValidatorDeposit, ContributorRewards, Journal) and DZ Ledger records (ComputedSolanaValidatorDebts, ShapleyOutputStorage)
  • Add PDA derivation, SHA256 discriminator validation, and forward-compatible deserialization that tolerates on-chain struct extensions
  • Add environment-based client constructors (Client.mainnet_beta(), etc.) with preconfigured Solana RPC and DZ Ledger RPC endpoints
  • Add SOL/2Z oracle client in all three languages
  • Add config modules with program ID and RPC URLs per environment
  • Add Rust fixture generator and shared cross-language test fixtures
  • Wire revenue distribution program ID into Go config package
  • Add dedicated sdk.yml CI workflow for SDK tests

Testing Verification

  • 22 Go unit tests covering struct sizes, deserialization, PDA derivation, client mocks, and Rust-generated fixture compatibility
  • 11 Python tests and 11 TypeScript tests covering fixture deserialization and PDA derivation
  • Fixture tests verify all three languages match authoritative Rust #[repr(C)] byte layouts
  • Mainnet compatibility tests available (gated behind REVDIST_COMPAT_TEST=1) that validate deserialized fields against raw byte offsets on live accounts

Add the revdist package providing programmatic read-only access to all
revenue distribution program on-chain accounts (ProgramConfig,
Distribution, SolanaValidatorDeposit, ContributorRewards, Journal) with
zero-copy deserialization via encoding/binary, PDA derivation, typed
discriminator validation, off-chain Borsh record support for validator
debts and Shapley rewards, and a SOL/2Z oracle client. Wire the new
client into the top-level SDK and add the mainnet program ID to config.
Add revdist-cli with commands for viewing on-chain revenue distribution
data: config, journal, distribution, deposits, contributors, swap-rate.
Uses --solana-env flag to select the Solana network (defaults to mainnet)
via config.NetworkConfigForEnv.

Fix oracle SwapRate struct to match the actual API response format
(camelCase JSON fields, additional price/timestamp fields).
DistributionParameters has StorageGap<8> (256 bytes), not 48 bytes.
This was causing all fields after it in ProgramConfig to be read from
the wrong offset — notably DebtWriteOffFeatureActivationEpoch and
RelayParameters.DistributeRewardsLamports were reading zeros instead
of their actual values. Validated against the Rust CLI output.
Consolidate deserialization into a generic deserializeAccount helper that
validates the discriminator, checks minimum data size, and tolerates
trailing bytes for forward compatibility with on-chain struct extensions.

Add compat_test.go that fetches live mainnet accounts and verifies
deserialized struct fields match raw byte reads at known offsets.
…ompat

Add a Rust fixture generator that creates binary test data using
bytemuck::bytes_of on real #[repr(C)] struct instances. The byte layout
is determined by the Rust compiler, making fixtures authoritative for
verifying Go deserialization matches the on-chain Rust struct layout.

Go fixture tests read each .bin/.json pair, deserialize with the SDK,
and assert field values match the expected values from the JSON sidecar.
Replace MustPublicKeyFromBase58 with error-returning variant in CLI,
add 30s HTTP timeout to oracle client, display u128 high bits when
non-zero, and switch fixture generator deps from SSH to HTTPS URLs.
Move fixtures from sdk/go/revdist/testdata/ to sdk/testdata/fixtures/revdist/
so all three languages share the same Rust-generated binary test data.

Add Python SDK (uv + solders) and TypeScript SDK (bun + @solana/web3.js)
with state deserialization, discriminator validation, PDA derivation, and
fixture-based compatibility tests. Both SDKs tolerate extra trailing bytes
for forward compatibility when structs are extended.

Add Makefile targets (sdk-test, python-test-revdist, typescript-test-revdist,
generate-fixtures) and a CI job in rust.yml.
Move the revenue distribution SDK out of smartcontract/sdk/ into a
top-level sdk/revdist/ directory with go/, python/, typescript/, and
shared testdata/fixtures/ subdirectories. Update all import paths,
fixture references, and Makefile targets accordingly. Move the CI
sdk-test job from rust.yml into its own sdk.yml workflow.
Not worth maintaining a CLI for one language; users can use the
library directly.
@snormore snormore changed the title sdk/go/revdist: add read-only Go SDK for revenue distribution program sdk/revdist: add multi-language revenue distribution SDK Feb 1, 2026
Add ledger record types (ComputedSolanaValidatorDebts,
ShapleyOutputStorage) and their PDA derivation to Python and
TypeScript SDKs. Update clients to take both Solana RPC and DZ Ledger
RPC connections, with environment constructors wiring both. Add
LEDGER_RPC_URLS to config modules. Update README to document the two
data sources.
@snormore snormore force-pushed the snor/revdist-go-sdk branch from 9272853 to 2603024 Compare February 1, 2026 01:06
Add missing compat test coverage for FetchValidatorDebts and
FetchRewardShares across all three SDKs (Go, Python, TypeScript).
These hit the DZ Ledger RPC, not Solana public RPC. Also switch
Go compat tests to use the global config package instead of
hardcoded RPC URLs.
Ledger records for validator debts and reward shares may not exist
for the most recent epoch. Use NextCompletedDZEpoch - 5 instead of
- 1 to target an epoch that has finalized ledger records.
Use create-with-seed (matching Rust create_record_key) instead of
FindProgramAddress for validator debt and reward share ledger records.
Fix reward share seeds to use ["dz_contributor_rewards", epoch,
"shapley_output"]. Skip 33-byte RecordData header before deserializing.
Add record key derivation unit tests with Rust test vectors. Fix
TypeScript base58 encoding bug in fetchAllByDiscriminator. Add tsc
--noEmit to CI for TypeScript type-checking.
Add NewRPCClient helper for Go and new_rpc_client for Python that
automatically retry on HTTP 429 Too Many Requests with exponential
backoff. TypeScript already retries via @solana/web3.js built-in
behavior. Use retry clients in SDK convenience constructors and
compat tests.
Add release.sdk-revdist.yml triggered by sdk-revdist/v* tags, using
OIDC trusted publishing for both npm and PyPI. Update TypeScript
package.json for public publishing under @doublezero scope.
@snormore
Copy link
Contributor Author

snormore commented Feb 2, 2026

Superseded by #2776

@snormore snormore closed this Feb 2, 2026
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.

1 participant