Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/contracts/streampay-stream/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Linear payment streams on Stellar/Soroban.
| `settle` | Yes | `stream.recipient` | Ends a stream and releases all remaining funds to recipient. |
| `get_stream` | No | None | Returns the stream record. |
| `withdrawable` | No | None | Returns the currently withdrawable amount. |
| `claim_drip` | No | None | Returns the unsettled accrual (vested minus released) — a convenience alias for `withdrawable`. |
| `stream_balance` | No | None | Returns the vested balance at the current time. |
| `stream_snapshot` | No | None | Captures a `StreamSnapshot` (vested, released, locked, withdrawable, status) at a given ledger timestamp. |
| `diff_snapshots` | No | None | Computes the field-by-field `SnapshotDiff` delta between two `StreamSnapshot` values from the same stream. |
Expand Down
89 changes: 89 additions & 0 deletions contracts/contracts/streampay-stream/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2436,3 +2436,92 @@ mod cancel_stream_test {
assert!(result.is_err());
}
}

#[cfg(test)]
mod claim_drip_test {
use super::*;
use soroban_sdk::testutils::{Address as _, Ledger as _};

fn setup() -> (Env, ContractClient<'static>) {
let env = Env::default();
env.mock_all_auths();
let contract_id = env.register(Contract, ());
let client = ContractClient::new(&env, &contract_id);
(env, client)
}

fn addresses(env: &Env) -> (Address, Address) {
let sender = Address::generate(env);
let recipient = Address::generate(env);
(sender, recipient)
}

fn token_and_client<'a>(env: &'a Env, admin: &'a Address) -> (Address, token::Client<'a>) {
let token_addr = env.register_stellar_asset_contract_v2(admin.clone()).address();
let tkn = token::Client::new(env, &token_addr);
(token_addr, tkn)
}

#[test]
fn claim_drip_returns_zero_before_start_time() {
let (env, client) = setup();
let (sender, recipient) = addresses(&env);
let (token, _) = token_and_client(&env, &sender);

client.initialize(&sender);
env.ledger().set_timestamp(1_000);
let id = client.create_stream(
&sender, &recipient, &token, &1000i128, &1_100u64, &2_000u64, &0u32,
);

// Before start_time (1 100) → nothing vested
assert_eq!(client.claim_drip(&id), 0);
}

#[test]
fn claim_drip_returns_half_at_midpoint() {
let (env, client) = setup();
let (sender, recipient) = addresses(&env);
let (token, _) = token_and_client(&env, &sender);

client.initialize(&sender);
env.ledger().set_timestamp(1_000);
let id = client.create_stream(
&sender, &recipient, &token, &1000i128, &1_000u64, &2_000u64, &0u32,
);

env.ledger().set_timestamp(1_500);
assert_eq!(client.claim_drip(&id), 500);
}

#[test]
fn claim_drip_decreases_after_withdrawal() {
let (env, client) = setup();
let (sender, recipient) = addresses(&env);
let (token, _) = token_and_client(&env, &sender);

client.initialize(&sender);
env.ledger().set_timestamp(1_000);
let id = client.create_stream(
&sender, &recipient, &token, &1000i128, &1_000u64, &2_000u64, &0u32,
);

env.ledger().set_timestamp(1_500);
assert_eq!(client.claim_drip(&id), 500);

client.withdraw(&recipient, &id, &200);
assert_eq!(client.claim_drip(&id), 300);
}

#[test]
fn claim_drip_nonexistent_stream_returns_not_found() {
let (env, client) = setup();
let (sender, _recipient) = addresses(&env);

client.initialize(&sender);

let result = client.try_claim_drip(&9999u64);
let err = result.expect_err("claim_drip on missing stream should fail");
assert_eq!(err, Ok(Error::NotFound));
}
}
2 changes: 2 additions & 0 deletions docs/contract-smoke-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ is exercised with at minimum one happy-path or expected-error invocation:
| `get_stream` | Error-path | `NotFound` (stream 9999) |
| `withdrawable` | Happy-path | returns `i128` |
| `withdrawable` | Error-path | `NotFound` (stream 9999) |
| `claim_drip` | Happy-path | returns `i128` (alias for `withdrawable`) |
| `claim_drip` | Error-path | `NotFound` (stream 9999) |
| `stream_balance` | Happy-path | returns `i128` |
| `stream_balance` | Error-path | `NotFound` (stream 9999) |
| `start_stream` | Error-path | `NotFound` (stream 9999) |
Expand Down
28 changes: 28 additions & 0 deletions issue716.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Description
This is a smart-contract issue for the GrantFox campaign. Read-only view returning unsettled accrual per (stream, recipient).

Requirements and Context
Implement per the description
Add focused tests for the change
Document any API/visible changes
Adhere to repo's lint and code style
Must be secure, tested, and documented
Suggested Execution
Fork the repo and create a branch
git checkout -b feature/claim-drip-view
Implement changes
Test and commit
Example commit message

feat: claim_drip read-only view
Acceptance Criteria

Implementation matches the description

Tests added and passing

Code review approved

Docs updated
Guidelines
Clear documentation and inline comments
Loading