Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- run: cargo clippy --all-targets -- -D warnings
- run: cargo test
- name: Check markdown links
run: npx -y markdown-link-check -q README.md docs/architecture.md docs/integrations.md docs/mainnet.md
run: npx -y markdown-link-check -q README.md docs/architecture.md docs/integrations.md docs/mainnet.md docs/quickstart.md docs/deploy.md
- run: cargo build --release --target wasm32v1-none -p tributary-splitter

contract-pedantic:
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ app web dashboard (Vite + React, Freighter wallet)

[docs/glossary.md](docs/glossary.md) defines core terms like split, share, controller, escrow and dust.

[docs/quickstart.md](docs/quickstart.md) is a five-minute SDK quickstart: install, read a split, create one, and pay through it.

[docs/splits-vs-multisend.md](docs/splits-vs-multisend.md) explains why atomic splits beat sending N separate transfers, and where manual multi-send still fits.

[docs/deploy.md](docs/deploy.md) walks through building and deploying the contract to testnet with the Stellar CLI, then regenerating the SDK.

## Contributing

Issues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get set up and what a good change looks like.
Expand Down
125 changes: 125 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Deploy Your Own Splitter

This guide walks through building the splitter contract from source and
deploying it to the Stellar testnet with the
[Stellar CLI](https://developers.stellar.org/docs/tools/cli). By the end you
will have your own contract instance, and the SDK regenerated to point at it.

The whole flow is wrapped in [`scripts/deploy.sh`](../scripts/deploy.sh); this
page explains each step so you can adapt it.

## Prerequisites

- Stable Rust with the `wasm32v1-none` target. The checked-in
[`rust-toolchain.toml`](https://github.com/tributary-protocol/tributary/blob/main/rust-toolchain.toml)
selects the right toolchain automatically once you run any `cargo` command.
- The [Stellar CLI](https://developers.stellar.org/docs/tools/cli) (`stellar`),
installed and on your `PATH`.
- A funded testnet identity. The deploy script uses the identity named
`deployer` by default; create and fund one with:

```bash
stellar keys generate deployer --network testnet --fund
```

Any identity name works — pass it as the first argument to `deploy.sh`.

## 1. Build the wasm

From the repo root:

```bash
cargo build --release --target wasm32v1-none -p tributary-splitter
```

This produces `target/wasm32v1-none/release/tributary_splitter.wasm`. The
contract is `no_std` and uses typed errors, so the build has no host OS
dependencies.

## 2. Deploy to testnet

The simplest path is the script:

```bash
./scripts/deploy.sh deployer
```

It builds the wasm, then deploys it under the `splitter` alias:

```bash
stellar contract deploy \
--wasm target/wasm32v1-none/release/tributary_splitter.wasm \
--source deployer \
--network testnet \
--alias splitter
```

`--alias splitter` stores the resulting contract id locally, so later commands
can reference it by name instead of by the long id. After this succeeds, the
deployed contract id is in your local Stellar CLI config under that alias.

## 3. Smoke-test it

`scripts/demo.sh` runs a full create-and-pay cycle against whatever contract
the `splitter` alias points at, so it exercises your fresh deployment:

```bash
./scripts/demo.sh deployer
```

It creates a 60/40 split between two fresh accounts, pays 1 XLM through it, then
pays 0.5 XLM via `pay_many`, and prints the resulting balances. A clean run
means your contract is live and accepting calls.

## 4. Regenerate the SDK bindings

The published SDK is pinned to the project's testnet deployment. To point your
local SDK at your own contract, regenerate the TypeScript bindings from your
instance:

```bash
stellar contract bindings typescript \
--contract-id "$(stellar contract id splitter --network testnet)" \
--network testnet \
--output-dir sdk --overwrite
```

Then rebuild the SDK so the new contract id and spec take effect:

```bash
cd sdk
npm install
npm run build
```

If you maintain a fork, restore `sdk/README.md` and the package name in
`sdk/package.json` afterward, or keep your deployment as the default — that is
your call.

## 5. (Optional) Point the dashboard at it

The web app reads the contract id from the SDK's `networks` map. After
regenerating bindings, build the app and run it locally to drive your
deployment from the UI:

```bash
cd app
npm install
npm run build
```

## Troubleshooting

- **`target wasm32v1-none not found`** — the toolchain file should add it on
first build. If it did not, run `rustup target add wasm32v1-none`.
- **`insufficient balance` on deploy** — fund the deploying identity with
`stellar keys fund deployer --network testnet`.
- **`contract id splitter not found`** — the alias is created only on a
successful deploy. Re-run `scripts/deploy.sh` or pass `--id <contract-id>`
explicitly to later `stellar contract` commands.

## Where to go next

- [SDK quickstart](quickstart.md) to make your first read and write calls.
- [Architecture](architecture.md) for storage layout, money paths, and error codes.
- [Glossary](glossary.md) for split, share, controller, escrow, and dust.
134 changes: 134 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# SDK Quickstart

This guide takes you from a clean machine to your first on-chain call with the
Tributary TypeScript SDK in about five minutes. It covers install, read, and
write (create + pay) against testnet.

The SDK is a generated client for the [splitter contract](../README.md). It is
pre-wired to the testnet deployment, so you only need an account and a way to
sign transactions.

## Prerequisites

- Node.js 18 or newer
- A funded testnet Stellar account. Create one in the
[Freighter](https://freighter.app) wallet, then fund it at
[friendbot](https://lab.stellar.org/account/fund?$=network$id=testnet).
- A signing function. The snippets below use a minimal inline signer built on
`@stellar/stellar-sdk`; in a real app you would route this through a wallet
like Freighter or a backend key manager.

## Install

```bash
npm install tributary-sdk
```

Or build it from this repo checkout:

```bash
cd sdk
npm install
npm run build
```

## Read-only call

Reading a split does not require signing. Point the client at the testnet
network and call `get_split`:

```ts
import { Client, networks } from "tributary-sdk";

const client = new Client({
...networks.testnet,
rpcUrl: "https://soroban-testnet.stellar.org",
});

// Splits are numbered from 0.
const { result } = await client.get_split({ id: 0n });
console.log(result);
```

`result` is a `Split`:

```ts
type Split = {
controller: string | null;
recipients: Array<{ tag: "Account"; values: [string] } | { tag: "Split"; values: [bigint] }>;
shares: Array<number>;
};
```

## Your first write: create a split

Writes go through `signAndSend`, which simulates the transaction, then signs and
submits it. The example below builds a signer from a secret key. **Never ship a
hardcoded key** — this is for the quickstart only.

```ts
import { Client, networks, contract, rpc } from "tributary-sdk";
import { Keypair } from "@stellar/stellar-sdk";

const client = new Client({
...networks.testnet,
rpcUrl: "https://soroban-testnet.stellar.org",
});

const keypair = Keypair.fromSecret("S..."); // your testnet secret key
const publicKey = keypair.publicKey();

const signTransaction = async (tx: string) => {
const prepared = rpc.assembledTransactionFromXDR(tx, networks.testnet.networkPassphrase);
prepared.sign(keypair);
return prepared.toEnvelope().toXDR().toString("base64");
};

// 60% / 40% split between two accounts.
const tx = await client.create_split({
creator: publicKey,
recipients: [
{ tag: "Account", values: [publicKey] },
{ tag: "Account", values: ["G..."] },
],
shares: [6000, 4000],
controller: undefined, // undefined locks the split forever
});

const { result } = await tx.signAndSend({ signTransaction });
console.log("created split id", result); // a bigint
```

`result` is the new split's id. Shares are basis points and must sum to exactly
`10_000`; `controller` is `undefined` to lock the split, or an address string to
make it editable later.

## Pay through the split

Pushing a payment through the split pays every recipient in one transaction.
Preview the per-recipient amounts first with `preview_payout`, then `pay`:

```ts
// Exact per-recipient amounts for a 1000-unit payment, no funds moved.
const { result: preview } = await client.preview_payout({ id: result, amount: 1000n });
console.log(preview); // e.g. [600n, 400n]

const payTx = await client.pay({
from: publicKey,
id: result,
token: "CAS3J7ZYVA3TBXEEZUWEXZYYH2F2LJGV7YQHVWPCLA7QZOKMVFSVWJQP", // a testnet asset
amount: 1000n,
});
await payTx.signAndSend({ signTransaction });
```

The payer must hold and have authorized the `token`. For a USDC-like asset on
testnet you typically need to set a trustline and grant the contract a spending
allowance first; the dashboard's Pay tab performs these steps for you.

## Where to go next

- [SDK README](../sdk/README.md) for the full method list and regenerating bindings.
- [Architecture](../docs/architecture.md) for storage layout, money paths, and error codes.
- [Glossary](../docs/glossary.md) for split, share, controller, escrow, and dust.
- [README](../README.md) for the two-minute web walkthrough and deployments.
Loading