1
0
forked from GRIN/grim
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
2026-05-03 10:05:03 +03:00
2024-04-14 14:04:34 +03:00

Goblin

Goblin

Goblin is a private, pay-by-username wallet for GRIN ツ - confidential digital cash on Mimblewimble, with no amounts or addresses on the chain.

Instead of passing slatepack files back and forth, you pay a username (or an npub) and the payment is delivered for you as an end-to-end encrypted message over nostr, routed through Tor. Relays only ever see ciphertext - never the amount, the sender, or the recipient. Tor hides your IP from the relay; the relay and encryption hide the rest - content, sender, timing.

Goblin is a fork of the Grim egui GRIN wallet: it keeps Grim's full GRIN node/wallet engine and layers a Nostr-native, mobile-first payments experience on top.

What it does

  • Send to people - pay a username or npub; the GRIN slatepack travels as a NIP-17 gift-wrapped DM (kind 1059) over Tor and is applied automatically by the recipient's wallet. No files to swap, no need to both be online at once.
  • Manual slatepacks too - when you need to pay or get paid without a handle, Settings → Wallet → Slatepacks exposes the classic by-hand flow: create a slatepack to send, or paste one to receive, finalize, or pay.
  • In-app identity - a nostr payment key that is deliberately not part of your seed, so you can rotate it any time to stay unlinkable without touching your funds. An optional human-readable name comes from the goblin.st identity service.
  • Private by construction - GRIN's address-less, confidential chain; your payments and identity (nostr relays, NIP-05 lookups, price) are routed through Tor, so who-pays-whom never touches the clear net. The GRIN node connection - block sync and broadcasting your transaction - is direct: public chain data, the same for everyone, and not tied to your identity. Keys, names and history stay on your device.
  • Configurable amount pairing - show balances against a world currency, Bitcoin, or sats (rates fetched over Tor), or turn the preview off.
  • News on Home - the latest post from the official Goblin news key (a kind 30023 long-form article) appears on the Home screen; it stays hidden when there is nothing to show, and only ever shows the newest article.
  • Cross-platform - Linux, macOS, Windows, Android, built in pure Rust on egui.

How a payment travels

   you ──slatepack──▶ NIP-17 gift wrap (kind 1059, NIP-44 encrypted)
                          │
                         Tor
                          │
            ┌─────────────┴─────────────┐
        your relays              recipient's DM relays (kind 10050)
            └─────────────┬─────────────┘
                          ▼
   recipient ◀──unwrap, verify seal author, apply slatepack

The wrap is NIP-44-encrypted, and delivery uses the recipient's DM relay list (kind 10050). Tor hides your IP from the relay; the relay and the encryption above hide the rest - content, sender, timing.

Both parties only need one relay in common. The default set is the Goblin relay plus large public relays (relay.damus.io, nos.lol), and the set is editable in Settings → Relays.

Build

Desktop (Linux / macOS / Windows)

Goblin links Tor in-process via arti - the wallet is a single self-contained binary, no sidecar, nothing separate to install:

git submodule update --init --recursive
cargo build --release
./target/release/goblin

Goblin's identity and payment traffic (nostr relays, NIP-05 lookups and price fetches) rides Tor: every relay, the money-path relay included, is reached over a Tor exit to its ordinary clearnet host. The GRIN node connection (block sync and transaction broadcast) is not routed through Tor: it connects directly, as it carries only public chain data that isn't linked to your wallet.

Android

Install the Android SDK / NDK, then from the repo root:

./scripts/android.sh build|release v7|v8|x86

v7/v8/x86 is the device CPU architecture for build; for release pass a version in major.minor.patch form.

Identity service (goblin-nip05d)

The optional name service lives in goblin-nip05d/ (axum + SQLite) and is deployed at goblin.st. It implements NIP-05 resolution, NIP-98-authenticated registration and release (names are never transferred - on a key rotation you release the old name and re-register, or import your existing identity). The wallet is fully usable - and fully anonymous - without it. Avatars aren't stored or served - clients render them from the pubkey (an npub gradient with the username's first letter, else the Grin mark).

License

Apache License v2.0.

Credits

🤖 Built with AI pair-programming assistance (Claude)

The underlying cross-platform GRIN wallet engine is the upstream Grim project.

S
Description
No description provided
Readme Apache-2.0 48 MiB
Languages
Rust 96.4%
Java 2.4%
Shell 1.1%