Streaming Payments System Development (Superfluid, Sablier)
Streaming payments are continuous flow of cryptocurrency over time: recipient can withdraw already "earned" tokens at any moment without waiting for period end. Instead of monthly salary payment — a stream that flows per second. Technically implemented differently in Superfluid and Sablier, and choice between them determines entire system architecture.
Superfluid vs Sablier: Fundamental Difference
Superfluid: Real-Time Balance Without On-Chain Transactions
Superfluid uses Super Token concept — ERC-20-compatible token with extended mechanics. Super Token balance recalculates in real-time without separate transactions: balance(t) = initialBalance + flowRate * (t - startTime).
Creating stream is one transaction. After that, recipient balance grows continuously, no additional transactions needed to update balance. This is main advantage: gas only on stream creation and closure.
Token wrapping into Super Token: USDCx is Super Token for USDC. Wrap/unwrap via ISuperToken.upgrade(amount) and downgrade(amount). For native ETH work — ETHx via native wrapper in Superfluid.
Critical liquidation moment. Superfluid requires maintaining sender's deposit (buffer). If sender balance drops to zero — stream becomes "critical". Anyone can call deleteFlow and get liquidation bonus from buffer. If no one calls — stream continues and sender goes into debt (Patrician Period). Need to account for this in UI: warn about low balance and automatic top-up.
Sablier: Linear Flows with Flexible Vesting
Sablier v2 (contracts SablierV2LockupLinear, SablierV2LockupDynamic) are NFT-streams. Each stream tokenized as ERC-721, allowing transfer and use as collateral.
LockupLinear is linear flow from start to end. LockupDynamic is custom schedule with segments (cliff + linear, exponential, etc). For vesting with cliff: first 12 months nothing, then linear flow 24 months — two segments in LockupDynamic.
// Creating stream in Sablier v2
ISablierV2LockupLinear.CreateWithRange({
asset: IERC20(USDC),
sender: msg.sender,
recipient: employee,
totalAmount: 120_000e6, // 120k USDC
range: ISablierV2LockupLinear.Range({
start: uint40(block.timestamp),
cliff: uint40(block.timestamp + 365 days),
end: uint40(block.timestamp + 3 * 365 days)
}),
cancelable: true,
transferable: true
})
Sablier doesn't require deposit and no liquidation risk. Entire totalAmount is locked in contract at stream creation. Recipient withdraws accumulated amount via withdraw(). Gas per each withdraw is trade-off vs Superfluid.
Choosing Protocol for Task
| Parameter | Superfluid | Sablier v2 |
|---|---|---|
| Gas on stream creation | Low | Medium |
| Gas on token receipt | None (realtime balance) | Yes (withdraw transaction) |
| Liquidation risk | Yes (buffer system) | No |
| Stream as NFT | No | Yes |
| Vesting with cliff | Via configuration | Native |
| Suitable for | Salaries, subscriptions | Vesting, grants |
Superfluid — for regular payments (salaries, streaming subscriptions, DCA), where sender maintains active balance. Integrations with Gelato for automatic top-up.
Sablier — for vesting, grants, one-way payments with fixed amount. NFT position allows secondary market integration.
Product Integration
Superfluid Integration
SDK: @superfluid-finance/sdk-core. Main operations via Framework:
import { Framework } from '@superfluid-finance/sdk-core'
const sf = await Framework.create({ chainId: 137, provider })
const usdc_x = await sf.loadSuperToken('USDCx')
const createFlowOp = usdc_x.createFlow({
sender: senderAddress,
receiver: receiverAddress,
flowRate: '3858024691358024' // ~10k USDC/month в wei/sec
})
await createFlowOp.exec(signer)
flowRate in wei/second: for $10,000/month = 10000 * 1e6 / (30 * 24 * 3600) = 3858 wei USDC/sec.
For stream monitoring — Superfluid Subgraph (The Graph):
query {
streams(where: { receiver: "0x..." }) {
currentFlowRate
streamedUntilUpdatedAt
}
}
Sablier Integration
SDK: @sablier/v2-sdk or direct contract calls via ethers.js/viem. Contract addresses for each chain in documentation.
Before creating stream, need ERC-20 token approve: token.approve(sablierAddress, totalAmount).
After approve — stream creation, get streamId. This ID is needed for all subsequent operations: withdraw, cancel, transferFrom.
Supported Chains
Superfluid: Ethereum, Polygon, Arbitrum, Optimism, Base, BNB Chain, Avalanche, Gnosis.
Sablier v2: Ethereum, Arbitrum, Optimism, Base, Polygon, BNB Chain, Avalanche, Blast.
If client's chain unsupported — option with own basic streaming logic implementation exists, though significantly more expensive and audit-required.
Development Process
Protocol Selection (1 day). Analyze use case: one-off vesting streams or continuous payments, is liquidation risk important, need tradeable position.
Integration (2-3 days). SDK + smart contract if custom logic needed (e.g., distributing to multiple recipients from one source).
UI (1-2 days). Dashboard with current streams, balances, management. wagmi/viem for on-chain reading.
Tests and Deployment (1 day). Fork tests on mainnet. Testnet deployment, then mainnet.
Timeline Estimates
Superfluid or Sablier integration into existing product — 3-5 days. Creating stream management system with UI (create/cancel/monitor) — up to 2 weeks.







