mirror of
https://code.gri.mw/GUI/grim.git
synced 2026-07-14 18:58:54 +00:00
908df117e6
Stability (found via GUI testing):
- tor: create arti runtime on a clean thread; lazy TOR_STATE init panicked
inside tokio contexts and poisoned the whole Tor/nostr stack
- store: open rkv SafeMode envs with capacity headroom; reopening at
exactly DEFAULT_MAX_DBS crashed every wallet restart (DbsFull)
- goblin ui: centered_column hands children a full-height rect; ScrollAreas
inside clipped everything below the first widget
- build: webtunnel client was silently embedded as 0 bytes without Go;
warn at build, extract with create_dir_all + exec bit at runtime
- price: CoinGecko requires a User-Agent (403 otherwise); add retry-once
backoff and a parse-failure diagnostic
- tor: retry http_request up to 3x on fresh isolated circuits
UX overhaul (per owner direction + Cash App references):
- floating icon-only 3-tab pill: Wallet / center accent ツ Pay puck /
Activity (requests badge kept); Me opens via header avatar
- Pay tab: amount-first surface (numpad on mobile, typed on desktop) with
Request and Pay; Pay carries the amount straight to Review
- Request flips Receive into "Requesting Nツ" state with a clear chip
- full-bleed goblin surface: GRIM title panel and network column hidden
while a wallet is open; node status card lives in the sidebar above the
profile chip; Lock wallet row added (Settings -> Wallet)
- goblin branding: titlebar, wallet-list logo + GOBLIN, new mark assets
(white master, theme-tinted) in wordmark, QR center, wallet list
- build-based versioning: Build N = commits since the GRIM fork base,
emitted by build.rs; About leads with it, Third party credits GRIM,
grin node, nostr-sdk, arti, egui and the implemented NIPs
Accessibility & settings:
- surface_text{,_dim,_mute} tokens: yellow theme has dark cards on a
bright bg; all on-surface text now readable in every theme (incl. QR)
- settings rows clickable across the whole row; profile card fills width;
density option removed (comfy fixed)
- editable Node connections (integrated/external, add/remove) and Relays
(add/remove + live service restart); NIPs explainer page with goblin.st
context; third-party rows link to upstream projects
- standardized npub truncation (head 12 ... tail 6) shown in profile
Identity (owner decision: drop NIP-06 seed binding):
- random standalone nsec (Keys::generate); seed proves nothing about the
identity and cannot resurrect it; legacy Derived identities still unlock
- key rotation: double warning (pending payments disrupted), typed RESET +
wallet password, fresh random key, username moved atomically via the
name server transfer endpoint; aborts cleanly if the move fails
- encrypted identity backup export (NIP-49 ncryptsec JSON, includes
username + history) and import accepting nsec or backup JSON
- nip05d: POST /api/v1/transfer (NIP-98 by current owner, atomic
owner-guarded swap, one-name-per-pubkey enforced) + SQL invariant tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
133 lines
3.5 KiB
Rust
133 lines
3.5 KiB
Rust
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
use std::{env, fs};
|
|
|
|
/// The GRIM commit Goblin forked from; builds count commits on top of it.
|
|
const GOBLIN_FORK_BASE: &str = "b51a46b";
|
|
|
|
fn main() {
|
|
built::write_built_file().expect("Failed to acquire build-time information");
|
|
|
|
// Goblin versioning is build-based: Build N = commits since the fork.
|
|
let build = Command::new("git")
|
|
.args([
|
|
"rev-list",
|
|
"--count",
|
|
&format!("{}..HEAD", GOBLIN_FORK_BASE),
|
|
])
|
|
.output()
|
|
.ok()
|
|
.filter(|o| o.status.success())
|
|
.and_then(|o| String::from_utf8(o.stdout).ok())
|
|
.map(|s| s.trim().to_string())
|
|
.filter(|s| !s.is_empty())
|
|
.unwrap_or_else(|| "dev".to_string());
|
|
println!("cargo:rustc-env=GOBLIN_BUILD={}", build);
|
|
println!("cargo:rerun-if-changed=.git/HEAD");
|
|
|
|
// Setting up git hooks in the project: rustfmt and so on.
|
|
let git_hooks = format!(
|
|
"git config core.hooksPath {}",
|
|
PathBuf::from("./.hooks").to_str().unwrap()
|
|
);
|
|
|
|
if cfg!(target_os = "windows") {
|
|
Command::new("cmd")
|
|
.args(&["/C", &git_hooks])
|
|
.output()
|
|
.expect("failed to execute git config for hooks");
|
|
} else {
|
|
Command::new("sh")
|
|
.args(&["-c", &git_hooks])
|
|
.output()
|
|
.expect("failed to execute git config for hooks");
|
|
}
|
|
|
|
let out_dir = env::var("OUT_DIR").unwrap();
|
|
let tor_out_dir = format!("{}/tor", out_dir);
|
|
let mut webtunnel_file = format!("{}/webtunnel", tor_out_dir);
|
|
let exists = fs::exists(&webtunnel_file).unwrap();
|
|
if !exists {
|
|
// Create empty webtunnel file to allow build with include_bytes! macro.
|
|
fs::create_dir(&tor_out_dir).unwrap_or_default();
|
|
fs::File::create(&webtunnel_file).unwrap();
|
|
}
|
|
|
|
let target = env::var("TARGET").unwrap();
|
|
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
|
if target_os == "ios" {
|
|
return;
|
|
}
|
|
|
|
let is_android = target_os == "android";
|
|
if is_android {
|
|
// Set a path to Android Webtunnel binary.
|
|
let arch = if target.contains("aarch64") {
|
|
"arm64-v8a"
|
|
} else if target.contains("arm") {
|
|
"armeabi-v7a"
|
|
} else {
|
|
"x86_64"
|
|
};
|
|
let root = env::var("CARGO_MANIFEST_DIR").unwrap();
|
|
webtunnel_file = format!(
|
|
"{}/android/app/src/main/jniLibs/{}/libwebtunnel.so",
|
|
root, arch
|
|
);
|
|
}
|
|
|
|
// Build if Webtunnel binary is empty or not exists.
|
|
let empty = match fs::File::open(&webtunnel_file) {
|
|
Ok(file) => file.metadata().unwrap().len() == 0,
|
|
Err(_) => true,
|
|
};
|
|
let build = !exists || empty;
|
|
if build {
|
|
// Setup GOOS env variable.
|
|
let go_os = if target_os == "macos" {
|
|
"darwin"
|
|
} else {
|
|
target_os.as_str()
|
|
};
|
|
// Setup GOARCH env variable.
|
|
let go_arch = if target.contains("aarch64") {
|
|
"arm64"
|
|
} else if target.contains("arm") {
|
|
"arm"
|
|
} else {
|
|
"amd64"
|
|
};
|
|
// Run Webtunnel Go build.
|
|
let output = if env::consts::OS == "windows" {
|
|
Command::new("./scripts/webtunnel.bat")
|
|
.arg(go_os)
|
|
.arg(go_arch)
|
|
.arg(&webtunnel_file)
|
|
.output()
|
|
} else {
|
|
Command::new("bash")
|
|
.arg("./scripts/webtunnel.sh")
|
|
.arg(go_os)
|
|
.arg(go_arch)
|
|
.arg(&webtunnel_file)
|
|
.output()
|
|
};
|
|
if let Ok(out) = output {
|
|
if out.status.code().is_none() || out.status.code().unwrap() != 0 {
|
|
panic!("webtunnel go build failed:\n{:?}", out);
|
|
}
|
|
}
|
|
// The build script exits 0 when Go is absent, leaving the placeholder
|
|
// empty — surface that loudly instead of shipping broken bridges.
|
|
let still_empty = fs::metadata(&webtunnel_file)
|
|
.map(|m| m.len() == 0)
|
|
.unwrap_or(true);
|
|
if still_empty {
|
|
println!(
|
|
"cargo:warning=webtunnel client was not built (is Go installed?) — \
|
|
Tor webtunnel bridges will not work at runtime"
|
|
);
|
|
}
|
|
}
|
|
}
|