Skip to content
A high performance, lightweight alternative to the NANO Node developer wallet.
Python
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets
pippin
tests
.gitignore
.gitlab-ci.yml
CHANGELOG.md
LICENSE
MANIFEST.in
README.md
benchmark.py
requirements.txt
setup.cfg
setup.py

README.md

Pippin Wallet

PyPI PyPI - Python Version License Pipeline

Pippin is a production-ready, high-performance developer wallet for Nano and BANANO. Pippin's API is a drop-in replacement for the Nano developer wallet that is built in to the Nano node software.

About Pippin

Pippin is written in Python. It achieves high performance across the board using libraries such as asyncio, uvloop, aiohttp, asyncpg/aiosqlite/aiomysql, and rapidjson.

For block signing and work generation, Pippin uses nanopy, which is a high-performance library that utilizes C-bindings for blake2b and ed25519.

Benefits of Pippin

The Nano developer wallet (aka "node wallet") is not recommended for production use. One of the goals of Pippin is to provide a production-ready external key management that can be used by developers who are using Nano.

Pippin is the first drop-in replacement for the Nano developer wallet. It's incredibly easy to transition to Pippin if you are already using the Nano developer wallet.

  • Pippin is independent of the node. You can use Pippin with any public RPC, so you don't have to run your own node
  • Pippin is extremely fast and lightweight
  • Pippin supports encrypted secret keys
  • Pippin natively supports DPoW and BPoW
  • Pippin supports multiple database backends (SQLite, PostgreSQL, and MySQL)

Pippin can be used by exchanges, games, payment processors, tip bots, faucets, casinos, and a lot more.

Pippin Performance

Pippin Benchmarks

The benchmark script that was used is available here

There were 3 independent runs for each wallet, 62 blocks each, same node, and the same work peer. Pippin was consistently twice as fast versus the node wallet.

How Pippin Works

Pippin provides an API that mimics the Nano Wallet RPC Protocol

Every wallet-related RPC gets intercepted by Pippin and handled internally. It builds the blocks and signs them using locally-stored keys, it uses a node to publish the blocks.

Every non-wallet related RPC gets proxied to the publishing node. Which means you can make all of your RPC requests directly to Pippin whether they are wallet-related or not.

API Documentation

Recommended reference is the NANO RPC documentation, Pippin's APIs are mostly identical.

You send an HTTP Post request to pippin with the desired action and parameters, example:

{
    "action": "accounts_create",
    "wallet": "12345",
    "count": 100
}

Supported

  • wallet_create
  • account_create
  • accounts_create
  • account_list
  • receive
  • send - Use the id parameter to prevent duplicate sends!
  • account_representative_set
  • password_change - This will also set a password, if one isn't already set
  • password_enter
  • password_valid
  • wallet_representative_set
  • wallet_add - This is for adding ad-hoc private keys to a wallet
  • wallet_lock
  • wallet_locked
  • wallet_balances
  • wallet_frontiers
  • wallet_pending
  • wallet_destroy
  • wallet_change_seed
  • wallet_contains
  • wallet_representative
  • receive_all - Not in the nano API, it takes a wallet and it will receive every pending block in that wallet (respecting receive_minimum).

Differences: Pippin vs NANO Node Wallet

These are the known differences between Pippin's API and the Nano node wallet API

Different Behavior

APIs that are different between Pippin and the Nano node wallet.

  • account_list accepts a count parameter that defaults to 1000
  • Pippin has an auto_receive_on_send option that will automatically receive pending blocks when you do a send, it will only do this if balance isnt high enough to make the transaction.
  • account_create does not accept an index

Fuzzy Behavior

The Nano documentation isn't perfectly clear on these, but these are how Pippin behaves.

  • wallet_change_seed will result in the wallet no longer being locked, if it is. The wallet has to already be unlocked before you can use this RPC, though.

Missing/Not Implemented

APIs that the Nano node wallet supports but are not implemented in Pippin.

  • account_move
  • account_remove
  • receive_minimum - Receive minimum can be set in config.yaml
  • receive_minimum_set
  • wallet_add_watch
  • wallet_history
  • search_pending
  • search_pending_all
  • wallet_export
  • wallet_ledger
  • wallet_republish
  • wallet_work_get
  • work_get
  • work_set

CLI Documentation

Pippin has a CLI interface available, you can see available subcommands with:

pippin-cli --help

The primary goal of the CLI is key management. It's a more secure way to import a seed and backup your seed.

For example a typical flow of creating a new wallet with a specific seed might look like (add --encrypt to wallet_change_seed if you want to lock the wallet with a password):

% pippin-cli wallet_create
Wallet created, ID: d897b5ec-1897-4e7e-8a90-4526f454c8de
First account: nano_31a7wzm4rayik1hthahzkekntsqz86u6dko5adg8jxueehzt5yhmhsqsuzdy
% pippin-cli wallet_change_seed --wallet d897b5ec-1897-4e7e-8a90-4526f454c8de
Enter new wallet seed: <hidden_input>
Seed changed for wallet d897b5ec-1897-4e7e-8a90-4526f454c8de
First account: nano_3ejy6ha1iuqhi5cshhifu57p5othdcymfbzsmxhjucdks53eh41yd4qpjtxf

To backup a seed (warning: this prints seed to stdout)

% pippin-cli wallet_view_seed --wallet <id>

Setting up Pippin

Requirements

  • Python 3.6 or newer
  • GCC, for MacOS and Linux
  • libb2 (blake2b)
  • A Redis server

MacOS Instructions

  1. Install homebrew, if it isn't already installed

  2. Install Redis (skip if you already have done so)

% brew install gcc@9 python libb2 redis
% launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

To start redis at boot (optional):

% ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents

You may find it convenient to priorize homebrew binaries by including the install location first in your PATH.

% export PATH=/usr/local/bin:$PATH

To make it permanent:

# Catalina
% echo "export PATH=/usr/local/bin:$PATH" >> ~/.zprofile
# Others
% echo "export PATH=/usr/local/bin:$PATH" >> ~/.profile

Ubuntu 18.04

Instructions for other Linux distributions should be similar.

% sudo apt install build-essential python3.6 python3.6-dev python3-pip libb2-dev redis-server

Installing Pippin

First, update PIP to latest version.

% pip3 install -U pip

For MacOS you might need to set the following environment variable:

export CC=/usr/local/bin/gcc-9

To install Pippin

% pip install --user pippin-wallet

To upgrade Pippin in the future, add --upgrade

% pip install --upgrade pippin-wallet

Configuring Pippin

Pippin creates a PippinData directory in your home directory.

Run: pippin-server --generate-config to generate a sample in ~/PippinData/sample.config.yaml

Using Distributed PoW or BoomPoW

Want to use DPoW or BPoW?

Pippin will use them automatically for work generation if the key/user is present in the environment.

For DPoW:

% echo "DPOW_USER=mydpowuser" >> ~/PippinData/.env
% echo "DPOW_KEY=mydpowkey" >> ~/PippinData/.env

For BPoW:

% echo "BPOW_USER=mybpowuser" >> ~/PippinData/.env
% echo "BPOW_KEY=mybpowkey" >> ~/PippinData/.env

Replace mybpowuser and mybpowkey with the actual user and keys you have. If you need keys, visit their respected websites for instructions on how to request them.

Configuring PostgreSQL or MySQL

Pippin uses SQLite by default, which requires no extra configuration.

To use postgres or mysql, you need to put your database information in some environment variables

Postgres:

Required (replace database_name, user_name, and mypassword with the actual values):

% echo "POSTGRES_DB=database_name" >> ~/PippinData/.env
% echo "POSTGRES_USER=user_name" >> ~/PippinData/.env
% echo "POSTGRES_PASSWORD=mypassword" >> ~/PippinData/.env

Optional:

# 127.0.0.1 is default
% echo "POSTGRES_HOST=127.0.0.1" >> ~/PippinData/.env 
# 5432 is default
% echo "POSTGRES_PORT=5432" >> ~/PippinData/.env

MySQL:

Required (replace database_name, user_name, and mypassword with the actual values):

% echo "MYSQL_DB=database_name" >> ~/PippinData/.env
% echo "MYSQL_USER=user_name" >> ~/PippinData/.env
% echo "MYSQL_PASSWORD=mypassword" >> ~/PippinData/.env

Optional:

# 127.0.0.1 is default
% echo "MYSQL_HOST=127.0.0.1" >> ~/PippinData/.env 
# 3306 is default
% echo "MYSQL_PORT=3306" >> ~/PippinData/.env

Changing Redis Host/Port

Pippin uses Redis for distributed locks, so that every account works on its own chain in a synchronous fashion.

By default, it will look for redis on 127.0.0.1 on port 6379 and use db 0, you can also change these with environment variables.

echo "REDIS_HOST=127.0.0.1" >> ~/PippinData/.env
echo "REDIS_PORT=6379" >> ~/PippinData/.env
echo "REDIS_DB=0" >> ~/PippinData/.env

Pippin Configuration

Pippin uses a yaml based configuration for everything else.

All available options are in a sample file here

You can override any default by creating a file called ~/PippinData/config.yaml and choosing your own settings.

It must be in your users home directory in a folder called PippinData

Configuring Pippin for BANANO

In config.yaml set banano: true

# Settings for the pippin wallet
wallet:
  # Run in banano mode
  # If true, the wallet will operate based on the BANANO protocol
  # Default: false
  banano: true

Configuring the node

At the bare minimum, Pippin requires a node for the RPC api. It will default to http://[::1]:7076 for Nano, or http://[::1]:7072 for BANANO. If you want to change it to https://coolnanonode.com/rpc then it would look like this:

server:
  # The RPC URL of the remote node to connect to
  # Non-wallet RPCs will be routed to this node
  # Default: http://[::1]:7076 for nano, https://[::1]:7072 for banano
  node_rpc_url: https://coolnanonode.com/rpc

Running Pippin

Once configured, just start it with pippin-server

It can be started on boot using systemd (Linux)

Create a file /etc/systemd/system/pippin.service

With the contents:

[Unit]
Description=Pippin Wallet
After=network.target

[Service]
Type=simple
User=YOUR_LINUX_USER
Group=YOUR_LINUX_USER
ExecStart=/home/myuser/.local/bin/pippin-server

[Install]
WantedBy=multi-user.target

If you aren't sure what the full path of pippin-server is, run which pippin-server

Then enable and start

% sudo systemctl enable pippin
% sudo systemctl start pippin

Endpoints

Send HTTP POST requests to Pippin just like you would a normal node.

% curl -g -d '{"action":"wallet_create"}' localhost:11338
% curl -g -d '{"action":"account_balance", "account": "nano_3jb1fp4diu79wggp7e171jdpxp95auji4moste6gmc55pptwerfjqu48okse"}' localhost:11338

Auto-receive & Dynamic PoW

To automatically pocket pending transactions as they arrive, callback is required.

Hooking up the websocket also adds support for dynamic PoW which means that blocks will get confirmed faster if the active difficulty is higher than the minimum.

Pippin only supports the websocket callback, which can be setup like so in config.yaml:

server:
  # The WebSocket URL of the node to connect to
  # Optional, but required to receive transactions as they arrive to accounts
  # Default: None
  #node_ws_url: ws://[::1]:7078

Feature requests

Notice an API that's missing a feature or not behaving the same as nano's APIs?

Open a bug report/feature request on the issues page

You can’t perform that action at this time.