Files
grim/Cargo.toml
T
2ro d5ae136cf1 Goblin: route macOS goblin: link clicks to the send-review screen
The goblin: scheme was registered everywhere last night, but macOS is the one
platform that delivers a scheme click as a Carbon/Apple Event (kAEGetURL), not on
argv and not through any path winit or eframe surface, so on a Mac the click went
nowhere.

Install a kAEGetURL handler straight on the shared NSAppleEventManager at startup
(macOS only), pull the URL string out of the event, and feed it to on_data, the
exact same entry the desktop argv path uses. The per-frame Goblin router then lands
the pay URI on the prefilled review screen, identical to a scanned checkout QR or a
Linux argv link. This covers both a cold launch (event queued at start-up) and a
warm click (app already running).

The bridge is entirely cfg(target_os = "macos"): zero bytes on Linux, Windows and
Android (Linux binary size byte-for-byte unchanged). It talks to the Objective-C
runtime through the classic objc crate, which is already in the macOS build graph
via nokhwa/cocoa/metal/wgpu, so it adds no new dependency tree, only its own small
handler class. It registers its own Apple Event handler rather than touching the
NSApplicationDelegate winit owns, so nothing winit does is clobbered.
2026-07-05 03:14:45 -04:00

240 lines
9.6 KiB
TOML

[package]
name = "grim"
version = "0.3.6"
authors = ["Ardocrat <ardocrat@gri.mw>"]
description = "Goblin: a peer-to-peer wallet for Grin. Send and receive instantly with a handle - slatepacks and Tor handled for you."
license = "Apache-2.0"
repository = "https://code.gri.mw/GUI/grim"
keywords = [ "crypto", "grin", "mimblewimble", "nostr" ]
edition = "2024"
build = "build.rs"
[[bin]]
name = "goblin"
path = "src/main.rs"
[lib]
name="grim"
crate-type = ["rlib"]
# Desktop/CI release binaries ship stripped of debug symbols — the nym + nostr +
# grin tree leaves a large symbol table that's dead weight for users (~16 MB on
# Linux). opt-level stays at the default 3 for wallet/runtime speed.
[profile.release]
strip = true
[profile.release-apk]
inherits = "release"
strip = true
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
[features]
## Default build uses the Tor transport only. The `nym` feature gates the dormant
## mixnet path (src/nym/). Cargo resolves OPTIONAL deps into the graph too, so
## nym-sdk cannot merely be `optional` — it links a different libsqlite3-sys than
## arti (a native-lib `links` conflict Cargo rejects at resolution). The nym
## path-deps are therefore commented out below; the module code is retained on
## disk but building `--features nym` requires restoring them (and drops arti —
## the two transports cannot coexist in one binary, which is why Tor replaced Nym).
default = []
nym = []
## Compiles the internal E2E harness (src/wallet/e2e.rs); off by default and the
## file is untracked, so a fresh clone builds without it.
e2e-internal = []
[dependencies]
log = "0.4.27"
# node
grin_api = { path = "node/api" }
grin_chain = { path = "node/chain" }
grin_config = { path = "node/config" }
grin_core = { path = "node/core" }
grin_p2p = { path = "node/p2p" }
grin_servers = { path = "node/servers" }
grin_keychain = { path = "node/keychain" }
grin_util = { path = "node/util" }
# wallet
grin_wallet_impls = { path = "wallet/impls" }
grin_wallet_api = { path = "wallet/api"}
grin_wallet_libwallet = { path = "wallet/libwallet" }
grin_wallet_util = { path = "wallet/util" }
grin_wallet_controller = { path = "wallet/controller" }
## ui
egui = { version = "0.33.3", default-features = false }
egui_extras = { version = "0.33.3", features = ["image", "svg"] }
egui-async = "0.3.4"
rust-i18n = "3.1.5"
## other
log4rs = "1.4.0"
anyhow = "1.0.97"
pin-project = "1.1.10"
backtrace = "0.3.76"
thiserror = "2.0.18"
futures = "0.3.31"
dirs = "6.0.0"
sys-locale = "0.3.2"
chrono = "0.4.43"
parking_lot = "0.12.3"
lazy_static = "1.5.0"
toml = "0.9.11+spec-1.1.0"
serde = "1.0.228"
local-ip-address = "0.6.9"
url = "2.5.8"
rand = "0.9.2"
serde_derive = "1.0.228"
serde_json = "1.0.149"
tokio = { version = "1.49.0", features = ["full"] }
image = "0.25.9"
rqrr = "0.10.1"
qrcodegen = "1.8.0"
qrcode = "0.14.1"
ur = "0.4.1"
gif = "0.14.1"
rkv = "0.20.0"
usvg = "0.45.1"
ring = "0.16.20"
hyper = { version = "1.6.0", features = ["full"], package = "hyper" }
hyper-util = { version = "0.1.19", features = ["http1", "client", "client-legacy", "tokio"] }
http-body-util = "0.1.3"
bytes = "1.11.0"
hyper-socks2 = "0.9.1"
hyper-proxy2 = "0.1.0"
hyper-tls = "0.6.0"
async-std = "1.13.2"
uuid = { version = "0.8.2", features = ["v4"] }
num-bigint = "0.4.6"
## nostr
nostr-sdk = { version = "0.44", features = ["nip06", "nip44", "nip49", "nip59", "nip98"] }
nostr-relay-pool = "0.44"
## NIP-44 v3 (+ v2) encryption for the NIP-17 backward-compat extension (G4).
## Now published to crates.io as v0.3.0 (the M0 deliverable, all upstream test
## vectors green) — no local sibling checkout required. secp256k1 0.31, bridged
## to nostr-sdk's 0.29 in wrapv3.rs (see the secp256k1 note below).
nip44 = "0.3.0"
## Only to construct the key types the `nip44` crate takes: nostr-sdk pins
## secp256k1 0.29, the nip44 crate 0.31 — bridged via byte arrays in wrapv3.rs.
secp256k1 = "0.31"
async-wsocket = "0.13"
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }
regex = "1"
base64 = "0.22"
hex = "0.4"
## rustls is pulled by both our TLS (tungstenite, ring) and nym-sdk
## (aws-lc-rs); with two providers present rustls 0.23 can't auto-pick a default,
## so we install ring explicitly at startup (see lib.rs). Direct dep just to make
## `rustls::crypto::ring::default_provider()` reachable. NOTHING here may pull
## rustls-platform-verifier — it panics on Android outside a full app context.
rustls = { version = "0.23", features = ["ring"] }
## TLS-over-tunnel for the mixnet HTTP client (webpki roots, never the platform
## verifier — see the rustls note above).
tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }
webpki-roots = "1"
## Tor — embedded arti (the DIALING half only: connect OUT to the relay's .onion,
## and to clearnet HTTP hosts through a Tor exit). Copied from our sister wallet
## GRIM's proven, shipping engine. Two choices inherited VERBATIM from GRIM: arti
## 0.43 across the family, and the native-tls Tor runtime (TokioNativeTlsRuntime),
## NOT rustls — this deliberately sidesteps the rustls/ring crypto-provider
## conflict fought during the Nym era (our relay/HTTP rustls still uses ring, see
## lib.rs; arti's own TLS is native-tls and never touches the rustls provider).
## `static` vendors openssl (self-contained Android/cross builds, as GRIM ships);
## `onion-service-client` enables dialing .onion. We drop GRIM's `pt-client`
## (bridges) and `onion-service-service` (hosting) — Goblin only dials.
arti-client = { version = "0.43.0", features = ["static", "onion-service-client"] }
tor-rtcompat = { version = "0.43.0", features = ["static"] }
## Nym mixnet — DORMANT since the Tor transport swap. The mixnet path (src/nym/)
## is retained on disk but its deps are COMMENTED OUT, because arti's `tor-dirmgr`
## needs libsqlite3-sys 0.34 (rusqlite 0.36) while nym-sdk's credential-storage
## needs libsqlite3-sys 0.30 (sqlx) and BOTH link the native `sqlite3` library —
## Cargo forbids two packages linking the same native lib, and it rejects this at
## RESOLUTION even for optional/unused deps. The two transports therefore cannot
## coexist in one binary (exactly why Tor replaced Nym). To build the old path,
## restore these three deps and build `--features nym` (which then drops arti).
## Full deletion is a later phase; for now the code stays on disk for reference.
## Path deps into the local nym checkout, PINNED at rev
## f6ed17d949cc19fee0fb51db3cb65771fd510d5b ("http-api-client: preconfigured
## webpki roots on Android").
# nym-sdk = { path = "../nym/sdk/rust/nym-sdk" }
# smolmix = { path = "../nym/smolmix/core" }
# hickory-proto = { version = "0.26", default-features = false, features = ["std"] }
## NIP-98 payload hashing
sha2 = "0.10.8"
## stratum server
tokio-old = { version = "0.2", features = ["full"], package = "tokio" }
tokio-util-old = { version = "0.2", features = ["codec"], package = "tokio-util" }
[target.'cfg(target_os = "linux")'.dependencies]
nokhwa = { version = "0.10.10", default-features = false, features = ["input-v4l"] }
[target.'cfg(target_os = "windows")'.dependencies]
nokhwa = { version = "0.10.10", default-features = false, features = ["input-msmf"] }
[target.'cfg(target_os = "macos")'.dependencies]
nokhwa = { version = "0.10.10", default-features = false, features = ["input-avfoundation", "output-threaded"] }
## Objective-C runtime shim for the macOS `goblin:` deep-link bridge (src/lib.rs,
## mac_deeplink). Already in the macOS build graph via nokhwa/cocoa/metal/wgpu, so
## this pulls no new crate — it just lets us name it directly. Not compiled on any
## other platform.
objc = "0.2"
[target.'cfg(not(target_os = "android"))'.dependencies]
env_logger = "0.11.3"
winit = { version = "0.30.12" }
wgpu = { version = "27.0.1" }
eframe = { version = "0.33.2", features = ["wgpu"] }
arboard = "3.2.0"
rfd = "0.17.2"
interprocess = { version = "2.2.1", features = ["tokio"] }
## native-tls (via hyper-tls) uses OpenSSL only on Linux/Android. Upstream Grim
## got a vendored, statically-linked OpenSSL for free through arti's `static`
## feature; dropping arti for Nym took that with it, breaking Android/cross
## builds (no system OpenSSL for the target) and leaving desktop dynamically
## linked to libssl. Restore the vendored build for exactly those two targets so
## each is self-contained. Windows (SChannel) and macOS (Security.framework)
## don't use OpenSSL at all, so they must NOT pull it — building openssl-src
## there is both pointless and fragile (the Windows MSVC runner's bash perl is
## missing modules its Configure needs).
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.15.0"
jni = "0.21.1"
android-activity = { version = "0.6.0", features = ["game-activity"] }
winit = { version = "0.30.12", features = ["android-game-activity"] }
eframe = { version = "0.33.2", default-features = false, features = ["glow", "android-game-activity"] }
[build-dependencies]
built = "0.8.0"
# Windows hosts only: embed the Goblin icon (wix/Product.ico) into goblin.exe via
# build.rs. Not compiled on Linux/macOS/Android hosts, so other builds are
# unaffected.
[target.'cfg(windows)'.build-dependencies]
winresource = "0.1"
[dev-dependencies]
nostr-sdk = { version = "0.44", features = ["nip06", "nip44", "nip49", "nip59", "nip98"] }
tokio = { version = "1.49.0", features = ["full"] }
base64 = "0.22"
sha2 = "0.10"
hex = "0.4"
serde_yaml = "0.9"
## Re-expose deps that already live in the main graph so the E2E harness can be
## exercised and its logs captured. No new compiles — same versions unify.
log = "0.4.27"
env_logger = "0.11.3"
rustls = { version = "0.23", features = ["ring"] }