Skip to content

feat: support manual (self-supplied) wallets - #270

Merged
paratoxicdev merged 10 commits into
parasitepool:masterfrom
mrv777:dispenser-multi-options
Jul 27, 2026
Merged

feat: support manual (self-supplied) wallets#270
paratoxicdev merged 10 commits into
parasitepool:masterfrom
mrv777:dispenser-multi-options

Conversation

@mrv777

@mrv777 mrv777 commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Replaces #237
Add a manual wallet type alongside Xverse so users with wallets that have no browser extension (e.g. Sparrow) can connect by entering their address and approve actions by pasting BIP322 signatures from their own wallet.

Decisions

Decision Why
Central signMessage() primitive Replce 6 copy-pasted signing blocks; manual logic lives in one place
No Lightning for manual wallets LN auth needs ECDSA + a public key a pasted address can't provide; hide balance + Refinery
Connect stays Xverse-direct Manual via "Use another wallet" link + no-Xverse help modal → zero UX change for Xverse users
Owner UI gated by ownership, not LN-auth Manual wallets have no LN token/activation, so they'd otherwise see nothing
Manual ownership left unverified only public/derivable data shown; all actions are BIP322-verified server-side anyways

mrv777 added 3 commits June 16, 2026 09:55
Add a `manual` wallet type alongside Xverse so users with wallets that
have no browser extension (e.g. Sparrow) can connect by entering their
address and approve actions by pasting BIP322 signatures from their own
wallet.

- Centralize the six duplicated `request('signMessage')` call sites
  behind one `signMessage()` primitive on the wallet context. Xverse
  signs via sats-connect; manual surfaces the message in a global modal
  and resolves once the user pastes a signature.
- Add `walletType` + `connectManual` to the wallet context; manual
  wallets persist address-only (no public key, no Lightning).
- Connect stays Xverse-direct; manual is reachable via a "Use another
  wallet" link and a "Connect manually" entry in the help modal.
- Decouple owner gating so manual owners see Stratum + Dispenser +
  privacy toggle by ownership, with no Lightning balance and no
  Refinery. Xverse flow is unchanged.
- Dispenser claim gains a manual path: enter a destination Ordinals
  address, then sign the claim message manually.

Add ManualSignModal and ManualConnectModal.
@mrv777
mrv777 marked this pull request as ready for review July 3, 2026 13:35
…ptions

# Conflicts:
#	app/components/dispenser/DispenserClaim.tsx
@mrv777

mrv777 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Sorry for the delay on this, should be ready for review now

@Celshade

Celshade commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Related to an old issue I raised back in January: #138 (which, I'm creating a PR for - slight deviation from the original issue suggestion)

@paratoxicdev
paratoxicdev requested review from parabitdev and paratoxicdev and removed request for parabitdev July 14, 2026 15:51
@paratoxicdev

Copy link
Copy Markdown
Contributor

@mrv777 This is good PR, I tweaked and fixed some stuff and allowed the Refinery to render in Manual mode. I couldn't really test the Dispenser flow because none of my testing wallets currently has any rewards. @parabitdev Could you checkout this branch and run and review the Dispenser flow specifically to make sure everything works correctly there?

@paratoxicdev

Copy link
Copy Markdown
Contributor

@mrv777 maybe also check the branch out and run it locally and let me know if you agree/disagree with any changes I made pls

@paratoxicdev

Copy link
Copy Markdown
Contributor

Just a heads up, we've updated the runtime to node 24 and pnpm to 11.15

@paratoxicdev

Copy link
Copy Markdown
Contributor

you might have to do pnpm rebuild (for better-sqlite3)

@parabitdev parabitdev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread app/utils/validators.ts
return trimmed;
}

export function isValidBitcoinAddress(value: string): boolean {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't love the use of try{}catch{} as control-flow, but it is acceptable as the underlying throws force this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want me to try and do this better? or is it fine for now?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you see a way to make this better go ahead but I think it's fine for now. I'll merge and deploy this over the weekend, latest by Monday

@paratoxicdev paratoxicdev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@paratoxicdev
paratoxicdev merged commit 94e91d2 into parasitepool:master Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants