Quick Start with Synapse SDK
The Synapse SDK is your gateway to Filecoin Onchain Cloud, a decentralized, programmable cloud platform built on Filecoin. The SDK handles all the complexity of blockchain interactions, provider selection, and data management, so you can focus on building your application.
By the end of this guide, you’ll understand how to:
- Install and configure the Synapse SDK
- Connect to Filecoin networks (mainnet and calibration)
- Prepare and fund your storage balance
- Upload and download data
Prerequisites
Section titled “Prerequisites”- FIL for gas fees. On testnet, get tFIL from the Calibration Faucet. For mainnet, see Getting FIL.
- USDFC for storage payments. On testnet, get tUSDFC from the USDFC Faucet. For mainnet, see Getting USDFC.
Installation
Section titled “Installation”The Synapse SDK works in Node.js and the browser. Install it with your preferred package manager:
npm install @filoz/synapse-sdk viempnpm add @filoz/synapse-sdk viemyarn add @filoz/synapse-sdk viembun add @filoz/synapse-sdk viemviem is a peer dependency and must be installed separately.
Quick Start
Section titled “Quick Start”The Synapse class provides a complete, easy-to-use interface for interacting with Filecoin storage services.
Get started with storage in just a few lines of code.
import { class Synapse
Synapse, const mainnet: Chain
mainnet } from "@filoz/synapse-sdk"import { function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount
privateKeyToAccount } from 'viem/accounts'
// 1) Initialize the Synapse SDKconst const synapse: Synapse
synapse = class Synapse
Synapse.Synapse.create(options: SynapseOptions): Synapse
create({ SynapseOptions.account: `0x${string}` | Account
account: function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount
privateKeyToAccount('0x...'), SynapseOptions.source: string | null
source: 'my-app', SynapseOptions.chain?: Chain | undefined
chain: const mainnet: Chain
mainnet, // default is calibration testnet // Uncomment for high-performance incentive-aligned data retrievability through Filecoin Beam // withCDN: true})// 2) Prepare account (single tx handles deposit + approval)const const file: Uint8Array<ArrayBuffer>
file = new var TextEncoder: new () => TextEncoder
The TextEncoder interface takes a stream of code points as input and emits a stream of UTF-8 bytes.
TextEncoder().TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>
The TextEncoder.encode() method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object.
encode( `🚀 Welcome to decentralized storage on Filecoin Onchain Cloud! Your data is safe here. 🌍 You need to make sure to meet the minimum size requirement of 127 bytes per upload.`);const const prep: PrepareResult
prep = await const synapse: Synapse
synapse.Synapse.storage: StorageManager
storage.StorageManager.prepare(options: PrepareOptions): Promise<PrepareResult>
prepare({ PrepareOptions.dataSize: bigint
dataSize: var BigInt: BigIntConstructor(value: bigint | boolean | number | string) => bigint
BigInt(const file: Uint8Array<ArrayBuffer>
file.Uint8Array<ArrayBuffer>.byteLength: number
The length in bytes of the array.
byteLength),})if (const prep: PrepareResult
prep.PrepareResult.transaction: { depositAmount: bigint; includesApproval: boolean; execute: (options?: { onHash?: (hash: Hash) => void; }) => Promise<{ hash: Hash; receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null; }>;} | null
transaction) { const { const hash: `0x${string}`
hash } = await const prep: PrepareResult
prep.PrepareResult.transaction: { depositAmount: bigint; includesApproval: boolean; execute: (options?: { onHash?: (hash: Hash) => void; }) => Promise<{ hash: Hash; receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null; }>;}
transaction.execute: (options?: { onHash?: (hash: Hash) => void;}) => Promise<{ hash: Hash; receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;}>
execute() var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`✅ Account funded and approved (tx: ${const hash: `0x${string}`
hash})`)}// 3) Upload — stores 2 copies across independent providers for durabilityconst { const pieceCid: PieceLink
pieceCid, const size: number
size, const complete: boolean
complete, const copies: CopyResult[]
copies, const failedAttempts: FailedAttempt[]
failedAttempts } = await const synapse: Synapse
synapse.Synapse.storage: StorageManager
storage.StorageManager.upload(data: UploadPieceStreamingData, options?: StorageManagerUploadOptions): Promise<UploadResult>
upload(const file: Uint8Array<ArrayBuffer>
file)var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`✅ Upload complete!`);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`PieceCID: ${const pieceCid: PieceLink
pieceCid}`);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`Size: ${const size: number
size} bytes`);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`Stored on ${const copies: CopyResult[]
copies.Array<CopyResult>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length} providers`);if (!const complete: boolean
complete) var console: Console
console.Console.warn(...data: any[]): void
The console.warn() static method outputs a warning message to the console at the 'warning' log level.
warn(`${const failedAttempts: FailedAttempt[]
failedAttempts.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length} copy attempt(s) failed`);// 4) Downloadconst const bytes: Uint8Array<ArrayBufferLike>
bytes = await const synapse: Synapse
synapse.Synapse.storage: StorageManager
storage.StorageManager.download(options: StorageManagerDownloadOptions): Promise<Uint8Array>
download({ pieceCid: string | PieceLink
pieceCid })const const decodedText: string
decodedText = new var TextDecoder: new (label?: string, options?: TextDecoderOptions) => TextDecoder
The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, KOI8-R, GBK, etc.
TextDecoder().TextDecoder.decode(input?: AllowSharedBufferSource, options?: TextDecodeOptions): string
The TextDecoder.decode() method returns a string containing text decoded from the buffer passed as a parameter.
decode(const bytes: Uint8Array<ArrayBufferLike>
bytes);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`✅ Download successful!`);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(`Downloaded data: ${const decodedText: string
decodedText}\n`);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("🎉 Data storage and retrieval successful!");Now let’s break down each step…
-
Initialize the SDK
Set up the Synapse SDK with your credentials. In Node.js, you’ll typically use a private key:
constsynapse =const synapse: SynapseSynapse.class Synapsecreate({Synapse.create(options: SynapseOptions): Synapseaccount:SynapseOptions.account: `0x${string}` | AccountprivateKeyToAccount('0x...'),function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccountsource: 'my-app',SynapseOptions.source: string | nullchain:SynapseOptions.chain?: Chain | undefinedmainnet, // default is calibration testnetconst mainnet: Chain})In the browser, connect to the user’s wallet instead:
import 'viem/window'import {custom } from 'viem'function custom<provider extends EthereumProvider>(provider: provider, config?: CustomTransportConfig): CustomTransportconst [address] = awaitconst address: `0x${string}`window.var window: Window & typeof globalThisThe
windowproperty of a Window object points to the window object itself.ethereum!.Window.ethereum?: {on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;request: EIP1193RequestFn<EIP1474Methods>;} | undefinedrequest({request: <undefined, {method: "eth_requestAccounts";}, `0x${string}`[]>(args: {method: "eth_requestAccounts";}, options?: EIP1193RequestOptions | undefined) => Promise<`0x${string}`[]>method: 'eth_requestAccounts' })method: "eth_requestAccounts"constsynapse =const synapse: SynapseSynapse.class Synapsecreate({Synapse.create(options: SynapseOptions): Synapseaccount:SynapseOptions.account: `0x${string}` | Accountaddress,const address: `0x${string}`transport:SynapseOptions.transport?: Transport | undefinedcustom(custom<{on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;request: EIP1193RequestFn<EIP1474Methods>;}>(provider: {on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;request: EIP1193RequestFn<EIP1474Methods>;}, config?: CustomTransportConfig): CustomTransportwindow.var window: Window & typeof globalThisThe
windowproperty of a Window object points to the window object itself.ethereum!),Window.ethereum?: {on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;request: EIP1193RequestFn<EIP1474Methods>;} | undefinedsource: 'my-app',SynapseOptions.source: string | nullchain:SynapseOptions.chain?: Chain | undefinedmainnet, // default is calibration testnetconst mainnet: Chain})The
sourceparameter identifies your application. It is stored as metadata on each dataset so that multiple apps sharing the same wallet can distinguish their own data. -
Payment Setup
The
prepare()method calculates the exact deposit needed for your data size and returns a single transaction that handles both funding and approval.To size your deposit, check the up-to-date rates in Pricing and use the storage costs guide for a detailed breakdown.
// Check current USDFC balanceconstwalletBalance = awaitconst walletBalance: bigintsynapse.const synapse: Synapsepayments.Synapse.payments: PaymentsServicewalletBalance({PaymentsService.walletBalance(options?: {token?: TokenIdentifier;}): Promise<bigint>token:token?: string | undefinedTOKENS.const TOKENS: {readonly USDFC: "USDFC";readonly FIL: "FIL";}USDFC });type USDFC: "USDFC"constformattedBalance =const formattedBalance: stringformatUnits(function formatUnits(value: bigint, options?: FormatUnitsOptions): stringwalletBalance);const walletBalance: bigint// Prepare accountconstprep = awaitconst prep: PrepareResultsynapse.const synapse: Synapsestorage.Synapse.storage: StorageManagerprepare({StorageManager.prepare(options: PrepareOptions): Promise<PrepareResult>dataSize: 1073741824n, // 1 GiBPrepareOptions.dataSize: bigint});console.var console: Consolelog("Deposit needed:",Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.prep.const prep: PrepareResultcosts.PrepareResult.costs: getUploadCosts.OutputTypedepositNeeded);depositNeeded: bigintconsole.var console: Consolelog("Rate per month:",Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.prep.const prep: PrepareResultcosts.PrepareResult.costs: getUploadCosts.OutputTyperate.rate: {perEpoch: bigint;perMonth: bigint;}perMonth);perMonth: bigintconsole.var console: Consolelog("Ready to upload:",Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.prep.const prep: PrepareResultcosts.PrepareResult.costs: getUploadCosts.OutputTypeready);ready: boolean// Execute the transaction if needed (handles deposit + approval in one tx)if (prep.const prep: PrepareResulttransaction) {PrepareResult.transaction: {depositAmount: bigint;includesApproval: boolean;execute: (options?: {onHash?: (hash: Hash) => void;}) => Promise<{hash: Hash;receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;}>;} | nullconst {hash } = awaitconst hash: `0x${string}`prep.const prep: PrepareResulttransaction.PrepareResult.transaction: {depositAmount: bigint;includesApproval: boolean;execute: (options?: {onHash?: (hash: Hash) => void;}) => Promise<{hash: Hash;receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;}>;}execute();execute: (options?: {onHash?: (hash: Hash) => void;}) => Promise<{hash: Hash;receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;}>console.var console: Consolelog(`Account funded and approved (tx: ${Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.hash})`);const hash: `0x${string}`} -
Store and Download Data
Upload data to decentralized storage and retrieve it:
// Upload data (stores 2 copies by default for durability)constfile = newconst file: Uint8Array<ArrayBuffer>TextEncoder().var TextEncoder: new () => TextEncoderThe
TextEncoderinterface takes a stream of code points as input and emits a stream of UTF-8 bytes.encode(TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>The
TextEncoder.encode()method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object.`Welcome to decentralized storage on Filecoin Onchain Cloud!Your data is safe here.You need to make sure to meet the minimum sizerequirement of 127 bytes per upload.`);const {pieceCid,const pieceCid: PieceLinkcomplete,const complete: booleancopies,const copies: CopyResult[]failedAttempts } = awaitconst failedAttempts: FailedAttempt[]synapse.const synapse: Synapsestorage.Synapse.storage: StorageManagerupload(StorageManager.upload(data: UploadPieceStreamingData, options?: StorageManagerUploadOptions): Promise<UploadResult>file);const file: Uint8Array<ArrayBuffer>console.var console: Consolelog(`Stored on ${Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.copies.const copies: CopyResult[]length} providers`);Array<CopyResult>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
if (!complete)const complete: booleanconsole.var console: Consolewarn(`${Console.warn(...data: any[]): voidThe
console.warn()static method outputs a warning message to the console at the 'warning' log level.failedAttempts.const failedAttempts: FailedAttempt[]length} copy attempt(s) failed`);Array<T>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
// Download data from any provider that has itconstdownloadedData = awaitconst downloadedData: Uint8Array<ArrayBufferLike>synapse.const synapse: Synapsestorage.Synapse.storage: StorageManagerdownload({StorageManager.download(options: StorageManagerDownloadOptions): Promise<Uint8Array>pieceCid });pieceCid: string | PieceLinkconstdecodedText = newconst decodedText: stringTextDecoder().var TextDecoder: new (label?: string, options?: TextDecoderOptions) => TextDecoderThe
TextDecoderinterface represents a decoder for a specific text encoding, such asUTF-8,ISO-8859-2,KOI8-R,GBK, etc.decode(TextDecoder.decode(input?: AllowSharedBufferSource, options?: TextDecodeOptions): stringThe
TextDecoder.decode()method returns a string containing text decoded from the buffer passed as a parameter.downloadedData);const downloadedData: Uint8Array<ArrayBufferLike>console.var console: Consolelog(`Downloaded data: ${Console.log(...data: any[]): voidThe
console.log()static method outputs a message to the console.decodedText}`);const decodedText: string
Next Steps
Section titled “Next Steps”You’ve just stored and retrieved data on Filecoin. See the Developer Guides overview to find the right approach for your application, then dive into specific topics:
- Upload Pipeline - From simple one-liner to manual store, pull, and commit control
- Storage Operations - Data set management, retrieval, and lifecycle
- Payment Operations - Fund your account and manage storage payments
- Session Keys - Delegate signing to ephemeral keys for better UX
- API Reference - Complete SDK classes, methods, and types
- Example Application - Full-stack upload dapp
Want to understand the protocol? See Foundations & Architecture for how PDP, Filecoin Pay, and the service provider network fit together.
Join the #fil-builders on Filecoin Slack or Telegram for help and discussions.