Skip to content

Commit 90d6ea8

Browse files
authored
Add install script (#71)
1 parent d8f23f4 commit 90d6ea8

File tree

2 files changed

+280
-2
lines changed

2 files changed

+280
-2
lines changed

README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ Spaces are sovereign Bitcoin identities. They leverage the existing infrastructu
1414

1515
## Quick Start
1616

17-
Check out the [documentation](https://docs.spacesprotocol.org)
17+
Paste the following into your terminal to install the latest version of Spaces:
18+
```bash
19+
curl --proto '=https' --tlsv1.2 -sSf https://install.spacesprotocol.org | sh
20+
```
21+
1822

1923
## Development setup on testnet4
2024

@@ -66,13 +70,19 @@ spaced --chain testnet4 --bitcoin-rpc-user testnet4 --bitcoin-rpc-password testn
6670

6771
## Project Structure
6872

73+
6974
| Package | Requires std | Description |
7075
|----------|-----------------|-------------------------------------------------------------------------------------------------|
7176
| client | Yes | Bitcoin consensus client and wallet service |
7277
| wallet | Yes (no-std WIP) | Wallet library for building spaces transactions |
7378
| protocol | No | Protocol consensus library |
7479
| veritas | No | Stateless verifier library for mobile and other resource constrained devices with wasm support. |
7580

81+
## Documentation
82+
83+
Visit [docs](https://docs.spacesprotocol.org/) to get more information about Spaces protocol.
84+
85+
7686
## License
7787

78-
Spaces is released under the terms of the MIT license. See LICENSE for more information or see https://opensource.org/licenses/MIT.
88+
Spaces is released under the terms of the MIT license. See LICENSE for more information or see https://opensource.org/licenses/MIT.

install.sh

+268
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
#!/usr/bin/env sh
2+
set -eu
3+
(set -o pipefail 2>/dev/null) && set -o pipefail
4+
5+
help() {
6+
cat <<'EOF'
7+
Install spaces binaries (spaced and space-cli) from GitHub releases.
8+
9+
USAGE:
10+
install.sh [options]
11+
12+
FLAGS:
13+
-h, --help Display this message
14+
-f, --force Force overwriting existing binaries
15+
-v, --verbose Show detailed output
16+
17+
OPTIONS:
18+
--tag VERSION Specific version to install (e.g., 0.0.6a), defaults to latest release
19+
--to LOCATION Where to install the binaries (default: auto-detected based on OS)
20+
For macOS: ~/.local/bin if exists, else ~/bin
21+
For Linux: ~/.local/bin
22+
23+
NOTES:
24+
The script will automatically choose an appropriate user-writable location.
25+
The chosen directory will be added to your PATH if needed.
26+
EOF
27+
}
28+
29+
say() {
30+
echo "install: $*" >&2
31+
}
32+
33+
err() {
34+
if [ -n "${td-}" ]; then
35+
rm -rf "$td"
36+
fi
37+
say "error: $*"
38+
say "run './install.sh --help' to see available options"
39+
exit 1
40+
}
41+
42+
need() {
43+
if ! command -v "$1" > /dev/null 2>&1; then
44+
err "need $1 (command not found)"
45+
fi
46+
}
47+
48+
add_to_path() {
49+
local install_dir="$1"
50+
local shell_rc
51+
local reload_needed=false
52+
53+
# Detect shell configuration file based on $SHELL environment variable
54+
if [[ "$SHELL" == */zsh ]]; then
55+
shell_rc="$HOME/.zshrc"
56+
shell_type="zsh"
57+
else
58+
shell_type="bash"
59+
shell_rc="$HOME/.bashrc"
60+
[ "$(uname -s)" = "Darwin" ] && shell_rc="$HOME/.bash_profile"
61+
fi
62+
63+
if ! echo "$PATH" | tr ':' '\n' | grep -Fq "$install_dir"; then
64+
say "Adding $install_dir to PATH in $shell_rc"
65+
echo "export PATH=\"$install_dir:\$PATH\"" >> "$shell_rc"
66+
reload_needed=true
67+
fi
68+
69+
# Return whether reload is needed
70+
[ "$reload_needed" = true ] && echo "reload" || echo "noreload"
71+
}
72+
73+
determine_install_dir() {
74+
local os="$1"
75+
local specified_dir="$2"
76+
local install_dir
77+
78+
if [ -n "$specified_dir" ]; then
79+
install_dir="$specified_dir"
80+
else
81+
case "$os" in
82+
darwin)
83+
if [ -d "$HOME/.local/bin" ]; then
84+
install_dir="$HOME/.local/bin"
85+
else
86+
install_dir="$HOME/bin"
87+
fi
88+
;;
89+
linux)
90+
install_dir="$HOME/.local/bin"
91+
;;
92+
*)
93+
err "unsupported operating system: $os"
94+
;;
95+
esac
96+
fi
97+
98+
# Create directory if it doesn't exist
99+
if [ ! -d "$install_dir" ]; then
100+
mkdir -p "$install_dir" || err "failed to create $install_dir"
101+
fi
102+
103+
echo "$install_dir"
104+
}
105+
106+
download() {
107+
url="$1"
108+
output="$2"
109+
if command -v curl > /dev/null; then
110+
if [ "$output" = "-" ]; then
111+
curl --proto =https --tlsv1.2 -sSfL "$url"
112+
else
113+
curl --proto =https --tlsv1.2 -sSfL "$url" -o "$output"
114+
fi
115+
else
116+
wget --https-only --secure-protocol=TLSv1_2 --quiet "$url" -O "$output"
117+
fi
118+
}
119+
120+
# Initialize default values
121+
force=false
122+
verbose=false
123+
dest=""
124+
tag=""
125+
td=""
126+
127+
# Process command line arguments
128+
while test $# -gt 0; do
129+
case $1 in
130+
--force | -f)
131+
force=true
132+
;;
133+
--help | -h)
134+
help
135+
exit 0
136+
;;
137+
--verbose | -v)
138+
verbose=true
139+
;;
140+
--tag)
141+
tag="$2"
142+
shift
143+
;;
144+
--to)
145+
dest="$2"
146+
shift
147+
;;
148+
*)
149+
say "error: unrecognized argument '$1'"
150+
help
151+
exit 1
152+
;;
153+
esac
154+
shift
155+
done
156+
157+
# Check for required commands
158+
command -v curl > /dev/null 2>&1 || command -v wget > /dev/null 2>&1 || err "need wget or curl"
159+
need mktemp
160+
need tar
161+
162+
# Detect OS and architecture
163+
os=$(uname -s | tr '[:upper:]' '[:lower:]')
164+
arch=$(uname -m)
165+
166+
# Map architecture to match release files
167+
case "$arch" in
168+
x86_64) arch="x86_64" ;;
169+
aarch64|arm64) arch="arm64" ;;
170+
*) err "unsupported architecture: $arch" ;;
171+
esac
172+
173+
# Determine installation directory
174+
dest=$(determine_install_dir "$os" "$dest")
175+
[ "$verbose" = true ] && say "installing to: $dest"
176+
177+
# Get latest version if not specified
178+
if [ -z "$tag" ]; then
179+
[ "$verbose" = true ] && say "fetching latest release version..."
180+
api_response=$(download "https://api.github.com/repos/spacesprotocol/spaces/releases/latest" - || echo "failed")
181+
if [ "$api_response" = "failed" ]; then
182+
err "could not fetch release information from GitHub"
183+
fi
184+
185+
tag=$(echo "$api_response" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
186+
if [ -z "$tag" ]; then
187+
err "no releases found in the repository"
188+
fi
189+
fi
190+
191+
# Standardize tag format
192+
tag_without_v="${tag#v}" # Remove 'v' prefix if present
193+
check_tag="v$tag_without_v" # Add 'v' prefix for consistency
194+
195+
# Verify the tag exists
196+
[ "$verbose" = true ] && say "verifying tag $check_tag exists..."
197+
api_response=$(download "https://api.github.com/repos/spacesprotocol/spaces/releases/tags/$check_tag" - || echo "failed")
198+
if [ "$api_response" = "failed" ] || echo "$api_response" | grep -q "Not Found"; then
199+
err "release tag '$check_tag' not found"
200+
fi
201+
202+
[ -z "$tag_without_v" ] && err "could not determine version to install"
203+
204+
[ "$verbose" = true ] && say "installing spaces version $check_tag"
205+
206+
# Create temporary directory
207+
td=$(mktemp -d || mktemp -d -t tmp)
208+
trap 'rm -rf "$td"' EXIT
209+
210+
# Construct download URL
211+
download_url="https://github.com/spacesprotocol/spaces/releases/download/$check_tag/spaces-$check_tag-${os}-${arch}.tar.gz"
212+
213+
[ "$verbose" = true ] && say "downloading from: $download_url"
214+
215+
# Download and extract
216+
download "$download_url" "$td/spaces.tar.gz" || err "download failed"
217+
tar xzf "$td/spaces.tar.gz" -C "$td" || err "failed to extract archive"
218+
219+
# Install binaries
220+
for binary in spaced space-cli; do
221+
if [ -f "$dest/$binary" ] && [ "$force" = false ]; then
222+
err "Found existing spaces executables at $dest. Use --force flag to overwrite"
223+
fi
224+
225+
binary_path="$dest/$binary"
226+
if ! find "$td" -type f -name "$binary" -exec cp {} "$binary_path" \; ; then
227+
err "failed to copy $binary to $dest (permission denied)"
228+
fi
229+
230+
if ! chmod 755 "$binary_path"; then
231+
err "failed to set permissions on $binary (permission denied)"
232+
fi
233+
234+
[ "$verbose" = true ] && say "installed $binary to $binary_path"
235+
done
236+
237+
# Verify installation
238+
for binary in spaced space-cli; do
239+
if ! [ -x "$dest/$binary" ]; then
240+
err "installation verification failed for $binary"
241+
fi
242+
done
243+
244+
# Add to PATH if needed and get reload status
245+
reload_status=$(add_to_path "$dest")
246+
247+
# Final instructions
248+
say "Successfully installed spaces $check_tag to $dest"
249+
250+
# Reload shell if needed
251+
if [ "$reload_status" = "reload" ]; then
252+
if [[ "$SHELL" == */zsh ]]; then
253+
say "Please run 'source $HOME/.zshrc' to update your PATH"
254+
else
255+
if [ "$(uname -s)" = "Darwin" ]; then
256+
say "Please run 'source $HOME/.bash_profile' to update your PATH"
257+
else
258+
say "Please run 'source $HOME/.bashrc' to update your PATH"
259+
fi
260+
fi
261+
say "Or start a new terminal session to apply changes"
262+
fi
263+
264+
# Show versions if verbose
265+
if [ "$verbose" = true ]; then
266+
say "installed version:"
267+
"$dest/spaced" --version
268+
fi

0 commit comments

Comments
 (0)