-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathdeploy.sh
More file actions
220 lines (199 loc) · 7.89 KB
/
Copy pathdeploy.sh
File metadata and controls
220 lines (199 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env bash
set -euo pipefail
# AnonVote Soroban deployment script.
#
# Usage:
# STELLAR_ACCOUNT=<stellar-cli-identity-name> ./deploy.sh testnet
# # or, with a raw secret key:
# STELLAR_SECRET_KEY=S... ./deploy.sh testnet
#
# Optional:
# STELLAR_ADMIN_ADDRESS=G... Admin passed to initialize(). If unset, it is
# derived from STELLAR_ACCOUNT (a named identity);
# if it cannot be derived, initialization is
# skipped and the manual command is printed.
# SOROBAN_RPC_URL=... Recorded in deployments.json (defaults per network).
NETWORK="${1:-}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONTRACT_DIR="$SCRIPT_DIR/contracts/anonvote"
WASM_PATH="$CONTRACT_DIR/target/wasm32v1-none/release/anonvote.wasm"
DEPLOYMENTS_FILE="$SCRIPT_DIR/deployments.json"
CONTRACT_NAME="anonvote"
RUST_TOOLCHAIN="1.91" # Soroban SDK 27.0.6 requires 1.91.0 (with wasm32v1-none)
usage() {
echo "Usage: $0 <testnet|mainnet>"
echo ""
echo "Environment variables:"
echo " STELLAR_ACCOUNT Named stellar-cli identity to sign with (preferred)"
echo " STELLAR_SECRET_KEY Raw secret key to sign with (alternative)"
echo " STELLAR_ADMIN_ADDRESS G-address passed to initialize() (optional)"
echo " SOROBAN_RPC_URL RPC endpoint recorded in deployments.json (optional)"
exit 1
}
if [[ -z "$NETWORK" ]]; then usage; fi
if [[ "$NETWORK" != "testnet" && "$NETWORK" != "mainnet" ]]; then
echo "Error: network must be 'testnet' or 'mainnet'"
usage
fi
# ---------- prerequisite checks ----------
for cmd in cargo stellar jq git rustup; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: $cmd is not installed."
exit 1
fi
done
# Signing source: prefer a named identity, fall back to a raw secret key.
SOURCE="${STELLAR_ACCOUNT:-${STELLAR_SECRET_KEY:-}}"
if [[ -z "$SOURCE" ]]; then
echo "Error: set STELLAR_ACCOUNT (identity name) or STELLAR_SECRET_KEY."
exit 1
fi
if ! rustup toolchain list | grep -q "^${RUST_TOOLCHAIN}"; then
echo "Error: rustc ${RUST_TOOLCHAIN} is required to build a Soroban-compatible WASM."
echo " Install it with:"
echo " rustup toolchain install ${RUST_TOOLCHAIN}"
echo " rustup target add wasm32v1-none --toolchain ${RUST_TOOLCHAIN}"
exit 1
fi
# ---------- network config (recorded in deployments.json) ----------
case "$NETWORK" in
testnet) SOROBAN_RPC_URL="${SOROBAN_RPC_URL:-https://soroban-testnet.stellar.org}" ;;
mainnet) SOROBAN_RPC_URL="${SOROBAN_RPC_URL:-https://soroban-mainnet.stellar.org}" ;;
esac
echo "=== AnonVote Contract Deployment ==="
echo "Network: $NETWORK"
echo "RPC URL: $SOROBAN_RPC_URL"
echo "Toolchain: rustc $RUST_TOOLCHAIN"
echo "WASM: $WASM_PATH"
echo "Deployments: $DEPLOYMENTS_FILE"
echo ""
# ---------- 1. Build (rustc 1.84+ with wasm32v1-none for Soroban SDK 27.0.6 compatibility) ----------
echo ">>> Building contract with rustc ${RUST_TOOLCHAIN}..."
rustup run "$RUST_TOOLCHAIN" cargo build \
--manifest-path "$CONTRACT_DIR/Cargo.toml" \
--target wasm32v1-none --release --locked
if [[ ! -f "$WASM_PATH" ]]; then
echo "Error: WASM not found at $WASM_PATH"
exit 1
fi
echo " Build complete."
echo ""
# ---------- 2. Compute hashes ----------
WASM_HASH=$(sha256sum "$WASM_PATH" | awk '{print $1}')
GIT_COMMIT=$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo " WASM SHA-256: $WASM_HASH"
echo " Git commit: $GIT_COMMIT"
echo ""
# Helper: pull the 64-hex transaction hash out of stellar-cli stderr.
extract_tx() { grep -oE '/tx/[a-f0-9]{64}' "$1" | head -1 | cut -d/ -f3; }
# ---------- 3. Upload WASM ----------
echo ">>> Uploading WASM to $NETWORK..."
UPLOAD_ERR=$(mktemp)
UPLOADED_HASH=$(stellar contract upload \
--wasm "$WASM_PATH" \
--source-account "$SOURCE" \
--network "$NETWORK" 2>"$UPLOAD_ERR")
UPLOAD_TX=$(extract_tx "$UPLOAD_ERR")
cat "$UPLOAD_ERR"; rm -f "$UPLOAD_ERR"
echo " Uploaded WASM hash: $UPLOADED_HASH (upload tx: ${UPLOAD_TX:-n/a})"
echo ""
# ---------- 4. Deploy instance ----------
echo ">>> Deploying $CONTRACT_NAME instance..."
DEPLOY_ERR=$(mktemp)
CONTRACT_ID=$(stellar contract deploy \
--wasm-hash "$UPLOADED_HASH" \
--source-account "$SOURCE" \
--network "$NETWORK" 2>"$DEPLOY_ERR")
DEPLOY_TX=$(extract_tx "$DEPLOY_ERR")
cat "$DEPLOY_ERR"; rm -f "$DEPLOY_ERR"
if [[ -z "$CONTRACT_ID" || ! "$CONTRACT_ID" =~ ^C[A-Z0-9]{55}$ ]]; then
echo "Error: failed to obtain a valid contract ID (got: '$CONTRACT_ID')."
exit 1
fi
echo " Contract ID: $CONTRACT_ID (deploy tx: ${DEPLOY_TX:-n/a})"
echo ""
# ---------- 5. Initialize contract ----------
echo ">>> Initializing contract..."
ADMIN_ADDRESS="${STELLAR_ADMIN_ADDRESS:-}"
if [[ -z "$ADMIN_ADDRESS" && -n "${STELLAR_ACCOUNT:-}" ]]; then
ADMIN_ADDRESS=$(stellar keys public-key "$STELLAR_ACCOUNT" 2>/dev/null || true)
fi
if [[ -z "$ADMIN_ADDRESS" ]]; then
echo " Warning: no admin address (set STELLAR_ADMIN_ADDRESS). Skipping initialization."
echo " Run manually:"
echo " stellar contract invoke --id $CONTRACT_ID --source-account <SOURCE> \\"
echo " --network $NETWORK -- initialize --admin <G-ADDRESS>"
else
stellar contract invoke \
--id "$CONTRACT_ID" \
--source-account "$SOURCE" \
--network "$NETWORK" \
-- initialize \
--admin "$ADMIN_ADDRESS"
echo " Initialized with admin: $ADMIN_ADDRESS"
fi
echo ""
# ---------- 6. Record deployment ----------
echo ">>> Recording deployment to $DEPLOYMENTS_FILE..."
if [[ ! -f "$DEPLOYMENTS_FILE" ]]; then echo '{}' > "$DEPLOYMENTS_FILE"; fi
TEMP_FILE=$(mktemp)
jq --arg net "$NETWORK" \
--arg cid "$CONTRACT_ID" \
--arg tx "${DEPLOY_TX:-}" \
--arg wasm "$WASM_HASH" \
--arg commit "$GIT_COMMIT" \
--arg ts "$TIMESTAMP" \
--arg rpc "$SOROBAN_RPC_URL" \
'.[$net] = {
"contract_id": $cid,
"transaction_id": (if $tx == "" then null else $tx end),
"timestamp": $ts,
"wasm_hash": $wasm,
"git_commit": $commit,
"rpc_url": $rpc
}' "$DEPLOYMENTS_FILE" > "$TEMP_FILE"
mv "$TEMP_FILE" "$DEPLOYMENTS_FILE"
echo " Saved."
echo ""
# ---------- 7. Update CONTRACT_ID file ----------
CONTRACT_ID_FILE="$SCRIPT_DIR/CONTRACT_ID"
echo ">>> Updating CONTRACT_ID file..."
if [[ -f "$CONTRACT_ID_FILE" ]]; then
TEMP_ID_FILE=$(mktemp)
sed "s|^${NETWORK}:.*|${NETWORK}: ${CONTRACT_ID}|" "$CONTRACT_ID_FILE" > "$TEMP_ID_FILE"
mv "$TEMP_ID_FILE" "$CONTRACT_ID_FILE"
echo " Updated ${NETWORK} entry in CONTRACT_ID."
else
echo " Warning: CONTRACT_ID file not found at $CONTRACT_ID_FILE — skipping."
fi
echo ""
# ---------- 8. Git tag ----------
TAG="contract-${NETWORK}-v1.0.0"
echo ">>> Creating git tag: $TAG"
git -C "$SCRIPT_DIR" add "$DEPLOYMENTS_FILE" "$CONTRACT_ID_FILE"
if git -C "$SCRIPT_DIR" diff --cached --quiet; then
echo " No changes to commit."
else
git -C "$SCRIPT_DIR" commit -m "deploy: $CONTRACT_NAME to $NETWORK ($CONTRACT_ID)"
fi
git -C "$SCRIPT_DIR" tag -f "$TAG" -m "Deploy $CONTRACT_NAME to $NETWORK: $CONTRACT_ID" 2>/dev/null || \
git -C "$SCRIPT_DIR" tag -a "$TAG" -m "Deploy $CONTRACT_NAME to $NETWORK: $CONTRACT_ID"
echo ""
# ---------- 9. Summary ----------
echo "============================================"
echo " Deployment complete!"
echo " Network: $NETWORK"
echo " Contract ID: $CONTRACT_ID"
echo " WASM Hash: $WASM_HASH"
echo " Deploy Tx: ${DEPLOY_TX:-n/a}"
echo " Git Commit: $GIT_COMMIT"
echo " Git Tag: $TAG"
echo "============================================"
echo ""
echo "Next steps:"
echo " 1. Verify on Stellar Explorer: https://stellar.expert/explorer/$NETWORK/contract/$CONTRACT_ID"
echo " 2. Set in contracts/.env: SOROBAN_CONTRACT_ID=$CONTRACT_ID"
echo " 3. Set in backend/.env: SOROBAN_CONTRACT_ID=$CONTRACT_ID"
echo " 4. Push tag: git push origin $TAG"
echo " 5. Push commit: git push origin HEAD"