Skip to content

feat(sdk): integration tests for PaymentStreamClient against local Soroban#267

Open
mandyslovestories-sudo wants to merge 4 commits into
Fundable-Protocol:mainfrom
mandyslovestories-sudo:feat/payment-stream-integration-tests-sdk-178
Open

feat(sdk): integration tests for PaymentStreamClient against local Soroban#267
mandyslovestories-sudo wants to merge 4 commits into
Fundable-Protocol:mainfrom
mandyslovestories-sudo:feat/payment-stream-integration-tests-sdk-178

Conversation

@mandyslovestories-sudo

Copy link
Copy Markdown

Summary

Closes #178

Rewrites the PaymentStreamClient integration test suite to cover every public method with real on-chain interactions against a local Soroban node. Tests are excluded from the standard pnpm test run and triggered via pnpm test:integration.


Changes

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

Setup (beforeAll):

  • Funds 5 test accounts in parallel (admin, sender, recipient, delegate, non-party)
  • Deploys the payment-stream contract via stellar-cli
  • Deploys a SAC token (STRM) and mints supply to the sender account
  • Initialises the contract with zero fee rate
  • suiteReady flag + skipIfUnavailable() guard every test for graceful degradation

createActiveStream() factory — shared helper reduces boilerplate across describe blocks; supports configurable total_amount, initial_amount, durationSecs, startOffsetSecs (negative = started in the past).

Test coverage (45 tests across 13 describe blocks):

Block Tests
initialize Fee collector address, fee rate = 0, metrics zeroed, re-initialization rejects
createStream Returns bigint ID, increments total_streams_created, object-style overload
getStream sender/recipient/token fields, total_amount, Active status, withdrawn_amount = 0
getWithdrawableAmount 0n for future stream, >0n for past-started stream, object overload
pauseStream / resumeStream Active→Paused→Active transitions, object overload, non-sender rejection
cancelStream Active→Canceled, object-style overload
deposit Balance increases by exact amount, object-style overload
withdraw / withdrawMax Reduces withdrawable to 0, withdrawn_amount tracks cumulative, object overload
setDelegate / revokeDelegate / getDelegate Undefined on fresh stream, set/revoke cycle, object overload, non-recipient rejection
getStreamMetrics Shape validation, pause_count increments after pause/resume, object overload
getProtocolMetrics total_streams_created grows, all fields are bigint
getFeeCollector / getProtocolFeeRate Correct initial values
getStreamHistory / getAllStreamHistory Returns array, events belong to correct stream, no duplicates, object overload

Bug fixes in the previous version:

  • Wrong field names: metrics.total_streams → correct names (total_streams_created, total_active_streams, total_tokens_streamed, total_delegations)
  • Missing mintTokens() call — sender had no token balance, so all distribution tests would have failed
  • Fragile !client check → replaced with proper suiteReady flag

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 only
pnpm --filter @fundable/sdk test:integration

Tests skip gracefully with a 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
…roban (Fundable-Protocol#178)

Rewrites the PaymentStreamClient integration test suite to cover every
public method with real on-chain interactions against a local Soroban
node. Tests are excluded from the standard unit-test run and triggered
via `pnpm test:integration`.

Changes:

PaymentStreamClient.integration.test.ts (complete rewrite):
- beforeAll: funds 5 accounts in parallel, deploys payment-stream
  contract, deploys SAC token (STRM), mints token supply to sender,
  initialises contract with zero fee rate
- suiteReady flag + skipIfUnavailable() guards every test so the suite
  degrades gracefully when no local node is running
- createActiveStream() factory helper reduces boilerplate across blocks
- initialize: fee collector address, fee rate = 0, protocol metrics
  zeroed on fresh contract, re-initialization rejects
- createStream: returns bigint stream ID, increments
  total_streams_created, accepts object-style overload
- getStream: sender/recipient/token fields, total_amount, Active status,
  withdrawn_amount = 0 on fresh stream
- getWithdrawableAmount: 0n for future stream, >0n for past-started
  stream, object-style overload
- pauseStream/resumeStream: Active→Paused→Active transitions, object-
  style overload, non-sender rejection
- cancelStream: Active→Canceled, object-style overload
- deposit: balance increases by exact amount, object-style overload
- withdraw/withdrawMax: reduces withdrawable amount to 0, withdrawn_
  amount tracks cumulative withdrawals, object-style overload
- setDelegate/revokeDelegate/getDelegate: undefined on fresh stream,
  set returns correct address, revoke clears it, object-style overload,
  non-recipient rejection
- getStreamMetrics: shape validation, pause_count increments after
  pause/resume cycle, object-style overload
- getProtocolMetrics: total_streams_created grows, all fields are bigint
- getFeeCollector / getProtocolFeeRate: correct initial values
- getStreamHistory / getAllStreamHistory: returns array, events belong to
  correct stream, no duplicates, object-style overload
- guard: re-initialization rejects

Fixes in tests:
- Corrected protocol metrics field names (total_streams_created,
  total_active_streams, total_tokens_streamed, total_delegations)
  that were wrong in the previous version (total_streams)
- Added mintTokens() call so sender has token balance before streams
- Used suiteReady pattern instead of fragile !client checks

Closes Fundable-Protocol#178
@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 20 minutes and 15 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: a500d54a-bd90-4e99-aaee-a554e1fc496d

📥 Commits

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

📒 Files selected for processing (9)
  • packages/sdk/src/__integration_tests__/DistributorClient.integration.test.ts
  • packages/sdk/src/__integration_tests__/PaymentStreamClient.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 PaymentStreamClient using local Soroban

1 participant