1
0
forked from GRIN/grim

Build 50: production Nym requester; correct sender amount/fee; Nym copy

- Bake the always-on us-ea.st network requester into NETWORK_REQUESTER so a
  shipped wallet routes through the mixnet out of the box (override with
  GOBLIN_NYM_PROVIDER). Verified e2e: real wallet-to-wallet payment across two
  mainnet nodes (grincoin.org → main.gri.mw), recipient received the exact
  amount, all traffic over Nym.
- Fix the sender's displayed amount: a sent tx debits inputs and credits change,
  so debited-minus-credited is amount PLUS fee. Subtract the fee so the activity
  feed, receipt and history show the value that reached the recipient (0.01),
  not the fee-inclusive net (0.033). The receipt's "Network fee" now reads the
  real kernel fee instead of the change.
- Replace the remaining user-facing "Tor" copy with Nym (send/request review
  delivery line, connection status chips, onboarding, the Privacy settings row).

38 lib tests pass.
This commit is contained in:
2ro
2026-06-13 15:15:41 -04:00
parent c4d26d3b7f
commit c05074faac
6 changed files with 27 additions and 18 deletions
+2 -2
View File
@@ -99,11 +99,11 @@ pub fn receipt_detail(wallet: &Wallet, tx_id: u32) -> Option<ReceiptDetail> {
.or(Some(tx.data.creation_ts))
.map(|t| t.timestamp())
.unwrap_or(0);
// A send's fee is the debit beyond the amount; a receive doesn't pay one.
// The actual network fee from the tx kernel; a receive doesn't pay one.
let fee = if incoming {
None
} else {
Some(tx.data.amount_debited.saturating_sub(tx.amount))
Some(tx.data.fee.map(|f| f.fee()).unwrap_or(0))
};
let confs = if tx.data.confirmed {
None
+8 -4
View File
@@ -586,7 +586,7 @@ impl GoblinWalletView {
);
ui.label(
RichText::new(if connected {
"synced · Tor"
"synced · Nym"
} else {
"connecting…"
})
@@ -1766,7 +1766,7 @@ impl GoblinWalletView {
);
}
let status = if connected {
"Connected over Tor"
"Connected over Nym"
} else {
"Connecting…"
};
@@ -1930,7 +1930,11 @@ impl GoblinWalletView {
ui.add_space(16.0);
let mut open_pairing = false;
settings_group(ui, "Privacy", |ui| {
settings_row(ui, "Tor routing", "All payments routed over Tor");
settings_row(
ui,
"Mixnet routing",
"All traffic routed over the Nym mixnet",
);
// Tap to cycle the incoming-payment accept policy.
if settings_row_btn(ui, "Auto-accept", accept_policy_label(wallet)) {
cycle_accept_policy(wallet);
@@ -3380,7 +3384,7 @@ fn relay_summary(wallet: &Wallet) -> String {
}
/// Compute a fiat preview line for the balance, when a rate is available.
/// One-line node summary: "Block 1,847,221 · main.gri.mw · Tor".
/// One-line node summary: "Block 1,847,221 · main.gri.mw".
/// Bare node host (or "integrated node") for the sidebar card's third line.
fn node_host(wallet: &Wallet) -> String {
match wallet.get_current_connection() {
+3 -3
View File
@@ -702,9 +702,9 @@ impl OnboardingContent {
);
ui.label(
RichText::new(if connected {
"connected over Tor"
"connected over Nym"
} else {
"connecting over Tor"
"connecting over Nym"
})
.font(FontId::new(12.0, fonts::regular()))
.color(t.surface_text_mute),
@@ -839,7 +839,7 @@ impl OnboardingContent {
ui.add_space(6.0);
ui.label(
RichText::new(
"Available once Tor is connected — or skip and claim later.",
"Available once the mixnet connects — or skip and claim later.",
)
.font(FontId::new(12.0, fonts::regular()))
.color(t.surface_text_mute),
+2 -2
View File
@@ -968,11 +968,11 @@ impl SendFlow {
}
if self.request {
w::info_row(ui, "They pay", "Only if they approve");
w::info_row(ui, "Delivery", "Encrypted nostr DM over Tor");
w::info_row(ui, "Delivery", "Encrypted nostr DM over Nym");
} else {
w::info_row(ui, "Network fee", "Deducted from your balance");
w::info_row(ui, "Privacy", "Mimblewimble");
w::info_row(ui, "Delivery", "Encrypted nostr DM over Tor");
w::info_row(ui, "Delivery", "Encrypted nostr DM over Nym");
}
ui.add_space(16.0);
+6 -6
View File
@@ -38,12 +38,12 @@ const BIN_NAME: &str = "nym-socks5-client";
const CLIENT_ID: &str = "goblin";
/// Network requester (the mixnet exit) Goblin routes through — the SOCKS5
/// client's `--provider`. Set this to the always-on requester we run on
/// us-ea.st (standard exit policy, which permits wss/443 + HTTPS) once it is
/// deployed; until then it is configured at runtime via `GOBLIN_NYM_PROVIDER`.
/// Empty means "not configured": the sidecar won't be auto-launched, but an
/// already-running SOCKS5 endpoint (a dev sidecar / system service) is reused.
pub const NETWORK_REQUESTER: &str = "";
/// client's `--provider`. This is the always-on requester we run on us-ea.st
/// (standard Nym exit policy, which permits the wss/443 + HTTPS hosts Goblin
/// needs). Overridable at runtime with `GOBLIN_NYM_PROVIDER`. If left empty,
/// the sidecar isn't auto-launched but an already-running SOCKS5 endpoint (a
/// dev sidecar / system service on :1080) is still reused.
pub const NETWORK_REQUESTER: &str = "5ibBQ9SS1er3tks5tfmrzCQ29qU1uBSvZN2dUwLKPRwu.HdbktiMVniUyaKBnorFVXLRHdwRb8iG9dV481r5xyopV@2RmEBKhQHsqvw5sjnnt2Bhpy96MPDUkbfWkT6r2RWNCR";
lazy_static! {
/// Handle to the spawned child so it is killed when Goblin exits.
+6 -1
View File
@@ -244,8 +244,13 @@ impl WalletTx {
action: Option<WalletTxAction>,
action_error: Option<Error>,
) -> Self {
// For a sent tx the wallet debits inputs and credits change, so
// `debited - credited` is the amount sent PLUS the network fee. Subtract
// the fee so `amount` is the value that actually reached the recipient
// (matching what their wallet receives). Receives don't pay a fee.
let fee = tx.fee.map(|f| f.fee()).unwrap_or(0);
let amount = if tx.amount_debited > tx.amount_credited {
tx.amount_debited - tx.amount_credited
(tx.amount_debited - tx.amount_credited).saturating_sub(fee)
} else {
tx.amount_credited - tx.amount_debited
};