> For the complete documentation index, see [llms.txt](https://docs.zebec.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zebec.io/developer-docs/sdks/streaming-sdk/solana-streaming-sdk.md).

# Solana

Solana Streaming SDK - TypeScript SDK for Zebec payment streams on Solana via Anchor.

A TypeScript SDK for interacting with the Zebec Stream protocol on Solana. This SDK provides a comprehensive interface for creating, managing, and interacting with payment streams on the Zebec Network.

## Overview

The Solana Streaming SDK enables developers to build applications that leverage continuous, programmable SPL-token streams on Solana. It wraps the underlying Anchor program interactions, handling instruction building, associated token account (ATA) resolution, fee quoting, and transaction composition while exposing strongly-typed, ergonomic APIs.

Typical use cases include:

* **Payroll** — Stream salaries to employees continuously per second / minute / hour.
* **Vesting** — Distribute tokens over time with configurable cliffs.
* **Subscriptions** — Recurring payments and metered billing.
* **Grants & Bounties** — Time-locked, cancelable token distribution.

## Installation

Install the package using npm or yarn:

```bash
npm install @zebec-network/zebec-stream-sdk
```

```bash
yarn add @zebec-network/zebec-stream-sdk
```

### Peer dependencies

The SDK relies on the following runtime dependencies (installed automatically):

* [`@coral-xyz/anchor`](https://www.npmjs.com/package/@coral-xyz/anchor) — Anchor framework for Solana program interaction
* [`@solana/web3.js`](https://www.npmjs.com/package/@solana/web3.js) — Solana Web3 JavaScript API
* [`@solana/spl-token`](https://www.npmjs.com/package/@solana/spl-token) — SPL token utilities
* [`@metaplex-foundation/mpl-token-metadata`](https://www.npmjs.com/package/@metaplex-foundation/mpl-token-metadata) — On-chain token metadata resolution
* [`@zebec-network/core-utils`](https://www.npmjs.com/package/@zebec-network/core-utils) — Zebec core utility functions
* [`@zebec-network/solana-common`](https://www.npmjs.com/package/@zebec-network/solana-common) — Common Solana helpers
* [`bignumber.js`](https://www.npmjs.com/package/bignumber.js) — Arbitrary-precision arithmetic

### Requirements

* Node.js 18+ recommended
* TypeScript 5+ (when consuming from TS projects)

## Quick start

```ts
import { Connection } from "@solana/web3.js";
import { ZebecStreamService, createAnchorProvider } from "@zebec-network/zebec-stream-sdk";

// 1. Create a connection to devnet or mainnet-beta
const connection = new Connection("https://api.devnet.solana.com");

// 2. Create an AnchorProvider using your wallet
const provider = createAnchorProvider(connection, wallet);

// 3. Initialize the service with a config name and network
const streamService = ZebecStreamService.create("my-app-config", provider, "devnet");

// 4. Create a stream
const tx = await streamService.createStream({
  sender: "SenderPublicKeyHere",
  receiver: "ReceiverPublicKeyHere",
  streamToken: "TokenMintAddressHere",
  amount: "1000",              // Amount in human-readable token units
  duration: 86400,             // Total stream duration in seconds (1 day)
  autoWithdrawFrequency: 3600, // Auto-withdrawal interval in seconds (1 hour)
  streamName: "Monthly Salary",
  startNow: true,
  startTime: Math.floor(Date.now() / 1000),
  cliffPercentage: 0,
  automaticWithdrawal: true,
  cancelableByRecipient: true,
  cancelableBySender: true,
  isPausable: true,
  transferableByRecipient: false,
  transferableBySender: false,
  canTopup: true,
  rateUpdatable: false,
});

const signature = await tx.execute();
console.log("Stream created:", signature);
```

## Core concepts

### Streams

A **stream** is an on-chain agreement to transfer SPL tokens from a sender to a receiver over a defined duration. Streams can be paused, resumed, canceled, transferred, and topped up depending on the permissions set at creation.

### Stream config

Every stream belongs to a named **stream config** PDA that holds the global protocol state: admin, fee tiers, allowed frequencies, withdraw account, fee vault, and whitelisted tokens. The config name is passed when creating the `ZebecStreamService`.

### Fee model

Fees are configured globally per stream config:

* **Platform fee** — a percentage charged on every stream.
* **Base fee** — a flat percentage applied to every stream.
* **Fee tiers** — amount-banded percentage fees based on the USD value of the stream amount.

Fees are quoted dynamically from the Zebec backend at stream creation time. The SDK fetches the fee quote, computes the fee token and amount, and includes the fee transfer instruction automatically.

### Decimals

The SDK automatically converts human-readable amounts to raw token units using the SPL token's on-chain decimals. Inputs like `"1000"` are scaled correctly before being passed to the program.

## SDK methods

All write methods return a [`TransactionPayload`](#transactionpayload) that must be executed. All read methods return parsed, human-readable values directly.

The service is constructed as:

```ts
ZebecStreamService.create(streamConfigName: string, provider: Provider, network: RpcNetwork)
```

| Parameter          | Type                         | Description                                                       |
| ------------------ | ---------------------------- | ----------------------------------------------------------------- |
| `streamConfigName` | `string`                     | Unique name identifying the stream config PDA.                    |
| `provider`         | `Provider`                   | Anchor provider (read/write) or read-only provider.               |
| `network`          | `"mainnet-beta" \| "devnet"` | Target network. Must match the connection's RPC endpoint network. |

### Admin methods

These methods configure the global protocol state and require the caller to be the config admin.

#### `initializeStreamConfig(params): Promise<TransactionPayload>`

Initializes the global stream configuration (admin only, one-time setup per `streamConfigName`).

* `params.admin?` — optional admin address (defaults to provider wallet).
* `params.config.baseFeePercent` — base fee as a percent string (e.g. `"0.1"`).
* `params.config.platformFeePercent` — platform fee as a percent string (e.g. `"0.05"`).
* `params.config.frequencies` — allowed auto-withdraw frequencies in seconds (e.g. `[3600, 86400, 604800]`).
* `params.config.withdrawAccount` — address that performs automatic withdrawals.
* `params.config.feeVault` — address that collects fees.
* `params.config.feeTiers` — array of `FeeTier` objects defining amount-banded fees.

```ts
await streamService.initializeStreamConfig({
  admin: adminAddress,
  config: {
    baseFeePercent: "0.1",
    platformFeePercent: "0.05",
    frequencies: [3600, 86400, 604800],
    withdrawAccount: "WithdrawAccountAddressHere",
    feeVault: "FeeVaultAddressHere",
    feeTiers: [
      { minThreshold: "0",     maxThreshold: "1000",  feeRateInPercent: "1.0" },
      { minThreshold: "1000",  maxThreshold: "10000", feeRateInPercent: "0.75" },
      { minThreshold: "10000", maxThreshold: "99999999", feeRateInPercent: "0.5" },
    ],
  },
});
```

#### `updateStreamConfig(params): Promise<TransactionPayload>`

Updates an existing stream configuration (admin only). Same parameter shape as `initializeStreamConfig`.

#### `whiteListTokens(params): Promise<TransactionPayload>`

Adds token mint addresses to the whitelist of streamable tokens (admin only).

| Field    | Type        | Description                                 |
| -------- | ----------- | ------------------------------------------- |
| `admin`  | `Address`   | Admin public key.                           |
| `tokens` | `Address[]` | Array of token mint addresses to whitelist. |

### Stream methods

#### `createStream(params): Promise<TransactionPayload>`

Creates a new payment stream. Automatically fetches the fee quote from the Zebec backend and includes the fee transfer instruction in the transaction.

| Field                     | Type      | Description                                                                                                         |
| ------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------- |
| `sender`                  | `Address` | Sender's public key.                                                                                                |
| `receiver`                | `Address` | Recipient's public key.                                                                                             |
| `streamToken`             | `Address` | SPL token mint address.                                                                                             |
| `amount`                  | `Numeric` | Amount to stream in human-readable token units.                                                                     |
| `duration`                | `number`  | Stream duration in seconds.                                                                                         |
| `autoWithdrawFrequency`   | `number`  | Auto-withdrawal interval in seconds (must be in config's allowed frequencies when `automaticWithdrawal` is `true`). |
| `streamName`              | `string`  | Human-readable stream name (max 128 bytes).                                                                         |
| `startNow`                | `boolean` | Whether to start immediately.                                                                                       |
| `startTime`               | `number`  | Unix timestamp for scheduled start.                                                                                 |
| `cliffPercentage`         | `Numeric` | Percentage of amount locked until cliff expires.                                                                    |
| `automaticWithdrawal`     | `boolean` | Enable automatic withdrawals.                                                                                       |
| `cancelableByRecipient`   | `boolean` | Allow recipient to cancel.                                                                                          |
| `cancelableBySender`      | `boolean` | Allow sender to cancel.                                                                                             |
| `isPausable`              | `boolean` | Allow stream to be paused.                                                                                          |
| `transferableByRecipient` | `boolean` | Allow recipient to transfer.                                                                                        |
| `transferableBySender`    | `boolean` | Allow sender to transfer.                                                                                           |
| `canTopup`                | `boolean` | Allow adding funds to stream.                                                                                       |
| `rateUpdatable`           | `boolean` | Allow rate modifications.                                                                                           |
| `feePayer?`               | `Address` | Optional custom fee payer (defaults to sender).                                                                     |
| `streamMetadataKeypair?`  | `Keypair` | Optional custom metadata keypair (defaults to a generated keypair).                                                 |

#### `cancelStream(params): Promise<TransactionPayload>`

Cancels an existing stream. Either sender or receiver can cancel (if allowed by stream permissions).

| Field            | Type      | Description                                             |
| ---------------- | --------- | ------------------------------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address.                        |
| `user`           | `Address` | User canceling the stream (must be sender or receiver). |
| `feePayer?`      | `Address` | Optional custom fee payer.                              |

#### `pauseResumeStream(params): Promise<TransactionPayload>`

Toggles a stream between paused and active states. Only the sender can call this.

| Field            | Type      | Description                      |
| ---------------- | --------- | -------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address. |

#### `withdrawStream(params): Promise<TransactionPayload>`

Withdraws vested tokens from a stream to the receiver.

| Field            | Type      | Description                                        |
| ---------------- | --------- | -------------------------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address.                   |
| `receiver`       | `Address` | Recipient's public key.                            |
| `withdrawer?`    | `Address` | Optional custom withdrawer (defaults to receiver). |
| `feePayer?`      | `Address` | Optional custom fee payer.                         |

#### `changeStreamReceiver(params): Promise<TransactionPayload>`

Transfers stream ownership to a new recipient.

| Field            | Type      | Description                                                                         |
| ---------------- | --------- | ----------------------------------------------------------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address.                                                    |
| `newRecipient`   | `Address` | New recipient's public key.                                                         |
| `signer`         | `Address` | Currently authorized signer (sender or current receiver, depending on permissions). |

### Information retrieval

#### `getStreamMetadataInfo(streamMetadata, commitment?): Promise<StreamMetadataInfo>`

Retrieves detailed information about a stream. Amounts are returned as human-readable strings.

```ts
const info = await streamService.getStreamMetadataInfo("StreamMetadataAddressHere");
console.log(info.parties.sender.toBase58());
console.log(info.financials.depositedAmount); // human-readable
console.log(info.schedule.startTime);
console.log(info.permissions.isPausable);
```

#### `getStreamConfigInfo(configName, commitment?): Promise<StreamConfigInfo>`

Retrieves the global stream configuration for a given config name. Fee values are returned as human-readable percents.

```ts
const config = await streamService.getStreamConfigInfo("my-app-config");
console.log(config.frequencies);   // allowed auto-withdraw intervals
console.log(config.feeTiers);      // tiered fee schedule
console.log(config.feeVault.toBase58());
```

#### `getWhitelistedTokens(configName, commitment?): Promise<TokenMetadata[]>`

Fetches the list of whitelisted tokens with full on-chain mint info and Metaplex metadata.

```ts
const tokens = await streamService.getWhitelistedTokens("my-app-config");
tokens.forEach(t => {
  console.log(t.metadata?.symbol, t.mint.toBase58());
});
```

### Low-level instruction builders

Each high-level method has a corresponding instruction builder for composing custom transactions:

| Method                                      | Returns                           |
| ------------------------------------------- | --------------------------------- |
| `getCreateStreamInstruction(...)`           | `Promise<TransactionInstruction>` |
| `getCancelStreamInstruction(...)`           | `Promise<TransactionInstruction>` |
| `getPauseResumeStreamInstruction(...)`      | `Promise<TransactionInstruction>` |
| `getWithdrawStreamInstruction(...)`         | `Promise<TransactionInstruction>` |
| `getChangeStreamReceiverInstruction(...)`   | `Promise<TransactionInstruction>` |
| `getWhitelistTokensInstruction(...)`        | `Promise<TransactionInstruction>` |
| `getInitializeStreamConfigInstruction(...)` | `Promise<TransactionInstruction>` |
| `getUpdateStreamConfigInstruction(...)`     | `Promise<TransactionInstruction>` |

## Data types

All types are exported from the package root.

### `RpcNetwork`

```ts
type RpcNetwork = "mainnet-beta" | "devnet";
```

### `Numeric`

Human-readable number representation used for amounts and percentages.

```ts
type Numeric = string | number;
```

### `StreamConfigInfo`

Read shape returned by `getStreamConfigInfo`.

| Field               | Type          | Description                                   |
| ------------------- | ------------- | --------------------------------------------- |
| `configName`        | `string`      | The config name used to derive the PDA.       |
| `address`           | `PublicKey`   | The stream config PDA address.                |
| `admin`             | `PublicKey`   | Config admin address.                         |
| `withdrawerAccount` | `PublicKey`   | Address that performs automatic withdrawals.  |
| `whitelistedTokens` | `PublicKey[]` | Whitelisted token mint addresses.             |
| `platformFee`       | `number`      | Platform fee as a human-readable percent.     |
| `baseFee`           | `number`      | Base fee as a human-readable percent.         |
| `frequencies`       | `number[]`    | Allowed auto-withdraw frequencies in seconds. |
| `feeTiers`          | `FeeTier[]`   | Tiered fee schedule.                          |
| `feeVault`          | `PublicKey`   | Fee collection vault address.                 |

### `StreamMetadataInfo`

Read shape returned by `getStreamMetadataInfo`.

| Field                                 | Type        | Description                                               |
| ------------------------------------- | ----------- | --------------------------------------------------------- |
| `address`                             | `PublicKey` | Stream metadata account address.                          |
| `parties.sender`                      | `PublicKey` | Sender's public key.                                      |
| `parties.receiver`                    | `PublicKey` | Receiver's public key.                                    |
| `financials.streamToken`              | `PublicKey` | SPL token mint address.                                   |
| `financials.cliffPercentage`          | `number`    | Cliff percentage as a human-readable percent.             |
| `financials.depositedAmount`          | `string`    | Total deposited amount (human-readable).                  |
| `financials.withdrawnAmount`          | `string`    | Total withdrawn amount (human-readable).                  |
| `schedule.startTime`                  | `number`    | Unix timestamp when streaming starts.                     |
| `schedule.endTime`                    | `number`    | Unix timestamp when streaming ends.                       |
| `schedule.lastWithdrawTime`           | `number`    | Unix timestamp of the last withdrawal.                    |
| `schedule.frequency`                  | `number`    | Auto-withdraw frequency in seconds.                       |
| `schedule.duration`                   | `number`    | Total stream duration in seconds.                         |
| `schedule.pausedTimestamp`            | `number`    | Unix timestamp when the stream was paused (0 if never).   |
| `schedule.pausedInterval`             | `number`    | Total paused duration in seconds.                         |
| `schedule.canceledTimestamp`          | `number`    | Unix timestamp when the stream was canceled (0 if never). |
| `permissions.cancelableBySender`      | `boolean`   | Whether sender can cancel.                                |
| `permissions.cancelableByRecipient`   | `boolean`   | Whether recipient can cancel.                             |
| `permissions.automaticWithdrawal`     | `boolean`   | Whether automatic withdrawals are enabled.                |
| `permissions.transferableBySender`    | `boolean`   | Whether sender can reassign the receiver.                 |
| `permissions.transferableByRecipient` | `boolean`   | Whether receiver can reassign themselves.                 |
| `permissions.canTopup`                | `boolean`   | Whether the stream supports top-ups.                      |
| `permissions.isPausable`              | `boolean`   | Whether the stream supports pause/resume.                 |
| `permissions.rateUpdatable`           | `boolean`   | Whether the stream rate can be updated.                   |
| `streamName`                          | `string`    | Human-readable stream name.                               |

### `CreateStreamParams`

Parameters for `createStream`.

| Field                     | Type      | Description                                      |
| ------------------------- | --------- | ------------------------------------------------ |
| `sender`                  | `Address` | Sender's public key.                             |
| `receiver`                | `Address` | Recipient's public key.                          |
| `streamToken`             | `Address` | SPL token mint address.                          |
| `amount`                  | `Numeric` | Amount to stream in human-readable token units.  |
| `duration`                | `number`  | Stream duration in seconds.                      |
| `autoWithdrawFrequency`   | `number`  | Auto-withdrawal interval in seconds.             |
| `streamName`              | `string`  | Human-readable stream name (max 128 bytes).      |
| `startNow`                | `boolean` | Whether to start immediately.                    |
| `startTime`               | `number`  | Unix timestamp for scheduled start.              |
| `cliffPercentage`         | `Numeric` | Percentage of amount locked until cliff expires. |
| `automaticWithdrawal`     | `boolean` | Enable automatic withdrawals.                    |
| `cancelableByRecipient`   | `boolean` | Allow recipient to cancel.                       |
| `cancelableBySender`      | `boolean` | Allow sender to cancel.                          |
| `isPausable`              | `boolean` | Allow stream to be paused.                       |
| `transferableByRecipient` | `boolean` | Allow recipient to transfer.                     |
| `transferableBySender`    | `boolean` | Allow sender to transfer.                        |
| `canTopup`                | `boolean` | Allow adding funds to stream.                    |
| `rateUpdatable`           | `boolean` | Allow rate modifications.                        |
| `feePayer?`               | `Address` | Optional custom fee payer.                       |
| `streamMetadataKeypair?`  | `Keypair` | Optional custom metadata keypair.                |

### `CancelStreamParams`

Parameters for `cancelStream`.

| Field            | Type      | Description                                             |
| ---------------- | --------- | ------------------------------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address.                        |
| `user`           | `Address` | User canceling the stream (must be sender or receiver). |
| `feePayer?`      | `Address` | Optional custom fee payer.                              |

### `WithdrawStreamParams`

Parameters for `withdrawStream`.

| Field            | Type      | Description                      |
| ---------------- | --------- | -------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address. |
| `receiver`       | `Address` | Recipient's public key.          |
| `withdrawer?`    | `Address` | Optional custom withdrawer.      |
| `feePayer?`      | `Address` | Optional custom fee payer.       |

### `ChangeStreamReceiverParams`

Parameters for `changeStreamReceiver`.

| Field            | Type      | Description                      |
| ---------------- | --------- | -------------------------------- |
| `streamMetadata` | `Address` | Stream metadata account address. |
| `newRecipient`   | `Address` | New recipient's public key.      |
| `signer`         | `Address` | Currently authorized signer.     |

### `InitializeStreamConfigParams` / `UpdateStreamConfigParams`

Parameters for `initializeStreamConfig` and `updateStreamConfig`.

| Field                       | Type        | Description                                           |
| --------------------------- | ----------- | ----------------------------------------------------- |
| `admin?`                    | `Address`   | Optional admin address (defaults to provider wallet). |
| `config.baseFeePercent`     | `Numeric`   | Base fee as a percent.                                |
| `config.platformFeePercent` | `Numeric`   | Platform fee as a percent.                            |
| `config.frequencies`        | `number[]`  | Allowed auto-withdraw frequencies in seconds.         |
| `config.withdrawAccount`    | `Address`   | Withdraw account address.                             |
| `config.feeVault`           | `Address`   | Fee vault address.                                    |
| `config.feeTiers`           | `FeeTier[]` | Tiered fee schedule.                                  |

### `WhiteListTokensParams`

Parameters for `whiteListTokens`.

| Field    | Type        | Description                        |
| -------- | ----------- | ---------------------------------- |
| `admin`  | `Address`   | Admin public key.                  |
| `tokens` | `Address[]` | Token mint addresses to whitelist. |

### `FeeTier`

A single fee tier band.

| Field              | Type      | Description                                   |
| ------------------ | --------- | --------------------------------------------- |
| `minThreshold`     | `Numeric` | Minimum USD amount for this tier (inclusive). |
| `maxThreshold`     | `Numeric` | Maximum USD amount for this tier (exclusive). |
| `feeRateInPercent` | `Numeric` | Fee rate for this tier as a percent.          |

### `TokenMetadata`

On-chain token metadata with Metaplex resolution.

| Field             | Type                                                      | Description                            |
| ----------------- | --------------------------------------------------------- | -------------------------------------- |
| `mint`            | `PublicKey`                                               | Token mint address.                    |
| `decimals`        | `number`                                                  | Token decimals.                        |
| `freezeAuthority` | `PublicKey \| null`                                       | Freeze authority (if any).             |
| `supply`          | `string`                                                  | Total supply (human-readable).         |
| `isInitialized`   | `boolean`                                                 | Whether the mint is initialized.       |
| `mintAuthority`   | `PublicKey \| null`                                       | Mint authority (if any).               |
| `metadata`        | `{ address, updateAuthority, name, symbol, uri } \| null` | Metaplex metadata (null if not found). |

### `StreamFeeInfo`

Returned by the Zebec backend fee quote API and used internally during stream creation.

| Field             | Type                                          | Description                    |
| ----------------- | --------------------------------------------- | ------------------------------ |
| `tokenSymbol`     | `string`                                      | Stream token symbol.           |
| `mintAddress`     | `string`                                      | Stream token mint address.     |
| `chain`           | `string`                                      | Chain identifier.              |
| `streamAmount`    | `string`                                      | Raw stream amount.             |
| `streamAmountUi`  | `string`                                      | Human-readable stream amount.  |
| `tokenPriceUsd`   | `number`                                      | Token price in USD.            |
| `streamAmountUsd` | `number`                                      | Stream amount in USD.          |
| `feeTier`         | `{ tier, range, feeRatePercent }`             | Matched fee tier details.      |
| `feeRatePercent`  | `number`                                      | Effective fee rate percent.    |
| `feeAmountUsd`    | `number`                                      | Fee amount in USD.             |
| `feeToken`        | `{ symbol, decimals, priceUsd, mintAddress }` | Token used to pay fees.        |
| `feeAmount`       | `number`                                      | Fee amount in fee token units. |
| `feeAmountRaw`    | `string`                                      | Raw fee amount (atomic units). |

## TransactionPayload

All write methods return a `TransactionPayload` (from `@zebec-network/solana-common`) rather than submitting directly, giving consumers control over the signing and submission flow.

```ts
class TransactionPayload {
  execute(): Promise<string>;
}
```

Call `.execute()` to sign (via the provider's wallet) and submit the transaction to the network. The payload internally handles address lookup tables, fee payer assignment, and optional signer injection.

The SDK also maps program error codes to human-readable messages using the IDL's error definitions, so failed transactions surface descriptive error messages.

## Provider setup

### AnchorProvider (read/write)

Use for operations that sign transactions:

```ts
import { createAnchorProvider } from "@zebec-network/zebec-stream-sdk";

const provider = createAnchorProvider(connection, wallet, {
  commitment: "confirmed",
  preflightCommitment: "confirmed",
});
```

### ReadonlyProvider (read-only)

Use for read-only queries without a wallet:

```ts
import { createReadonlyProvider } from "@zebec-network/zebec-stream-sdk";

const provider = createReadonlyProvider(connection, optionalWalletAddress);
```

The `ReadonlyProvider` class exposes `connection` and an optional `walletAddress` for convenience in read-only contexts.

### Wallet interface

The SDK exports an `AnchorWallet` interface for wallets that work with `createAnchorProvider`:

```ts
import type { AnchorWallet } from "@zebec-network/zebec-stream-sdk";
```

## PDA utilities

```ts
import { deriveStreamConfigPda, deriveStreamVaultPda } from "@zebec-network/zebec-stream-sdk";

// Derive the stream config PDA
const [configPda] = deriveStreamConfigPda("my-app-config", programId);

// Derive the stream vault PDA for a given stream metadata address
const [vaultPda] = deriveStreamVaultPda(streamMetadataAddress, programId);
```

## Utilities

### Fee quote

Fetch a fee quote from the Zebec backend for a given token and stream amount. This is used internally by `createStream`, but can be called directly:

```ts
import { getFeeInfoForStream } from "@zebec-network/zebec-stream-sdk";

const feeInfo = await getFeeInfoForStream(tokenMint, amount, decimals, "devnet");
console.log(feeInfo.feeAmountRaw);
console.log(feeInfo.feeTier.range);
```

### On-chain fee rate lookup

Given a USD amount and on-chain fee tiers, compute the fee rate in basis points:

```ts
import { getFeeRateForUsdAmount } from "@zebec-network/zebec-stream-sdk";

const feeBps = getFeeRateForUsdAmount("5000", feeTiers); // returns number in bps
```

## Error handling

The SDK surfaces three classes of errors:

1. **Validation errors** — thrown immediately for invalid parameters (e.g., mismatched network, invalid stream frequency, stream name too long).
2. **Simulation errors** — returned by the Solana RPC during transaction simulation.
3. **Transaction failures** — on-chain errors mapped via the program IDL to human-readable messages.

Common error cases to handle:

```ts
try {
  const tx = await streamService.createStream(params);
  const signature = await tx.execute();
  console.log("Success:", signature);
} catch (error) {
  if (error.message.includes("Invalid stream frequency")) {
    console.error("autoWithdrawFrequency must be one of the config's allowed frequencies");
  } else if (error.message.includes("Network mismatch")) {
    console.error("Provider connection network does not match the service network");
  } else {
    console.error("Stream operation failed:", error);
  }
}
```

## Constants

| Constant                              | Description                                                            |
| ------------------------------------- | ---------------------------------------------------------------------- |
| `STREAM_PROGRAM_ID`                   | Program ID per network (`zSTRMmYcFF8SPdHmsAmAUjBnx4zDHvnqqGz2mPcc5QC`) |
| `STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS` | Address lookup table per network                                       |
| `SUPERAPP_BACKEND_URL`                | Zebec backend URL per network (used for fee quotes)                    |
| `STREAM_NAME_BUFFER_SIZE`             | Fixed buffer size for stream names (128 bytes)                         |

## Network support

| Network      | Status        |
| ------------ | ------------- |
| Mainnet Beta | Supported     |
| Devnet       | Supported     |
| Testnet      | Not supported |

## Related

* [Streaming SDK overview](/developer-docs/sdks/streaming-sdk.md)
* [Enterprise Payroll streaming guide](/zebec-application-suite/enterprise-payroll/streaming-payroll.md)
* [Partner API overview](/developer-docs/partner-api.md)
