Skip to content

multi: Add Monero wallet - Phase I#3295

Merged
JoeGruffins merged 22 commits into
decred:masterfrom
dev-warrior777:xmr-wallet
Oct 20, 2025
Merged

multi: Add Monero wallet - Phase I#3295
JoeGruffins merged 22 commits into
decred:masterfrom
dev-warrior777:xmr-wallet

Conversation

@dev-warrior777
Copy link
Copy Markdown
Contributor

@dev-warrior777 dev-warrior777 commented Jun 13, 2025

Fix Task: #3231

  • Add an XMR wallet that can:
    - Configure a monerod
    - configure and run monero rpc server
    - Send, Receive & Withdraw funds
    - Live reconfigure fee priority
    - Tx Fee estimation
    - New sub-addresses

  • later phases will add trading capability

Copy link
Copy Markdown
Collaborator

@martonp martonp left a comment

Choose a reason for hiding this comment

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

Initial pass. I got it to connect to simnet by starting updating the command to monero-wallet-rpc but the sync on the UI is staying at 0%.

Comment thread client/asset/xmr/xmrrpc.go
Comment thread client/asset/xmr/wallet.go Outdated
Comment thread client/asset/xmr/process.go Outdated
Comment thread client/asset/xmr/process.go Outdated
Comment thread client/asset/xmr/xmr.go Outdated
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Jun 25, 2025

Initial pass. I got it to connect to simnet by starting updating the command to monero-wallet-rpc but the sync on the UI is staying at 0%.

I will play around with this. Simnet is not very useful at the moment.

I think what should happen is the simnet option should only use the running daemon from the harness-alpha. Then follow the same pattern of starting a new monero-rpc-client child process in Connect.

  • Allows testing using simnet-walletpair.
  • Coins could be mined manually from the harness to the simnet dex wallet.
  • Expectation is the simnet-walletpair folder would be deleted after use.

Comment thread client/webserver/site/src/js/coinexplorers.ts
Comment thread client/asset/xmr/process.go Outdated
Comment thread client/asset/xmr/xmr.go Outdated
Comment thread client/asset/xmr/xmr.go Outdated
Comment thread client/asset/xmr/xmr.go Outdated
Comment thread client/asset/xmr/wallet.go Outdated
Comment thread client/asset/xmr/wallet.go Outdated
Comment thread client/asset/xmr/wallet.go
Comment thread client/asset/xmr/wallet.go
Comment thread client/asset/xmr/wallet.go Outdated
@dev-warrior777 dev-warrior777 marked this pull request as draft July 1, 2025 03:42
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Aug 7, 2025

Resolved merge conflict in client/cmd/bisonw-desktop/go.mod by keeping github.com/zalando/go-keyring v0.2.6 in bisonw-desktop (required for Monero wallet, commit 4cf6bdd). CI passed.

I cannot build bisonw-desktop due to missing libs on Ubuntu 24.04 but have qemu set up with Ubuntu 22.04. Will test tomorrow.

UPDATE:
Verified bisonw & bisonw-desktop on ubuntu 22.04 using qemu.

@dev-warrior777
Copy link
Copy Markdown
Contributor Author

Still TODO:

  • Build a small bash tool to create monero simnet wallets; the simnet daemon is done and separate.
  • Write monero tx parsing - needed to get tx outputs (stealth addresses) and likely other uses.
  • Add Lock/Unlock wallet I think
  • +++

dev-warrior777 added 8 commits August 25, 2025 21:16
        Add an XMR wallet that can:
        - Configure a monerod
        - configure and run monero rpc server
        - Send, Receive & Withdraw funds
	- Live reconfigure fee priority
	- Rescan wallet transactions
	- Tx Fee estimation
	- New sub-addresses
	Note: remote daemon login removed. It is unused by any
	remote daemons on <https://monero.fail> which all seem
	to be configured as 'restricted'. That means the RPCs
	they can answer are restricted in the monero code itself.
	- Use monero-wallet-cli for initial sync
	- Enable wallet password storeage in os keystore
	- Allow 2 simnet wallet-rpc servers for simnet
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Aug 25, 2025

TODO:

previous bad suggestions

Rewrite transferSimple and withdrawSimple to work in stages
build transfer - no relay
parse and verify outputs, if not == 2, error
broadcast
assign stealth address index 0 concat index 1 as an identifier for Coin in DecodeCoinID

- Implement the simplifications and mitigations to ensure that the rare but possible monero splitting a single payment across 2 outputs is handled.
- allow only 1 (one) destination
- ensure no super high amounts are sent which might mean too many inputs

  • manage dust periodically by using sweep_dust in a goroutine every hour or on demand.

  • Build a small bash tool to create 2 monero simnet wallets; the simnet daemon is done and separate.

    +++

dev-warrior777 added 2 commits August 27, 2025 01:06
	- app starts locked and user cannot unlock during initial sync
	- refactor keystore and tests
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Aug 29, 2025

Key-store Test failed due to

Missing Secret Service Implementation:

There is no software installed that provides the org.freedesktop.secrets D-Bus service. Common implementations include:

  • GNOME Keyring (gnome-keyring): The standard secret storage solution for GNOME and many other desktop environments.
  • KDE Wallet (KWallet): KDE's credential management system. While it handles secrets, its compatibility with the org.freedesktop.secrets API can sometimes be an issue, especially with older versions or in non-KDE environments.
  • KeePassXC: A popular password manager that offers Secret Service integration, allowing it to act as a provider for this API.
  • secret-service: A standalone implementation of the Secret Service API.

Will comment out the test for CI

@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Aug 29, 2025

* Implement the simplifications and mitigations to ensure that the rare but possible monero splitting a single payment across 2 outputs is handled.

Ok all the above is erroneous thinking. It was based on thinking we had need of the actual outputs (as we do for bitcoin, etc.)

I looked again at monero swap flow we did last year and there are no contracts,etc on monero side .. just txs
which we will trust monero to build for us. We will know the amount sent, tx hash and the fee which is enough.

We may need to parse out key images to freeze unspents .. I will ask @martonp what he needs for Private Swaps
EDIT: no need, new Sender interface with fn. SendAndLock to send a tx with a monero spending lock until block n

	- scripts and support to enable simnet development
	- added minimal back end code
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

README-BETA.md

dev-warrior777 added 2 commits September 5, 2025 23:26
	// Sender sends with more granular control parameters
	type Sender interface {
		// SendAndLock sends the exact value to the specified address with an unlock time.
		// This can be n blocks or n milliseconds depending on interpretation.
		SendAndLock(address string, value uint64, unlock uint64, feeRate uint64) (Coin, error)
	}
@dev-warrior777 dev-warrior777 marked this pull request as ready for review September 6, 2025 13:54
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

This is the end of Phase I.

Some things to do in Phase II:

  • Integrate Private Swaps with @martonp
  • Add TxHistory
  • Generally test the heck out of it all

Copy link
Copy Markdown
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

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

Looks great. Some comments.

Comment on lines +25 to +35
func (ks *keystore) get(net dex.Network) (string, error) {
svc, user, err := makeCreds(net)
if err != nil {
return "", err
}
pw, err := keyring.Get(svc, user)
if err != nil {
return "", err
}
return pw, nil
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How is this better than just saving the password as plaintext? It may be just genuinely don't know.

Copy link
Copy Markdown
Contributor Author

@dev-warrior777 dev-warrior777 Sep 9, 2025

Choose a reason for hiding this comment

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

I am not sure where else to put the password (derived from appPass) I receive in the first (*Driver).Create call .. it is already not plaintext and not available after that in (*Driver).Open or in asset.Wallet.Connect that follows in sequence. (See also: xmr.go)

  • Since this is used as the monero wallet .keys file encryption password I would not want to store in plain text in ram.
  • Some of the structures in xmr.go/xmrpc.go where things could be stored are not yet initialized when the password is first used.
  • As a seeded wallet the password can be recovered.

Create is where a monero wallet database file (dex.keys) is created and synced. There is no dex database access. So I use the keystore supplied by the OS in windows/linux/mac to store a stringified version of asset.CreateWalletParams.Pass which is a 32 byte slice.

This is also not new as a similar technique is used in Ethereum.

Note: Fitting monero requirements into basic dex structure is quite awkward .. I re-wrote startup and sync several times.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can another program use the svc value to get the password?

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.

Nuanced: Here is what the Gnome keyring developer has to say:

https://bugzilla.gnome.org/show_bug.cgi?id=574315#c4

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like yes, any program can get the password if they have the key, which is easy to duplicate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I made the test program in their readme here https://github.com/zalando/go-keyring

Then I commented out the part about setting the password and I was able to get the password. So, any program can get the password if they know the "service" and "user". imo this is not secure at all. Am I missing something? Also, this is not working on arch out of the box, I must be missing something there.

Anyway, I think we should find another answer to the problem if any program can grab the password. It's not much better than saving in plain text to a file. Am I wrong here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No need to change this in this pr, lets look into it in another.

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.

@JoeGruffins Have left you a message about my understanding of the threat you pose.

Leaving open

Comment thread client/asset/xmr/process.go Outdated
Comment thread client/asset/xmr/txn/tx_parse.go Outdated
Comment thread client/asset/xmr/wallet.go
Comment thread client/asset/xmr/txn/tx_parse.go Outdated
Comment thread client/asset/xmr/xmrrpc.go
Comment thread client/asset/xmr/xmrrpc.go
Comment thread server/asset/xmr/backend.go Outdated
Comment thread server/asset/xmr/daemon.go
Comment thread client/asset/xmr/xmrrpc.go
@JoeGruffins
Copy link
Copy Markdown
Member

JoeGruffins commented Sep 10, 2025

Looks good but I'm just a little worried about the password. We need it sooner correct? Like, the wallet isn't useable at all unless we "unlock" it? We may need to figure something out there. Did you say we are doing something similar with eth? Need to look.

@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Sep 10, 2025

Looks good but I'm just a little worried about the password. We need it sooner correct? Like, the wallet isn't useable at all unless we "unlock" it? We may need to figure something out there. Did you say we are doing something similar with eth? Need to look.

  • The wallet needs to be initially created and synced .. that happens in (*Driver).Create using the encrypted password provided.
  • On (*asset.Wallet).Connect the password needs to be used again to open and decrypt the wallet file dex.keys.
  • func CreateEVMWallet(chainID int64, createWalletParams *asset.CreateWalletParams, compat *CompatibilityData, skipConnect bool) error {

    Other changes:
  • Increased WalletServerInitializeWait to 5s and used select to allow context cancel.
  • Removed the "Unlock button does not unlock while syncing" logic .. am gonna go with your instinct.

	- Increased WalletServerInitializeWait to 5s and used select to allow context cancel.
	- Removed the "Unlock button while syncing" logic.
	- Other minor changes
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

Proposed Additional for Phase II based on above comments:

  • Download Monero tools from github so user does not have to.
  • Run sweep_dust RPC every hour or on demand after failed transfer with error suggestion to do so.

Comment thread client/asset/xmr/xmrrpc.go Outdated
@dev-warrior777
Copy link
Copy Markdown
Contributor Author

You are right

  • e1c0ce4 I removed the version check for upper bound so higher patch will now work.

Comment thread client/asset/xmr/version.go
Copy link
Copy Markdown
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

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

This is ongoing review, but wanted to comment on the password thing again.

Comment on lines +39 to +40
var td = make([]string, 0)
td = getUserDamons(td, net, cli, dataDir)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably just create the td wth "getUserDaemons"

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.

Leaving open for transfer to a new PR

Comment on lines +67 to +75
b, err := os.ReadFile(userDaemonFilepath)
if err != nil {
return td
}
var daemons []daemon
err = json.Unmarshal(b, &daemons)
if err != nil {
return td
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you log error if either of these errors? Also in getTrustedDaemons you already made var td = make([]string, 0) so if this errors that's nil again. If something is appended its no longer nil so it's fine really, but its weird to overwrite the td in the first place.

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.

Leaving open for transfer to a new PR

Comment on lines +62 to +65
// getUserDamons returns any user defined daemons in dataDir/daemons.json.
// [cli] indicates that we can also select an HTTPS URL to send to monero-wallet-cli
// for initial sync.
func getUserDamons(td []string, net dex.Network, cli bool, dataDir string) []string {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// getUserDamons returns any user defined daemons in dataDir/daemons.json.
// [cli] indicates that we can also select an HTTPS URL to send to monero-wallet-cli
// for initial sync.
func getUserDamons(td []string, net dex.Network, cli bool, dataDir string) []string {
// getUserDaemons returns any user defined daemons in dataDir/daemons.json.
// [cli] indicates that we can also select an HTTPS URL to send to monero-wallet-cli
// for initial sync.
func getUserDaemons(td []string, net dex.Network, cli bool, dataDir string) []string {

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.

Leaving open for transfer to a new PR

# It is for XMR golang development usage alongside the simnet-walletpair tool.
# The design of the golang code is such that it needs only a monerod instance
# and creates and tears down a monero-wallet-rpc process, maybe several times.
# The main harness is overkill for this and could be could be confusing when
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
# The main harness is overkill for this and could be could be confusing when
# The main harness is overkill for this and could be confusing when

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.

Leaving open for transfer to a new PR

Comment on lines +25 to +35
func (ks *keystore) get(net dex.Network) (string, error) {
svc, user, err := makeCreds(net)
if err != nil {
return "", err
}
pw, err := keyring.Get(svc, user)
if err != nil {
return "", err
}
return pw, nil
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I made the test program in their readme here https://github.com/zalando/go-keyring

Then I commented out the part about setting the password and I was able to get the password. So, any program can get the password if they know the "service" and "user". imo this is not secure at all. Am I missing something? Also, this is not working on arch out of the box, I must be missing something there.

Anyway, I think we should find another answer to the problem if any program can grab the password. It's not much better than saving in plain text to a file. Am I wrong here?

Copy link
Copy Markdown
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

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

I'm unable to run atm because of the keystore gives me an error:
``
2025-10-16 08:56:16.916 [ERR] WEB: error creating xmr wallet: Error creating wallet: failed to store pw The name is not activatable


But that's fine. Everything looks great. Three things that I think we should look at further in ohter prs, no need to do now:

1. I still don't think the version checking is correct as it doesnt allow higher patches. Also looking at the dir name isn't great, I think something there needs to change.

2. The keystore looks to be easily exploitable and doesn't work for me out of the box anyhow.

3. Having the user download the tools separately. We can probably check if they have them installed already. Download for them like you suggested maybe even? Related to number 1

)

func (r *xmrRpc) probeDaemon() error {
r.log.Trace("probeDaemon")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can trace a sentence, like, "Running probeDaemon."

But there is a debug later, so I don't think this log is necessary.

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.

Leaving open for transfer to a new PR

Comment on lines +76 to +77
r.log.Debugf("daemon %s -- height: %d, synchronized: %v, restricted: %v, untrusted: %v", r.daemonAddr,
r.daemonState.height, r.daemonState.synchronized, r.daemonState.restricted, r.daemonState.untrusted)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Its probably better all the logs be sentences, or at least have some more info. This could start with "Probing daemon %s" so we know where it's being called.

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.

Leaving open for transfer to a new PR

}
// started
r.walletRpcProcess = cmd.Process
r.log.Debug("wallet rpc server is started")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'll not dwell on these, but for instance, probably better as a sentence. Anyway should put in that this is xmr otherwise we dont know what wallet rpc server started:

Suggested change
r.log.Debug("wallet rpc server is started")
r.log.Debug("Started xmr wallet rpc server.")

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.

Leaving open for transfer to a new PR

_, err := r.wallet.GetVersion(verCtx)
// just assume error means RPC or net error and the process is not running
if err != nil {
r.log.Debugf("get_version from the wallet server: %v", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
r.log.Debugf("get_version from the wallet server: %v", err)
r.log.Debugf("Error getting xmr version from the wallet server: %v", err)

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.

Leaving open for transfer to a new PR

Comment thread client/asset/xmr/xmrrpc.go Outdated
Comment thread client/asset/xmr/xmrrpc.go
emit *asset.WalletEmitter
peersChange func(uint32, error)
dataDir string
cliToolsDir string
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need this? I think we can just ask the user to have the tools monero-wallet-rpc and monero-wallet-cli in path. My package manager has already installed these for me on arch with its xmr package. Is ubuntu different?

I guess it doesn't hurt to do it like this, but I have to download everything separately. Mine are just in /usr/bin/

For dcrwallet we ask the wallet already be running. Can we not just ask the user to run the wallet and cli tool first before starting bisonw?

Although that is more steps...

Sorry no need to change now I guess.

Copy link
Copy Markdown
Contributor Author

@dev-warrior777 dev-warrior777 Oct 18, 2025

Choose a reason for hiding this comment

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

This is ongoing for sure:

My preference would be to have a button on the monero wallet Create/Settings that:

  • downloads the latest valid monero version of the tools.
  • does not have to search for existing that may be already hard forked; or adjust paths

Monero's GUI wallet presents an update when it becomes available. I have not had the GUI wallet long enough to see what happens when there is a hard fork or other reason to discard outdated version.

There is also infrastructure in the daemon related to this and the possibility of downloading an update hash.

But let's try and find the best way that is a good UX but safe

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.

Leaving open for transfer to a new PR

@dev-warrior777
Copy link
Copy Markdown
Contributor Author

dev-warrior777 commented Oct 18, 2025

  1. The keystore looks to be easily exploitable and doesn't work for me out of the box anyhow.

Additional notes (Grok)

Overview of go-keyring Usage for Cross-Platform Private Data Storage

The github.com/zalando/go-keyring library (v0.2.6) is a solid choice for securely storing private data like passwords or API keys across Windows, macOS, and Linux. It abstracts the native credential storage systems on each platform:

  • Windows: Uses the Credential Manager (via Windows APIs).
  • macOS: Interfaces with the Keychain using the /usr/bin/security command-line tool (available by default).
  • Linux: Relies on the DBus Secret Service API, typically provided by GNOME Keyring.

This works out-of-the-box on all three platforms for basic use cases, with no additional setup on Windows or macOS. Focus on Linux below, as requested.

1. Only Works for the Logged-On User

The library is strictly per-user (i.e., scoped to the currently logged-in user). It does not support system-wide storage:

  • Why? Each platform's backend is user-specific:
    • Windows Credential Manager stores per-user credentials.
    • macOS Keychain is tied to the user's session.
    • Linux GNOME Keyring uses the user's ~/.local/share/keyrings/ directory and DBus session bus.
  • Implications: Secrets stored by one user are inaccessible to others (even root, without explicit unlocking). If you need system-wide storage, consider alternatives like a shared encrypted file (e.g., via age or gocryptfs) or a dedicated secret manager like HashiCorp Vault. For your use case (private data), per-user is usually secure and sufficient.

No configuration changes this behavior—it's inherent to the library's design.

2. Linux Distros Without GNOME such as Arch

non-GNOME distros (or minimal setups without GNOME Keyring) require installing and enabling the GNOME Keyring service, as the library exclusively uses its DBus Secret Service interface. There's no built-in support for alternatives like KDE Wallet (KWallet). Here's a breakdown:

  • Core Dependency: GNOME Keyring must be installed and running via DBus. The library connects to org.freedesktop.secrets on the session bus and expects a default "login" collection (a password-protected keyring unlocked at login).
  • What "Importing the Service" Means: This likely refers to installing the gnome-keyring package and ensuring its daemon (gnome-keyring-daemon) starts automatically. It "imports" the Secret Service API via DBus, allowing the library to interact with it. Without this, you'll get errors like ErrUnsupportedPlatform or DBus connection failures.
Setup for Linux (Prioritizing Common Distros)

Use your package manager to install. The library assumes the "login" collection exists (standard in most distros); if not, create it manually.

Distro/Base Installation Commands Auto-Start Notes Testing the Setup
Ubuntu/Debian (GNOME default) sudo apt update && sudo apt install gnome-keyring
(Often pre-installed.)
Starts via PAM (login hooks). Check: ps aux | grep gnome-keyring-daemon. Run seahorse (GUI) to verify "Login" keyring. Or test your Go app.
Fedora/RHEL/CentOS (GNOME default) sudo dnf install gnome-keyring
Or sudo yum install gnome-keyring.
Auto-starts on login. Enable if needed: systemctl --user enable gnome-keyring-daemon. Use seahorse or secret-tool store --label="test" service my-app username test pass test (CLI test).
Arch/Manjaro (Any DE, e.g., KDE) sudo pacman -S gnome-keyring
Install dbus if missing: sudo pacman -S dbus.
For non-GNOME (e.g., KDE): Add to ~/.xinitrc or ~/.profile: eval $(/usr/bin/gnome-keyring-daemon --start --components=pkcs11,secrets,ssh).
Or use PAM: Edit /etc/pam.d/login to include auth optional pam_gnome_keyring.so and session optional pam_gnome_keyring.so auto_start.
Run dbus-run-session -- gnome-keyring-daemon --components=secrets for manual test. Verify with your Go binary.
Minimal/Headless (e.g., Server, WSL2, Docker) Install as above + dbus.
Example (Ubuntu server): sudo apt install gnome-keyring dbus-x11.
No GUI login, so manual unlock needed. Add to shell profile (e.g., ~/.bashrc):
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then eval dbus-launch --exit-with-session; fi
gnome-keyring-daemon --start --components=secrets
For unlock: dbus-run-session -- gnome-keyring-daemon --unlock (prompts for password).
CLI: secret-tool store service my-app username test pass test.
In Docker/WSL: Ensure X11 forwarding or headless DBus; test with go test using keyring.MockInit() for mocking if issues persist.
  • Creating the "login" Collection if Missing:

    • GUI: Install seahorse (sudo apt install seahorse on Debian-based), open it, File > New > Password Keyring, name it "login", set a password.
    • CLI Alternative: Use secret-tool (from libsecret-tools package): secret-tool monitor to check DBus, or script creation via DBus calls (advanced; see library's secret_service package for inspiration).
  • Common Pitfalls on Non-GNOME:

    • KDE or Other DEs: GNOME Keyring can coexist but may conflict with KWallet. Disable KWallet if needed (kde-wallet package). Users report success on KDE by forcing GNOME Keyring in session startup.
    • Headless/WSL: DBus session bus must be active. Issues like Add the UnknownOrderType OrderType as 0x0. #48 on GitHub highlight needing dbus-run-session wrappers for unlocking without GUI.
    • Errors: If DBus fails, check logs (journalctl -u user@<uid>.service -u dbus or dmesg | grep dbus). Performance note: Avoid >100KiB secrets on Linux.
Compatibility Across Distros
  • Works on 99% of distros with GNOME Keyring (e.g., Ubuntu, Fedora).
  • For pure non-GNOME (e.g., minimal Debian without DE), install as above—it's lightweight (~5-10MB).
  • Tested on major distros; no distro-specific patches needed.

NOTE: Some edits for clarity only

@dev-warrior777
Copy link
Copy Markdown
Contributor Author

  1. I still don't think the version checking is correct as it doesnt allow higher patches. Also looking at the dir name isn't great, I think something there needs to change.

That was updated in commit e1c0ce4

	go-monero is a wrapper library on monero RPC's

	- previous repo: github.com/dev-warrior777/go-monero
	- current  repo: github.com/bisoncraft/go-monero

	Also: answered most of JoeGruffins review decred#2. any
	outstanding issues will be addressed in a new PR.
@JoeGruffins JoeGruffins merged commit d34d12f into decred:master Oct 20, 2025
5 checks passed
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.

3 participants