Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitbook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root: ./docs/

structure:
readme: README.md
summary: SUMMARY.md
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,5 @@ jobs:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm test
- run: pnpm build
- run: mkdir -p artifacts
- run: pnpm pack --pack-destination ./artifacts
- run: pnpm verify
- run: pnpm package:verify
3 changes: 1 addition & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ jobs:
- name: Install trusted-publishing-capable npm
run: npm install --global "npm@^11.15.0"
- run: pnpm install --frozen-lockfile
- run: pnpm test
- run: pnpm build
- run: pnpm package:verify
- name: Verify release tag
run: >-
node --input-type=module -e
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ adapter can be added without changing application code.

> The `0.x` API is under active development.

Detailed guides live in [`docs/`](./docs):
Detailed, GitBook-ready guides live in [`docs/`](./docs):

- [Documentation home](./docs/README.md)
- [Getting started](./docs/getting-started.md)
- [Configuration](./docs/configuration.md)
- [Flow streams](./docs/flows.md)
- [Transactions and authorization](./docs/transactions.md)
- [Example implementations](./docs/examples.md)
- [Backend indexing](./docs/backend-indexing.md)
- [Multichain architecture](./docs/multichain-architecture.md)
- [Generated binding provenance](./docs/generated-bindings.md)
- [Router, Stream NFT, and Paymaster development](./docs/router-paymaster.md)
- [API reference](./docs/api-reference.md)
- [Troubleshooting and versioning](./docs/troubleshooting-and-versioning.md)
- [SDK delivery checklist](./docs/delivery-checklist.md)

## Install

Expand Down
35 changes: 35 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Fundable SDK

`@fundable/sdk` is the TypeScript integration layer for Fundable Protocol.
It gives applications a typed, high-level API for token streams while keeping
chain-specific transaction handling inside adapters.

Stellar is the first production adapter. The shared model is intentionally
chain-neutral so an EVM adapter can be added without redesigning application
code.

## What you can build

- create and manage continuous Flow streams;
- create NFT-backed Flow and Lockup streams through the Router;
- read and transfer Stream NFTs;
- prepare bounded Paymaster forwarding transactions;
- use exact `bigint` token amounts across browser and server applications.

## Start here

1. Follow [Getting started](getting-started.md) to install and configure the
SDK.
2. Review [configuration](configuration.md) and
[transaction signing](transactions.md) before enabling writes.
3. Run the [example implementations](examples.md) against your deployment.
4. Read [Multichain architecture](multichain-architecture.md) to understand
the stable core and chain-adapter boundary.
5. Use [Router, Stream NFT, and Paymaster](router-paymaster.md) for the
protocol composition contracts.
6. Review [Generated bindings](generated-bindings.md) when validating contract
and SDK release provenance.

The package is currently a prerelease. Review the
[delivery checklist](delivery-checklist.md) for the remaining work required
before the SDK is promoted to a stable release.
17 changes: 17 additions & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Table of contents

- [Fundable SDK](README.md)
- [Getting started](getting-started.md)
- [Configuration](configuration.md)
- [Flow streams](flows.md)
- [Transactions and authorization](transactions.md)
- [Example implementations](examples.md)
- [Backend indexing](backend-indexing.md)
- [Multichain architecture](multichain-architecture.md)
- [Router, Stream NFT, and Paymaster](router-paymaster.md)
- [API reference](api-reference.md)
- [Generated Stellar bindings](generated-bindings.md)
- [Troubleshooting and versioning](troubleshooting-and-versioning.md)
- [Publishing with GitBook](gitbook-publishing.md)
- [Release process](releasing.md)
- [Delivery checklist](delivery-checklist.md)
94 changes: 94 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# API reference

The package exposes three import boundaries:

```ts
import { createFundableClient } from "@fundable/sdk";
import { parseUnits, formatUnits, FundableError } from "@fundable/sdk/core";
import type { StellarFundableClientConfig } from "@fundable/sdk/stellar";
```

## Top-level client

`createFundableClient(config)` returns `StellarFundableClient` for
`chain: "stellar"`. Its capability groups are:

| Property | Availability |
| --- | --- |
| `flows` | Always present; `contracts.flow` is required. |
| `router` | Present when `contracts.router` is configured. |
| `streamNft` | Present when `contracts.streamNft` is configured. |
| `paymaster` | Present when `contracts.paymaster` is configured. |

## Flow client

| Method | Result |
| --- | --- |
| `create` | Assembled transaction returning stream ID. |
| `createAndDeposit` | Assembled transaction returning stream ID. |
| `deposit`, `withdraw`, `pause`, `restart`, `adjustRate`, `refund`, `void` | Assembled state-changing transaction. |
| `withdrawMax`, `refundMax` | Assembled transaction returning the affected amount. |
| `getStream` | Normalized `FlowRecord`. |
| `getStatus` | Normalized `FlowStatus`. |
| Amount and debt getters | `bigint`. |

## Router client

| Method | Result |
| --- | --- |
| `createFlow` | Assembled transaction returning Stream NFT token ID. |
| `createLockup` | Assembled transaction returning Stream NFT token ID. |
| `withdraw` | Assembled transaction for an amount and token ID. |
| `withdrawMax` | Assembled transaction returning the withdrawn amount. |

## Stream NFT client

| Method | Result |
| --- | --- |
| `ownerOf` | Owner Stellar address. |
| `balanceOf` | Number of Stream NFTs owned as `bigint`. |
| `getStreamData` | `{ tokenId, streamId, streamKind }`. |
| `transfer` | Assembled transfer transaction. |

## Paymaster client

| Method | Result |
| --- | --- |
| `isFeeTokenAllowed` | `boolean`. |
| `forward` | Assembled transaction returning the target result. |

`forward` requires the user, fee token and bounded fee amounts, expiration
ledger, fee recipient, target contract, function name, and raw Soroban
arguments. It is an advanced API: construct arguments from a reviewed target
contract specification and never forward an arbitrary function supplied by an
untrusted user.

## Core values

- `parseUnits(value, decimals)` converts a decimal string to exact `bigint`
base units.
- `formatUnits(value, decimals)` formats base units without floating-point
arithmetic.
- `toUnixSeconds(value, label?)` normalizes a `Date` or non-negative `bigint`.
- `CHAIN_FAMILIES`, `FLOW_STATUSES`, and `STREAM_KINDS` provide stable string
constants.

## Errors

SDK validation and adapter failures use `FundableError`:

```ts
try {
await fundable.flows.getStream("42");
} catch (error) {
if (error instanceof FundableError) {
console.error(error.code, error.chain, error.message);
}
}
```

The stable error codes are `INVALID_ARGUMENT`, `INVALID_CONFIGURATION`,
`UNSUPPORTED_CHAIN`, `UNSUPPORTED_CAPABILITY`, `SIMULATION_FAILED`,
`TRANSACTION_FAILED`, and `RPC_UNAVAILABLE`. The underlying failure may be
available as `error.cause`; do not display raw provider responses to end users
without filtering sensitive data.
65 changes: 65 additions & 0 deletions docs/backend-indexing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Backend indexing and transaction tracking

The SDK does not report user activity to Fundable's backend. That is deliberate:
a public integration library should not require a central API call for an
on-chain transaction to work, and clients can bypass the library and call the
contracts directly.

To track every interaction with Fundable contracts, index the chain rather
than relying on SDK callbacks.

## Recommended architecture

```text
Application using SDK ──signs and submits──> Fundable contracts
│ contract events and ledger data
Fundable chain indexer
normalized backend database
```

The production client and third-party applications may submit transaction
hashes to an ingestion endpoint for faster user feedback, but that endpoint is
only a hint. The indexer remains the source of completeness.

## Indexer responsibilities

1. Maintain the approved contract deployment registry for each network.
2. Ingest ledgers and events for Flow, Lockup, Router, Stream NFT, Paymaster,
and Distributor contracts.
3. Decode events using the contract release that was active for that address.
4. Upsert normalized streams, ownership, deposits, withdrawals, cancellations,
and sponsored calls using an idempotent event key.
5. Record transaction hash, ledger sequence, event position, network, contract
ID, and contract release as provenance.
6. Advance a durable checkpoint only after all events in a ledger are stored.
7. Reconcile submitted transaction hints against indexed on-chain results.
8. Alert on decode failures, checkpoint lag, and unknown contract addresses.

An idempotency key should include at least network, ledger sequence,
transaction position, and event position. Never identify an event only by a
stream ID, because multiple operations can affect the same stream.

## SDK responsibility

The SDK should:

- return the native assembled transaction and decoded result;
- expose the final transaction hash after submission;
- keep public input and output types stable across adapters;
- avoid hidden telemetry or a hard dependency on Fundable's backend.

An optional future convenience method may notify a Fundable API after
submission, but it cannot provide complete accounting. Direct contract calls,
failed notifications, and alternative SDKs would otherwise create gaps.

## Database boundary

Store chain facts separately from application metadata. On-chain amounts and
IDs should be losslessly stored as integer strings or database numeric types,
not JavaScript floating-point numbers. Associate off-chain users or projects
through a separate mapping so re-indexing chain state does not overwrite
product-specific data.
93 changes: 93 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Configuration

Create one client for each Stellar network and contract deployment your
application uses.

```ts
import { createFundableClient } from "@fundable/sdk";

const fundable = createFundableClient({
chain: "stellar",
network: "testnet",
rpcUrl: "https://soroban-testnet.stellar.org",
networkPassphrase: "Test SDF Network ; September 2015",
contracts: {
flow: process.env.FUNDABLE_FLOW_CONTRACT!,
router: process.env.FUNDABLE_ROUTER_CONTRACT,
streamNft: process.env.FUNDABLE_STREAM_NFT_CONTRACT,
paymaster: process.env.FUNDABLE_PAYMASTER_CONTRACT,
},
publicKey: connectedAccount,
signTransaction: wallet.signTransaction,
signAuthEntry: wallet.signAuthEntry,
});
```

## Required values

| Field | Purpose |
| --- | --- |
| `chain` | Must be `"stellar"` in the current release. |
| `network` | `"public"`, `"testnet"`, or `"custom"`. |
| `rpcUrl` | Soroban JSON-RPC endpoint used for reads and simulation. |
| `networkPassphrase` | Passphrase of the network served by `rpcUrl`. |
| `contracts.flow` | Deployed Flow engine contract ID. |

The SDK does not infer a passphrase or contract deployment from the network
label. Keep all three values in the same environment configuration to prevent
cross-network signing errors.

## Optional capabilities

`router`, `streamNft`, and `paymaster` are only present on the client when the
matching contract ID is configured:

```ts
if (!fundable.router) {
throw new Error("Router is not configured for this deployment");
}
```

This makes a missing deployment explicit instead of sending a transaction to
an invented or stale address.

## Signing callbacks

`publicKey`, `signTransaction`, and `signAuthEntry` are optional for read-only
clients. Supply them for write workflows. The callback shapes come from
`@stellar/stellar-sdk/contract` and can be backed by a browser wallet, a mobile
wallet bridge, or a controlled server signer.

Never put a secret seed in browser source, environment variables exposed to a
frontend build, documentation examples, or SDK configuration committed to
Git.

## Server and local RPC

HTTPS is required by default. Set `allowHttp: true` only for a trusted local
development RPC endpoint. Custom request headers can be supplied with
`headers`, for example when an RPC provider requires an API key. Keep those
headers server-side when they contain credentials.

## Contract deployment registry

Production applications should maintain a reviewed registry keyed by network,
release, and chain:

```ts
const deployments = {
stellar: {
testnet: {
release: "contracts-v0.1.0-alpha.2",
flow: "C...",
router: "C...",
streamNft: "C...",
paymaster: "C...",
},
},
} as const;
```

Do not accept contract IDs directly from an untrusted URL or user input. A
malicious replacement address would cause the SDK to simulate and sign calls
to a different contract.
Loading
Loading