@goodsdks/streaming-sdk
v1.0.0
Published
TypeScript SDK for Superfluid streaming flows on Celo and Base, with GoodDollar-aware token resolution, GDA pool helpers, live CFA reads, and subgraph-backed historical queries.
Downloads
164
Readme
@goodsdks/streaming-sdk
TypeScript SDK for Superfluid streaming flows on Celo and Base, with GoodDollar-aware token resolution, GDA pool helpers, live CFA reads, and subgraph-backed historical queries.
Features
- Stream lifecycle helpers for
create,update,delete, andcreateOrUpdate - Auto-resolved default tokens:
- Celo ->
G$ - Base ->
SUP
- Celo ->
- Live CFA reads through the Superfluid forwarder (
getFlowRate,getFlowInfo) - Indexed stream, balance, balance-history, pool-membership, and reserve queries through the Superfluid subgraph
- GDA pool connect/disconnect helpers plus member-scoped pool listing and status queries
- Environment-aware token resolution for
production,staging, anddevelopment
Installation
yarn add @goodsdks/streaming-sdk viemQuick Start
import { StreamingSDK, calculateFlowRate } from "@goodsdks/streaming-sdk"
import { parseEther } from "viem"
const sdk = new StreamingSDK(publicClient, walletClient, {
environment: "production",
})
const flowRate = calculateFlowRate(parseEther("100"), "month")
await sdk.createOrUpdateStream({
receiver: "0x...",
flowRate,
})Address Resolution
The SDK resolves addresses from two sources:
- Superfluid protocol forwarders come from
@sfpro/sdkaddress maps.CFA_FORWARDER_ADDRESSESGDA_FORWARDER_ADDRESSES
- GoodDollar token addresses come from this package's environment maps.
getG$Token(chainId, environment)getSUPToken(chainId, environment)
That means developers can usually initialize once with an environment and omit token addresses from individual calls:
const sdk = new StreamingSDK(publicClient, walletClient, {
environment: "staging",
defaultToken: "G$",
})You can still override the token per call with either "G$", "SUP", or a raw token address.
StreamingSDK
Write methods
createOrUpdateStream(params)
Uses the recommended CFA forwarder setFlowrate(token, receiver, flowRate) path.
await sdk.createOrUpdateStream({
receiver: "0x...",
flowRate: 1500n,
token: "G$",
})Passing 0n stops the stream.
createStream(params)
Low-level explicit createFlow wrapper. Prefer createOrUpdateStream() unless you specifically need the one-shot create call.
await sdk.createStream({
receiver: "0x...",
flowRate: 1000n,
token: "G$",
userData: "0x",
})updateStream(params)
Low-level explicit updateFlow wrapper. Prefer createOrUpdateStream() unless you specifically need the separate update call.
await sdk.updateStream({
receiver: "0x...",
newFlowRate: 2000n,
token: "G$",
userData: "0x",
})deleteStream(params)
await sdk.deleteStream({
receiver: "0x...",
token: "G$",
userData: "0x",
})Live reads
getFlowRate(params)
Reads the current live flow rate directly from the CFA forwarder.
const flowRate = await sdk.getFlowRate({
sender: "0x...",
receiver: "0x...",
token: "G$",
})getFlowInfo(params)
Returns live flow metadata from the CFA forwarder.
const flowInfo = await sdk.getFlowInfo({
sender: "0x...",
receiver: "0x...",
token: "G$",
})
console.log(flowInfo.flowRate, flowInfo.lastUpdated)Indexed subgraph reads
getActiveStreams(options)
Returns active streams from the Superfluid subgraph.
const streams = await sdk.getActiveStreams({
account: "0x...",
direction: "all",
})Pagination is supported:
const streams = await sdk.getActiveStreams({
account: "0x...",
direction: "all",
first: 20,
skip: 20,
})For direction: "all", pagination is applied after outgoing and incoming results are merged and sorted by createdAtTimestamp descending. Internally, the SDK batches requests to avoid unbounded scans.
getSuperTokenBalance(account, token?)
const balance = await sdk.getSuperTokenBalance("0x...", "SUP")If token is omitted, the SDK uses its configured default token.
getBalanceHistory(options)
Returns historical balance snapshots from the subgraph.
const history = await sdk.getBalanceHistory({
account: "0x...",
first: 10,
skip: 0,
})fromTimestamp / toTimestamp accept unix seconds, and millisecond inputs are normalized automatically.
getSubgraphClient()
Use the underlying client for subgraph-only operations such as SUP reserve lookups.
SUP Reserves
SUP reserve queries use The Graph Gateway endpoint and require an API key.
import { SubgraphClient, SupportedChains } from "@goodsdks/streaming-sdk"
const client = new SubgraphClient(SupportedChains.BASE, {
apiKey: process.env.GRAPH_API_KEY,
})
const reserves = await client.querySUPReserves("0x...")
for (const locker of reserves) {
console.log(locker.id, locker.stakedBalance) // bigint, 18-decimal SUP
}Each SUPReserveLocker includes the locker's id, lockerOwner, blockNumber, blockTimestamp, and a stakedBalance (bigint, sourced from stakingData.currentStakedBalance). stakedBalance is 0n when the locker has never staked.
The reserve query is intentionally account-scoped. You must pass the wallet or account whose reserves you want to inspect.
GdaSDK
connectToPool(params)
const gda = new GdaSDK(publicClient, walletClient)
await gda.connectToPool({
poolAddress: "0x...",
userData: "0x",
})disconnectFromPool(params)
await gda.disconnectFromPool({
poolAddress: "0x...",
userData: "0x",
})getPoolMemberships(account)
const memberships = await gda.getPoolMemberships("0x..." as Address)getDistributionPools(account)
Lists only distribution pools where account is a member, including per-pool isConnected status for that account.
const pools = await gda.getDistributionPools("0x..." as Address)getPoolDetails(poolId, account)
Looks up a specific pool within the queried account's distribution pools.
const pool = await gda.getPoolDetails("0xPool..." as Address, "0xAccount..." as Address)Supported Chains
| Token | Chain | Chain ID | Environment | | --- | --- | --- | --- | | G$ | Celo | 42220 | production, staging, development | | SUP | Base | 8453 | production |
SUP is a production-only token on Base. Resolving SUP for staging or
development returns undefined by design, and any SDK call that would
require such an address throws a clear "Token address not available" error.
License
MIT
