Azable is a Stellar/Soroban platform for payment streaming and clean-water-access crowdfunding: creators run recurring payment streams, launch milestone-based funding campaigns, and get on-chain, donor-verifiable credit for the wells their campaigns fund.
🟢 Live (testnet): azableweb-production.up.railway.app
- Node.js v18+
- pnpm v9+ (
npm install -g pnpm) - Rust (for the Soroban contracts and the backend)
- Soroban CLI / stellar-cli v25.0.0+:
cargo install --locked stellar-cli@25.0.0
- Docker (optional — only needed to run
services/backendlocally)
git clone https://github.com/skiboso/Azable.git
cd Azable
pnpm installstellar keys generate my-account --network testnet --fund
cp .env.example .env
# set STELLAR_SECRET_KEY in .env to the secret printed abovepnpm build:contractsdocker compose up -d postgres
cp services/backend/.env.example services/backend/.env
pnpm dev:backendpnpm devThe app starts at http://localhost:3000. Connect a wallet (e.g. Freighter) to interact with the contracts on testnet.
Need more detail? See docs/getting-started.md, services/backend/README.md, and scripts/README.md.
azable/
├── apps/
│ └── web/ # Next.js frontend
│
├── contracts/ # Soroban smart contracts (Rust), one Cargo workspace
│ ├── payment-stream/ # Payment streaming
│ ├── distributor/ # Token distribution
│ ├── campaign-funding/ # Campaign fundraising
│ ├── nft-stream/ # NFT-gated streams
│ ├── soulbound-badge/ # Contributor badges
│ ├── water-technician/ # Well-completion job tracking & referral rewards
│ ├── dispute-arbiter/ # Stream/campaign dispute resolution
│ ├── verifier-penalty/ # Verifier staking & slashing
│ ├── timelock/ # Timelocked admin actions
│ ├── upgrade-proxy/ # Contract upgrade proxy
│ ├── sponsor-crowdfunding/ # Sponsor pool crowdfunding
│ ├── sponsor-insurance/ # Sponsor insurance pools
│ └── donor-verification/ # ZK nullifier-based donor verification
│
├── services/
│ └── backend/ # Rust/Axum: Soroban event indexer, wallet auth, off-chain data API
│
├── packages/
│ └── sdk/ # @azable/sdk — TypeScript bindings for the contracts
│
├── docs/ # Architecture, API, and contract documentation
├── scripts/ # Operational scripts (TTL renewal bot, digests, deploy helpers)
├── migrations/ # See services/backend/migrations/ (moved there)
└── docker-compose.yml # Local Postgres + backend for development
- Payment streaming — continuous, revocable token streams for subscriptions, salaries, and recurring transfers
- Campaign funding — milestone-based on-chain fundraising with escrow, refunds, and creator payouts
- Clean water access tracking — verified well-completion records, liters-per-year impact estimates, and donor-facing certificates
- Donor verification — ZK nullifier-based proof of contribution without exposing donor identity
- Sponsor tools — crowdfunded sponsor pools, insurance pools, and leaderboard/referral rewards
- Multi-asset support — USDC, XLM, and other Stellar assets
- Offramp integration — convert crypto to fiat
| Component | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS v4 |
| Contracts | Soroban SDK, Rust |
| Backend | Rust, Axum, sqlx/Postgres |
| SDK | TypeScript, @stellar/stellar-sdk |
The campaign-funding Soroban contract powers on-chain fundraising campaigns.
State machine: Draft → Active → Paused → Successful/Failed → PaidOut/Refunded
Draft— creator configures the campaign and milestone payout schedule.Active— contributions are accepted.Paused— emergency stop; contributions suspended, state preserved.Successful— all milestones verified and claimed by the creator.Failed— end time reached without meeting the funding goal, or cancelled by an admin.PaidOut— final milestone released and the campaign fully settled.Refunded— backers can claim proportional refunds after failure.
Only the admin or campaign_owner may invoke restricted transitions.
Security model
- Admin-guarded privileged operations, validated per state transition.
- Checks-effects-interactions: external token calls happen after internal state updates.
- Checked/overflow-safe arithmetic throughout.
- Escrow accounting — contributions are only released via explicit
payout/refundcalls. - Milestone approvals require reviewer sign-off before a creator can claim funds.
Scalability
- Campaigns are stored as persistent map entries keyed by campaign id — no unbounded collections.
- Contributions are aggregated rather than stored as individual ledger entries.
- Payouts batch milestone claims to minimize transaction count.
- The contract is stateless with respect to off-chain indexing;
services/backend's indexer replicates event data into Postgres for the frontend and analytics.
See docs/CAMPAIGN_CONTRACT_ARCHITECTURE.md for the full design doc.
import { Horizon } from "@stellar/stellar-sdk";
const server = new Horizon.Server("https://horizon-testnet.stellar.org");
async function checkAccount(address: string) {
const account = await server.loadAccount(address);
console.log(`Account ID: ${account.id}`);
account.balances.forEach((balance) => {
console.log(`Type: ${balance.asset_type}, Balance: ${balance.balance}`);
});
}import { PaymentStreamClient, signAndWait } from "@azable/sdk";
const client = new PaymentStreamClient({
contractId: "C...", // deployed contract ID
networkPassphrase: "Test SDF Network ; September 2015",
rpcUrl: "https://soroban-testnet.stellar.org",
});
const tx = await client.createStream({
sender: "GAAA...",
recipient: "GBBB...",
token: "CDDD...",
total_amount: 1_000_000_000n,
initial_amount: 0n,
start_time: BigInt(Math.floor(Date.now() / 1000)),
end_time: BigInt(Math.floor(Date.now() / 1000) + 86400 * 30),
});
const result = await signAndWait(tx, "https://soroban-testnet.stellar.org", async (xdr) => {
return wallet.signTransaction(xdr); // e.g. Freighter
});See services/backend/README.md for the full route reference (wallet-signature auth, indexed stream events, campaigns).
POST /api/presign-upload issues a short-lived AWS S3 presigned PUT URL so
clients can upload milestone proof photos directly to a private evidence
bucket. See .env.example for the required AWS_* variables.
| Package | Description |
|---|---|
apps/web |
Next.js frontend |
contracts/ |
13 Soroban contracts (payment streaming, campaigns, badges, insurance, ...) |
packages/sdk |
@azable/sdk — generated + hand-written TypeScript bindings |
services/backend |
Rust/Axum indexer, auth, and data API |
See CONTRIBUTING.md.
See SECURITY.md to report a vulnerability.
MIT