DEV Community

Carl Barrdahl
Carl Barrdahl

Posted on

Journey into Web Monetization - day 3

After the first day of idea generation and the second day of learning, I thought I'd get into the more practial side of it and try to get something up to play around with.

Here's what I did:

  • Connect to a Interledger testnet with moneyd
  • Create an ILP stream server to connect to the moneyd instance.
  • Generate stream credentials and send money

Run npx moneyd local to start the moneyd instance with a local testnet.

Next, set up a simple node project:

npm init -y
npm i -S ilp-protocol-stream ilp-plugin @interledger/connection-tag-utils
mkdir src
touch src/index.js
// src/index.js
const { randomBytes } = require("crypto");
const { createServer, createConnection } = require("ilp-protocol-stream");
const { encode, decode } = require("@interledger/connection-tag-utils");
const createPlugin = require("ilp-plugin");

// Used for encoding and decoding connectionTag
const SECRET_KEY = randomBytes(32);

async function createStreamServer() {
  const server = await createServer({ plugin: createPlugin() });
  server.on("connection", (connection) => {
    // connectionTag contains encrypted data, in this case about the user account
    const { account } = JSON.parse(
      decode(SECRET_KEY, connection.connectionTag)
    );
    connection.on("stream", (stream) => {
      stream.setReceiveMax(10000);
      stream.on("money", (amount) => {
        console.log(`Received payment from ${account} for: ${amount}`);
      });
    });
  });

  return server;
}

async function sendMoney({ amount, destinationAccount, sharedSecret }) {
  const connection = await createConnection({
    plugin: createPlugin(),
    destinationAccount,
    sharedSecret,
  });

  const stream = connection.createStream();
  await stream.sendTotal(amount);
  await connection.end();
}

async function run() {
  const server = await createStreamServer();

  // Encode the user account here so we can use when we receive money
  const data = encode(SECRET_KEY, JSON.stringify({ account: "userAccountId" }));

  const { destinationAccount, sharedSecret } = server.generateAddressAndSecret(
    data
  );

  const amount = 10000;
  await sendMoney({ amount, destinationAccount, sharedSecret });
  await server.close();
}

run().catch((err) => console.log(err));

And finally run it:

npx nodemon src/index.js

Received payment from userAccountId for: 10000
  • Plugins such as ilp-plugin determines where the server connects. It looks for env variable ILP_BTP_SERVER and defaults to btp+ws://localhost:7768 if not found. This is the local moneyd instance.
  • Data such as information about user or invoice can be encoded in the connectionTag. This will allow us to update databases for example.
  • To create a stream client and send money we need: destinationAccount and sharedSecret which we can get from a server.

Possible next steps

  • Connect to a non-local testnet
  • Send money between other wallets
  • Build a REST server and handle different users and payment pointers
  • Build a browser extension to handle the functionality currently in sendMoney

Discussion (0)