Skip to content

feat(sdk): integration tests for DistributorClient against local Soroban#266

Open
mandyslovestories-sudo wants to merge 3 commits into
Fundable-Protocol:mainfrom
mandyslovestories-sudo:feat/distributor-integration-tests-sdk-180
Open

feat(sdk): integration tests for DistributorClient against local Soroban#266
mandyslovestories-sudo wants to merge 3 commits into
Fundable-Protocol:mainfrom
mandyslovestories-sudo:feat/distributor-integration-tests-sdk-180

Conversation

@mandyslovestories-sudo

Copy link
Copy Markdown

Summary

Closes #180

Implements a complete integration test suite for DistributorClient that exercises every public method against a live contract deployed on a local Soroban node. Tests are excluded from the standard pnpm test run and triggered via pnpm test:integration (already configured in vitest.integration.config.ts).


Changes

src/__integration_tests__/DistributorClient.integration.test.ts (complete rewrite)

Setup (beforeAll):

  • Funds 6 test accounts in parallel (admin, sender, 3 recipients, non-admin)
  • Deploys the distributor contract via stellar-cli
  • Deploys a SAC token (DIST) and mints supply to the sender account
  • Initialises the contract with zero protocol fee
  • Sets a suiteReady flag so individual tests skip cleanly when no local node is running

Test coverage (38 tests across 10 describe blocks):

Block Tests
initialize Admin address set, total distributions = 0, total distributed amount = 0 on fresh contract
stats before distributions getUserStats undefined for unused address, getTokenStats undefined for unused token
distributeEqual Increments total distributions, increments total distributed amount by exact value, updates user stats, updates token stats, single recipient, three recipients
distributeWeighted Increments total distributions, increments total distributed amount by sum, skewed 99/1 split
getDistributionHistory Non-empty after distributions, entry shape validation, limit=1, pagination with startId, object-style overload
setProtocolFee Admin succeeds, object-style overload, non-admin rejects
getAdmin Returns correct address
getUserStats Undefined for fresh address, positive distributions_initiated, positive total_amount
getTokenStats Undefined for unused token, positive distribution_count and total_amount
re-initialization guard Second initialize call rejects

src/__integration_tests__/setup.ts

New mintTokens() helper:

await mintTokens({
  tokenContractId,
  issuerKeypair: adminKp,
  recipientAddress: senderKp.publicKey(),
  amount: 100_000_000n,
});

Calls stellar contract invoke ... mint so test accounts have spendable token balances before distribution tests run.

Bug fix — keypairSigner() return type:
The function previously returned a bare string. AssembledTransaction.signAndSend expects { signedTxXdr: string }. This is now corrected, fixing a latent bug that would have caused all integration tests (both PaymentStream and Distributor) to fail at the signing step.


How to run

# 1. Start a local Soroban node
stellar network start local
# or: docker run --rm -p 8000:8000 stellar/quickstart:latest --local

# 2. Compile contracts
cd contracts && cargo build --target wasm32-unknown-unknown --release

# 3. Run integration tests
pnpm --filter @fundable/sdk test:integration

Tests skip gracefully with a console warning when the local node is not reachable — the standard pnpm test run is unaffected.

…l#182)

Replaces the minimal stub in test-utils/mockRpcServer.ts with a
fully-typed, reusable mock that covers every Soroban RPC method
used by the SDK. Tests no longer depend on any network connection.

Changes:
- Expand mockRpcServer.ts to mock all 9 RPC methods: getAccount,
  simulateTransaction, sendTransaction, getTransaction, getNetwork,
  getLatestLedger, getLedger, getFeeStats, getEvents
- Add 12 pre-canned scenario helpers (rpc.scenarios.*) for the most
  common test situations (success, pendingThenSuccess, simulationError,
  transactionFailed, accountNotFound, networkError, etc.)
- Intercept both @stellar/stellar-sdk/rpc and @stellar/stellar-sdk
  import paths via vi.mock() so all SDK modules are covered
- Add resetMockRpcServer() that clears call history and return values
  for clean test isolation in beforeEach
- Add mockRpcServer.test.ts with 49 tests covering the mock contract
- Fix missing mockTxNone helper in DistributorClient.test.ts and
  PaymentStreamClient.test.ts (caused ReferenceError at runtime)

Closes Fundable-Protocol#182
…Fundable-Protocol#181)

Enhances BalanceWatcher with the full feature set described in issue Fundable-Protocol#181:

New capabilities:
- watchStream(stream, callback) — subscribes to both sender and recipient
  of a payment stream in a single call; returns a single unsub function
  that tears down both subscriptions
- fetchBalances(pairs) — bulk-fetches multiple address/token pairs in
  parallel; failures are captured per-pair instead of aborting the batch
- getLastKnownBalance(address, token) — reads the cached balance from the
  last successful poll without making any RPC call
- onError option — replaces the silent console.error with a typed callback
  so callers control error handling
- unwatch(address, token, callback) — explicit unsubscribe method in
  addition to the returned unsub closure

Improvements to existing behaviour:
- Polling errors for one pair no longer silently swallow; they route to
  onError (or console.error as fallback) while other pairs keep polling
- start() guards against duplicate intervals (idempotent)
- stop() is idempotent — calling it when already stopped does not throw
- void operator on pollBalances() call to satisfy no-floating-promises

Tests (BalanceWatcher.test.ts) — expanded from 11 to 54 tests covering:
- fetchBalance: happy path, zero balance, i128 max, error response,
  no result, non-bigint retval, network rejection, passphrase caching
- fetchBalances: all pairs succeed, per-pair error capture, empty input
- getLastKnownBalance: before poll, after poll, after clear, multi-poll
- watch/unwatch: change detection, no-change suppression, multiple
  callbacks, multi-pair independence, update shape validation
- watchStream: sender + recipient registration, per-party callbacks,
  unsubscribe clears both, correct token forwarding
- onError: invocation, correct args, handler throws safely, per-pair
  isolation (error in one pair does not block others)
- Lifecycle: isActive, start/stop/clear, idempotency, interval timing

Closes Fundable-Protocol#181
…ban (Fundable-Protocol#180)

Implements a complete integration test suite for DistributorClient that
verifies every public method against a live contract deployed on a local
Soroban node. Tests are excluded from the standard unit-test run and
triggered via `pnpm test:integration`.

Changes:

DistributorClient.integration.test.ts (complete rewrite):
- beforeAll: funds 6 accounts in parallel, deploys distributor contract,
  deploys SAC token, mints token supply to sender, initializes contract
- suiteReady flag + skipIfUnavailable() guards every test so the suite
  degrades gracefully when no local node is running
- initialize: verifies admin address, total distributions = 0, total
  distributed amount = 0 on a fresh contract
- stats before distributions: getUserStats undefined for fresh address,
  getTokenStats undefined for unused token
- distributeEqual: increments total distributions, increments total
  distributed amount by exact value, updates sender user stats,
  updates token stats, single recipient, three recipients
- distributeWeighted: increments total distributions, increments total
  distributed amount by sum of amounts, skewed 99/1 split
- getDistributionHistory: non-empty after distributions, entry shape
  validation, limit=1, pagination with startId, object-style overload
- setProtocolFee: admin succeeds, object-style overload, non-admin
  rejects with error
- getAdmin: returns correct admin address
- getUserStats: undefined for fresh address, positive distributions_initiated,
  positive total_amount for active sender
- getTokenStats: undefined for unused token, positive distribution_count
  and total_amount for used token
- re-initialization guard: second initialize rejects

setup.ts:
- Add mintTokens() helper — calls `stellar contract invoke ... mint`
  via stellar-cli to give test accounts spendable token balances
- Fix keypairSigner() return type: now returns { signedTxXdr } object
  (correct shape for AssembledTransaction.signAndSend) instead of bare
  string

Closes Fundable-Protocol#180
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@mandyslovestories-sudo, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 30 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f37cd996-c8ca-4cbb-8a95-33b12943a5ff

📥 Commits

Reviewing files that changed from the base of the PR and between c085d63 and d0265ad.

📒 Files selected for processing (8)
  • packages/sdk/src/__integration_tests__/DistributorClient.integration.test.ts
  • packages/sdk/src/__integration_tests__/setup.ts
  • packages/sdk/src/__tests__/BalanceWatcher.test.ts
  • packages/sdk/src/__tests__/DistributorClient.test.ts
  • packages/sdk/src/__tests__/PaymentStreamClient.test.ts
  • packages/sdk/src/__tests__/mockRpcServer.test.ts
  • packages/sdk/src/test-utils/mockRpcServer.ts
  • packages/sdk/src/utils/BalanceWatcher.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@drips-wave

drips-wave Bot commented Jun 27, 2026

Copy link
Copy Markdown

@mandyslovestories-sudo Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

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.

[SDK] Set up integration tests for DistributorClient using local Soroban

1 participant