Javascript SDK

Interact with the protocol to create streams and vesting contracts

This package allows you to create, createMultiple, withdraw, cancel, topup, transfer, update a token stream. You can also getOne stream and get multiple streams.

Installation

npm i -s @streamflow/stream

or

yarn add @streamflow/stream


Documentation

API Documentation available here: docs site →

Import SDK

Most common imports:

import { BN } from "bn.js";
import { Types, GenericStreamClient, getBN, getNumberFromBN } from "@streamflow/stream";

Check the SDK for other types and utility functions.


Create StreamClient instance

Before creating and manipulating streams, a chain-specific or generic StreamClient instance must be created. All stream functions are methods in this instance.

Solana

import {
  StreamflowSolana,
  Types,
} from "@streamflow/stream";

const solanaClient = new StreamflowSolana.SolanaStreamClient(
  "https://api.mainnet-beta.solana.com"
);

Aptos

import {
  StreamflowAptos,
  Types,
} from "@streamflow/stream";

const aptosClient = new StreamflowAptos.AptosStreamClient(
  "https://fullnode.mainnet.aptoslabs.com/v1"
);

Ethereum

import {
  StreamflowEVM,
  Types,
} from "@streamflow/stream";

const ethereumClient = new StreamflowEVM.EvmStreamClient(
  "YOUR_ETHEREUM_NODE_URL",
  Types.IChain.Ethereum,
  signer // will be sender in a stream and authority for all stream related transactions
);

Polygon

import {
  StreamflowEVM,
  Types,
} from "@streamflow/stream";

const polygonClient = new StreamflowEVM.EvmStreamClient(
  "YOUR_POLYGON_NODE_URL",
  Types.IChain.Polygon,
  signer // will be sender in a stream and authority for all stream related transactions
);

BNB Smart Chain

import {
  StreamflowEVM,
  Types,
} from "@streamflow/stream";

const bnbClient = new StreamflowEVM.EvmStreamClient(
  "https://bsc-dataseed1.binance.org/",
  Types.IChain.BNB,
  signer // will be sender in a stream and authority for all stream related transactions
);

Generic Stream Client

GenericStreamClient provides an isomorphic interface to work with streams agnostic of the chain.

import { GenericStreamClient, Types } from "@streamflow/stream";

const client =
  new GenericStreamClient<Types.IChain.Solana>({
    chain: Types.IChain.Solana, // Blockchain
    clusterUrl: "https://api.mainnet-beta.solana.com", // RPC cluster URL
    cluster: Types.ICluster.Mainnet, // (optional) (default: Mainnet)
    // ...rest chain specific params e.g. commitment for Solana
  });

Create stream

Creating a stream requires a wallet with tokens for gas fees.

const createStreamParams: Types.ICreateStreamData = {
  recipient: "4ih00075bKjVg000000tLdk4w42NyG3Mv0000dc0M00", // Recipient address.
  tokenId: "DNw99999M7e24g99999999WJirKeZ5fQc6KY999999gK", // Token mint address.
  start: 1643363040, // Timestamp (in seconds) when the stream/token vesting starts.
  amount: getBN(100, 9), // depositing 100 tokens with 9 decimals mint.
  period: 1, // Time step (period) in seconds per which the unlocking occurs.
  cliff: 1643363160, // Vesting contract "cliff" timestamp in seconds.
  cliffAmount: new BN(10), // Amount unlocked at the "cliff" timestamp.
  amountPerPeriod: getBN(5, 9), // Release rate: how many tokens are unlocked per each period.
  name: "Transfer to Jane Doe.", // The stream name or subject.
  canTopup: false, // setting to FALSE will effectively create a vesting contract.
  cancelableBySender: true, // Whether or not sender can cancel the stream.
  cancelableByRecipient: false, // Whether or not recipient can cancel the stream.
  transferableBySender: true, // Whether or not sender can transfer the stream.
  transferableByRecipient: false, // Whether or not recipient can transfer the stream.
  automaticWithdrawal: true, // Whether or not a 3rd party (e.g. cron job, "cranker") can initiate a token withdraw/transfer.
  withdrawalFrequency: 10, // Relevant when automatic withdrawal is enabled. If greater than 0 our withdrawor will take care of withdrawals. If equal to 0 our withdrawor will skip, but everyone else can initiate withdrawals.
  partner: null, //  (optional) Partner's wallet address (string | null).
};

const solanaParams = {
    sender: wallet, // SignerWalletAdapter or Keypair of Sender account
    isNative: // [optional] [WILL CREATE A wSOL STREAM] Wether Stream or Vesting should be paid with Solana native token or not
};

const aptosParams = {
    senderWallet: wallet, // AptosWalletAdapter Wallet of sender
};

const ethereumParams = undefined;

try {
  const { ixs, tx, metadata } = await client.create(createStreamParams, solanaParams); // second argument differ depending on a chain
} catch (exception) {
  // handle exception
}

Protocol

a program that lives on chain, an implementation of Scheduled Token Transfer

Stream

an entity that is created by the Protocol, contains information about Token Transfer

Contract

a synonym for a Stream. In the code there is no consistency how we name it, in the Protocol we often use Contract referring to a Stream.

Sender

an account that creates a Scheduled Token Transfer

Recipient

an account that is the receiver of Tokens

Referral

an account that will be used to calculate streamflow and referral fees when creating a Stream

Partner

a synonym for a Referral

Treasury

a Streamflow account that receives fees as a reward

Withdrawor

a Streamflow account that processes automated Token Transfers to the Recipient

Protocol

a program that lives on chain, an implementation of Scheduled Token Transfer

Stream

an entity that is created by the Protocol, contains information about Token Transfer


Create multiple streams at once

const recipients = [
  {
    recipient: "4ih00075bKjVg000000tLdk4w42NyG3Mv0000dc0M00", // Solana recipient address.
    amount: getBN(100, 9), // depositing 100 tokens with 9 decimals mint.
    name: "January Payroll", // The stream name/subject.
    cliffAmount: getBN(10, 9), // amount released on cliff for this recipient
    amountPerPeriod: getBN(1, 9), //amount released every specified period epoch
  },
];
const createStreamParams: Types.ICreateMultipleStreamData = {
  recipients: recipients, // Solana recipient address.
  tokenId: "DNw99999M7e24g99999999WJirKeZ5fQc6KY999999gK", // SPL Token mint.
  start: 1643363040, // Timestamp (in seconds) when the stream/token vesting starts.
  period: 1, // Time step (period) in seconds per which the unlocking occurs.
  cliff: 1643363160, // Vesting contract "cliff" timestamp in seconds.
  canTopup: false, // setting to FALSE will effectively create a vesting contract.
  cancelableBySender: true, // Whether or not sender can cancel the stream.
  cancelableByRecipient: false, // Whether or not recipient can cancel the stream.
  transferableBySender: true, // Whether or not sender can transfer the stream.
  transferableByRecipient: false, // Whether or not recipient can transfer the stream.
  automaticWithdrawal: true, // Whether or not a 3rd party (e.g. cron job, "cranker") can initiate a token withdraw/transfer.
  withdrawalFrequency: 10, // Relevant when automatic withdrawal is enabled. If greater than 0 our withdrawor will take care of withdrawals. If equal to 0 our withdrawor will skip, but everyone else can initiate withdrawals.
  partner: null, //  (optional) Partner's wallet address (string | null).
};

const solanaParams = {
    sender: wallet, // SignerWalletAdapter or Keypair of Sender account
    isNative: // [optional] [WILL CREATE A wSOL STREAM] Wether Stream or Vesting should be paid with Solana native token or not
};

const aptosParams = {
    senderWallet: wallet, // AptosWalletAdapter Wallet of sender
};

const ethereumParams = undefined;

try {
  const { txs } = await client.createMultiple(createMultiStreamsParams, solanaParams);
} catch (exception) {
  // handle exception
}

Identifying created contracts (streams or vesting)

All Stream Clients return Types.ICreateResult object (createdMultiple returns an Array) that has the following structure

interface ICreateResult {
  ixs: (TransactionInstruction | Types.TransactionPayload)[];
  txId: string;
  metadataId: MetadataId;
}

metadataId is the id of the created stream.


Interacting with existing streams

const withdrawStreamParams: Types.IWithdrawData = {
  id: "AAAAyotqTZZMAAAAmsD1JAgksT8NVAAAASfrGB5RAAAA", // Identifier of a stream to be withdrawn from.
  amount: getBN(100, 9), // Requested amount to withdraw. If stream is completed, the whole amount will be withdrawn.
};

const solanaParams = {
    invoker: wallet, // SignerWalletAdapter or Keypair signing the transaction
};

const aptosParams = {
    senderWallet: wallet, // AptosWalletAdapter Wallet of wallet signing the transaction
    tokenId: "0x1::aptos_coin::AptosCoin", // Aptos Coin type
};

const ethereumParams = undefined;

try {
  const { ixs, tx } = await client.withdraw(withdrawStreamParams, solanaParams);
} catch (exception) {
  // handle exception
}

Get one stream by its ID

const data: Types.IGetOneData = {
  id: "AAAAyotqTZZMAAAAmsD1JAgksT8NVAAAASfrGB5RAAAA", // Identifier of a stream
};

try {
  const stream = await client.getOne(data);
} catch (exception) {
  // handle exception
}

Get multiple streams for a specific wallet address

const data: Types.IGetAllData = {
  address: "99h00075bKjVg000000tLdk4w42NyG3Mv0000dc0M99",
  type: Types.StreamType.All,
  direction: Types.StreamDirection.All,
};

try {
  const streams = client.get(data);
} catch (exception) {
  // handle exception
}

Fetching unlocked amount

const stream = await client.getOne({
  id: "AAAAyotqTZZMAAAAmsD1JAgksT8NVAAAASfrGB5RAAAA",
});

const unlocked = stream.unlocked(tsInSeconds); // bn amount unlocked at the tsInSeconds
console.log(getNumberFromBN(unlocked, 9));
  • Note: unlocked amount is determined based on configuration set on creation, no dynamic data is involved.


Reading withdrawn amount and remaining funds

const stream = await client.getOne({
  id: "AAAAyotqTZZMAAAAmsD1JAgksT8NVAAAASfrGB5RAAAA",
});
const withdrawn = stream.withdrawnAmount; // bn amount withdrawn already
console.log(getNumberFromBN(wihtdrawn, 9));
const remaining = stream.remaining(9); // amount of remaining funds
console.log(remaining);

Please note that transaction fees for the scheduled transfers are paid upfront by the stream creator (sender).

Our Github: https://github.com/streamflow-finance

To see some examples of what you can build with Streamflow, check out: https://streamflow.finance/integrations.

Last updated