piper-move is the core smart contract repository for the Piper protocol. It contains the Sui Move modules that power non‑custodial, programmable payment streams — continuous (per‑second), on‑demand (pay‑per‑use), and automated DCA (dollar‑cost averaging) — all secured by Sui’s object model and executed atomically via Programmable Transaction Blocks (PTBs).
This is the immutable financial infrastructure. The frontend, SDK, and indexer all build on top of this package.
📖 Read the full Protocol Overview → — use cases, scenarios, architecture deep dive, and security model.
| Module | Description |
|---|---|
stream.move |
Core stream logic: creation, ticking, paying, revoking, top‑up. |
split.move |
Percentage‑based split configuration and execution. |
events.move |
Standard event emissions for off‑chain indexing. |
The package is published as a single Sui Move package (piper) on Testnet (and soon Mainnet). Its public entry functions are designed to be called by any other contract or directly by users via PTBs.
Every payment stream is a live Move object:
struct Stream<phantom T> has key, store {
id: UID,
balance: Balance<T>, // remaining locked funds
flow_rate: u64, // tokens per second (0 for on‑demand)
recipient: address,
authorized_spender: Option<address>, // only for on‑demand mode
splits: vector<Split>,
ledger: Table<u64, Event>, // immutable on‑chain payment log
created_at: u64,
last_tick_at: u64,
is_active: bool,
}Balance<T>ensures funds cannot be double‑spent or created out of thin air.last_tick_atenables precise streaming calculation:streamed = flow_rate * (now - last_tick_at).ledgerprovides a transparent, tamper‑proof history of every payment event.
All financial operations are executed via Programmable Transaction Blocks (PTBs) that atomically combine:
tick/pay → swap (via DeepBook) → split → transfer/deposit into other protocols.
- Sui CLI (testnet or devnet)
- Move compiler (
sui move)
# Clone the repo
git clone https://github.com/piper-protocol/piper-move.git
cd piper-move
# Build the package
sui move build
# Run all unit tests
sui move test- Configure your Sui client for testnet:
sui client new-env --alias testnet --rpc https://fullnode.testnet.sui.io:443 sui client switch --env testnet
- Publish the package:
sui client publish --gas-budget 50000000
- Record the package ID – you’ll need it to integrate the SDK or frontend.
⚠️ The package is currently immutable (no upgrade capability) for trust minimisation. A migration path for future upgrades is documented inMIGRATION.md.
All functions are called via Sui transactions or PTBs. The full Move specification is in the source files.
create_stream<T>(coin: Coin<T>, flow_rate: u64, recipient: address, splits: vector<Split>)
Creates a continuous stream. Flow rate is in smallest token units per second.create_on_demand_stream<T>(coin: Coin<T>, budget: u64, recipient: address, authorized_spender: address)
Creates a pay‑per‑use stream (flow_rate = 0). Onlyauthorized_spendercan callpay.
tick<T>(stream: &mut Stream<T>)– Permissionless. Calculates owed amount sincelast_tick_at, deducts from balance, applies splits, emits events.pay<T>(stream: &mut Stream<T>, amount: u64)– On‑demand payment; must be called byauthorized_spender. Deductsamountand transfers to recipient.revoke<T>(stream: &mut Stream<T>)– Stream creator stops the stream, burns it, and returns remaining balance.top_up<T>(stream: &mut Stream<T>, coin: Coin<T>)– Adds more funds to an existing stream.
add_split<T>(stream: &mut Stream<T>, recipient: address, percent: u8)remove_split<T>(stream: &mut Stream<T>, index: u64)
All functions emit corresponding events (Event::PaymentSent, Event::StreamRevoked, etc.) that can be listened to by off‑chain indexers.
You normally do not call these Move functions directly. Instead, use the Piper TypeScript SDK (@piper/sdk) which constructs correct PTBs and handles coin management.
However, if you are building a Sui Move contract that composes with Piper, you can call the public functions directly in your own module’s PTBs:
// Inside your contract
public entry fun my_complex_flow(stream: &mut piper::stream::Stream<USDC>, ...) {
// First trigger a stream tick to release funds
piper::stream::tick(stream);
// The tick returns a Coin<USDC> that can be used immediately
// (In a PTB, you can route this coin to DeepBook, lending, etc.)
}For web / TypeScript integrations, refer to the SDK repository.
- Unit tests: Found in
tests/. Each module has tests that simulate stream lifecycles: creation, multiple ticks, splits, revocation, and edge cases (depleted streams, invalid flow rates, unauthorized pay). - Integration tests: Use the DeepBook Sandbox or a local Sui network to test composability with other protocols (DeepBook, lending). Scripts coming soon in
scripts/.
Run all tests with:
sui move testpiper-move/
├── Move.toml # Package manifest
├── sources/
│ ├── stream.move # Core stream logic
│ ├── split.move # Split utilities
│ └── events.move # Event definitions
├── tests/
│ ├── stream_tests.move
│ └── split_tests.move
├── scripts/
│ └── deploy.sh # Deployment helper
└── README.md
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
For feature discussions, join the Piper Protocol Telegram group or open an issue.
piper-sdk– TypeScript SDK for building Piper PTBs (repo)piper-app– PWA frontend for users (repo)piper-docs– Full protocol documentation (repo)piper-indexer– Off‑chain indexer and API (repo)
Piper — Money that moves like music.