Maya Sharafian

Coil's extension is with you wherever you go on the web. The extension looks for sites where Web Monetization is enabled, and tells Coil to send micropayments. The whole process happens without requiring any user interaction.

Extensions like Coil's are powerful, and with great power comes great responsibility. At Coil, we take this responsibility very seriously. We want to make sure that use of our extension doesn't expose any sensitive data, not even to us.

In our most recent effort on the privacy front, we've deployed a new feature called “sender-side privacy” which uses the cryptographic protocol from Privacy Pass to further protect your browsing history. The feature is included in version 0.0.49 of the Coil extension.

But before we get into that I want to give you a crash course on Coil's existing privacy features, before this update.

Header image by Mikel Ibarluzea on Unsplash

Wallet-side privacy

When we started building Web Monetization, we were hit with a problem: How do we pay all the sites that a user is visiting without Coil learning the user's browsing history?

It might seem impossible; how do you pay someone without knowing who they are?

To solve this problem, we use a scheme called “wallet-side privacy.” Wallet-side privacy is implemented by Interledger-capable wallets to shield browsing history from Coil.

Wallet-side privacy works by only exposing essential routing information to Coil. Sensitive information like the identity of the receiver is encrypted so it's known only to the wallet. This prevents Coil from learning which sites you visited based on who you're sending micropayments to.

It's easier to understand with an example. Let's say that I'm visiting catpictures.example (a made-up web monetized site), which uses the wallet provider ExampleWallet.

Without wallet-side privacy, I might send micropayments to an Interledger address that looks like g.examplewallet.catpictures. That isn't very good—Coil can guess just from that address that I'm visiting catpictures.example.

With wallet-side privacy enabled, my Coil extension asks ExampleWallet to provide a new Interledger address each time I visit catpictures.example. ExampleWallet will return an encrypted address, which looks like g.examplewallet.8d6f329bbd0d14e5.

Coil can see that the address is for ExampleWallet, but Coil can't see who it's for on ExampleWallet. There could be hundreds or thousands of sites using ExampleWallet, and so it's not very useful for learning my browsing history.

ExampleWallet, on the other hand, can decrypt that address and make sure the money goes to catpictures.example.

ExampleWallet doesn't know my identity, they only see that there are micropayments coming in from Coil. So ExampleWallet can't determine my browsing history either.

Where does wallet-side privacy fall short?

The problem with wallet-side privacy is in its name: It's up to the wallet to protect users' browsing history.

When we only have a few wallets, it's fine. Coil has spoken to every wallet provider and ensured they're implementing wallet-side privacy correctly. But what about when we have more wallets?

If one of the wallet providers made a mistake and didn't encrypt their Interledger addresses, it would leak browsing history to Coil. Or if there were many smaller wallet providers with fewer users, Coil could guess at what site you're browsing.

In any of these failure cases the user's identity will not leak to the wallet. But these are still risks we don't want to take when it comes to sensitive data like browsing history.

Sender-side privacy

To address these risks, we don't just hide the site's URL from our servers. We also hide the user's identity. We'll call this “sender-side privacy.”

Sender-side privacy vs. wallet-side privacy

The difference may not be obvious, so let's go over an example. Below is the information Coil learns under sender-side privacy and wallet-side privacy when our example user “Alice” visits “catpictures.example

• If no privacy scheme is used, Coil learns Alice is visiting catpictures.example

• If wallet-side privacy is used alone, Coil learns Alice is visiting a site which uses ExampleWallet as its wallet.

• If sender-side privacy is used alone, Coil learns an unknown user is visiting catpictures.example.

With the two used together, Coil learns that an unknown user is visiting some site which uses ExampleWallet as its wallet.

Now that sender-side privacy and wallet-side privacy are both available, they're combined to provide multiple layers of privacy. Even in the case of a failure in wallet-side privacy (as described in the previous section) sender-side privacy prevents your browsing history from leaking.

How does sender-side privacy work?

“Hiding the user's identity from Coil” sounds like another impossible problem: Coil must know who you are in order to let you use the service. If we don't know who you are, how do we know if you're a paying member? How can you use Web Monetization at all?

It turns out we don't need to know who you are; we only need to know whether you're a member authorized to use Web Monetization.

Fortunately for us, some very smart people have come up with schemes that let you learn whether a user is authorized without revealing the user's identity. In implementing sender-side privacy, we looked to Privacy Pass for reference.

Privacy Pass protocol

Privacy Pass is a cryptographic scheme and browser extension which comes out of Cloudflare. They use this scheme to let people quickly bypass Cloudflare's captchas without Cloudflare learning their browsing history.

Privacy Pass has two stages: issue and redeem.

In the “issue” stage, you solve a captcha for Cloudflare. This proves to them that you're a real human. Cloudflare issues you several digital signatures that say, “I'm a real human.”

In the “redeem” stage, you visit a site which is protected by a Cloudflare captcha. Instead of making you solve the captcha, the Privacy Pass extension redeems one of these “I'm a real human” signatures. Cloudflare verifies the signature and lets you bypass the captcha.

You might notice the problem here. Doesn't Cloudflare remember the signatures they issued to you? If you redeem those signatures on 30 different sites won't Cloudflare know which sites you visited?

This problem is called “linkability.” Because the signatures given to you by Cloudflare are the same between the issue and redeem steps, they can be used like tracking IDs to learn your browsing habits.

Privacy Pass addresses linkability by using blind signatures. With a blind signature scheme, you use a “blinding factor” to turn the signature that you've been issued into an unrecognizable (but still valid) signature before redeeming it.

This “blinding” makes the signature unusable as a tracking ID, solving the linkability problem. With linkability solved, the Privacy Pass protocol is both secure and private.

Sender-side privacy in Coil

The cryptographic scheme used for Coil's sender-side privacy is the same as the one used by Privacy Pass.

When the extension is started, Coil issues it several signatures that say, “I'm a Coil subscriber.”

When the extension loads a site, it redeems the blinded “I'm a Coil subscriber” signatures. Coil verifies the signatures and starts sending Web Monetization micropayments to the site.

Coil doesn't learn which user triggered the Web Monetization micropayments, because you're using blind signatures. These blind signatures are used for a minute or less, so Coil can't build up a short-term profile of you. It's like you're constantly changing disguises.

What's next?

Sender-side privacy combines with wallet-side privacy to create a strong privacy model, but we're still working on additional ways that Coil users can increase their privacy.

Even with sender-side privacy, we want to fight side-channels like timing attacks or browser fingerprinting that could threaten to link a user's browsing habits back to them.

In order to neutralize these threats, Coil collects as little information as possible and strips IP address information and fingerprintable headers like user-agent at the CDN level via a Cloudflare worker. We're working on schemes to improve this protection further.

The Coil extension is already compatible with privacy-focused browsers like Puma, Firefox, and Brave. Next, we're working on making it compatible with the Tor browser for users who want to take extra steps to protect their privacy while they browse. You can read more about that project here.

Further reading

In this article I've tried to explain our privacy model to people who aren't cryptographers, but some readers will want to dive deeper into the technical details.

The best resource for learning more about the Privacy Pass scheme (also used by Coil) is through this document written by the Privacy Pass team. If you want to understand the math behind blind signatures, the Wikipedia article does a pretty good job at explaining it. (The Wikipedia article mainly discusses RSA blind signatures which are conceptually similar but subtly different from the elliptic-curve blind signatures used by Privacy Pass or Coil).

The Coil extension is open source. If you want to see Coil's code for the sender-side privacy scheme based on Privacy Pass, it's kept here. The cryptography is taken from Cloudflare's own implementation.

A common question that we get about Web Monetization is “how do I share a portion of my revenue?” It’s an important question: more often than not, the creation of high quality content involves more than one person.

Web Monetization is a pretty flexible system, so there’s several ways you can do revenue sharing:

One way to do revenue sharing is at the Interledger layer. You can run some software that hooks into the same Interledger network as your wallet, and it splits the streams of incoming money into multiple outgoing streams. Even for an advanced user, this can be hard to set up.

Another way to do revenue sharing would be to add support for multiple monetization tags on one page. But sending to a lot of payment pointers at once would cause performance issues, and the Web Monetization standard would also get more complicated. We need a solution that is performant and simple.

A particularly interesting alternative, and the topic of this article, is probabilistic revenue sharing. The name sounds a little intimidating but it’s actually pretty easy to understand and use.

Edit: We've now created a probabilistic revenue sharing tool on that you can try out right away!

Header photo by Brett Jordan on Unsplash

What is probabilistic revenue sharing?

Probability-based payments have been proposed many times for many purposes. For instance, this 1997 paper by Ron Rivest uses the concept of expected value to implement a micropayment scheme. The probabilistic revenue sharing we discuss in this article is inspired by these ideas, and applies them to the problem of revenue sharing in Web Monetization.

In Web Monetization, probabilistic revenue sharing works by having a random choice every time a Web Monetized visitor loads your page.

You have several possible payment pointers, each with a different chance of getting chosen. The visitor pays to the chosen pointer until the page is reloaded or closed.

If Alice’s payment pointer has a 50% chance of getting chosen, then ~50% of the Web Monetized visitors will be paying to Alice. Because our random choice is not correlated to other variables like the length of time the visitor spends on the page, the amount of money per-second you make off the visitor, and so on, the laws of probability say that Alice’s share will approach 50% of the page’s total revenue as more users visit the site.

This gives us a straightforward rule: The chance of choosing somebody’s payment pointer is equal to their expected share of the revenue.

How can you use it today?

We’re working on tools to make it really easy for anybody to make a probabilistic revshare. But until then, you can use some JavaScript to do it yourself!

This snippet of code chooses a payment pointer randomly every time somebody loads your page. You can replace the pointers at the top with your own, and modify the weights to whatever you want. Then put it in a script tag in your site’s head.

Here’s a live demo using Glitch that shows how the random choices will approach the correct percentages over enough tries. You can customize the number of times to randomly choose a pointer and it will show you the results:

Advanced Topics and Future Ideas

Imagine that I have a blog post and I’m embedding an image into it. The creator of the image has said “If you want to include my image, just give me a percent of your article’s earnings.” So that’s fine, you add the image’s creator to your revshare.

But what if the photographer were also sharing their revenue? Then you would have to include everyone in the photographer’s revshare into your revshare, but with a scaled-down percentage. And you’d have to keep updating your revshare if the photographer’s changes. That’s a huge pain!

To make this much smoother, we can put the probabilistic revshare into your payment pointer itself instead of your page’s JavaScript.

The idea is really similar to the vanity payment pointers in this article by A vanity payment pointer is a redirect to your actual payment pointer. If we want to make this do a probabilistic revshare, we need to make that redirect random instead of redirecting to the same pointer each time.

You can pick several payment pointers and a chance for each of them to be chosen, just like the example from earlier. The chance that you redirect to each pointer is equal to that pointer’s expected share of the revenue.

Here’s an example of how you can implement this in an Express.js server. It uses the same code as our previous snippet to implement the pickPointer function. We plan on offering a hosted tool that lets you manage revenue sharing payment pointers without writing code in the near future!

The cool thing about this scheme is that your payment pointer contains all the revenue sharing logic and you don’t need to repeat that information on every page.

This also means that it works recursively. One of the pointers that my vanity pointer randomly chooses could go on to make a random choice of its own. 1% of the time my blog could choose the photographer’s pointer and then 10% of the time the photographer’s pointer chooses the photo editor’s pointer.

This lets you make some revenue sharing schemes that would be wildly impractical with existing revenue sharing schemes. By taking the pain out of revenue sharing, we can help everyone get compensated fairly!

There’s been a call for year-end blog posts in the Interledger community. Following a tradition that other successful projects have adopted, members of the Interledger community have written up their thoughts on Interledger’s progress and roadmap.

I spend a lot of time working on Interledger, and I spend a lot of time using Interledger. I hope this blog post gives some valuable perspective on the Interledger project from somebody who is both an Interledger contributor and one of the earliest Interledger users.

Header photo by Video LUT App on Unsplash

We’ve come a long way

Before listing areas that could use improvement, I want to highlight some of the big triumphs.

*We have a live network:* This is a big one. For a long time there was nobody using Interledger in practice. Not only were we lacking real-world feedback, there was also nothing to stop us from rewriting the specs every few months. Now there are people who have a financial interest in making sure the network doesn’t go down.

We have multiple companies involved: There was a time when Interledger was just a Ripple project. This wasn’t the best look for Interledger, because an open protocol should involve people of many different interests and backgrounds. In addition to Ripple’s Xpring, we now have Coil, Puma, Cinnamon, XRPTipBot, Gatehub, and more.

We have (some) scale: The peak Interledger throughput that Coil experienced this year was 3k packets per second. That’s higher than the average transactions per second of Visa! The amounts were many orders of magnitude smaller, but our experience has answered a lot of questions about how best to scale Interledger. Now that we can effectively horizontally scale connectors, the sky’s the limit! Efficiency and interoperability are the foundation that a better financial system can be built on.

We have stable implementations: Interledger.js has been crucial for Coil. It lets us keep moving fast, and without JavaScript we wouldn’t be able to make Web Monetization work (did you know that the Coil extension runs the entire Interledger stack in your browser?). Now that we have a Rust implementation as well, we can start to push the limits on Interledger’s performance.

What's next?

Interledger has such a broad application that it can be tough to direct our focus. The problem space of Interledger is “anything where money has to move.”

In the next year, however, I have some specific goals that I’d like to see us achieve as a community.

We need a way for individuals to get direct Interledger access

Right now, all Interledger access for individuals is through graphical interfaces. Wallets like Gatehub and XRPTipBot use Interledger under the hood, but it’s exposed through the web UI rather than low-level APIs.

This can offer a really easy experience, but it’s not complete. Developers need a way to interface with the low-level Interledger functionality.

Companies can get raw Interledger access (ILP over HTTP) by peering with an existing network participant manually, but it requires them to run a lot of Interledger infrastructure.

Some people on the network are also running community connectors that peer over low-trust crypto, but the settlement integrations are a little rusty and it’s unclear whether existing financial services regulations would apply to such connectors.

I believe the best path forward is to offer raw Interledger access through wallets, where the accounting can be done off of the user’s balance and where the wallet has strong KYC information about users.

By the end of 2020, we should have a way for individual users to get direct BTP or HTTP access to Interledger for general sending/receiving. This should be offered as a service on Interledger wallets, and should be scalable enough to build a production application on. You should be able to hook the uplink directly into your app or run a tier 2 connector to forward Interledger traffic to multiple sending/receiving apps.

We need wallet APIs to work with Web Monetization

I see direct Interledger access as an important feature for the most advanced users of Interledger. But for the people who want a straightforward integration path, we also need a comprehensive set of high-level APIs.

I’m excited about Open Payments, which groups a lot of these general use cases together. In particular, the “sessions” API will make it easy to securely detect Web Monetization on your site. This will allow a massive amount of creativity with Web Monetization without requiring everyone to learn the full Interledger stack.

By the end of 2020, we should make the Open Payments sessions API ubiquitous across wallets. The other Open Payments APIs will also be important as Interledger is applied to retail-sized payments in addition to Web Monetization.

We need enough users to matter

Another important aspect of Interledger is the demand side. We need more users who are capable of sending payments with Interledger, so that Interledger applications can be profitable.

Coil’s subscription works towards this goal this by paying Web Monetized creators. The more users that Coil has, the more income potential your Web Monetized project has. The more money there is flowing through the Interledger network, the higher the chance that larger players will integrate Interledger.

You can expect more developments from Coil in 2020 that will help bring a higher volume of users to the Web Monetization ecosystem.

In Conclusion

Solving monetization on the web will be a huge undertaking for Coil, but the full vision of Interledger is far greater than that.

Interledger promises to fundamentally improve the way that money moves, and our relationship to the financial system. When the fixed cost of a payment approaches zero, the volume of payments can explode. We’re closer to this than ever, but there’s still a long way to go. We can’t lose sight of the big-picture goal as we work our way there.

It’s been a while since the days when we debated number formats and address separators. I’m excited for us to keep working on the challenges that real-world adoption bring up. As a community, I know we can solve them!

I welcome any feedback on this post, my twitter is @sharafian_ and I’ll also be posting this to the Interledger Forum thread.

Web games are among the best ways to waste time on the internet. They let you transmit a cool experience to someone without any download required.

Some games are action-packed, some are meditative, and they're almost all addictive. Pictured above is my game, Goblin Farmer, which is none of these. But it's OK, because anybody reading this will have the tools to make something better.

Note: all the techniques outlined here act on the client side. That means a clever user could mess with their browser to pretend they're monetized. It's usually fine for games, just keep in mind that it's possible.

Why Web?

Over the years, web games have given way somewhat to mobile games. Mobile phones are ubiquitous these days, and games are a great way to kill a few minutes when you're on the go. But there's more to it then just that.

Mobile apps also have a built-in way to monetize. You can unlock premium in-game items in just a couple of taps, which has led the mobile gaming space to be massively successful financially.

The web hasn't really had a way to monetize aside from advertising, but Web Monetization changes that equation. By accepting micropayments from Web Monetized users, the web gaming market could catch up to mobile gaming.

How Can I Get Started?

OK, I've talked a lot of talk so now I'll show you how you can make a Web Monetized game.

The first step is to embed your payment pointer in the top of your file. This is all you need to start making money off of your game.

Just including a meta tag doesn't give anything special to the players who are supporting you, which isn't very nice. So let's throw in some extra features for them.

Adding Bonus Features

In my game, Goblin Farmer, you get your in-game money from Web Monetization micropayments.

You spend your in-game money to purchase units. These units make you more in-game money which lets you get more units. So it's not entirely dependent on your Web Monetization micropayments but they can give you a starting boost.

If you want to add a mechanic like this to your game, you can bind the monetizationprogress event. Here's how I do it in Goblin Farmer:

Every time a Web Monetization micropayment occurs, the page gets a monetizationprogress event. You can get the amount of the micropayment out of the event (it's denominated in receiver's units, typically nano-USD). In my game I just add that straight onto the user's “cash” resources that they use to buy units.

Checking if Web Monetization is Active

But what if you don't care how much the player is paying? Maybe you just want a rule to activate when the player is monetized, like an on/off switch. Maybe the player unlocks a new power when web monetization is active.

To determine whether Web Monetization is on or off you can look at is document.monetization.state. This event fires on the very first Web Monetization micropayment. So if you want to apply some rules depending on whether or not the user is web monetized you could do this:

Locking the Whole Game

You can use the following technique to restrict your whole game to Web Monetized users, but be aware it will turn away a lot of your players and some might not be happy.

In my game I use React Web Monetization to show/hide the entire game screen based on whether the user is Web Monetized, because only Web Monetized users can play. You can use this pattern if you want your game to only be usable by Web Monetized users. The code looks like this:

In Conclusion

If you want to write a web game and make some money off of it, I encourage you to try out Web Monetization. By using the straightforward javascript API, you can add a lot of creative features for your users.

If you're interesting in making a Web Monetized game then I recommend you check out the competition! Participants will get a free Coil subscription (see the details on the linked site).

Message me on twitter @sharafian_ if you have any feedback, questions, or if you have a Web Monetized game you want to show off!

My Source Code

If you want to read the source code to Goblin Farmer you can read the source code here. (source code as of Aug. 19). I basically hacked it all together so the code is an absolute mess, but hopefully you can use it to get a slightly more complete picture of how the game works.

Moneyd is a daemon that connects to the Interledger network. You can think of Moneyd as your “home router” for the internet of value. If you’re new to Interledger, this is a good place to start.

Moneyd uses “uplinks” to connect to Interledger. So far, we’ve published moneyd-uplink-xrp, which uses payment channels on XRP to connect to peer with an Interledger connector. We’re working on modules for Ethereum and Lightning too, but they’re not yet ready to publish. Stay tuned for progress on them.

In this tutorial, I’ll describe how you can join the ILP testnet without having any previous experience with Interledger.

(header image by Nicholas Thomas)

Install Moneyd

Before you start, you’ll need to set up Node.js on your machine.

- Install Node.js (version 8.9.4 or higher)

- Set up node to install modules globally

Once you've done that, you can install and configure moneyd from the command-line.

npm install -g moneyd moneyd-uplink-xrp

moneyd xrp:configure --testnet

moneyd xrp:start --testnet

Congratulations! You're connected to the Interledger testnet!


I'll break down what just happened. When you run moneyd xrp:configure --testnet, Moneyd will:

- Query the XRP testnet for a new secret and address, which comes with 10,000 test XRP

- Pick a connector from the list of “bootstrap nodes” for the Interledger testnet. As of right now, the only public connector on the testnet is run by Strata.

- Write a configuration file with these details to ~/.moneyd.test.json

When you run moneyd xrp:start --testnet:

- Moneyd loads ~/.moneyd.test.json and instantiates an ILP Connector.

- The connector opens a websocket connection to its peer, Strata, and creates an XRP payment channel. The connector listens on a local port to process ILP packets.

Since Coil’s launch, hundreds of sites have become web-monetized. It’s just a matter of adding a couple of scripts, and you can make money (through Interledger) for every Coil subscriber who visits your site.

(header photo by Khai Sze Ong on Unsplash)

Based on feedback from these sites, the Interledger community has reworked the Web Monetization standard, making it even simpler to use. The improvements and trade-offs are listed below. Credit to Michiel de Jong for originally suggesting this idea.

The old way to monetize your site was by including this code snippet:

<script src=""></script>

<script src=""></script>



paymentPointer: '$'



The new way to monetize your site is by adding a single tag to your page’s :

<meta name="monetization" content="$" >

This feature is available in the Coil extension version 0.0.21 and higher. An upgrade to the open-source Minute extension is in-progress.

What has Improved?


Loading external scripts into your site is a big risk. The previous version of Web Monetization required external scripts in order to work. For sites that dealt with sensitive data, it could be a deal-breaker.

Web Monetization is now a static HTML tag. That means it can’t be used to compromise any sites.


Loading the Web Monetization polyfill took time and bandwidth. It also needed to be parsed every time you loaded a Web Monetized page.

Now, Web Monetization loads no files into the page. All the logic is handled by your browser extension in the background.


The “donate” script that most sites use to wrap Web Monetization is 450 lines of code. If you tried to use the Web Monetization API directly, it was very easy to make mistakes.

The new Web Monetization standard lets the user’s extension handle the complex logic instead of the page.

Events are still emitted when monetization occurs, so you can still easily add counters and thank-you messages to your sites.

What was sacrificed?

Client-Side Flexibility

Web Monetization no longer exposes the entire STREAM library. That means you can’t do things like turn the stream on/off, pay to multiple destinations, or other advanced features. What we noticed, though, was that all of these features can be implemented server-side.

For example, a revenue-splitting SPSP server is already implemented for anybody to run. Premium content on the server side is also implemented. As Web Monetization gets more adoption, we expect hosted versions of these services to become available.

A Browser Extension is Now Required

The polyfill-based version of Web Monetization used iframe communication to work on some browsers without any extension. Many browsers, such as Safari, didn’t support this flow.

Few people used Web Monetization without an extension, so we decided that it’s easier to always require an extension. This makes things simpler for the user as well as developers.

EDIT: on, we have a script that enables Web Monetization for Coil users with no extension. You can still use with a non-Coil web monetization extension!


- You can see the discussion for this spec change here.

- You can read the current draft of the Web Monetization standard here.

Bonus: Some Great Web-Monetized sites