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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/target
soroban/target
.contract-ids.json
**/*.rs.bk
.env
.DS_Store
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.PHONY: build test deploy-testnet deploy-mainnet

build:
cd soroban && cargo build --target wasm32-unknown-unknown --release

test:
cd soroban && cargo test --workspace

deploy-testnet:
NETWORK=testnet ./scripts/deploy.sh

deploy-mainnet:
NETWORK=mainnet ./scripts/deploy.sh
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,49 @@
- [`contracts/`](./contracts/README.md) β€” reserved layout / pointers
- [`soroban/`](./soroban/README.md) β€” Soroban design and future Rust workspace

Scaffold on-chain code with the **Stellar CLI** (`stellar contract init`) when you are ready, then publish factory and pool contract IDs to the frontend repo’s environment variables.
Contract sources live under [`soroban/`](./soroban/README.md). After deployment, publish the factory contract ID and RPC URL to the frontend repo’s environment variables.

## Quick Start (deployment)

### Prerequisites

- [Rust](https://rustup.rs/) with the `wasm32-unknown-unknown` target
- [Stellar CLI](https://developers.stellar.org/docs/tools/developer-tools) (`stellar`)
- A funded Stellar identity on the target network (testnet or mainnet)

```bash
rustup target add wasm32-unknown-unknown
stellar keys generate default --network testnet # if you do not already have an identity
```

Fund testnet accounts via [Friendbot](https://friendbot.stellar.org/?addr=YOUR_ADDRESS).

Network RPC URLs and passphrases are defined in [`stellar.toml`](./stellar.toml). The deploy script registers the selected network with the CLI automatically.

### Build, test, and deploy

```bash
make build # compile release WASM to soroban/target/wasm32-unknown-unknown/release/
make test # run contract unit tests

make deploy-testnet # install pool WASM, deploy factory, initialize, write .contract-ids.json
make deploy-mainnet # same flow on mainnet (requires a funded mainnet identity)
```

`scripts/deploy.sh` accepts optional environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `NETWORK` | `testnet` | `testnet` or `mainnet` |
| `SOURCE` | `default` | Stellar CLI identity used to sign transactions |
| `ADMIN` | address of `SOURCE` | Factory admin passed to `initialize` |
| `STELLAR_TOML` | `./stellar.toml` | Network configuration file |
| `CONTRACT_IDS_FILE` | `./.contract-ids.json` | Output path for deployed IDs |

Example with a custom identity:

```bash
SOURCE=alice ADMIN=G... make deploy-testnet
```

On success, `.contract-ids.json` contains the factory contract ID and installed pool WASM hash (gitignored).
131 changes: 131 additions & 0 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
STELLAR_TOML="${STELLAR_TOML:-$ROOT_DIR/stellar.toml}"
CONTRACT_IDS_FILE="${CONTRACT_IDS_FILE:-$ROOT_DIR/.contract-ids.json}"

NETWORK="${NETWORK:-testnet}"
SOURCE="${SOURCE:-default}"
ADMIN="${ADMIN:-}"

POOL_WASM="${ROOT_DIR}/soroban/target/wasm32-unknown-unknown/release/farming_pool.wasm"
FACTORY_WASM="${ROOT_DIR}/soroban/target/wasm32-unknown-unknown/release/factory.wasm"

die() {
echo "error: $*" >&2
exit 1
}

run_stellar() {
local attempt combined last_line
for attempt in 1 2 3; do
if combined="$("$@" 2>&1)"; then
last_line="$(printf '%s\n' "$combined" | awk 'NF { line = $0 } END { print line }')"
printf '%s' "$last_line"
return 0
fi
if [[ "$combined" == *TxBadSeq* ]] && [[ "$attempt" -lt 3 ]]; then
echo "warning: transaction sequence mismatch, retrying ($attempt/3)..." >&2
sleep 3
continue
fi
echo "$combined" >&2
return 1
done
}

require_cmd() {
command -v "$1" >/dev/null 2>&1 || die "$1 is not installed or not on PATH"
}

toml_value() {
local section="$1"
local key="$2"
awk -v section="[$section]" -v key="$key" '
$0 == section { in_section = 1; next }
/^\[/ { in_section = 0 }
in_section && $1 == key {
line = $0
sub(/^[^=]*=[[:space:]]*/, "", line)
gsub(/"/, "", line)
print line
exit
}
' "$STELLAR_TOML"
}

require_cmd stellar

case "$NETWORK" in
testnet | mainnet) ;;
*)
die "NETWORK must be 'testnet' or 'mainnet' (got: $NETWORK)"
;;
esac

[[ -f "$STELLAR_TOML" ]] || die "missing $STELLAR_TOML"

RPC_URL="$(toml_value "$NETWORK" "rpc-url")"
NETWORK_PASSPHRASE="$(toml_value "$NETWORK" "network-passphrase")"

[[ -n "$RPC_URL" ]] || die "rpc-url not found for [$NETWORK] in $STELLAR_TOML"
[[ -n "$NETWORK_PASSPHRASE" ]] || die "network-passphrase not found for [$NETWORK] in $STELLAR_TOML"

stellar keys address "$SOURCE" >/dev/null 2>&1 \
|| die "Stellar identity '$SOURCE' not found. Generate one with: stellar keys generate $SOURCE"

if [[ -z "$ADMIN" ]]; then
ADMIN="$(stellar keys address "$SOURCE")" \
|| die "ADMIN is not set and could not resolve address for SOURCE=$SOURCE"
fi

[[ -f "$POOL_WASM" ]] || die "missing $POOL_WASM β€” run 'make build' first"
[[ -f "$FACTORY_WASM" ]] || die "missing $FACTORY_WASM β€” run 'make build' first"

stellar network add "$NETWORK" \
--rpc-url "$RPC_URL" \
--network-passphrase "$NETWORK_PASSPHRASE" \
>/dev/null 2>&1 || true

echo "Installing farming-pool WASM..."
POOL_HASH="$(
run_stellar stellar contract install \
--wasm "$POOL_WASM" \
--network "$NETWORK" \
--source "$SOURCE" \
--quiet
)"
sleep 2

[[ -n "$POOL_HASH" ]] || die "failed to install farming-pool WASM (empty hash returned)"

echo "Deploying factory..."
FACTORY_ID="$(
run_stellar stellar contract deploy \
--wasm "$FACTORY_WASM" \
--network "$NETWORK" \
--source "$SOURCE" \
--quiet
)"
sleep 2

[[ -n "$FACTORY_ID" ]] || die "failed to deploy factory (empty contract id returned)"

echo "Initializing factory..."
if ! run_stellar stellar contract invoke \
--id "$FACTORY_ID" \
--network "$NETWORK" \
--source "$SOURCE" \
--quiet \
-- initialize --admin "$ADMIN" --pool_wasm_hash "$POOL_HASH" >/dev/null; then
die "failed to initialize factory $FACTORY_ID"
fi

printf '{"factory": "%s", "pool_wasm_hash": "%s", "network": "%s"}\n' \
"$FACTORY_ID" "$POOL_HASH" "$NETWORK" >"$CONTRACT_IDS_FILE"

echo "Deployment complete."
echo " factory: $FACTORY_ID"
echo " pool_wasm_hash: $POOL_HASH"
echo " saved to: $CONTRACT_IDS_FILE"
7 changes: 7 additions & 0 deletions stellar.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[testnet]
rpc-url = "https://soroban-testnet.stellar.org"
network-passphrase = "Test SDF Network ; September 2015"

[mainnet]
rpc-url = "https://soroban-rpc.stellar.org"
network-passphrase = "Public Global Stellar Network ; September 2015"
Loading