Overview
Claiming rewards from a token stream is a two-step process:- Fetch the Merkle proof from the Turtle API (Get Merkle Proofs)
- Submit a claim transaction to the stream’s smart contract on-chain
Contract ABI
The stream contract exposes the following functions for claiming and display. This ABI is sufficient for all claim integration scenarios.Stream contract
Each stream is a separate contract. The address is returned in the Merkle proof API response ascontractAddress.
StreamFactory contract
The StreamFactory owns all stream contracts and provides batch operations. Use it to claim from multiple streams in a single transaction.Show claimable amount
CallcanClaim() as a staticCall (no gas, no transaction) to display the unclaimed balance before the user clicks “Claim.” It takes the same parameters from the Merkle proof API response plus the user’s address.
canClaim() returns the actual unclaimed amount. No additional math required. It accounts for previous claims automatically.Claim rewards
Submit aclaim() transaction using the proof data. The contract uses a cumulative model: amount is the user’s total allocation across all snapshots, and the contract releases only the difference between the total and what has already been claimed.
Batch claiming
If a user has rewards across multiple streams, you can claim all of them in a single transaction usingbatchClaim() on the StreamFactory instead of calling claim() on each stream contract separately.
The StreamFactory address depends on the chain. Contact Turtle or check the block explorer for the deployed address on your target network.
Claim on behalf of a user
To claim on behalf of another user, usebatchClaimFor() on the StreamFactory. The caller must first be approved as an operator by the user via toggleOperatorForUser().
claim() on the stream contract can only be called by the user themselves. Delegated claiming always goes through the StreamFactory’s batchClaimFor() with prior operator approval.React component
A drop-in<StreamsClaimButton> component for React/Next.js applications. It fetches proofs, displays the claimable amount, and handles the claim transaction.
Operational Notes
Cumulative amount model
Cumulative amount model
The
amount parameter in claim() is the user’s total cumulative allocation, not the unclaimed delta. The contract tracks how much has already been claimed and releases only the difference. Users can claim at any time and always receive their full outstanding balance in a single transaction.Amount is in raw token units
Amount is in raw token units
The
amount from the API is in raw token units. Use ethers.formatUnits(amount, decimals) to convert to a human-readable number for display. Call getRewardToken() on the contract to get the token address, then query the token’s decimals() if needed (most stream reward tokens use 18 decimals). Always pass the raw value to the contract. Do not format it before sending the transaction.Timestamp conversion
Timestamp conversion
The API returns
timestamp as an ISO 8601 string (e.g. "2026-05-20T13:05:10Z"), but the contract expects a uint40 Unix epoch in seconds. Convert before passing to the contract: Math.floor(new Date(proof.timestamp).getTime() / 1000).Multiple streams
Multiple streams
Each stream has its own contract. When calling
claim() directly, you need a separate transaction per stream. The React component above handles this automatically. Alternatively, use batchClaim() on the StreamFactory to claim from all streams in a single transaction.Claiming is idempotent
Claiming is idempotent
Calling
claim() when there is nothing new to claim will succeed but transfer zero tokens. There is no penalty for calling it multiple times.
