I wanted to share all the information I accumulated on the topic of "bitcoin:" URL's so that developers and merchants don't have to be intimidated by them (I was, at first). I recently figured all this out in the past two weeks while integrating full support into Armory, which is now available in version 0.75.1
But I may not be doing everything efficiently, and I will need to figure it out on Mac/OSX, too. So I wanted to share what I've learned, and use the discussion to fill in the gaps and make this a one-stop place for handling bitcoin URI strings. Also, if you know the proper
way to do this in Unity and KDE, please let me know!
Creating and parsing "bitcoin:" URI Strings
This is the easiest part, which is fully-documented in BIP 21: URI Scheme
. Here a simple example of how you would include it (using my donation address, of course!)
<a href="bitcoin:1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv?amount=1.0&label=Armory%20Donation%20Address&message=Donation%20to%20Armory">Donate 1.0 BTC to the Armory Project!</a>
...which looks like: Donate 1.0 BTC to the Armory Project!
In order to encode URI-reserved characters such as spaces, various punctuation, etc, you need to the percent encoding scheme
. It consists of taking the message you want to put into the URL, and replacing all spaces with "%20", all exclamation points with %21, etc. It's all on that link.
that the "label" field is to label the address
and that the "message" field is for marking the transaction
. i.e. if you click on a link that has label "Eto's Key" and mess "Donation to receive his Encryption Seminar", then the "Eto's Key" would show up in the address book, and the "Donation to receive..." would show up on the transaction ledger. For addresses that are only ever used once, I don't think it matters, but that's how I interpret the difference between the two.
I think both these fields is where the real value of bitcoin URLs happens. Merchants are best equipped to create these field entries automatically, and can insert things like Order#, purchase information, etc. Maybe even contact information. Then, the user ends up with full purchase history and documentation in their wallet without any effort.UPDATE:
For now it seems like a good idea to only use the "label=" field for any information that should be saved in the wallet. I believe Bitcoin-Qt will not save the "message=" data, which used to be described as "a message to display after the URI is clicked" (or something like that). I'll follow up with the devs about it.
Registering your application with the operating system: Windows
It was intimidating at first, but after some research I found out it's only a couple of registry key modifications. And of course, I use python so anything is easy
("import _winreg"). My python code for doing it is in ArmoryQt.py around line 500
. The following process is executed every time Armory is opened
- Check "HKEY_CLASSES_ROOT\bitcoin\shell\open\command" if it exists and if it's set to anything (should not be modified)
- If not, check "HKEY_CURRENT_USER\Software\Classes\bitcoin\shell\open\command" if it exists and it's set to anything.
- If it is set to another application, pop up message box asking if they want to use this program as the default
- If it's not set or does not exist, or the user confirms they want to make it default, create and set all the following registry keys:
HKEY_CURRENT_USER\Software\Classes\bitcoin Name: "" Setting: "URL:bitcoin Protocol"
HKEY_CURRENT_USER\Software\Classes\bitcoin Name: "URL Protocol" Setting: ""
HKEY_CURRENT_USER\Software\Classes\bitcoin\shell\open\command Name: "" Setting: "C:\Path\To\Program.exe %1"
HKEY_CURRENT_USER\Software\Classes\bitcoin\DefaultIcon Name: "" Setting: "C:\Path\To\Program\appicon.ico"
Where I put Name=="" means set the default param for that key (every entry has a default). Python uses an empty string to reference it
Don't modify the HKEY_CLASSES_ROOT objects -- you can't do so without admin/root, anyway. But I think this really needs to go under the HKEY_CURRENT_USER which is local settings for this user, and they can
be modified by a user-level program on application load. However, you could add an install option that modifies "HKEY_CLASSES_ROOT" to set it as the default for all users (which the user can then change for their own account using the HKEY_CURRENT_USER registry keys).
Update: Diapolo mentioned a way to overwrite registry keys using a .reg file. This could be useful at installation time, though it will overwrite the keys regardless of what's there already. I'm sure there's an easy way to expand this, though.
Registering your application with the operating system: Linux
I got this working in Ubuntu, tested successfully on 9.04 up to 12.04. However, this solution probably only works for Gnome, and for 10.10+ (or maybe 11.04+) there appears to be a bug in Unity desktop that requires a root-fix. I didn't find a user-level solution for the Unity-based versions.Gnome-Based Desktop
Very similar to the Windows registry solution, but using the gconf-editor instead. I didn't know how to modify it directly through python, so I just collected the correct command-line calls and execute them using subprocess.Popen(). Check for an existing [user-level] handler with the command:
gconftool-2 --get /desktop/gnome/url-handlers/bitcoin/command
which in my case returns: "python /usr/share/armory/ArmoryQt.py %s". I simply search for "ArmoryQt.py" in the output and use that to identify whether Armory is currently set as the default.
Then to set it, I use the following calls:
gconftool-2 -t string -s /desktop/gnome/url-handlers/bitcoin/command "python /usr/share/armory/ArmoryQt.py "%s"
gconftool-2 -s /desktop/gnome/url-handlers/bitcoin/needs_terminal false -t bool
gconftool-2 -t bool -s /desktop/gnome/url-handlers/bitcoin/enabled true
You can see where I do this in ArmoryQt.py around line 465
. If another app is set and this is the first time the user has loaded Armory, I skip the question window... the user has enough to worry about with this new program...Unity-Based Desktop (and maybe KDE...?)
This works for Ubuntu 11.04+, and also shows one way to get your app into the user's Applications menu. Note that this solution is a root-level fix: you're not going to be able to do this for on-load unless the user is running your app with root/admin permission. Because the gconftool-2 stuff is borked in 11.04+. For installing your own app into the menu, you need to create a desktop file: My armory.desktop file looks like this:
Comment=Full-featured Bitcoin wallet management application
Exec=python /usr/share/armory/ArmoryQt.py %u
The text that is bolded is left out on Ubuntu 9.04-10.10. It is included for 11.04+ so that it permanently registers the app with Ubuntu during installation. I believe root is needed to change this. Of course, just having the desktop file made isn't enough, it needs to be installed:
xdg-icon-resource install --novendor --context apps --size 64 /usr/share/armory/img/armory_icon_64x64.png armoryicon
xdg-desktop-menu install --novendor /usr/share/applications/armory.desktop
(note that the .desktop file uses "Icon=armoryicon", so the first line registers a relationship between the string "armoryicon" and the actual location of the icon to use).
At least this can be done and put in the Makefile, and you don't have to deal with extra startup operations... but it is kind of rude to other client developers. I'm happy to take recommendations for how this could be improved. And also support for non-Gnome-based desktop managers.
Registering your application with the operating system: Mac/OSX
I got nothing. I haven't even tried yet. Maybe someone can fill me in, in preparation of having to support it in Armory one day (I promise, Armory will support Mac...eventually).