Opening Bitcoin URIs on Mac OS X

Put Payments Here

Wouldn't it be nice if making a Bitcoin payment were as easy as clicking on a link? In principle, this is already supported with Bitcoin URIs. Clicking a Bitcoin URI should launch a preferred wallet, pre-populating a payment transaction with data pulled from the link. Clicking one button would approve the transaction. Copying addresses or payment amounts would be unnecessary.

In practice, support for Bitcoin URIs by software wallets has been patchy at best, particularly on OS X. This article describes a solution that can be immediately implemented by any Mac owner using any downloadable wallet.

Terminal

Although Macs are renowned for their usability, the need to define URI handlers slipped under Cupertino‘s radar. The solution described here requires some mucking around in your Mac’s software internals. If that idea makes you uncomfortable, you may want to get the advice of someone you trust with Mac technical questions.

We're going to use a utility called Terminal. Terminal is an application for communicating with a Mac, not through the usual graphics and gestures, but through text commands.

Access the terminal by pressing ⌘‑space. This pulls up a system-wide search box. Typing the word “terminal” should reveal an option for the Terminal application.

Search for Terminal

Clicking this option launches the terminal. Your terminal will look somewhat different from mine. The main point to notice is that there is a prompt consisting of a “$” symbol and a cursor. Commands are entered after the prompt.

Terminal Application

To get a feel for how the terminal works, display your home directory contents by issuing the ls command (“ls” followed by the return key).

$ ls

Step 1. Find the Wallet's Resource Identifier

Some Mac applications such as Web browsers can launch other applications. Each application defines a unique resource identifier for this purpose. Your first goal is to find the resource identifier that will be used by browsers and applications to launch your wallet when Bitcoin URIs are clicked.

The simplest way to obtain this identifier is to ask OS X for it. For example, if Bitcoin Core is installed on your Mac, its resource identifier can be found with a short bit of AppleScript:

$ osascript -e ‘id of app “Bitcoin-Qt”’

This command should return org.bitcoinfoundation.Bitcoin-Qt. In other words, this string is the resource identifier for Bitcoin Core, still called “Bitcoin-Qt” for historical reasons.

Resource identifiers for other popular OS X wallets are:

  • Electrum: org.pythonmac.unspecified.Electrum
  • Armory: com.armory.armory

Step 2: Update Launch Services

Given a resource identifier, it's now possible to tell OS X to open your wallet in response to clicking Bitcoin URIs.

OS X makes a system called Launch Services available to applications that launch other applications. We're going to use a utility called PlistBuddy to edit the Launch Services preferences. Begin by opening the Launch Services preferences file.

$ /usr/libexec/PlistBuddy ~/Library/Preferences/com.apple.LaunchServices.plist

PlistBuddy is an interactive program that supports editing preferences files and then saving the changes. Other tools can accomplish the same task, but none of them are installed on OS X by default.

First find out if any handlers have been previously installed by using the print command:

Command: print LSHandlers

This should display a listing of all LSHandlers. For example, here are two of the handlers installed on my system:

Array {
Dict {
LSHandlerURLScheme = http
LSHandlerRoleAll = com.google.chrome
}
Dict {
LSHandlerURLScheme = https
LSHandlerRoleAll = com.google.chrome
}

}

Each entry is composed of two properties: the scheme (LSHandlerURLScheme); and the role (LSHandlerRoleAll).

Scan the output of the print command to find an entry in which the scheme reads bitcoin. If you find one, hold tight. We'll first handle the case in which no bitcoin role is defined.

We can issue a series of commands to PlistBuddy to create a new handler that will launch Electrum in response to clicking a bitcoin: link. Replace the LSHandlerRoleAll property with the wallet bundle identifier you found in Step 1.

Command: add LSHandlers:0 dict
Command: add LSHandlers:0:LSHandlerRoleAll string
Command: set LSHandlers:0:LSHandlerRoleAll org.pythonmac.unspecified.Electrum
Command: add LSHandlers:0:LSHandlerURLScheme string
Command: set LSHandlers:0:LSHandlerURLScheme bitcoin

If all goes well, you should see a handler for the bitcoin protocol.

Command: print LSHandlers:0
Dict {
LSHandlerURLScheme = bitcoin
LSHandlerRoleAll = org.pythonmac.unspecified.Electrum
}

If so, save and exit your PlistBuddy session. Otherwise, you can simply use the exit command to start again. Your changes will only be recorded if you use the save command.

Command: save
Command: exit

If you should find a pre-existing Bitcoin URI handler when running PlistBuddy for the first time, you'll want to delete it before adding a new handler. Find the zero-based index of the entry. For example, if you find a bitcoin handler as the fifth item in the list, its index is “4”. It can be deleted with the delete command, in which “4” is replaced by the index you found.

Command: delete LSHandlers:4

You can verify that the handler was deleted with the print command. Continue deleting any additional bitcoin handlers, printing the list each time afterwards, until none remain.

Command: print LSHandlers

At this point you can add a new LSHandler using the procedure described above.

Step 3: Restart

Although we've changed the LSHandler settings file, the old settings are still active because of caching. In my experience, the only way to clear the settings cache is to perform a system restart. Simply logging out and back in won't work, nor will listing the preferences file with the defaults command.

Step 4: Click on a Bitcoin URI

After your system restarts, find a Bitcoin URI and click on it. For convenience, here's a Bitcoin URI you can use to donate if you found this article helpful. Clicking the link should open your favorite Bitcoin wallet with pre-populated address and amount fields.

Using the Payment Protocol with Bitcoin Core

The Payment Protocol extends the utility of Bitcoin URIs with useful features including refund addresses, multiple outputs, and payer authentication. Although the Payment Protocol has not been implemented by many wallets yet, Bitcoin Core does support it. Payment Protocol support can be tested through merchants using Coinbase and BitPay.

Bitcoin Core Payment Protocol

A green background indicates that the Payment Protocol is being used rather than a bare Bitcoin URI.

Is This Really Necessary?

Although the procedure described here is straightforward, it feels distinctly hackish. At this point it's reasonable to ask if there might be a better way.

Ideally, wallet developers would build the ability to handle Bitcoin URIs into their OS X applications. To date, few have. One wallet that does support Bitcoin URIs is MultiBit. Unfortunately, disabling MultiBit‘s URI handler through its preferences screen was not possible in my tests. The procedure described here will allow you override MultiBit’s handler should you want another wallet to launch when Bitcoin URIs are clicked.

Both the Electrum and Armory teams have had issues building Bitcoin URI support into their releases. In my tests, neither program handled Bitcoin URIs by default, nor did Bitcoin Core.

Certain Web wallets support adding themselves as URI handlers through browser-specific interfaces. These wallets include Coinbase and Blockchain.info. However, a URI handler set through a browser will only launch Web wallets, not native applications.

Conclusions

Adding a Bitcoin URI handler to OS X offers a convenient way to make online payments without the need to manually copy transaction data. Unfortunately, support for this feature on OS X has been limited so far. The procedure described here fixes the problem, and makes it possible to launch any downloadable wallet in response to clicking a Bitcoin URI.

Mastering Bitcoin book cover

Comments