Only this pageAll pages
Powered by GitBook
1 of 68

Oxen Docs

Loading...

Loading...

Loading...

About the Oxen blockchain

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Using the Oxen Blockchain

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Products built on Oxen

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Support

The Oxen Network has transitioned to the Session Network. More information here.

Having trouble, want to check if you're experiencing a bug, or found an issue with the Oxen Docs? Let us know! The Oxen team is always happy to help.

Check out our support centre here, where you can browse our articles or submit a ticket if those don't cut it.

Advanced

Downloads

The Oxen Network has transitioned to the Session Network. More information .

Need some help using our wallets? Check out the . You can also find out more about and from our wallets.

Oxen Wallet downloads

The Oxen GUI Wallet is the most user friendly Oxen Wallet, and is perfect for beginners or those simply looking to send or store their OXEN.

The CLI wallet is for more advanced users, and offers more tools to interact with the Oxen blockchain.

Windows

  • v1.8.3

  • (packaged with Oxen Core)

macOS

  • v1.8.3

  • (packaged with Oxen Core)

Linux

  • v1.8.3

  • (packaged with Oxen Core)

Android

iOS

here
Oxen wallet guides
setting up service nodes
staking
Oxen GUI Wallet
Oxen CLI Wallet
Oxen GUI Wallet
Oxen CLI Wallet
Oxen GUI Wallet
Oxen CLI Wallet
Oxen Mobile Wallet from Play Store
Oxen Mobile Wallet from GitHub
Oxen Mobile Wallet

Overview

The Oxen blockchain is a private payments system that enables the creation of many privacy-preserving applications

The Oxen Network has transitioned to the Session Network. More information here.

The Oxen blockchain and the $OXEN token are at the heart of Oxen. Together they brought privacy, incentivisation, and decentralisation to the Oxen tech stack.

Oxen's blockchain was maintained by the Oxen Service Node network, a network of blockchain nodes operated by members of the Oxen community. Running a service node requires staking — which means voluntarily locking — a certain amount of $OXEN tokens.

The staking requirement to run a service node was 15,000 $OXEN or 3,750 $OXEN for a shared node.

In exchange for maintaining reliable and trustworthy blockchain nodes, node operators periodically received rewards in the form of $OXEN tokens.

Oxen was originally forked from Monero, and it's still based on the CryptoNote protocol. From these beginnings, Oxen has inherited world class privacy and security features — including ring signatures, stealth addresses, and ring confidential transactions. Just like $XMR, $OXEN is fungible, private, and untraceable.

The Oxen blockchain got started in 2018, with its first ever block being confirmed on March 5 of that year. Ever since then, the blockchain has been successfully and securely operating. On October 15 2019, we made the transition to Pulse — making Oxen one of the first ever Proof of Stake CryptoNote projects. The entire history of the Oxen blockchain can be easily viewed via this block explorer. As for the future, you can stay up to date on the project by checking out our Oxen Labs Updates.

The Oxen blockchain also boasts Blink — truly private, instant transactions. Blink allows you to make transactions with all the confidence Monero enthusiasts love, but with a 1 second transaction time.

Overview

Here's a quick overview of the services provided by the Oxen blockchain

The Oxen Network has transitioned to the Session Network. More information here.

💸 $OXEN and the 💰Oxen Wallet: Private instant transactions

The Oxen Wallet, available in user-friendly GUI or powerful CLI versions, enables you to send and receive private anonymous transactions in the blink of an eye. You can download your preferred Wallet version here.

🖥 Oxen Service Nodes: Earn $OXEN rewards for powering up the Oxen network

Running an Oxen Service Node is a great way to grow the Oxen network and support the project while receiving $OXEN rewards for your valuable contribution. Check out our guides to setting up a service node and staking to a service node, or see here for some service node tools and utilities to help with starting up and maintaining your service nodes.

Oxen Name System (ONS): Human-readable names for Session, Lokinet, and more

Oxen Name System enables you to register alphanumeric names to be used in place of the long, hard-to-use default formats for Lokinet addresses, Session IDs, and Oxen Wallet addresses. For a look at registering names using ONS, check out our guide.

Restoring an Oxen CLI Wallet from keys

If you have a Mnemonic Seed Phrase, restoring your wallet from it would probably be a good option. Otherwise, you can restore your wallet from private keys. You will need to have the following keys to proceed:

  • Wallet public address

  • Spend Key

  • View Key

Step 1: Download and unzip CLI wallet

  • Download the latest release of wallet CLI software for your desired operating system

  • Unzip oxen-[operating-system]-[platform]-[version].zip file

Step 2: Run wallet in restore mode

  • Open a Command Prompt (Windows) or Terminal (Linux / OSX) and navigate to the wallet folder

  • Run wallet with --generate-from-keys argument:

./oxen-wallet-cli --generate-from-keys [New Wallet Name]

Where [New Wallet Name] is a new wallet name. You can enter any name here, use something memorable and meaningful.

Step 3: Enter wallet address, view and spend keys

On the next step, specify all 3 wallet keys, one by one:

  • Enter Standard address and press [Enter]

  • Enter Secret spend key and press [Enter]

  • Enter Secret view key and press [Enter]

Step 4: Enter wallet password

  • You will be prompted for a password. Enter a new password that follows the Password Policy and press [Enter].

  • Confirm password and press [Enter].

Step 5: Specify a blockchain height

If you know the block height at which wallet was created or a first transaction was made, you can enter it here. Specifying a blockchain height will help to scan the wallet faster.

If you don't know a specific blockchain height, press [Enter] for scanning from block height 0.

Step 6: Wait for the refresh process to finish

For refresh process to start, you need to have your daemon running. Another option would be to use a remote node. For that, use the following command, replacing and with the host and port number of the remote node you are connecting to:

./oxen-wallet-cli --daemon-address <host>:<port>

Once refresh is done, you can use your full functioning restored wallet. Your public wallet address will remain the same.

Token economics

Learn about the economics of the Oxen token

The Oxen Network has transitioned to the Session Network. More information here.

The Oxen network is run by a decentralised network of incentivised nodes called service nodes.

As the workhorses of the network, service nodes get the lion's share of the reward: 16.5 $OXEN per block.

This results in the creation of 11,880 $OXEN per day.

Because of the nature of Pulse, a large proportion of $OXEN's total supply is locked in service nodes and unavailable on the market. On top of this, our research has shown that people earning rewards through staked nodes are much more likely to hold their tokens and continue participating in the network than those who earnt their tokens via mining.

These two qualities help increase buy pressure and decrease sell pressure in $OXEN markets, respectively.

More details about the cryptoeconomic theory which underpins Oxen can be found here.

The not-for-profit Oxen Privacy Tech Foundation receives a governance reward of 9240 $OXEN every 7 days. This reward is used to pay for development, marketing, and community projects, more information about how the Oxen treasury and governance reward is managed can be found on the OPTF website.

Service node tools and upkeep

Service node rewards calculator

A simple calculator to help you estimate the rewards you should receive from operating an Oxen Service Node. Check it out:

https://imaginary.stream/sn/

Service node status bot

A handy Telegram bot which can report on service node status, including uptime alerts and reward notifications.

https://github.com/jagerman/loki-sn-bot

Migrating to the new Session Network

The Oxen Network has transitioned to the Session Network. More information here.

This section contains important guides and resources for node operators migrating to the new Session Network:

Migration Checklist

Migration FAQ

Connecting to an Arbitrum One RPC Endpoint

How to set up an oxend L2 proxy

Introduction to Oxen

Oxen is an ecosystem of privacy tools built on top of a fully decentralised layer-1 blockchain.

The Oxen Network has transitioned to the Session Network. More information here.

Service Node operators and contributors who participated in the Service Node Bonus Program earned additional Session Tokens and had their staked OXEN automatically converted to Session Tokens. More information can be found here.

Oxen can now be swapped for the new Session Token using the Oxen Coin Claims Portal. More information can be found here.

Oxen was one of the largest app ecosystems in the entire crypto industry. Applications like Session and Lokinet serviced hundreds of thousands of active users thanks to the power of the Oxen Service Node Network, recently migrated to the new Session Network.

The network was powered by the Oxen blockchain, a privacy preserving cryptocurrency network that enables fast and private value transfer. The blockchain was maintained by a distributed network of community-operated 🖥 Oxen Service Nodes, which ran all the network features and services offered by Oxen's tech stack.

The Coin

Oxen was originally forked from Monero, and was based on the CryptoNote protocol. From these beginnings, Oxen inherited privacy and security features — including ring signatures, stealth addresses, and ring confidential transactions. Just like $XMR, $OXEN is fungible, private, and untraceable.

Service Nodes

Oxen was fully proof of stake, with a set of incentivised nodes called Oxen Service Nodes maintaining an securing the blockchain, providing services to Oxen Apps, and receiving block rewards. Nodes that migrated to the Session Network are now functioning as Session Nodes and receiving block rewards in the form of Session Tokens.

The Apps

Session — An end-to-end encrypted, decentralised messaging app. Because Session doesn’t require any identifying information—such as a phone number or email address—to sign up, it has become popular with civil rights groups, whistleblowers, and other people who require high levels of privacy and anonymity.

Lokinet — An onion-router that allows people to browse the internet privately and securely. Lokinet operates on the network layer and is therefore able to onion-route any IP-based protocol, making it fast, dynamic, and adaptable.

Blink: Instant transactions

Bink is Oxen's revolutionary instant payment system

The Oxen Network has transitioned to the Session Network. More information here.

What is Blink?

Blink is $OXEN’s instant payments mechanism. We’re leveraging the Oxen Service Node network to confirm transactions before they’re entered into the blockchain, while maintaining the privacy, anonymity, and security you expect from $OXEN. Blink is the first and only instant payment solution for a CryptoNote-based privacy coin.

How does Blink work?

Normal $OXEN transactions are sent to a pool of unconfirmed transactions (the mempool), where they sit until randomly selected for inclusion in a new block to be added to the blockchain ledger. This can take several minutes, and while this is fine for many transactions, sometimes people need transactions that are private, anonymous, and instant. Enter Blink.

When a Blink transaction is made, the transaction makes a few extra stops on the way to the mempool — but, paradoxically, those extra stops make the transaction effectively instant. Blink transactions look like this:

  1. Blink transaction is sent to two quorums (randomly-selected groups of 10 Oxen Service Nodes)

  2. Quorums check transaction for legitimacy

  3. Malicious or invalid transactions (e.g. duplicates of a previous transaction, or an attempt to spend $OXEN which does not belong to the sender) are denied

  4. Valid transactions are confirmed by the quorums

  5. Sender and receiver see transaction confirmation

  6. Blink transaction is passed to mempool for inclusion in blockchain

What does Blink enable?

With Blink, $OXEN is the first cryptocurrency to offer secure, private, anonymous transactions in real-time. The possibilities are endless — limited only by your imagination. Powered by Blink, $OXEN presents a viable solution for privacy-conscious point-of-sale applications, and any other situation where users want security, privacy, and anonymity in the blink of an eye.

Pulse: PoS on Oxen

Pulse is Oxen's Proof of Stake consensus mechanism

The Oxen Network has transitioned to the Session Network. More information here.

Fundamentally, every blockchain — including Oxen — is exactly what it says in the name: a chain of blocks. One 'block' in the Oxen blockchain is made up of a set of $OXEN transactions which have been deemed valid by the network. But when the network consists of thousands of computers all over the world, how does it come to consensus about the state of the blockchain?

That's where Pulse comes in.

Pulse is Oxen's implementation of the 'Proof of Stake' consensus mechanism, and it forms the foundation of the Oxen Service Node network. Let's dive into how it works and why we use it.

Proof of Stake: How does it work?

In our Proof of Stake (PoS) consensus system, active Oxen Service Nodes are randomly selected to create and publish new blocks of transactions to the blockchain approximately every 2 minutes, with each node being rewarded for doing so.

Once a service node has been selected to create a block, a set of other nodes (the validators) are chosen to validate the new block — checking to ensure it doesn't contain duplicate transactions or any other potentially malicious activity. Once these validator nodes have verified the block’s legitimacy, the block is published to the blockchain.

Security benefits of Proof of Stake

In a PoS-based blockchain, an attacker would need to control more than 50% of the total supply of staked or stakeable cryptocurrency tokens in order to carry out a 51% attack (allowing them to publish fake or invalid transactions, re-order the blockchain, etc.).

Acquiring this much of the total supply can be extremely expensive — and in some PoS-based blockchains, it be nearly (or completely) impossible. When crypto tokens are staked into nodes, they are locked for a pre-determined amount of time. This means they're removed from the marketplace and can't be bought. If more than 50% of the total cryptocurrency supply for a given blockchain network is staked, a 51% attack becomes extremely unlikely, because for an external attacker (i.e. someone not already invested in the network), buying up or otherwise being able to control enough tokens to control more than half the nodes on the network becomes almost impossible. And there's a second layer of security here, too: if someone does buy up such a huge amount of tokens that they could gain control of the network, they would then be disincentivised from wanting to attack the network simply because attacking the network would harm the value of their tokens — once they're invested, they're simply better off acting in good faith, so their tokens gain value rather than losing value.

Preparing for GUI Wallet setup (Windows)

When installing the Oxen Wallet, overzealous antivirus software can sometimes block the wallet or some of its components from functioning, or even delete them entirely. To avoid these issues on Windows, follow the below steps.

Note: when you reach Step 6 (downloading the Oxen Wallet), ensure you are downloading the Wallet directly from an official source: either here on the Oxen Docs, or on the official Oxen Github releases page.

For the purposes of this example, our images show how to do this on Windows Defender

Antivirus Steps

  1. Create a folder called “Wallet” at the root of your C: drive (or another convenient location)

  2. Open your antivirus program and go to “Manage Exceptions”, “Exceptions”, "Exclusions", or similar:

  1. Click “Add an exception”, "Add an exclusion", or similar:

  1. Select your Wallet folder as the location for the exception:

  1. Disable protection features for this folder:

  1. Download the latest version of the Oxen Wallet directly into the Wallet folder:

  1. Run the Oxen Wallet installer and select the Wallet folder as the install location:

  1. Check your antivirus program’s firewall and ensure all executables named “Oxen xxx” are permitted through the firewall:

Congratulations! You can now proceed to our GUI Wallet setup guide as normal.

Note: If you’re using Bitdefender specifically, and your wallet still does not function after following the above steps exactly, disable Advanced Threat Detection under Features

GUI Wallet setup

This document will tell you exactly how to set up and operate the Oxen GUI wallet. You can download the appropriate GUI Wallet for your desktop operating system .

Step 0 (Windows only): Install Electron wallet and allow Defender permissions.

Mac and Linux users skip to .

Open the executable file we downloaded from the Oxen Github Oxen.Electron.Wallet.Setup.X.X.X-windows.exe to start installion.

When installing the wallet the Windows Defender SmartScreen will prevent you from opening it unless you give the file permission.

Click Run anyway to give the executable permission.

Now run through the installation prompts and then click install.

Once the installation has finalised open the Oxen Wallet by clicking your "Windows" key or the start menu and searching for oxen electron wallet.

Step 1: Running the Wallet for the first time

Once the installation has finalised open the Oxen Wallet by clicking your "Windows" key or the start menu and searching for oxen electron wallet.

Once opened the wallet will need to be configured.

1.1: Choose your language.

1.2: Configure your settings.

Default settings are fine to use.

This is not required but if you would like to run your own node and broadcast your own transactions check the Local + Remote Daemon or the Local Daemon Only option.

Click Next when ready.

Step 2: Creating/importing Wallet

Once your settings have been configured if you do not already have a wallet generated yet then your screen will look like the following:

2.1: Creating new Wallet

To create a new wallet click the Create new wallet button.

Next fill in the input fields that are required. It is recommended that you should consider encrypting your key with an optional password.

Once input boxes are filled in click CREATE WALLET button.

2.2: Importing Wallet from seed

To import a wallet from seed click the Restore wallet from seed button.

Next fill in the following input fields:

  • Wallet Name: Enter a name for your wallet.

  • Mnemonic Seed: Enter the seed phrase that was generated when intially creating your wallet.

  • Restore from Date: Enter the date or blockheight in which you want to restore your wallet from.

It is quicker to restore from the date in which you generated the wallet.

  • Password: Enter an optional password.

  • Confirm Password: Enter the same password to confirm spelling.

Once input boxes are filled in click RESTORE WALLET button.

Mobile Wallet Staking Guide

This guide explains how to stake to an Oxen Service Node via the Oxen Mobile Wallet

The latest versions of the Oxen Mobile Wallet can be found on .

Step 1.

Open the Oxen Mobile Wallet, enter your password/pin, and let it fully sync to the latest blockheight.

Step 2.

Press the icon in the top right of the screen to open the menu.

From there, press "Stakes" to navigate to the staking section.

Next, press "Start Staking" to begin the staking process

Step 3.

Search for nodes that are awaiting contribution on .

Step 4.

Copy the service node public key into the box at the top of the screen labelled 'Service Node Key'

Step 5.

Enter the amount of Oxen you wish to stake in the other box. The minimum stake amount will be listed on , but to work it out yourself you can simply divide the amount of Oxen available to stake by the number of slots left for that Service Node.

For example, if a node had 2 slots remaining and 7500 Oxen available for stake, the minimum contribution would be 7500/2 = 3750 Oxen.

Step 6.

Once you have entered the Service Node public key and the amount you wish to stake, simply swipe 'Stake Oxen' to contribute to the Service Node.

Congratulations! You're all staked up, and you'll receive your Service Node rewards directly to your wallet.

Unstaking

To unlock your stake from a Service Node, navigate to the stakes section of the wallet your contributions will be listed. You can unstake a contribution by swiping left and confirming. Your Oxen will be unlocked after 15 days.

Getting help

If something in this guide doesn't make sense, or if you’re running into issues that you can’t identify on your own, the first place to go would be the Oxen . Alternatively, you can find help on our other communication channels: , or .

Reporting bugs

If you've sought help through our communication channels but have not arrived at a solution for your issue, we recommend opening an issue ticket on the GitHub repository.

Exporting a CSV of your wallet transaction history

The Oxen Wallet allows you to export a CSV of transactions that have occurred in the wallet. The process for both the GUI wallet and the CLI wallet are as follows:

GUI Wallet

The Oxen GUI wallet as of v1.6.0 supports the exporting of your transactions. After logging into your wallet:

  • Click on SETTINGS at the top right of the app

  • Click on Export Transfers

  • The wallet will then prompt you for a folder to save the CSV to. This defaults to a CSV directory within the Oxen folder (Same directory your wallet keys are stored) but you can edit this to any location.

  • Click Export and you will be prompted for your wallet password

  • You will then see a green notification at the bottom of the window if the export is successful. For example: “Transfers exported to /home/sean/Desktop/transfers.csv”

CLI Wallet

Note you will either need to be running a local daemon (oxend) or have a remote node that the CLI wallet can communicate with.

Navigate to the directory that the oxen-wallet-cli executable is stored in:

Run the oxen-wallet-cli:

If you are using a remote node instead of a local daemon you will need to add additional command line arguments here:

The wallet will ask you to enter the name of your wallet file. If you are coming from the GUI wallet these are stored in the following locations

  1. Linux: ~/Oxen/wallets/MyWallet.keys

  2. Windows: C:\Users&lt;username>\Documents\Oxen\wallets

  3. Mac: ~/Oxen/wallets/MyWallet.keys

These can alternatively be included as command line flags

Once the wallet has synced you will be able to call `export_transfers` which saves the CSV to the same location as where you ran the oxen-wallet-cli (Most likely the same location as the executable).

Connecting to an Arbitrum One RPC Endpoint

The Anchor hardfork introduces a new requirement for all Service Nodes to maintain an active connection to an Arbitrum One RPC node.

The Oxen Network has transitioned to the Session Network. More information .

As part of the migration to the new Session Network, the Anchor software upgrade and hardfork implements the ability for Service Nodes to witness the Arbitrum One blockchain. All Service Nodes will be required to maintain an active and up-to-date Arbitrum One RPC endpoint to complete the upgrade. This endpoint will be crucial to allow Service Nodes to witness the state of Arbitrum smart contracts, which in the future will contain the list of active Session Nodes. Operators who have participated in the Session Testnet may already be familiar with this requirement using the Arbitrum Sepolia network. There are two main options for fulfilling this requirement:

  1. Public RPC providers

  2. Running your own Arbitrum node

Public RPC providers

Public RPC providers handle the complexity and overhead of running an Arbitrum One node. These providers offer a public endpoint for querying. Some examples of public RPC providers that support Arbitrum One are:

  • A comprehensive list of official and third party RPC providers for Arbitrum can also be found

You can sign up for a free account with most of these providers, which typically offer free usage up to a certain limit. In most cases, their free tiers will support up to 2 or 3 Session Nodes without exceeding usage limits. If you need to support more nodes, you can either register for multiple providers and use different endpoints for each set of nodes, or consider upgrading to a paid plan for higher usage.

Note: If you are operating several nodes (More than 2-3 nodes per public provider) you might want to consider deploying a caching server, such as. This setup allows you to significantly reduce the number of calls made to your RPC provider by caching common queries, improving performance and reducing costs.

Running your own Arbitrum Node

If you are staking multiple nodes or prefer not to rely on a public RPC provider, you may want to run your own Arbitrum One node. But be aware that the hardware requirements for running an Arbitrum One node are very demanding.

A full guide on how to run an Arbitrum One node using Nitro can be found .

Upgrading

Once you have your Arbitrum node or public provider setup, you will receive a URL or local address that will look something like this, depending on your provider or setup:

https://arb-mainnet.g.alchemy.com/v2/32bfi3gb298fbb32byfb32bf

Your node can be upgraded using the following simple commands in your CLI:

Syncing your repositories:

sudo apt update

Then installing updates using:

sudo apt upgrade

Please note: this will install both updated Oxen packages and any available system updates (this is a good thing!).

During the Anchor upgrade process, you will be prompted to enter your Arbitrum RPC address. Enter the URL or local address of your Arbitrum node. You also have the option to specify backup RPC nodes, by adding multiple URLs, separated by a comma. These will be queried if your primary endpoint is unavailable. Adding backup RPC nodes is optional and not required to complete the upgrade.

Guides

Staking to a shared Oxen Service Node

This document explains how to stake via the Oxen GUI Wallet.

The latest version of the wallet can be downloaded .

Please keep in mind, one can only stake via an open pool with the GUI wallet.

GUI Wallet Guide

Step 1

Open the Oxen GUI Wallet, enter your password, and let it fully sync to the latest blockheight.

Step 2

Click on the SERVICE NODE button.

Step 3

On this step you will need to enter the service node public key obtained from the node operator (or ) and the amount of Oxen you are contributing to the node.

This can be done automatically by clicking STAKE on one of the listed Service Nodes awaiting contribution in the wallet interface.

Step 4

Once that is filled out, simply hit the STAKE button.

Please note, if you receive an error at this step you will need to click the SWEEP ALL before you can stake from your wallet.

Congratulations, you're now staked!

If you have questions or need help with this guide feel free to reach out to us on or .

Installing on Linux (Debian based distros)

How to install Session on Debian based Linux distributions

Open a terminal and run the following commands

  1. Add the Oxen GPG key

2. Add repository list

3. Update repositories

4. Install Session

Updating Session

If you want to update Session, you can run the following commands

then

Service Node guides

The Oxen Network has transitioned to the Session Network. More information .

A directory of guides for setting up and maintaining your Oxen Service Node.

Guide
Outline
sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list
sudo apt update
sudo apt install session-desktop
sudo apt update
sudo apt upgrade
our downloads page
https://oxensn.com
https://oxensn.com
Telegram Group
Twitter
Reddit
Session public server
here
Infura
Alchemy
GetBlock
QuickNode
here
json-rpc-cache-proxy
here
Installing on Linux (Debian based distros)
Session Open Group Server Setup
here
OxenSN
Discord
Telegram

Express Service Node setup guide

How to configure a server as an Oxen Service Node (quickly)

Full Service Node setup guide

How to configure a server as an Oxen Service Node (in depth)

GUI Wallet Staking Guide

How to stake to an Oxen Service Node using the Oxen GUI Wallet.

Service node deregistration

Explanation of the conditions under which a service node may be deregistered (removed from the network), and some tips on how to avoid deregistration.

Service node tools and upkeep

Some handy tips and tools for maintaining your Oxen Service Node.

here

Restoring an Oxen CLI Wallet from seed

To fully restore your wallet and be able to view balance and make transactions, having your seed stored will be enough. You don't need your wallet password or other keys to restore the wallet once you have a seed phrase.

Step 1: Download and unzip CLI wallet

  • Download the latest release of wallet CLI software for your desired operating system

  • Unzip oxen-[operating-system]-[platform]-[version].zip file

Step 2: Run wallet in restore mode

  • Open a Command Prompt (Windows) or Terminal (Linux / OSX) and navigate to the wallet folder

  • Run wallet with --restore-deterministic-wallet argument: ./oxen-wallet-cli --restore-deterministic-wallet

Step 3: Enter wallet name

You will be prompted to enter a wallet name and click [Enter]. You can enter any name here, use something memorable and meaningful.

Step 4: Enter your seed phrase

  • You will be prompted to enter 25 word mnemonic seed you have stored. Paste it and press [Enter].

  • If you have a seed encryption passphrase, enter it on the next step. Otherwise, press [Enter].

Step 5: Enter wallet password

  • You will be prompted for a password. Enter a new password that follows the Password Policy and press [Enter].

  • Confirm password and press [Enter].

Step 6: Specify a blockchain height

If you know the block height at which wallet was created or a first transaction was made, you can enter it here. Specifying a blockchain height will help to scan the wallet faster.

If you don't know a specific blockchain height, press [Enter] for scanning from block height 0.

Step 7: Wait for the refresh process to finish

For refresh process to start, you need to have your daemon running. Another option would be to use a remote node. For that, use the following command, replacing and with the host and port number of the remote node you are connecting to:

./oxen-wallet-cli --daemon-address <host>:<port>

Once refresh is done, you can use your full functioning restored wallet. Your public wallet address will remain the same.

Read Only Room Setup

Some SOGS operators may want to setup a room on their SOGS which features one way style communication, these rooms allow moderators and administrators to update the room with new messages, but disallows unprivileged users to send new messages. These sorts of rooms can be useful for providing updates or information.

1. Create a new room

sogs --add-room TOKEN --name "NAME" --description "DESCRIPTION"

*Skip to step 3 if you already have a room and you are an administrator in that room*

Replace TOKEN with the address to use in the room URL (which must consist of ONLY lowercase letters, numbers, underscores, or dashes), replace NAME with the room name to display in Session and optionally replace DESCRIPTION with a short description of the topic of the room.

2. Ensure you are an administrator of the room

sogs --room TOKEN --admin --add-moderator ACCOUNTID

replacing TOKEN with the room token you created in step 1 and replacing ACCOUNTID with your own Account ID

3. Alter room permissions

There are 4 types of permission currently available in rooms

  • r = Read (ability to read messages)

  • w = Write (ability to write new messages)

  • u = Upload (ability to upload attachments, including files, voice notes, images and videos)

  • a = Access (ability to join the room)

When modifying these permissions changes will only apply to non admins/moderators, the default permissions in a room will be "rwua" for all users

To create a read only group we want to remove regular users ability to write and upload attachments, we can do this using the following command

sogs --add-perms ra --remove-perms wu --room TOKEN

This command will ensure read and access permissions are provided and remove write and upload permissions for regular users.

As the permission changes do not affect administrators and moderators, they will still be able to read, write and upload to the group. New Account ID's can be given write/upload access by making those Account ID's moderator or admin, this can be done directly in the Session Desktop client or via the CLI.

sean@sean-MS-7A33:~/oxen-core/build$ cd bin/
sean@sean-MS-7A33:~/oxen-core/build/bin$ ls
oxen-blockchain-ancestry  oxen-blockchain-import              oxen-blockchain-usage      oxen-sn-keys
oxen-blockchain-depth     oxen-blockchain-mark-spent-outputs  oxend                      oxen-wallet-cli
oxen-blockchain-export    oxen-blockchain-stats               oxen-gen-trusted-multisig  oxen-wallet-rpc
sean@sean-MS-7A33:~/loki-core/build/bin$ ./oxen-wallet-cli
sean@sean-MS-7A33:~/loki-core/build/bin$ ./oxen-wallet-cli --daemon-address public.loki.foundation:22023
sean@sean-MS-7A33:~/loki-core/build/bin$ ./oxen-wallet-cli --daemon-address public.loki.foundation:22023 --wallet-file ~/Oxen/wallets/MyWallet --password "password"
[wallet T6SjAL (has locked stakes)]: export_transfers all output=oxen.csv
here
Step 1

Oxen Service Nodes

Oxen Service Nodes provide the underlying support for the Oxen Network

The Oxen Network has transitioned to the Session Network. More information here.

Oxen’s networking functionality, scalability, and decentralisation tech stack is powered by a set of incentivised nodes called Oxen Service Nodes. To operate a service node, an operator time-locks 15,000 $OXEN, and the service node begins providing a minimum level of bandwidth and storage to the network. In return for their services, service node operators receive a portion of the block reward from each block mined on the Oxen blockchain.

The resulting network benefits from market-based resistance to Sybil attacks, addressing a range of problems with existing onion routers and privacy-centric services. This resistance is based on supply and demand interactions which help prevent single actors from possessing a large enough stake in Oxen to have a significant negative impact on the second-layer privacy services Oxen provides. DASH first theorised that cryptoeconomics can provide a network with properties of Sybil attack resistance. In our case, as an attacker accumulates $OXEN, the circulating supply decreases, in turn applying demand-side pressure and driving the price of $OXEN up. This effect spirals, making it increasingly costly for additional $OXEN to be purchased and thus making an attack prohibitively expensive.

To maintain this protection, Oxen encourages active suppression of the circulating supply. In particular, the emissions curve and staking requirement have been designed to ensure enough circulating supply is locked (and reasonable rewards are provided to operators) to ensure Sybil attack resistance.

Just looking for a guide on setting up a service node? Click here. Interested in staking into a shared service node? Check out our Staking Guide.

Service Node activities

An Oxen Service Node becomes active on the network when its owner stakes (locks up) the required amount of $OXEN, which submits a registration transaction. Once accepted by the network, the service node becomes eligible to receive block rewards. Multiple participants can stake to a single service node, combining their smaller stakes to meet the 15,000 $OXEN staking requirement. The block reward can be automatically distributed among the participants in a ratio proportional to each participant's staking contribution.

Once active on the network, Oxen Service Nodes are required to:

  • Monitor other service nodes and vote on their performance

  • Create new blocks on the Oxen blockchain (see Pulse)

  • Receive, temporarily store, and forward encrypted messages (see Session)

  • Participate in quorums to enable instant $OXEN transactions (see Blink)

  • Route end-user internet traffic (see Lokinet)

Guides & Resources

Resource Name
Description

How to host and maintain an Oxen Service Node using a Debian package and CLI wallet.

How to stake to a shared Oxen Service Node as a contributor.

Statistics, data, maps, and other information on Oxen Service Nodes.

List of Oxen Service Node JSON 2.0 RPC calls (advanced users only).

The Oxen Blockchain Explorer, with a list of current Service Node public keys.

Oxen Ledger Wallet setup: GUI Wallet

Using the Ledger hardware wallet with the Oxen GUI wallet is almost identical to the process with keys stored on your desktop. The two differences are:

  1. There is a special process to create the wallet file.

  2. When sending transactions the ledger device will prompt you to confirm the transaction.

Connect the hardware wallet to the PC and navigate to the oxen app.

The wallet needs to communicate with the Ledger and it must be on the Oxen dashboard page. This guide will demonstrate the process on a Ledger Nano S Plus. But both the Ledger Nano X and the Ledger Nano S will follow the same process.

From the Ledger app homepage (app selection) navigate to the Oxen app and press both buttons to select.

As the Oxen wallet app is currently being reviewed by the Ledger team you will first be prompted with a screen that reads “Pending Ledger review”. This screen will display for a few seconds and then allow you to progress by pressing both buttons at the same time.

You should now arrive on the Oxen dashboard. The divide will display “OXEN wallet” and a truncated string of the Oxen address. On this Ledger you can see that the Oxen Address is “LCYwfQr..XHS”. This address should also match the address displayed on the GUI wallet.

The device will need to be on this screen to work with the Oxen GUI wallet. All communications to the device happen via this page on the Oxen wallet app. If you are on any other page on your Ledger device, the GUI wallet will display an error message.

Setting up a hardware wallet file:

When you open the GUI wallet you will see the regular wallet select screen. We will select “Create New Wallet” from the dropdown menu which appears when clicking the + icon in the top right of the window.

The 1.8.0 version of the Oxen GUI wallet now has a checkbox on this page to confirm that the wallet will be a hardware wallet. Fill in the form with the new wallet name, password, check the hardware wallet box and click “Create Wallet”

You will then receive a prompt from the Ledger to “Export View Key” in order to create the wallet file on your desktop. Navigate to the “Always Export'' page by clicking the right button once, then click both buttons to accept.

Background on Exporting the View Key - Optional Technical Details on what just happened

One of the core functions of the wallet is to scan the blockchain which contains encrypted transactions. Each wallet has two keys that are used to:

1) Decrypt the encrypted transactions from the blockchain (View Key)

2) Craft transactions to spend funds in a transaction (Spend Key)

The wallet scans many transactions and processes a large amount of data to find the funds on the blockchain that belong to your wallet. This is an intensive computation that does take time on a regular computer. When using a hardware wallet the desktop does not have access to these keys, so we have two options to process the transaction:

  1. Do the heavy computation on the small ledger wallet chip

  2. Copy the View Key over to the desktop and let the bigger CPU handle this

There are drawbacks to both options. Doing the computation on the ledger is very slow. Exporting the view key is privacy reducing as it means if your desktop wallet is compromised it will be able to view your transactions (However it will not be able to make transactions).

Our recommendation is to export the view key and let the desktop process this calculation. The biggest benefit to having a hardware wallet is that a compromised computer will not be able to spend your funds so the tradeoff for processing the blockchain in a reasonable time is worth it in our opinion.

Continuing with the wallet creation

Once you have exported your view key (or not), the GUI wallet will display the “Wallet Created Page” which shows the address of your newly created hardware wallet. This address should match what is on your ledger device. At this point the wallet has been successfully created. Click “open wallet” and the GUI will navigate to the regular wallet dashboard page where you can spend/stake etc as usual.

To access the hardware from now on, simply navigate through the wallet select page and you will see the new hardware wallet available under a heading called “Hardware wallets”. Clicking into this wallet will require the ledger device to be opened to the Oxen App main screen.

Sending a transaction using the hardware wallet:

Navigate to the Send Transaction page on the wallet GUI

Create a transaction by filling in the address and amount fields of this page and then clicking “Send”

The hardware wallet will then begin processing the transaction. At first you will see the “Processsing TX” screen. This page may take some time as the ledger has to do some heavy calculations.

After this point the Ledger will confirm the transaction fee. Click the right button once to navigate to the “Accept” page and click both buttons to progress.

Next the wallet will confirm the amount and the recipient. Navigate right with the right button and the recipient should match what was entered into the GUI software page. Keep navigating right until the ledger displays the “Accept” page and click both buttons to progress

After this point the GUI wallet will prompt you to confirm send. Click “Send” to broadcast the transaction to the network.

The ledger will do some final processing and you will be rewarded with a green “Transaction Sent” notification in the GUI wallet.

Using Oxen Name System (ONS)

The following steps can be used to register and update ONS mappings in the CLI wallet. Note that you can access a detailed description of each command within the app, using “help <command_name>”.

Purchasing an Oxen Name System record

Purchasing an ONS record in the CLI wallet uses the ons_buy_mapping command. All arguments for the ons_buy_mapping command are optional except for the <name> and <value> that the name maps to.

ons_buy_mapping [index=<N1>[,<N2>,…]] [<priority>] [owner=<value>] [backup_owner=<value>] <name> <value>

Example: Buy an ONS record that maps ‘KeeJef’ to a Session ID: 053 … 254. The wallet buying is the owner of the record:

ons_buy_mapping KeeJef 053b6b764388cd6c4d38ae0b3e7492a8ecf0076e270c013bb5693d973045f45254

Example: Buy an ONS record that maps ‘KeeJef’ to a Session ID: 053 … 254. The wallet buying the mapping is the owner of the record, but specifies a backup owner who will also be authorised to update the record:

ons_buy_mapping backup_owner=T6U7AaNgN2cARpR7CNHGChGMjsmjq5ffh4hLa4DjUUXtKS3bPy2rKTX614RxmpPPX6KjZzqUSSpAEcoghASTXqvP1qMsJzWch KeeJef 053b6b764388cd6c4d38ae0b3e7492a8ecf0076e270c013bb5693d973045f45254

Example: Buy an ONS record that maps ‘KeeJef’ to a Session ID: 053…254. You buy on behalf of another wallet T6UD8...ppir and specify another backup wallet:

ons_buy_mapping owner=T6UD8TM1t7mUYmMCHXQ67Kg5jXBwoVxNqGpXctnsLXtGBEFnhq37RQAA8jgqgD9U6QbeNGqAkkVXucXQ5txE6Mrk2aRwpppir backup_owner=T6U7AaNgN2cARpR7CNHGChGMjsmjq5ffh4hLa4DjUUXtKS3bPy2rKTX614RxmpPPX6KjZzqUSSpAEcoghASTXqvP1qMsJzWch KeeJef 053b6b764388cd6c4d38ae0b3e7492a8ecf0076e270c013bb5693d973045f45254

Updating an Oxen Name System record: Wallet executing update is owner of record

Updating an ONS record in the CLI wallet uses the ons_update_mapping command. All arguments for the ons_update_mapping command are optional except the name of the record to update, and at least one field of the record to update (owner, backup_owner, or value). The [signature] argument is for deferring updates to the record, and is explained in detail in the next section.

ons_update_mapping [owner=<value>] [backup_owner=<value>] [value=<ons_value>] [signature=<hex_signature>] <name>

Example: Updating the owner of the record (essentially transferring ownership — after changing ownership, you will no longer be authorised to update the record):

ons_update_mapping owner=T6UC1nSy2289uX8R2jS3ci7y6eNnVdvhSQRoZtckPzmrQgJ3CyUhUtxgxuedusx9TCKVhZZBCuwFkKoJ3joXStWh1QozRsXXo KeeJef

Note: At this time you can only update Session ID mappings, you cannot yet add a wallet address mapping to your name — this will require additional changes which will be implemented at a later date.

Example: Update all fields of the mapping.

ons_update_mapping owner=T6UD8TM1t7mUYmMCHXQ67Kg5jXBwoVxNqGpXctnsLXtGBEFnhq37RQAA8jgqgD9U6QbeNGqAkkVXucXQ5txE6Mrk2aRwpppir backup_owner=T6TEJJRfvhMZbJpRuchJtmQAjuyCUAyYy2yVcc9ySxTHXWgwQkupjUJUQsyCoyYfRGReAY3pgaYxUHwoKEkWNh5o2qe5Btt3x value=0596d2fdc1407490e1bb7cbca3f3674606d3ef9b1d01cf46199ee5c8932d83f40a KeeJef

Updating an Oxen Name System Record: Wallet executing is not owner of record)

In this scenario, you have an ONS record that you wish to update, and you’re able to coordinate with the wallet owning the record. The wallet that owns the record can execute this command to generate a signature.

ons_make_update_mapping_signature [owner=<value>] [backup_owner=<value>] [value=<ons_value>] <name>

Example: User transfers ownership of a record to another person T6TEJ…t3x with the value 058c…c08. The original owner generates a signature.

ons_make_update_mapping_signature owner=T6TEJJRfvhMZbJpRuchJtmQAjuyCUAyYy2yVcc9ySxTHXWgwQkupjUJUQsyCoyYfRGReAY3pgaYxUHwoKEkWNh5o2qe5Btt3x value=058c72182ecf25172999414f098f91c07bcf12eae7e0c810659f533e81dc865c08 KeeJef

The generated signature:

3ede65e0a78eca500549dde612d02d8aeb3f3dd0f3accd767a2f013cab6e3d486582506fbeb7edb1bda209b333fe7f125fd29f6add6c72b20af320de3537788885fee8b6d76f14b4ad253db2f70a518054bb6f512465e1b6cc154c551d3d59b5bf528eef5a678dbee48e2da74a2803c47295acd6967ea5545f6213456a0f5ead

On the wallet to execute, the arguments must match the arguments specified in the ons_make_update_mapping_signature with the added signature argument:

ons_update_mapping owner=T6TEJJRfvhMZbJpRuchJtmQAjuyCUAyYy2yVcc9ySxTHXWgwQkupjUJUQsyCoyYfRGReAY3pgaYxUHwoKEkWNh5o2qe5Btt3x value=058c72182ecf25172999414f098f91c07bcf12eae7e0c810659f533e81dc865c08 signature=3ede65e0a78eca500549dde612d02d8aeb3f3dd0f3accd767a2f013cab6e3d486582506fbeb7edb1bda209b333fe7f125fd29f6add6c72b20af320de3537788885fee8b6d76f14b4ad253db2f70a518054bb6f512465e1b6cc154c551d3d59b5bf528eef5a678dbee48e2da74a2803c47295acd6967ea5545f6213456a0f5ead KeeJef

Migration Checklist

Everything you need to do to prepare for the migration to the new Session Network.

The Oxen Network has transitioned to the Session Network. More information here.

The migration from the Oxen Network to the new Session Network is complete. This page served as a for operators of active and registered Oxen Service Nodes who were migrating to the Session Network.

Node Preparation and Readiness

  • Confirm hardware and connectivity capacity. Session Nodes have largely similar requirements to Oxen Service Nodes, with some differences:

    • Ubuntu 22.04+ (latest LTS recommended) or Debian 11+ (latest stable recommended).

      • The 11.2 and 11.3 releases will be the last to support Ubuntu 20.04, as their upstream update support is close to ending. Future releases will support Ubuntu 22.04+.

    • 45GB or more of storage

      • Double check the amount of storage space on your server/s. Make sure you have at least 1GB additional space for future growth. Session Nodes have higher storage requirements compared to the previous minimum recommendation of 40GB for Oxen Service Nodes.

    • 4-8GB of RAM (4GB absolute minimum)

    • 100Mb or faster connectivity

    • 1TB traffic per month or more

    • Redundant power with remote cycling ability, as found in most data centres

  • Join relevant comms channels: Ensure you're in the Session Token Community on Discord and following on X (Oxen | Session Token) to receive timely updates

  • Register for the Service Node Bonus Program using your Oxen wallet address and Ethereum wallet address. This will automate the Session Token swapping process following the transition and ensure network continuity. Register here.

  • Make sure you can access the ETH wallet addresses you used to register for the Service Node Bonus and testnet programs. You can check here.

Optional:

  • Set up a testnet node on the Session testnet to explore how the new web-based Staking Portal works, from registering to managing nodes. Open a ticket in Discord to request access to test SESH tokens and test arbETH to stake to your testnet node, or post a message in the Oxen Service Node Operators community on Session.

Completing the Anchor Software Upgrade and Hardfork (22-29/04/2025)

  • Set up an Arbitrum RPC Provider. All Service Nodes must maintain an active connection to an Arbitrum One RPC node to complete the Anchor software upgrade and hardfork. Learn how to fulfill this requirement here.

  • Upgrade your Service Node to Oxen 11.2.0 (Anchor). Follow the upgrade instructions here and complete the upgrade as soon as possible during the one week upgrade period.

  • Monitor your Service Node in case something goes wrong and it gets decommissioned.

    • There is a 5-day grace period after the 29/04/25 hardfork takes effect during which network deregistrations won’t happen—in case anyone needs extra time to address an issue at the fork—but it is strongly recommended you address any problems as quickly as possible.

  • Back up your Service Node keys, including the new `key_bls`. Oxen 11 adds a new BLS key, used for interactions with the smart contract, that needs to be restored along with the existing key_ed25519 in case you need to move or restore your Service Node.

  • Double check you have registered for the Service Node Bonus program with the correct Ethereum address. Snapshots will be taken prior to Landing Hardfork to calculate Session Token distribution.

    • If you want to change your registered Ethereum address, simply register again using your updated Ethereum address.

Optional:

  • Set up an oxend L2 proxy to help reduce costs for running multiple nodes. For operators planning to run multiple nodes on the new Session Network, check out this guide.

Landing Software Upgrade and Hardfork (14/05/2025-TBD)

  • Fund your Ethereum address with some Ethereum on the Arbitrum One network. You will need a small amount to cover transaction fees which are required to claim rewards and register new nodes.

    • Note that SESH will be distributed on the Arbitrum One network, using the Ethereum address provided. To view your SESH at TGE, ensure you have selected the Arbitrum One network in your wallet.

  • Upgrade your Service Node to Oxen 11.3.0 (Landing).

    • Find upgrade instructions via the Oxen blog. There will be a mandatory upgrade period following the release of Landing binaries. The Landing Hardfork and network migration will be executed at the end of the upgrade period. The date for the activation of the Landing Hardfork has not yet been determined, but it will be within a few weeks of the Landing software upgrade release.

    • A grace period of 5 days will be implemented following the Landing Hardfork before nodes start to deregister

  • Query your node’s status using oxend print_sn_status to ensure that it is running correctly.

  • On TGE day, verify the Session Network contract addresses and add Session Token to your wallet, using this guide.

  • Confirm the re-staking of Session Tokens using the Staking Portal.

Guides

Installing on Windows

Installing on macOS

Installing on Linux (CLI)

Installing on Linux (GUI)

Configuring SRV Records

It is possible to configure your SNApp so that others can get service information when looking it up. For example, you may want to tell the user you are hosting an xmpp server at a specific port, or even at a different .loki address, or perhaps even load-balance a service across multiple .loki addresses.

To start open the Lokinet config file, If you have built Lokinet from Deb packages, you can open your lokinet.ini file in the nano text editor with the following command:

sudo nano /etc/loki/lokinet.ini

Otherwise, if you have built Lokinet from source, your lokinet.ini file will be in the folder ~/.lokinet/lokinet.ini, and can be opened in nano with the following command:

sudo nano ~/.lokinet/lokinet.ini

Under the section heading [network] add one or more entries with the following format:

srv=_service._protocol priority weight port [target]

An example:

srv=_xmpp._tcp 10 10 1234 mylokiaddress.loki

This would be an entry for the XMPP protocol, pointing to mylokiaddress.loki at port 1234.

Another example:

srv=_mumble._tcp 10 10 64738

This would be an entry for Mumble, pointing to the SNApp you are configuring at port 64738.

The target in this entry MUST be one of the following:

  • empty, which means "just use the .loki for this SNApp"

  • a single dot (.), which means "this SNApp does NOT have that service available"

  • any valid name in the .loki TLD.

For more information on SRV records and what you can do with them, visit the Wikipedia article.

Service Node setup
Staking to a shared service node as a contributor
Oxen Dashboard
Service node RPC Calls
Active service node list

Oxen Wallet & Guides

The Oxen Network has transitioned to the Session Network. More information here.

Just looking for the latest Oxen Wallet releases? Head to our downloads page.

The Oxen Wallet is your gateway to private decentralised transactions and communications. It allows you to hold and secure your $OXEN, stake into Oxen Service Nodes, and transact with $OXEN.

The Oxen wallet stores a collection of public and private keys which can be used to receive, view, or spend $OXEN.

The wallet uses these private keys through a daemon which synchronises with the Oxen network to scan for incoming transactions and send outgoing transactions.

Graphical User Interface (GUI) Wallet

The Oxen GUI Wallet, also referred to as the Oxen Electron Wallet, is the most user-friendly Oxen wallet. It has a graphical interface (like most PC applications), which is perfect for beginners or those just looking to store and send their Oxen. The GUI Wallet is available for Windows, macOS, and Linux.

To download the latest release of the Oxen GUI Wallet, head to our downloads page.

Guide
Description

How to prepare for setting up the Oxen GUI Wallet on Windows.

How to set up the Oxen GUI Wallet for the first time.

A brief walkthrough on how to use the GUI wallet.

How to export your Oxen wallet's transaction history as a CSV file.

Command Line Interface (CLI) Wallet

The Oxen CLI Wallet is for more advanced users, and offers additional tools to interact with the Oxen blockchain.

To download the latest release of the Oxen CLI Wallet, head to our downloads page.

Guide
Description

How to restore your wallet from spend and view keys.

How to restore your wallet using its 25-word mnemonic seed phrase.

A list and explanation of the different commands available within oxen-wallet-cli.

How to configure oxen-wallet-cli for the first time on macOS.

How to setup the Oxen CLI Wallet on the Ledger Hardware Wallet.

How to export your Oxen wallet's transaction history as a CSV file.

Mobile Wallet

The Oxen mobile wallet allows users to access and manage their Oxen without having access to a PC. The mobile wallet is available for both iOS and Android.

To download the latest release of the Oxen mobile wallet, head to our downloads page.

Guide
Description

How to use the Oxen Mobile wallet for the first time.

How to stake to an Oxen Service Node via the Oxen Mobile Wallet

GUI Wallet Staking

Oxen allows users to stake their oxen by running service nodes which support the Oxen Network. To run a service node an operator is required to stake 15,000 oxen which they can either contribute the full amount or share the burden between multiple contributors to reduce the amount required individually. This guide does not explain how to set up a service node, instead it explains for non-technical users how they can contribute to a service node which is run by a separate operator, allowing them to share in the rewards earned by that service node.

The first step is to find out if there are any service nodes which are "Awaiting Contribution", this occurs when a service node requires additional contributors to make up the 15,000 oxen requirement.

If you navigate to oxen.observer you can see on the front page a section titled "Service Nodes Awaiting Contributions" (Highlighted in Orange Below).

Service Nodes Awaiting Contributions

We are going to stake to the service node highlighted in green (a321e...)

Throughout this guide we will be using the Oxen "testnet" for demonstration purposes. This differs slightly to our mainnet in that you only need to contribute 100 oxen to set up a service node. Aside from this, the process is identical.

About Service Node Staking

This section will explain some of the technical details contained in the above image and is optional, please feel free to skip to the next section which explains the GUI wallet usage if you please. In the above image there are 2 Service nodes that are awaiting contribution, the columns in the table are as follows:

  • Public Key: Service nodes are identified by a unique public key, this will be used later in the staking process and for finding the node at later dates. So you will need to write this down

  • Contributors: A maximum of 4 contributors are allowed to stake to a single service node. For the identified service node there is a single contributor so far (The operator who set up the node)

  • Operator Fee: The operator is allowed to charge a "fee" which is used to cover their server expenses. In this case the operator is looking to charge a 10% fee for running the node. This fee is market driven and we see a range of fees depending on the token price, hosting fees etc. For a ballpark figure the range is usually between 5%-15%. The calculation for how the fee affects contributors is as follows:

    1. Each block that the service node creates will earn all contributors 16.5 oxen

    2. The operator will take their fee of 10% = 1.65 oxen

    3. The remaining balance 16.5 - 1.65 = 14.85 oxen will be distributed pro rata amongst all the contributors.

    4. In this guide we will be contributing 75% of the total staked amount. This means we will be receiving 11.1375 oxen per block the node creates.

    5. The operator who contributed 25% of the total staked amount will also receive 3.7125 oxen for their share. This is in addition to their fee so the operator will receive 5.3625 oxen in total.

  • Contributed: This keeps track of the total oxen staked so far by contributors. When this amount reaches 15,000 oxen the node will be considered fully staked and becomes an active service node that can earn rewards.

  • Open for Contribution: The remaining amount needed before the node is fully staked.

  • Min Contribution: As there is a maximum of 4 contributors to a service node there is a minimum amount to contribute enforced on the stakers. This formula is: Remaining Amount Open for Contribution / Slots left for stakers

    • In this case there is only 1 contribution so far, 3 slots out of 4 remaining. 75 oxen open for contribution divided by 3 = 25 oxen

    • This usually results in a minimum of about 25% of the total requirement (25% of 15,000 = 3,750). However if a person contributes over the minimum amount it means that later contributors have a lower minimum. So infrequently we see a minimum required amount of a few hundred oxen.

  • Expiry Date: Historically service nodes had an expiry date and operators were required to restake/restart the node. This has changed and now it is usual to run nodes infinitely with no expiry date.

Steps in the GUI wallet to stake to another Service Node

Open up the GUI wallet and click on "Service Nodes"

Home page of the GUI wallet

When on the service nodes page, you will see the following:

Service Nodes Page

There is a fair amount going on in this page. The areas identified by the green numbers above are:

  1. Buttons to navigate the service nodes page (You will want to stay on the "Staking" tab for now).

    • My Stakes: Keeps track of nodes you have staked to and will be discussed below

    • Staking: Current page and what we are using to stake to another persons node

    • Registration: Used to set up a service node and is outside of the scope of this guide

  2. Service Node Key: Here we enter in the the public key we identified from the oxen.observer page. We chose the key a321e... and have entered it in.

  3. Amount: This needs to be above the minimum contribution and a maximum that will completely fill the service node. There are buttons on the right that conveniently calculate this for you

  4. A list identical to the oxen.observer page is shown here. Clicking on the stake button on the right of the items will prefill the Service Node Key and Amount will be set to the minimum

We are deciding to fully stake the remaining amount to this service node, so have entered in 75 oxen (75+25 = 100 oxen required for testnet nodes, on mainnet this is 15,000).

When the fields are correct click on "Stake" (Highlighted with a green box above). You will be prompted with a confirmation.

Confirm Stake to proceed

After clicking Stake your wallet will send a transaction to the network. You should see a green notification that the staking transaction was sent successfully. This transaction will lock that amount so that you are unable to spend, but the funds still belong to you and are available to unlock (Which will be shown shortly). Navigating to the main page of the wallet will show the pending stake transaction.

Pending Staking Transaction

The pending transaction once confirmed on the blockchain will transform into a "Stake Transaction"

Stake transactions only lock your oxen while earning rewards, you remain owner and can unstake at any time

Once the transaction has been confirmed you will be able to check the oxen.observer website for the service node and it will confirm that the service node is active. You can find this page by searching the Service Node Public Key in the search box at the top of the page.

Fully Staked Service node

Back in the wallet you will also be able to navigate to the "My Stakes" tab which will show the staked service node. Please note that this page is updated on wallet startup, so you will need to restart the wallet to see the changes after staking.

My Stakes page showing active service nodes

On this page you will see a complete list of staked nodes and how much you have contributed. On the right of each node you will see the option to unlock (Highlighted in red). When you wish to stop staking you will need to begin the unlock process, this takes 15 days on the mainnet so careful planning needs to be done to ensure you unlock early enough if you need access to the funds. Clicking unlock will prompt you with with a confirmation popup.

Unlock warning

Please note that when you contribute to a node other users also have a vested interest in the node. Unlocking will force the other users to also unlock and the operator will need to restart the node staking process which many operators find frustrating. Frequent unlocking is rude. When unlocking the node will continue earning rewards until the point it is unlocked (15 days). Funds will also remain locked during this time. Once the 15 days have elapsed the funds will be unlocked and available to spend and the node will cease to earn rewards.

My Stakes confirming unlock

The My Stakes page will also show the node as unlocking and when visiting the oxen.observer website the service node page will also show the node as unlocking.

Service node scheduled to expire

At this point you have all the skills that are necessary to stake to a service node and to unlock the stake when you wish to exit. Visit https://oxen.observer/ and start exploring the nodes that are awaiting contribution today!

macOS troubleshooting

Common issues with macOS

Troubleshooting

Lokinet is not turning on when i press the start button

Go to System Preferences / Security & Privacy settings and press the lock to make changes

See if there are any pending requests from Lokinet, if so make sure you allow any Lokinet requests.

If there are no requests, try starting the Lokinet app again and see if a request shows up on the Security & Privacy page

Oxen Ledger Wallet setup: CLI Wallet

Background Information

The Ledger hardware wallet stores your private keys on-device so as to isolate your private keys from your PC (which can be at risk of viruses and other attacks). The use of a hardware wallet changes the way you interact with your software slightly.

The oxen-wallet-cli software usually creates 2 files which it uses for processing transactions. The files are named after your wallet name which you specify during startup.

After this initial step you will see the two files:

1) MyWallet – Large File ~15Mb

2) MyWallet.keys – Small File ~ 1.4Kb

The first file contains the saved state of the Oxen wallet. The wallet processes encrypted transactions on the blockchain and then records your unspent transactions here.

The second file contains your encrypted private keys.

When using the Ledger hardware wallet, the oxen-wallet-cli software will still create the first file to save the wallet state but the second file no longer contains your private keys. Instead, they will be saved securely on the hardware device (note: public keys and view keys, if exported, will still be saved here). This changes the process that oxen-wallet-cli will follow in order to sign a transaction.

Without a hardware wallet: oxen-wallet-cli will craft an unsigned transaction, then will reference the MyWallet.keys file to prepare a signed transaction which it will submit to the mempool and broadcast out to the Oxen network.

With a hardware wallet: oxen-wallet-cli will craft an unsigned transaction then submit it to the Ledger hardware wallet for signing. The Ledger hardware wallet will return a signed transaction to oxen-wallet-cli which the software will then submit to the network.

Steps to generate a wallet using the Ledger

Before being able to generate an Oxen wallet on the ledger you will need to have initialized your Ledger and should have your 24 word mnemonic seed previously generated.

You will also need to have the Oxen App installed on your Ledger.

The first step is to connect the Ledger to your PC via the microUSB cable and run the Oxen Ledger App.

Next, ensure that your daemon (oxend) is running with a fully synced blockchain (alternatively, you can connect oxen-wallet-cli to a remote node)

Navigate to the directory where oxen-wallet-cli is located (the following commands assume oxen-wallet-cli is located in the home directory and under a folder called oxen) and call the software using the “generate-from-device” flag

cd ~/oxen

./oxen-wallet-cli --generate-from-device <NEW_WALLET_NAME>

Replace <NEW_WALLET_NAME> with your desired wallet name. For instance if you want to name your wallet MyLedgerWallet you would use the following command:

./oxen-wallet-cli –generate-from-device MyLedgerWallet

The CLI will execute the command, then prompt you for a password to encrypt the wallet state information file mentioned above.

The Ledger device will ask you to confirm whether you want to export the private view key. This view key is used to search and decrypt the transactions in blockchain. Exporting this key to the software will enable oxen-wallet-cli to search the blockchain (rather than the Ledger device itself). The oxen-wallet-cli client will be able to search the blockchain significantly faster if you export the private view key. It should be noted that your funds cannot be compromised by this view key, but if an attacker was to obtain this key they could scan and identify your incoming transactions, which would be detrimental to your privacy.

Navigate using the left and right buttons on the Ledger to either the accept or reject screen and press both buttons simultaneously to confirm your choice. After confirming, the Ledger will then generate your wallet. Note this may take 5-10 minutes and the Ledger will not provide immediate feedback while doing so.

Next you will be prompted to enter the wallet restore height. This lets the wallet know that it can stop searching the blockchain for transactions prior to this block. If this is a new wallet then you can safely use the default [curr] by pressing Enter; if this is a wallet that has previously received transactions, then enter an appropriate restore height, or 0 to restore from the very start of the blockchain (a much slower process).

After the wallet has been generated, oxen-wallet-cli will start refreshing (scanning the blockchain for transactions). Wait until it has fully refreshed.

Congratulations, you can now use your Ledger wallet in conjunction with the Oxen CLI wallet!CLI

Usage of the Oxen CLI wallet with the Ledger wallet

You only use the --generate-from-device on the single occasion when creating the wallet. Going forward, you use the CLI wallet as usual but select the wallet file corresponding to the Ledger wallet.

Steps to use:

  1. Make sure your Ledger is plugged in and the Oxen app is running.

  2. Open oxen-wallet-cli

  3. Enter the wallet name of your Ledger Oxen wallet. This is the same as the name of the wallet state file mentioned above.

  4. Enter the password to open the wallet.

Sending a transaction using the Ledger

  1. Call oxen-wallet-cli from the same directory as the wallet file created above using the generate-from-device-flag

./oxen-wallet-cli

You will then be prompted to specify the wallet file name and enter the password. If you didn’t instruct your Ledger to always provide the view key, then your wallet will prompt you again for permission to provide it (you can change this setting later in the Settings within the Ledger app).

Afterwards, you will be able to enter commands into the wallet. This process is the same for both Ledger wallets and non-Ledger wallets, except that there will be an extra confirmation step on the Ledger before transactions can be submitted to the blockchain.

Enter the following command to transfer to another address:

transfer <DESTINATION_ADDRESS> <AMOUNT>

For example, transferring 50 Oxen to the following testnet address can be done via:

transfer T6SjALssDNvPZnTnV7vr459SX632c4X5qjLKfHfzvS32RPuhH3vnJmP9fyiD6ZiMu4XPk8ofH95mNRDg5bUPWkmq1LGAnyP3B 50

You will then be prompted to enter your password, and the Ledger device will start to process the transaction.

During this process, the Ledger will prompt you to confirm the following details of the transaction:

  • Fee

  • Recipient Address and Amount

After confirming the transaction on the Ledger wallet, the oxen-wallet-cli will also prompt you to confirm the transaction details. Typing ‘Yes’ to confirm will submit the transaction to the blockchain network

Congratulations, you have successfully transferred funds using the private keys saved securely on your Ledger.

Closing the wallet

Care should be taken when closing the wallet. If the Ledger is powered off incorrectly, there is a risk of data corruption. Follow these steps to close the app safely:

1) Shut down oxen-wallet-cli by typing “exit” and hitting Enter. The wallet will take a few moments to update the wallet cache file on disk.

2) Close the Oxen Ledger App

3) Unplug the Ledger device

How to set up an oxend L2 proxy

The Oxen Network has transitioned to the Session Network. More information .

With the 11.1.2 Oxen release, a new capability for oxend was been added to proxy requests to an L2 provider. This feature is aimed in particular at operators who intend to run multiple nodes on the new Session Network following the migration.

This feature works by having only 2-3 of your nodes configured with an L2 provider URL, and having all the others configured to talk to those 2-3 nodes to get Arbitrum updates, without having to use multiple or paid tier accounts for your set of nodes.

This feature works through the existing oxen "quorumnet" port, and so does not need to open additional ports, but it does require some one-time configuration that this guide will walk you through.

Step 1: Choosing your proxies

It is suggested to choose least two nodes, on different servers, ideally in different data centers. The idea here is redundancy: if one of your proxy nodes has a problem, you don't want that one node to take down all your other nodes relying on it. Configuring 2-3 different ones on different servers avoids this risk.

Note that it doesn't matter if the proxies are active service nodes or not: the main point is that they are running in service node mode so that they will have a reachable quorumnet port that the proxy-using nodes use to communicate with the proxy. In other words, even if the proxy gets deregistered or unlocks the network, it will still continue to function as a proxy.

On each of these proxies, you will need to edit the /etc/oxen/oxen.conf configuration file (or, if you are using a dedicated server with a multi-sn setup, the /etc/oxen/node-XX.conf file for whichever service node on the server will be the proxy), and add configuration lines to set up the L2 provider URLs.

There are a couple of config items you'll need to add to the oxen.conf file: one or more l2-provider lines specifying how the proxies themselves fetch Arbitrum data, and an l2-proxy=FILENAME option that specifies a file containing the pubkey of other nodes allowed to use your node as a proxy. You'll edit the file (e.g. with nano /etc/oxen/oxen.conf) and add some lines like this:

It's also suggested to add the following line when setting things up the first time so that you can track the L2 proxy usage in the logs. Once everything is set up and working, you can come back and delete this line to reduce the amount of log verbosity:

Also make a note of the service-node-public-ip=xxx line, and, if present, the quorumnet-port=xxx lines. You'll need these values in Step 4. (If the quorumnet-port= line is missing, that's fine. This just means it is using the default port).

On the second proxy node, you'll need to to reverse the order of the two l2-provider lines. That way the first proxy will use "first.provider.url" as its primary source of info, and the second will use "second.provider.url", and each one will use the other's primary source as a backup source. This is only one possible suggestion: you may want to have more backups, or use completely different providers on each proxy.

Step 2: Whitelisting proxy-using nodes

The second step we need to do is to list the service node pubkeys of all of our nodes that are allowed to use the proxy in the /etc/oxen/proxy.txt. This is relatively straightforward (if a bit tedious, if you have a lot of nodes):

Add the pubkeys of nodes to allow, one per line. You can use comments (starting with #) in here if you like. For example:

This would allow access from abc0..., def6..., and 1f21...

Two important notes here:

  • The proxies will monitor this file for changes, so it is not necessary to restart the oxend proxies if you add or remove node pubkeys to the file.

  • If you have very old nodes (first installed in Oxen 7.x or earlier) then you may have a node with different "primary" and "ed25519" keys: for such a node with dual keys you want to use the "ed25519" pubkey, not the main service node public key. (For nodes installed since then, the primary and ed25519 pubkeys will be the same. If you are unsure, dual-key service nodes will have both a key and a key_ed25519 file; unified key nodes have only the key_ed25519 file. Alternatively, you can look up your service node on https://oxen.observer: if the Session Node Details lists separate Session Node Public Key and Session Node Auxiliary Pubkey values then you want to use the latter (Auxiliary) key.

Step 3: Restart the proxy nodes

Now it's time to restart the proxy oxends with the new proxy-enabling configuration to set themselves up to allow proxy requests:

(If you are using a multi-sn config and have configured node "00" as the proxy, then you would use oxen-node@00 instead of just oxen-node).

Step 4: Configure the proxy-using nodes

All of the nodes using proxies now need to be configured to get their L2 data from the proxies. To do this, you edit the config file of the proxy-using node (e.g. nano /etc/oxen/oxen.conf) and add lines to the config file for each oxend proxy such as:

Also look for any existing l2-provider=... lines and either delete them or comment them out by adding a # at the beginning of the line: oxend does not support using L2 oxend proxies and direct L2 RPC providers at the same time.

You need to replace the IPs, ports and pubkeys listed here with those of your proxy nodes.

The whole line is logged by the proxy during startup, such as:

But you don't have to get it that way: The IP and port you may have written down from Step 1; the pubkey here is the Ed25519 pubkey of the proxy. If you didn't write them down, the IP is simply the public IP of the proxy, and the port is the quorumnet port of the proxy: by default this is 22025 for mainnet nodes and 11025 for stagenet nodes, but if your proxy node config file specifies an alternative you will need to use that port value instead.

The pubkey here is the node's Ed25519 pubkey, which could be different from the primary pubkey if node has dual pubkeys; see the note about this in Step 2.

Once you have added the l2-oxend= line, restart the node with systemctl restart oxen-node (or oxen-node@NN for a multi-sn node).

If you check the logs during startup, you should see some messages such as:

indicating that it has successfully subscribes to L2 updates from the proxy.

All done!

If you want to add new nodes in the future that use your proxies, all you need to do is add their pubkeys into your /etc/oxen/proxy.txt files on the proxies, and add the l2-oxend=... lines into the proxy-using oxend configs and restart the proxy-using oxends. (The proxy nodes themselves do not need to be restarted to pick up the proxy.txt changes).

Advanced Configurations

Non-service node proxy

Proxies do not have to be running in service node mode at all, but you will have to make one additional config change to make the proxy accessible to other nodes if they are not (because non-service-nodes do not listen on the quorumnet port by default). The change is to add a line to the proxy's config of:

This will add a listener on port 12345 (you can change this to whatever you like), accessible on the machine's IP. Note that you don't need to replace 0.0.0.0 here: that special address means to listen on all available IPs on the machine. The proxy-using nodes then specify the IP of the machine (the actual IP, not 0.0.0.0) and port 12345 in their config, along with the node's Ed25519 pubkey.

Nothing stops you from adding this line on a service node to add an additional listener, though there is no noticeable benefit of doing on a service node compared to simply using the required quorumnet port.

Local unix socket on the same machine

If your proxy-using node is on the same machine as the proxy node itself then you can use its local oxend socket rather than the quorumnet port. In this case you would configure the proxy-using nodes using:

For example:

When using such a local unix socket connection, you do not append the proxy's pubkey to the l2-oxend= line, nor is it necessary to list the pubkeys of nodes accessing via the unix socket in the proxy.txt file (it won't hurt, but it isn't needed).

Multi SN

For Multi SN users, please see this additional .

Session Open Group Server Setup

Session open groups servers (SOGS) are group chat servers that can host thousands of chat participants. This guide explains how to set up a Session open group server.

Note: Session open group servers provide transit encryption, but open group messages are not encrypted while stored on the server; closed groups (which can be created within Session itself) are a better solution for high-security communications with groups of 100 or less people.

Open groups are hosted using . Written in Python, PySOGS is the reference implementation of a Session open group server. PySOGS is used to run the official Session open groups, and is the officially supported open group server.

Below you can find a video guide walking you through the process of setting up a Session open group server, as well as a written guide.

Installation

Note: .debs for the Session Open Group server are currently available for Ubuntu 20.04 and newer, and for Debian 10 and newer. For other operating systems, you can

Video Guide

1. Find a suitable server to run SOGS

Typically, the simplest and cheapest way to host a server is by leasing a Virtual Private Server (VPS). There are hundreds of VPS providers to choose from, some popular options are: Vultr, Hetzner, DigitalOcean, Linode, Amazon Lightsail, etc.

You can run a SOGS from home, but consider most consumer internet connections have poor upstream bandwidth, typically don't provide a static IP address, and transient power and network outages are a relatively common. These factors can affect the stability of your SOGS and the ability for users to chat in your group.

Resource requirements are highly dependent on how many users you plan to support in your open groups and how frequent usage is, however, a good starting point would be:

1 Virtual core, 512 MB of RAM, 20GB HDD space

Once you have signed up for a provider you should receive a static IP address, you will need to SSH into your server, you can find instructions on how to do this online.

2. Add Oxen apt repository

Add the Oxen apt repository by running the following commands

3. Install

You have a choice to install either the sogs-standalone package or the sogs-proxied package.

sogs-standalone

This is the simple SOGS package for most setups. It installs a SOGS that listens on a public IP/port for HTTP connections. It does not support HTTPS connections (but since all messages to/from SOGS are separately encrypted, HTTPS is not necessary nor recommended).

sogs-proxied

This package provides a more advanced SOGS configuration where SOGS itself will listen on an internal port and expects to have requests proxied to it from an ngnix or apache2 front-end server that listens on the public IP/port. The package will install basic site configuration files for either nginx or apache2, but extra configuration may be necessary.

This package is required if you want your SOGS to be reached over HTTPS: the HTTPS handling is configured on the front-end server (i.e. in nginx or apache) using a tool such as certbot. (This package does not auto-configure such HTTPS certificates, but there are many online help pages on setting up such HTTPS support for a front-end web server).

If you don't know what any of this means then stick with the sogs-standalone package.

OR

If installing the standalone version you will see this prompt, asking you to enter a URL or IP address, if you have not setup DNS to point towards the IP address of your VPS then you should enter your VPS Public IP address, which can usually be found on your VPS provider's website.

4. Add a room

Once finished with installation, you will want to add a room, to add a room run:

Replace TOKEN with the address to use in the room URL (which must consist of ONLY lowercase letters, numbers, underscores, or dashes), replace NAME with the room name to display in Session and optionally replace DESCRIPTION with a short description of the topic of the room.

As an example, setting up a room for discussion of Australian fisheries

5. Make yourself an administrator

Make yourself a global administrator for all rooms hosted on your SOGS by running the following:

Replace SESSIONID with the Account ID you want to be an administrator

For example:

6. Join your SOGS

Once setup, you should be able to navigate to your VPS's IP address in a web browser, for example

Here you should see a list of your rooms, clicking on a room will display a QR code and the link required to join the room, this link can be copied and pasted into a Session client to join a group.

Upgrading SOGS

SOGS is configured as a Debian package, it will be updated when you update and upgrade other packages on your system, you can trigger this process by running the following commands

Having Issues?

If you're having trouble setting up your SOGS, we recommend opening an issue on the GitHub repository. Contributors to the PySOGS software should be able to assist you in getting everything up and running.

Lokinet

Lokinet is open-source software which uses the Oxen Service Node network to operate a low-latency onion routing protocol. This allows users to browse the web without the destination or origin of data packets being exposed via , as well as accessing internally-hosted services called .

Why Lokinet?

Lokinet is an open-source, fully decentralised overlay network which allows users to browse the internet privately and securely, as well as access services (called SNApps) hosted on Lokinet. Lokinet achieves this through use of a low-latency onion routing protocol (LLARP) designed as a hybrid between I2P and Tor, while providing additional benefits.

When using Lokinet to browse the internet, encrypted data packets are routed through multiple service nodes. No single node ever knows the full path your data takes, so you can browse with true anonymity. Since these nodes are part of the Oxen network, they are also required (and economically incentivised) to provide high-quality service, unlike onion routers like Tor which rely on volunteers.

Lokinet also provides the benefit of being protocol-agnostic — while competing onion routers operate on the transport layer and are only able to carry TCP traffic, Lokinet operates on the network layer and is therefore able to onion-route any IP-based protocol: TCP, UDP, ICMP, etc. In plainer terms, this means Lokinet can relay real-time voice and video calls, video streams, and other high-bandwidth content which simply can't be routed over other onion routers.

Get Lokinet

To download Lokinet, head over to .

Installing on Windows

Initial setup

  1. Download the latest Windows installer or on our

  2. Run the downloaded .exe file

  3. Check both "lokinet" and "gui" in the installer and then click "install"

  4. Run the application

  5. Press the big power button in the Lokinet interface to start or stop Lokinet

All done!

Using Lokinet

Head over to or for an overview of the exciting things you can do with Lokinet up and running!

Uninstalling

To uninstall Lokinet on Windows, open control panel and navigate to "Uninstall a Program", then find Lokinet and click uninstall.

Installing on Linux (GUI)

Initial setup

First add the oxen.io apt repository to your system:

Update your apt package list:

Install the lokinet-gui package:

This will also install and start a background service called lokinet.service that can be controlled with the lokinet-gui application.

Toggling Lokinet off and on

Simply jump into the lokinet-gui client and click the large green power button.

Using Lokinet

Head over to or for an overview of the exciting things you can do with Lokinet up and running!

See the troubleshooting guide if you have issues.

Attachments

Although have the ability to store data on behalf of clients, this responsibility only extends so far. Requiring service nodes to store attachments, which can easily be orders of magnitude larger than messages (and might need to be stored for longer periods of time) would place an undue burden on the service node network.

With this in mind, a logical solution is for Session to interface with an untrusted centralised server that stores data obliviously. As long as the central server cannot know the contents of files, or who is storing and requesting the files, this system does not cause any metadata leakage.

This is achieved by first padding each attachment to fit within a fixed number of constant sizes between 0 and 10 megabytes, then encrypting the attachment with a random symmetric AES key. The sender then uploads the encrypted file using an onion request. In response, the file server provides a link to the piece of content, returned via the onion request path.

Once the sender obtains this link, they then send a message to the recipient via an existing pairwise session. This message contains a link to the content, a hash of the content, and the decryption key. The recipient then uses an onion request to pull the encrypted attachment from the centralised file server and decrypt it locally using the decryption key provided by the sender. The recipient also checks the hash against the attachment, ensuring the file has not been modified in transit.

By default, all Session clients use a Session file server run by the for attachment sending and storage. Since attachments are not considered a core feature of Session, this design is in keeping with Session's design principles. The file server is fully open-source, with setup instructions provided so that users are able to set up their own file server. In an upcoming update users will be able to specify in the Session client which file server they want to use for attachment sending functionality. This is important both for providing users with choice and control, and ensuring the continued usefulness and functionality of Session if the OPTF were no longer able to maintain the default Session file server.

Accessing SNApps

Accessing SNApps is as simple as , opening your browser of choice, and entering the SNApp's .loki address in the address bar!

Test services

Jump into a browser such as Chrome or Firefox and enter the following SNApp address:

This should take you to the Lokinet Wiki, hosted within Lokinet. If this SNApp works, you have full Lokinet access!

Preparing for GUI Wallet Setup
GUI Wallet setup
GUI Wallet Quickstart
Exporting a CSV of your wallet transaction history
Restore CLI Wallet from keys
Restore CLI Wallet from seed
CLI Wallet commands
CLI Setup for macOS
Oxen Ledger Wallet setup: CLI Wallet
Exporting a CSV of your wallet transaction history
Oxen Mobile Wallet Quickstart
Mobile Wallet Staking
l2-provider=https://first.provider.url/abc
l2-provider=https://second.provider.url/xyz
l2-proxy=/etc/oxen/proxy.txt
log-level=l2_proxy=debug,l2_tracker=debug
nano /etc/oxen/proxy.txt
abc00a97b44e7a70202f8cb1f36637b25b9efc36ecab04a5e687290d1345e715 # my favourite
def647edf7706aa9d4e17ae871992dab6cd3654653960a5c1d18585c53d848a9
#9f022f08ecb801299cb43fafba721dfb7d9deb10a7734951f46b9c7c8ec1c274
1f216f4a8d132fcf7d74657dd82167a2037c5bbe40abefdf7a533133f0134601 # vps on SuperAwesomeISP!
systemctl restart oxen-node
l2-oxend=10.7.8.9:22025/1f203f36faecd16d1c1c9514143d4a6715be1b16e160760f57942ab6da3e4ed5
l2-oxend=10.99.88.77:22025/1f509f05c49da0478818ee5772c6e15b457b0923ece38d034d9d4f601a161419
[2025-03-13 16:51:20] [+0.011s] [l2_proxy:info|l2_tracker_proxy.cpp:150] L2 proxy whitelist intialized with 3 pubkeys
[2025-03-13 16:51:20] [+0.011s] [global:info|cryptonote_core.cpp:763] Running as an L2 proxy reachable at:
	10.23.45.67:22501/9f301f21400a69a43286b8f5add7faec26b948de2862a745f71eab822ccd7b1c
[2025-03-13 20:05:54] [+2.072s] [l2_proxy:info|l2_tracker_proxy.cpp:441] Connected to remote oxend L2 proxy 12345678...cdef @ tcp://1.2.3.4:22025
[2025-03-13 20:05:54] [+2.073s] [l2_proxy:info|l2_tracker_proxy.cpp:490] Subscribed to L2 updates from 12345678...cdef @ tcp://1.2.3.4:22025
lmq-curve=tcp://0.0.0.0:12345
l2-oxend=ipc://PATH_TO_OXEND_SOCK
l2-oxend=ipc:///var/lib/oxen/oxend.sock
here
guide
here
GitHub
Exit nodes
Accessing SNApps
sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list
sudo apt update
sudo apt install lokinet-gui
Exit nodes
Accessing SNApps
here
service nodes
Oxen Privacy Tech Foundation
installing Lokinet
http://dw68y1xhptqbhcm5s8aaaip6dbopykagig5q5u1za4c7pzxto77y.loki/wiki/

Express service node setup guide

Thinking of running an Oxen Service Node? Awesome! The guide below will help you configure a device with the necessary Service Node software packages, and stake $OXEN to register the node on the Oxen network.

Note: This guide assumes some familiarity with the command line and running a Linux server. For a more detailed walkthrough, check out our full Service Node set-up guide.

Operating system requirements

One of:

  • Debian 12 ("bookworm")

  • Debian 11 ("bullseye")

  • Ubuntu 22.04 ("jammy")

  • Ubuntu 20.04 ("focal")

Recommended: the latest Debian stable or Ubuntu LTS release (12 and 22.04, respectively, as of the time of writing).

Note: There are strict uptime requirements for Service Nodes (see Service Node deregistration). It is strongly discouraged to run a Service Node on a device that will not be continuously on-line. We recommend running your Service Node on a VPS with a reputable provider.

Firewall Configuration

If you are using a firewall then you should ensure that the following ports (TCP unless otherwise noted) are open and reachable:

  • Port 22020 (storage server connectivity; requires both TCP and UDP)

  • Port 22021 (client to storage server)

  • Port 22022 (blockchain syncing)

  • Port 22025 (Service Node to Service Node)

  • Port 1090 (Lokinet router data; UDP only)

Ultra-express guide

Configuring a new Oxen Service Node is as simple as running the following 4 commands on the Linux server you want to become a node (these commands will work on Debian and Ubuntu; modifications may be necessary for other Linux distributions):

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg

echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list

sudo apt update

sudo apt install oxen-service-node

The services will run via systemd as oxen-node.service, oxen-storage-server.service, and lokinet-router.service.

Once the blockchain has synced to the server (which can take several hours), your Service Node will be ready to be staked. You can use the oxend status command to check the sync progress.

Alternatively, the blockchain can typically be downloaded in a fraction of the time required to sync it via the Service Node network, using the following command:

sudo oxend-download-lmdb https://public.loki.foundation/loki/data.mdb

Express guide

Step 1: Initial repository set-up

To add the Oxen repository, run the following commands.

Note: You only need to follow this step once, to set up the repository. The repository will subsequently be automatically updated whenever you fetch new system updates.

This first command installs the public key used to sign the Oxen Service Node packages:

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg

The second command tells apt where to find the packages. Note: Replace <DISTRO>with the appropriate value to match your operating system.

To find your <DISTRO> run the following command: lsb_release -sc

Alternatively, <DISTRO> can be found in the following list:

  • sid (Debian testing/unstable)

  • bullseye (Debian 11)

  • buster (Debian 10)

  • jammy (Ubuntu 22.04)

  • focal (Ubuntu 20.04)

  • bionic (Ubuntu 18.04)

echo "deb https://deb.oxen.io <DISTRO> main" | sudo tee /etc/apt/sources.list.d/oxen.list

Then resync your package repositories with:

sudo apt update

Step 2: Oxen Service Node configuration

To configure your Service Node, simply install the oxen-service-node package:

sudo apt install oxen-service-node

This will detect your public IP (or allow you to enter it yourself) and automatically update the /etc/oxen/oxen.conf configuration file with the necessary additional settings to run a Service Node.

Congratulations! Your Service Node is now ready to be registered and staked.

Staking your Service Node

Preparing your Service Node for registration

To prepare your Service Node for registration, run the following command:

oxend prepare_registration

This will prompt you for some registration details, then output a registration command. Copy the output from this command in preparation for the next step.

Note: You can safely run this command multiple times if you change your mind about some of the registration questions before you submit the registration.

Staking and registering your Service Node

To stake and register your Service Node, open the Oxen GUI wallet. Make sure your wallet has a balance of at least 15,000 $OXEN to meet the Service Node staking requirement (less if you're configuring a shared Service Node). Navigate to the Service Nodestab > Registration section, and paste the output from the above command, then click Register Service Node.

Done! Your staking transaction will now be submitted to the network. After a short delay, your Service Node will be registered and start contributing to the network (and receiving rewards!).

Checking registration status

You can easily check if your Service Node is registered on the network. First, connect to the VPS where the Service Node is running and run the following command to retrieve your Service Node's public key:

oxend status

This will output a bunch of information about your Service Node, but there's one part we're interested in at this stage: The long string of random letters and numbers after the characters SN: . This string is your Service Node's public key, used to identify your Service Node on the list of registered and operational Service Nodes. Select and copy the public key (do not copy any of the surrounding information).

You can now jump onto oxen.observer, open the full list of active Service Nodes, and use Cmd+F/Ctrl+F to check if your Service Node's public key appears in the list.

Monitoring

We highly recommend setting up monitoring for your Service Node. This is as simple as calling on the services of our Telegram or Discord bot. Contact @OxenSNBot on Telegram or OxenSNBot#5812 on Discord and type /start or $help respectively to get started.

Another helpful tool is Konstantin Ullrich's Oxen Service Node Operator app for Android.

Upgrading

When a new release is available, upgrading is as simple as syncing your repositories:

sudo apt update

Then installing any updates using:

sudo apt upgrade

Note that this will install both updated Oxen packages and any available system updates (this is generally a good thing!)

During the upgrade, the running instance of oxend will be restarted to ensure that the updated oxend is now active.

If, for some reason, you want to install only updated Oxen package upgrades, but not other system packages, then instead of sudo apt upgrade you can use:

sudo apt install oxen-storage-server oxend lokinet-router

Back-ups

To show backup information for your Service Node's secret key (for future recovery/migration):

oxen-sn-keys show /var/lib/oxen/key_ed25519

For service nodes originally installed before 8.x there will be a /var/lib/oxen/key file that must also be backed up (if this file does not exist then you do not need it):

oxen-sn-keys show /var/lib/oxen/key

Restore from SN secret key:

oxen-sn-keys restore /var/lib/oxen/key_ed25519

and, only when restoring from an older installation with an additional .../key file:

oxen-sn-keys restore-legacy /var/lib/oxen/key

Support

Having trouble? Just head to our Support section.

Linux troubleshooting

Setting your DNS

If you're having issues with resolving .loki addresses, you need to edit your resolv.conf files and add your DNS resolver.

Method 1

Install systemd-resolved and let that manage dns.

apt install systemd-resolved

Method 2

Install resolvconf and let that manage dns.

apt install resolvconf

Then restart lokinet.service with systemd.

If resolvconf by itself doesn't work, you'll need to add the Lokinet nameserver manually to resolvconf.

sudo nano /etc/resolvconf/resolv.conf.d/head

Add the following line at the bottom of this file:

nameserver 127.3.2.1

Once that line is added, hold Ctrl and type X, then type Enter to confirm the file changes.

Next we need to update our /etc/resolv.conf file by running the command:

sudo resolvconf -u

Then restart lokinet.service with systemd.

Lokinet becomes "stuck" trying to connect to the network.

As of 0.9.11 there is an issue where sometimes lokinet will get into a bad state and refuse to connect to the network.

This case is not related network censors blocking lokinet, it's a bug. see https://github.com/oxen-io/lokinet/issues/2116

If this happens, makes ure you back up any persisting private keys for .loki and....

  • stop the lokinet service

  • remove /var/lib/lokinet/profiles.dat

  • start the lokinet service

This will remove the client's inferred network state that it slowly generates over time, thus will start retrying nodes it thought were dead before.

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list
sudo apt update
sudo apt install sogs-standalone
sudo apt install sogs-proxied
sogs --add-room TOKEN --name "NAME" --description "DESCRIPTION"
sogs --add-room fish --name "Fishing" --description "Australian fisheries chat"
sogs --rooms + --add-moderators ACCOUNTID --admin --visible
sogs --rooms + --add-moderators 05d871fc80ca007eed9b2f4df72853e2a2d5465a92fcb1889fb5c84aa2833b3b40 --admin --visible
sudo apt update
sudo apt upgrade
PySOGS
build from source
http://116.203.70.33/
Session open group server
U
Lokinet exit nodes
SNApps
the Lokinet website

Oxen Mobile Wallet Quickstart

This guide will walk you through using the Oxen Mobile wallet for the first time. This guide was created on an Android phone but the user experience of the Mobile wallet on iOS is identical.

General Workflow of the Mobile Wallet

We will discuss in detail the process of creating & using the wallet later in this guide. But a quick overview of the GUI wallet is as follows. The main wallet page looks like this:

This page displays:

1) Your wallet's available balance is shown front and centre in large text

2) Buttons in the middle for sending and receiving transactions

3) A list of historical transactions at the bottom

4) At the top we have the name of the wallet "TepidFlavor" which you will create when making the wallet

5) Your wallets synchronization status, in this photo the wallet is "Synchronized" which tells you how much of the blockchain your wallet has analysed

6) On the top right is a profile icon which allows you to configure the wallet, access settings, generate new wallets and stake to Oxen Service Nodes

7) The refresh icon on the right allows you to force refresh the blockchain and reconnect to the remote node if the wallet has synced incorrectly

Installing from the Play Store

The mobile wallet can be downloaded from Google Play Store under Oxen Wallet.

You can find this app via this link:

https://play.google.com/store/apps/details?id=io.oxen.wallet Please be mindful when downloading as the play store has been know to allow copycat apps designed to steal your crypto. The app developer is "Oxen Project" which is the same author as "Session" and "Loki Wallet" (Our old wallet app).

The iOS app can be found via this link: https://apps.apple.com/us/app/oxen-wallet-rangeproof/id1547745078

Your first time opening the mobile wallet, receiving and sending funds.

Congratulations on downloading the mobile wallet. The first time you open the app you will need to create your wallet, do this by clicking "Create new" to continue.

Your wallet is protected by a 4 or 6 digit PIN number. You will be required to enter this pin whenever you open the app and also when sending transactions. Enter a PIN you will remember.

The first thing the app asks is for a name of the new wallet. These are simply used to give a distinguishable name to identify the wallet. Choose something that is memorable because your wallet list can become unwieldy rather quickly when creating multiple wallets. For this reason using names such as: Wallet1, Wallet2, Wallet3 etc are not recommended. The app also provides a random default name (In this case "TepidFlavor").

In addition you will need to choose a language for the seed phrase generated in the next step. The most important part of the wallet creation process is the creation of your “Seed Phrase”. This is shown in the next step. Select your native language here to make the recording of your seed phrase easier.

Below you can see the app has now generated 25 words that are used to generate the private keys of your wallet.

Please note that these 25 seed words are by far the most important part of the wallet creation process. Write these somewhere safe! Don't lose them. If a malicious person gets access to these words they will be able to spend your funds. The Oxen team will NEVER ask you for your seed phrase and a person requesting them from you is likely a scammer trying to steal your funds.

You won’t need to regularly use these seed words. But if/when you need to recover your wallet or move the wallet to a different device then everything can be rebuilt using these 25 words.

After you have saved your seed phrase click "Next" to proceed.

At this point you now are brought to the wallet main page. When you first open the wallet the software needs to process blocks on the blockchain to check for transactions that belong to you. While the wallet is doing this you will see the status bar at the top stating how many blocks are remaining.

When the wallet is synchronising it is normal and expected that your transactions are not processed and therefore won't be shown in the app. Please wait until the wallet shows "SYNCHRONIZED" to continue.

Receiving Oxen

When purchasing Oxen from an exchange or requesting funds from another person you will need to provide your wallet address. Your wallet address is a 95 character text starting with “L”. This is shown by clicking on the "Receive" button:

A QR code is also provided that can be read by other users mobile wallets. If you enter a number into the "Amount" input box this will modify the QR code so the mobile wallet reading the QR code knows how much should be paid in the transaction.

Clicking on the address string ("L8jFZ...VhS9o) will copy the address to your phones clipboard.

When receiving funds from an exchange there will generally be some processing time from the exchange (This time varies depending on the exchange) then a transfer will occur on the blockchain which your wallet will recognise.

The wallet scans the blockchain to find transfers that belong to you, when it finds one it will be added to the transaction list at the bottom. If the wallet is not detecting your transfers the most common reason that the wallet is not yet fully synced.

You can also click into the transaction to show more details.

Please note that your "Available Balance" will not update immediately. This is normal so don't worry, this is because the wallet enforces a 10 block (20 minute) waiting time before allowing you to spend recently received funds. The reasons for this are interesting and complicated but the TLDR is that as a privacy coin the wallet needs to be mindful of statistical attacks, and spend transactions that occur immediately after receiving funds are easily traceable, which reduces the privacy of all the transactions the blockchain (not just your own transactions).

After 10 blocks your available balance will update and you can then spend/stake your coins:

Spending Oxen

From the main app display click "Send" to bring up the following page:

To send funds you will need to obtain the address of the recipient. This will be a 95 character text string provided by the recipient. Usually you will copy and paste this address into the "Oxen address" text box, however you can also click on the QR code button to scan the address through the mobile phones camera.

You will also need to enter in the amount that is to be transferred. This can be specified in the "Oxen" text box which represents number of whole oxen to be transferred.

Alternatively you can enter the amount value in USD, which will automatically calculate the correct amount of oxen to transfer using current market rates. You only need to enter the amount into one field.

When sending transactions on the blockchain there is always a small fee charged to the sender. The wallet shows an estimate on this page (but will confirm the exact amount at a later point).

To proceed with the transaction slide the "Send Oxen" slider to the right. You will be asked to enter your PIN and the final details of the transaction will be displayed.

The final amounts will be shown and the exact fee displayed. To confirm the transaction and send to the network click "OK". After this point the app should display "Transaction Sent"

After this point your transaction will have been sent to the network. After the nodes confirm this transaction into the blockchain your transaction will then appear in the transaction list on the main display screen.

And that's it! You have successfully used the wallet to send and receive a transaction!

Message routing

Message routing

Session follows one of two distinct cases for message routing, depending on the availability of participating clients:

Asynchronous (offline) routing

By default, or when either of the participating clients' statuses is determined as offline (see Synchronous Routing for how client status is determined), Session will use asynchronous routing. In asynchronous routing, the sender determines the recipient's swarm by obtaining the deterministic mapping between the recipient's long-term public key and the currently registered Oxen Service Nodes. This information is initially requested from a random service node by the sender and updated whenever the client gets an error message in the response that indicates a missing swarm.

Once this mapping is determined, the sender creates the message protobuf and packs the protobuf in an envelope with the information to be processed by service nodes: the long-term public key of the recipient, a timestamp, TTL ("time to live") and a nonce which proves the completion of the required proof of work. The sender then sends the envelope using an onion request to one or more random service nodes within the target swarm (in practice, each request is always sent to 3 service nodes to achieve a high degree of redundancy). These service nodes then propagate the message to the remaining nodes in the swarm, and each service node stores the message for the duration of its specified TTL.

Alice uses an onion request to communicate with three random service nodes in Bob’s swarm. Bob then uses an onion request to retrieve said message, by talking to three random service nodes in his swarm.

Synchronous (online) routing

Session clients include their online status in the encrypted protobuf of any asynchronous message they send. Along with their online status, a sending client also lists an Oxen Service Node in their swarm to which they are listening via onion request.

When a Session client receives a message which signals the online status of another client, the receiver sends an onion request to the sender's specified listening node. The recipient also exposes their own listening node to the sender. If this process is successful, both sender and receiver will have knowledge of each others' online status and corresponding listening nodes. Messages may now be sent synchronously through onion requests to the conversing clients' respective listening nodes.

Alice uses an onion request to send a message to Bob’s listening node. Bob receives this message using an onion request, then sends a message to Alice’s listening node.

Messages sent using this synchronous method do not contain proof of work, and listening nodes do not replicate or store messages. To ensure messages are not lost, receiving clients send acknowledgements after receipt of each message. If either device goes offline, this acknowledgement will not be received, and the client which is still online will fall back to using the above asynchronous method of message transmission.

Friend requests

Friend requests are sent the first time a client initiates communication with a new contact. Friend requests contain a short message with a written introduction, the sender's prekey bundle, and meta-information like the sender's display name and public key, which the recipient can use to respond. Friend requests are encrypted for the public key of the recipient using ECDH. When a friend request is received, the client can choose whether to accept it. Upon acceptance, the client can use the prekey bundle to begin a session and start sending messages asynchronously.

Domain Names For Lokinet (ONS)

Lokinet Addresses

By default Lokinet uses 52 character non human readable strings as addresses in the network, for example:

http://dw68y1xhptqbhcm5s8aaaip6dbopykagig5q5u1za4c7pzxto77y.loki

These default addresses can be hard to remember and communicate to users.

ONS Records

ONS (Oxen Name Service) allows SNApp operators to map a human readable name to any default .loki address, as an example

http://probably.loki Which is an ONS record mapping the human readable name probably and the Lokinet address dw68y1xhptqbhcm5s8aaaip6dbopykagig5q5u1za4c7pzxto77y

ONS records are registered as transactions the Oxen blockchain and can be resolved by Lokinet clients, which with the Service Node network. They work in a similar manner to other blockchain naming services like ENS

Registering a .loki ONS Record

Registering a .loki ONS mapping requires the user to create an Oxen wallet and deposit at least 7 Oxen (plus transactions fees), visit the Oxen website to find out where Oxen can be bought

You can register a ONS record by opening the "Oxen Name Service" tab in the Oxen GUI wallet

Once the "Oxen Name Service" tab is open, select the drop down menu underneath "ONS Record Type", and choose how long you would like to register your Lokinet name for.

Add your preferred human readable name, and your existing .loki address, an Oxen address may also be specified if you want to delegate ownership to a wallet separate from the wallet currently in use. Backup owners can be specified and have the same rights as the owner.

Once the relevant fields have been populated press "purchase" and confirm the transaction, transactions can take up to 20 minutes to confirm, once confirmed, you record will be registered and resolution between the human readable name and the default loki address should be complete.

🧑💻 SNApps

Lokinet SNApps allow users to interact with applications or services entirely within Lokinet, similar to Tor's hidden services. SNApps provide an even higher degree of anonymity than can be achieved when accessing externally hosted content through exit nodes. SNApps allow for users to set up and host marketplaces, forums, whistle-blowing websites, social media sites, and other web-based applications on their own servers while maintaining full server- and client-side anonymity. SNApps greatly expand what's possible with Lokinet, and allow users to build meaningful communities entirely within Lokinet itself.

SNApp operators use the traditional server-client model, with the key difference being that Oxen Service Nodes act as intermediaries in a user's connection to the SNApp server. When a SNApp wishes to register on the network, it must update the DHT with its descriptor. This descriptor contains various introducers, which are specific Oxen Service Nodes that users can contact to form a path to the SNApp. When these paths are set up, users can connect to the SNApp without either party knowing where the other is located in the network.

SNApp 📚 Guides

Guide

Description

How to access SNApps.

Hosting your own SNApp (making a web service available over Lokinet).

How to give your SNApp a human readable address

How to add and configure SRV records for your SNApp

Service Node deregistration

Deregistration rules are used to manage the network in a decentralised way by having Oxen Service Nodes police each other's performance, ensuring all operational service nodes are up to date and performing adequately to maintain a healthy network.

Service node states

Each Oxen Service Node can be in one of four states: awaiting, active, decommissioned or deregistered.

Decommission and credits

Active Oxen Service Nodes earn "credits" which are then used up during any periods where the service node goes offline (or otherwise stops meeting network requirements) to stop a deregistration from occuring. A new service node starts out with INITIAL_CREDIT, and then builds up CREDIT_PER_DAY for each day the service node remains active, up to a maximum of DECOMMISSION_MAX_CREDIT.

Example:

If an Oxen Service Node stops sending uptime proofs, a quorum of service nodes will analyse whether the service node has built up enough credits (at least MINIMUM). If so, instead of submitting a deregistration, the quorum instead submits a decommission. This removes the service node from the list of active service nodes, both for rewards and for any active network duties.

If the service node comes back online (i.e. starts sending the required performance proofs again) before its credits run out, a quorum will reinstate the service node using a recommission transaction, which adds the service node back to the bottom of the service node reward list, and resets the node's accumulated credits to 0. If the service node does not come back online within the required number of blocks (i.e. if the node does not come back online and begin performing as required before its credits are depleted) then a quorum will send a permanent deregistration transaction to the network, locking that node's stake for 30 days.

Testing quorums

A testing quorum is a random set of 10 Oxen Service Nodes that are required to test a portion of the network for uptime proofs and service node IP changes. At each block, a new quorum is formed, and this quorum is required to test 50 service nodes or 1% of the network.

If 7 of the 10 service nodes in a quorum (a "supermajority") vote that a service node is malicious or not meeting the minimum requirements then they will create a State_Change transaction to decommission or deregister the service node, or drop it to the bottom of the rewards list.

Quorum Tasks

State change transactions

A state change transaction changes the state of an Oxen Service Node. Typically, state change transactions are only created when a quorum comes to a consensus about a given service node's activities or lack thereof.

The only state change transaction that can be created by anyone is the Register transaction, which changes the state of a service node from awaiting to active.

State

Description

Awaiting

Service node is awaiting the staking requirement being met.

Active

Service node is staked, performing tasks as required, and receiving rewards.

Decommissioned

Service node is not performing tasks as required or is not meeting uptime standards, and has been put into an inactive state where it does not receive rewards.

Deregistered

Service node has been inactive for too long, and has been deregistered.

Variable

Value

INITIAL_CREDIT

60 blocks (~2 hours) of decommission time.

CREDIT_PER_DAY

24 blocks (~0.8 hours) of decommission time.

DECOMMISSION_MAX_CREDIT

1440 blocks (~48 hours) of decommission time.

MINIMUM

60 blocks(~2 hours) of decommission time.

Task

Description

Uptime Proofs

The quorum will check to see if a service node has provided uptime proofs within the last 2 hours. If a Service Node is found to have not provided uptime proofs, but it has at least MINIMUM credits, it will be decommissioned. If it does not have at least MINIMUM credits, it will be directly deregistered.

IP Changes

The quorum checks to see if the SN has advertised more than one IP to the network in the last 24 hours. If a service node's advertised IP has changed, it will be forced to the bottom of the service node reward list.

Checkpointing

The quorum checks that each service node within the quorum has provided a hash of a block for a specific block height (refer to Checkpointing for more information on this procedure). If a service node within the quorum does not provide a hash, but it has at least MINIMUM credits, it will be decommissioned. If it does not have at least MINIMUM credits, it will be directly deregistered.

State_Change_Transaction

Description

Register TX

A transaction (lock transfer) created from the client registering the service node.

State Change: Awaiting -> Active

Note: This is not a quorum transaction.

Decommission TX

The service node is temporarily deregistered; it remains in the service node list, but is removed from the rewards list and from any network duties. State Change: Active -> Decommissioned

Recommission TX

The service node is added back to the service node list and placed at the bottom of the rewards list. Stage Change: Decommissioned -> Active

IP Change TX

The service node is put at the bottom of the rewards list as punishment for changing its IP. Stage Change: N/A (no change)

Deregister TX

The service node is deregistered. State Change: Active -> Deregistered / Decommissioned -> Deregistered

Accessing SNApps
Hosting SNApps
Domain Names for Lokinet (ONS)
Configuring SRV Records

Service node 📞 RPC calls

Introduction

This is a list of JSON2.0 RPC calls to be used with Oxen Service Nodes, along with examples of each.

get_quorum_state

Get the quorum state which is the list of public keys of the nodes who are voting, and the list of public keys of the nodes who are being tested.

Testnet Example

    curl -X POST http://127.0.0.1:38157/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_quorum_state", "params": {"height": 200}}' -H 'Content-Type: application/json'

Result

    {
      "id": "0",
      "jsonrpc": "2.0",
      "result": {
        "nodes_to_test":
           ["578e5ee53150a3276dd3c411cb6313324a63b530cf3651f5c15e3d0ca58ceddd",
            …
            "c917034e9fcd0e9b0d423638664bbfc36eb8a2eeb68a1ff8bed8be5f699bc3c0"],
        "quorum_nodes":
           ["fc86a737756b6ed9f81233d22da3baee32537f3087901c3e94384be85ca1a9ee",
            …
            "ee597c5c7bbf1452e689a785f1133fc1355889b4111955d54cb5ed826cd35a32"],
        "status": "OK",
        "untrusted": false
      }
    }

Nodes have been omitted with “...” for brevity in nodes_to_test and quorum_nodes.

Inputs

  • Int height

The height to query the quorum state for

Outputs

  • String[] nodes_to_test

An array of public keys identifying service nodes which are being tested for the queried height.

  • String[] quorum_state

An array of public keys identifying service nodes which are responsible for voting on the queried height.

get_staking_requirement

Get the required amount of $OXEN to become an Oxen Service Node at the queried height. For stagenet and testnet values, ensure the daemon is started with the --stagenet or --testnet flags respectively.

Testnet Example

    curl -X POST http://127.0.0.1:38157/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_staking_requirement", "params": {“height”: 111111}}' -H 'Content-Type: application/json'

Result

    {
      "id": "0",
      "jsonrpc": "2.0",
      "result": {
        "staking_requirement": 100000000000,
        "status": "OK"
      }
    }

Inputs

  • Int height

The height to query the staking requirement for

Outputs

  • Uint64 staking_requirement

The staking requirement in Oxen atomic units for the queried height

get_service_node_key

Get the service node public key of the queried daemon. The daemon must be started in --service-node mode otherwise this RPC command will fail.

Testnet Example

    curl -X POST http://127.0.0.1:38157/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_service_node_key"}' -H 'Content-Type: application/json'

Result

    {
      "id": "0",
      "jsonrpc": "2.0",
      "result": {
        "service_node_pubkey": "8d56c1fa0304884e612ee2efe763b2c50991a66329418fd084a3f23c75399f34",
        "status": "OK"
      }
    }

Inputs

  • N/A

Outputs

  • String service_node_pubkey

The public key identifying the queried service node

get_service_nodes

Get the metadata currently associated with the queried service node public keys such as, registration height and contributors, etc. If no public key is specified, this returns all the metadata for every service node the queried daemon currently knows about.

Testnet Example

    curl -X POST http://127.0.0.1:38157/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_service_nodes", “params”: {“service_node_pubkeys”: []}}' -H 'Content-Type: application/json'

Result

    {
      "id": "0",
      "jsonrpc": "2.0",
      "result": {
        "service_node_states": [{
          "contributors": [{
            "address":    "T6T6kZfTEf5JGw2SgLrGuxRNFxRTf51fvbbcCYW949RsKjX75JMA1B1d8CT4VbwfGR8uf3f3AJSTaBHGpN3QRG2N2LyiksWVg",
            "amount": 100000000000,
            "reserved": 100000000000
          }],
          "last_reward_block_height": 2968,
          "last_reward_transaction_index": 4294967295,
          "last_uptime_proof": 0,
          "operator_address": "T6T6kZfTEf5JGw2SgLrGuxRNFxRTf51fvbbcCYW949RsKjX75JMA1B1d8CT4VbwfGR8uf3f3AJSTaBHGpN3QRG2N2LyiksWVg",
          "portions_for_operator": 18446744073709551612,
          "registration_height": 1860,
          "service_node_pubkey": "3afa36a4855a429f5eac1b2f8e7e77657a2e862999ab4d59e473826f9b15f2da",
          "staking_requirement": 100000000000,
          "total_contributed": 100000000000,
          "total_reserved": 100000000000
        }],
        "status": "OK"
      }
    }

Inputs

  • String[] service_node_pubkeys

An array of service node public keys in strings that you wish to query metadata for. If an empty array is given, this RPC command returns all service nodes it knows about.

Outputs

  • Entry[] service_node_states

The array of metadata for the queried service node(s)

  • String service_node_pubkey

The queried service node’s identifying public key

  • Uint64 registration_height

The height at which the registration transaction arrived on the blockchain

  • Uint64 last_reward_block_height

The last block height this service node received a reward. Rewards are sent to service nodes whom have been waiting longest since their last reward and are then sent to the back of the queue.

  • Uint64 last_reward_transaction_index

The position in the queue to receive a reward for the service nodes grouped in the last_reward_block_height.

  • Uint64 last_uptime_proof

Unix epoch timestamp of the last time this daemon has received a ping from the queried service node.

  • Contribution[] contributors

An array consisting of all the addresses that have contributed to the queried service node.

  • Uint64 Contribution.amount

The amount of $OXEN in atomic units the contributor has staked.

  • Uint64 Contribution.reserved

The amount of $OXEN in atomic units the contributor has reserved and must fulfill to completely contribute their part to the service node. Amount is equal to reserved once the contributor has fully contributed their part.

  • String Contribution.address

The $OXEN address that funds must come from to fulfill the contribution requirement.

  • Uint64 total_contributed

The total $OXEN currently contributed going towards the staking requirement.

  • Uint64 total_reserved

The total $OXEN that has been reserved by all contributors. The remaining $OXEN is open for other contributors to increase their stake towards the service node.

  • Uint64 portions_for_operator

The operator cut expressed as a value from 0 -> STAKING_PORTIONS (defined in oxen/src/cryptonote_config.h) which is the fee taken from the service node reward and given to the operator address before rewards are distributed to the contributors.

  • Uint64 operator_address

The wallet address which is the primary owner of the service node and also the address which the operator cut is sent to.

Migration FAQ

Get answers to key questions regarding the migration to the new Session Network.

The Oxen Network has transitioned to the Session Network. More information here.

What is the sequence of events for the migration?

The transition from the Oxen Network to the Session Network happens in three phases: Lighthouse, Anchor, and Landing.

During the Lighthouse phase, the contributors and community members have conducted work on the Session Network testnet and may have gained valuable experience by running a testnet node.

During the Anchor phase, final preparations are made for the transition to the Session Network. The Oxen Network undergoes the Anchor Hardfork, with mandatory upgrades to Oxen Core packages for all Service Nodes. Note that the Anchor release will introduce some new requirements for nodes to prepare for the transition.

During the Landing phase, the transition to the Session Network is executed. The Oxen Network undergoes the Landing Hardfork, becoming the Session Network. Session Token (SESH) is generated and distributed to node operators and contributors.

How does the automatic migration of nodes work?

The automatic migration mechanics are designed to ensure the majority of nodes are migrated to the new Session Network. This is ensured in a few different ways. Firstly, staking requirements on the Session Network will be determined in such a way that operators who have been registered for the Service Node Bonus Program since the beginning of the program will have more than enough SESH to have their nodes automatically restaked. Similarly, operators and contributors to multicontributor nodes, where the operator and all contributors were registered for the Service Node Bonus Program from the beginning, will also have more than enough SESH for their node to be auto re-staked on the Session Network.

Secondly, a system of automatic reallocation will ensure that any excess SESH generated goes to nodes that don’t meet the staking requirements of the Session Network after the conversion of staked Oxen and Service Node Bonus points, allowing as many of these nodes as possible to be re-staked. This is particularly important when it comes to ensuring multicontributor nodes are able to be re-staked.

At a high level, the migration process works by assigning each participating wallet a “pool” of SESH tokens, based on the converted value of their staked Oxen and the points earned in the Service Node Bonus Program. The SESH in this pool is then reallocated to nodes the wallet was operating or contributing to, following a predefined algorithm. This algorithm ensures that tokens are distributed in a way that preserves as many existing node relationships as possible.

Let’s walk through a few example scenarios with some invented values to illustrate how the algorithm works.

Scenario 1: An operator is running 3 solo nodes on the Oxen network and is enrolled in the Service Node Bonus Program. On TGE, their combined converted stake and bonus points amount to 1,000 SESH, which becomes the balance of the “pool” of tokens used by the auto migration algorithm.

  • Staking requirement: 200 SESH per Session Node

  • The algorithm will allocate 200 SESH to each of the 3 nodes (starting from the oldest registered to the newest registered), consuming 600 SESH total.

  • The remaining 400 SESH will be left over as excess, which the operator can claim from the Staking Portal and either re-stake or withdraw to their wallet.

The result is that the operator has 3 nodes which are automatically migrated and restaked on the Session network and has an amount of excess SESH which can be claimed from the Staking Portal and used to restake or stored in their wallet.

Scenario 2: Lets consider a more complex scenario, an operator stakes 2 solo nodes and contributes 25% of the stake to a third, multi-contributor node. At TGE, their pool contains 300 SESH (this smaller amount might be due to the fact that one of the solo nodes and the multi-contributor node were operating for only part of the duration of the Bonus Program later and thus earned fewer points).

  • The algorithm allocates 200 SESH to one solo node.

  • The second solo node is disbanded due to insufficient remaining stake, since it requires 200 SESH and only 100 SESH is available in the pool.

  • Of the 100 SESH left, 50 SESH is used to provide 25% of the required stake to the multi-contributor node.

  • The final 50 SESH is marked as excess and can be claimed through the Staking Portal.

The result is that the operator goes from operating 2 nodes down to 1 node, preserves their stake in the multicontributor node and ends up with 50 SESH excess. They could claim this excess SESH from the Staking Portal and use it to stake a new multicontributor node using the same VPS/hardware as they previously used to run their second node or just withdraw the excess to their wallet.

Note: SESH is only allocated to nodes that the wallet previously operated or contributed to, and only up to the same percentage they were originally staking.

Scenario 3: Lastly, let’s consider a scenario focused on contributors. A contributor is staking 25% of the stake for 5 different multicontributor nodes. At TGE, their pool is calculated to be 100 SESH. Assume nodes 1 and 2 were operated by operators who did not register for the Service Node Bonus Program.

  • Nodes 1 and 2 are disbanded because their operators did not register for the SN bonus program

  • The contributor’s pool is reallocated to the remaining nodes (3, 4, and 5), starting from the oldest.

    • 50 SESH is used to cover 25% of the stake for node 3.

    • 50 SESH is used to do the same for node 4.

    • Node 5 is disbanded due to lack of available stake from the contributor.

    • Contributors and operators signed up to the SN bonus program from disbanded nodes (1, 2, and 5) will have their converted stakes and points returned to their respective pools. The algorithm will re-run on these new pool values to try to preserve as many nodes as possible.

The end result here is that this contributor’s SESH tokens are automatically reallocated to 2 multicontributor Session Nodes instead of the previous 5 Oxen Network nodes and that the contributor completes the migration with no excess SESH.

What are the staking requirements for Session Nodes?

The exactly full stake amount for Session Nodes is yet to be determined, but it is estimated to be between 20k-23k SESH tokens.

What if my node deregisters after the Anchor Hardfork?

If your node deregisters after the Anchor Hardfork but before the Landing Hardfork, any points you have earned in the Service Node program will still be honored and the earned amount of SESH will be credited to your Ethereum address, available as a rewards, withdrawable any time after TGE, on the Arbitrum One network, via the Staking Portal. However, your principal stake will not be automatically swapped for Session Tokens. Your Oxen balance in your Oxen wallet will unlock at the Landing hardfork and you will need to manually migrate these coins using the Oxen to SESH bridge at or after TGE.

What if I end up with more SESH than is needed to restake my nodes?

If the amount of SESH you receive from the Service Node Bonus program and the automatic swap is more than is required to re-stake your nodes after migration, any additional leftover tokens will be claimable as staking rewards via the Staking Portal.

What if I don't end up with enough SESH for all my nodes to be restaked after the migration?

If the amount of SESH you receive from the Service Node Bonus program and the automatic swap is not sufficient for your nodes to be restaked following the migration, some of your nodes will be disbanded at TGE and the migrated SESH instead applied to fill the required stake for other nodes you have staked into. Any excess that does not get contributed into a Session Node stake will still be swapped automatically. You can then claim this excess SESH as staking rewards via the Staking Portal.

If I was operating a solo Service Node for the duration of the Service Node Bonus Program and I’m signed up for the program will I receive enough tokens to meet the new Session Node staking requirement?

Yes, the new Session staking requirement will be set such that a solo Service Node operator who has been running a Service Node for the entire Service Node Bonus Program and who is signed up will receive more than enough Session Tokens to be automatically staked to the Session network when the migration occurs. Operators who have started new nodes during the Bonus Program may not have accumulated enough points to cover all the new nodes, in which case some nodes might get disbanded to provide enough SESH to stake the remaining nodes (see the previous question).

If I was operating a multicontributor Service Node for the duration of the Service Node Bonus Program and my contributors and I are signed up will we receive enough tokens to meet the new Session Node staking requirement?

Yes, the new Session staking requirement will be set such that multicontributor Service Nodes which have been running for the entire Service Node Bonus Program and who have all contributors and the operator signed up will receive enough Session Tokens to be automatically re-staked to the Session Network when the migration occurs.

It is possible, however, that either the operator or some contributors may not have enough SESH to cover the stakes of all of their nodes, particularly if new nodes were started or contributed to in the middle or towards the end of the Bonus program. In such a case, SESH is reallocated to be staked in other Session Nodes you are part of, as per the automigration algorithm.

What if I'm operating a multi contributor Service Node and I'm signed up to the Service Node Bonus Program, but some or all of the contributors to my Service Node are not signed up for the program?

There's still time to get all of your contributors to sign up for the Service Node Bonus program here, and you should encourage them to do so. However if any contributor is not signed up for the Service Node Bonus Program when the snapshot is taken (a few days after the Anchor Hardfork) then that contributor will not be automigrated to the Session Network. As an operator signed up to the Service Node Bonus program your staked Oxen and earned points will still be automatically converted and swapped into SESH, however your node will be disbanded. If you were operating or contributing to other nodes, your auto converted SESH from disbanded nodes will be used as per the auto migration algorithm to fill the stakes of any of the nodes you were involved in. You can claim any excess SESH tokens on TGE from the Staking Portal, by connecting the Ethereum wallet you used to register for the Service Node Bonus Program.

What if I’m operating a multicontributor Service Node and I'm signed up to the Service Node Bonus Program but either I or some of the contributors to my Service Node do not meet the minimum staking requirement for the Session network

Service nodes where any contributor (including the operator) does not have sufficient SESH after the automatic swap, contributions as part of the conversion process will be disbanded at the hardfork, and all the contributions in the node will be credited to the contributors.

In the case where a contributor is part of multiple nodes, the SESH that you are credited is automatically used to fulfill the staking requirements of the other nodes they were staked to.

For example, a solo node operator staking since the start of the Service Node Bonus program would have earned enough Oxen to stake to a multicontributor node near the end of the program. However they likely wouldn’t have earned enough points from this multicontributor node alone to fill up a full slot in the multicontributor node during the migration. The catch here is that because of the design of the migration algorithm, excess SESH generated from the Solo node can be used to top up the SESH required to achieve staking of a full slot in the multi contributor node, ensuring both nodes are automigrated. Any leftover contributions that do not get staked will be credited as unstaked rewards that can be withdrawn to your registered Ethereum wallet via the Staking Portal once the network has successfully transitioned after TGE

What if I'm a contributor to a Service Node and the Service Node operator has not signed up to the Service Node Bonus program?

There's still time to get your node operator to sign up for the Service Node Bonus program here, and you should encourage them to do so. However if they are not registered for the Service Node Bonus Program when the snapshot is taken (just before the Landing Hardfork upgrade release) then your staked Oxen and accumulated points will still be automatically swapped into SESH tokens and run through the migration algorithm. You will be able to claim any unstaked excess SESH amount via the Staking Portal with the Ethereum wallet you signed up with for the Service Node Bonus Program on the Arbitrum One network.

Can I unstake and opt out of the hardfork, even if I am registered for the Service Node Bonus program?

If you choose to submit an unlock and opt out of this hardfork, any points you have earned in the Service Node Bonus program will still be honored, and Session Tokens will be available for withdrawal to your Ethereum address at TGE via the Staking Portal, on the Arbitrum One network. However, any unstaked OXEN balances will not be automatically swapped for Session Tokens, and you will need to manually swap these coins using the Oxen to SESH bridge at or after TGE.

What happens if I don’t register for the Service Node Bonus program?

If you are not registered for the Service Node Bonus program, you will not receive any bonus Session Tokens and any staked Oxen coins will not be automatically swapped and will become unlocked, unstaked coins in your Oxen wallet at TGE. You will need to manually swap these coins using the bridge, as above.

Installing on Linux (CLI)

Initial setup

1. Computer Preparation

Begin by updating your package lists. The below command downloads package lists from your repositories and "updates" them to get information on the newest versions of packages and their dependencies. It will do this for all repositories and PPAs.

Run the following command:

sudo apt-get update

You'll notice a bunch of package lists were downloaded. Once this is complete, run the below command to fetch new versions of any packages we currently have installed on the system:

sudo apt-get upgrade

You'll be prompted to authorise the use of disk space. Type y and press Enter to authorise.

If you do not have curl installed on your computer, now is also a good time to install it, as we will use it later:

sudo apt install curl

2. Installation

You only need to do this step the first time you want to set up the Lokinet repository. After you've done it once, the repository will automatically update whenever you fetch new system updates.

This first command installs the public key used to sign official Lokinet binaries.

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg

The next command tells apt where to find the packages:

echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list

Note: if you're running Linux Mint and get an error with this command, check out Troubleshooting.

Then resync your package repositories with:

sudo apt update

Now install Lokinet:

sudo apt install lokinet

Congratulations, Lokinet is now installed and running in the background.

Starting and stopping Lokinet

By default, lokinet will be running in the background on boot.

You can disable lokinet from starting on boot with:

sudo systemctl disable --now lokinet

You can re-enable lokinet to run on boot with:

sudo systemctl enable --now lokinet

You can stop the lokinet service with:

sudo systemctl stop lokinet

You can use stop, start or restart to start and stop lokinet using the command above replacing stop with start or restart

Updating Lokinet

To update Lokinet when installed with apt run the following command:

sudo apt update && sudo apt upgrade lokinet

Using Lokinet

Head over to Exit nodes or Accessing SNApps for an overview of the exciting things you can do with Lokinet up and running!

CLI installation troubleshooting

If lokinet gets "stuck" trying to connect to the network, back up any persisting private keys for .loki and....

  • stop the lokinet service

  • remove /var/lib/lokinet/profiles.dat

  • start the lokinet service

this will remove the client's inferred network state that it slowly generates over time, thus will start retrying nodes it thought were dead before.

Linux Mint does not work with (lsb-release)

It has been reported that Linux Mint users may need to use the following command instead of the second command in 2. Installation:

echo "deb https://deb.oxen.io jammy main" | sudo tee /etc/apt/sources.list.d/oxen.list
GUI Wallet Setup

GUI Wallet Quickstart

This guide will walk you through using the GUI wallet for the first time. It assumes you already have the GUI wallet installed and running. If this is not the case you can download the wallet from our downloads page. Some overzealous antivirus software may take issue with the Oxen wallet, if this happens we walk you what to do about that HERE.

General Workflow of the GUI Wallet

We will discuss in detail the process of creating & using the wallet later in this guide. But a quick overview of the GUI wallet is as follows. The wallet begins by displaying a list of your wallets and looks like this:

Wallet Selection Page

In this above image you can see 5 different wallets. Each wallet has a different address and holds a different amount of Oxen. Clicking on a wallet will ask you for a password which is used to decrypt the wallet file and brings you to the following page:

Wallet Main Page

This is the main wallet page which contains all of the basic information about the wallet.

1. The “Total Balance” of the wallet is shown just above the centre of the screen (16,475.448 Oxen). It also lists the 'unlocked' balance directly below. If you have staked to an Oxen service node, the amount of Oxen you have staked will be unavailable to send.

2. A list of sent and received transactions can be seen at the bottom. (Showing where you have previously received funds, and also previously spent funds)

3. The long alphanumeric text in the center is the wallet address (T6SYH3Lh…). In this image the wallet operates on the Oxen testnet (A network built to practice without risking real funds), this can be identified by the address beginning with the letter “T” and the address being 98 characters long. When interacting with the Oxen mainnet (The real network) the wallet address will begin with the letter “L” and will be 95 characters long.

4. The wallet name at the top left. This name is decided by you and matches with the names on the first page. This name is simply to help you identify which wallet you are using, if you have multiple wallets.

5. Action Buttons for wallet usage. These include sending funds, receiving funds, interacting with service nodes and purchasing and managing Oxen Name Service records (ONS Records). We will go into sending and receiving in detail later.

Your first time opening the GUI wallet software, selecting the network and creating a new wallet.

When you first open up the GUI wallet you will need to create a wallet and setup some default settings. You will first be greeted with a language selection page. We will be walking through the English version here. Click your native language to continue to the next page:

Language Selection Screen

The next page of the wallet is where you configure the network settings.

Network Configuration Screen

Basic Network Settings

To get started quickly and easily the following settings are recommended:

  • Type: Remote Daemon Only

  • Remote Node Host: public.loki.foundation

  • Remote Node Port: 22023

Additional Network Configuration Details The three radio buttons at the top of this page determine how the wallet connects to your daemon (which manages the blockchain). Remote means there is an external daemon that the wallet communicates with. Local Daemon means the wallet will spin up a subprocess for the daemon and interact with it directly.

Running a local daemon will require syncing the Oxen blockchain before you are able to interact with the wallet, which will take time. So for an immediate start, connecting to a remote daemon that the Oxen Foundation is running is the easiest option.

The downside to using a third party for your remote daemon is that it is privacy reducing (That third party will see your requests to the network). So for ultimate security one should run their own daemon, but as that is a more advanced topic we won't get into it here. If you wish to follow this route it is recommended you run the oxend daemon software separately, wait for the blockchain to sync, and from the wallet select “Remote Daemon Only” and point it at your own local daemon (Remote Node Host: Localhost). This means you do not need to keep the wallet open while syncing and have greater control over the daemon rather than letting the wallet manage the daemon. If this sounds like mumbo jumbo to you, don't stress, just choose the basic network settings above and continue.

The next page will present 3 options to decide how to create/load/import/open a wallet into the application. If you have not used the GUI wallet before will want to choose “Create new wallet”

Creating a new wallet

New Wallet Page

When creating a new wallet you will need to choose the following:

  1. Wallet Name: represents the name of the datafile and is used throughout the application to identify the wallet. Choose something that is memorable because your wallet list can become unwieldy rather quickly when creating multiple wallets. For this reason using names such as: Wallet1, Wallet2, Wallet3 etc are not recommended.

  2. Seed language: The most important part of the wallet creation process is the creation of your “Seed Phrase”. This is shown in the next step. Select your native language here to make the recording of your seed phrase easier.

  3. Password: Your wallet file will be encrypted by this password to prevent malicious persons from accessing your wallet if they get control of the wallet file. Please note that you can still access your wallet if you forget the password but still have the seed phrase. A password is not necessary (resulting in an unencrypted wallet save file) but it is highly recommended.

Create New Wallet Page

After filling in the appropriate fields click “Create Wallet”

Seed Wallet Confirmation Page

On this page you are shown the details of your newly created wallet. At the top you can see your new wallet address which is used by other persons to send funds to you. Beneath this you can see your seed words.

Important!

Please note that these 25 seed words are by far the most important part of the wallet creation process. Write these somewhere safe! Don't lose them. If a malicious person gets access to these words they will be able to spend your funds. The Oxen team will NEVER ask you for your seed phrase and a person requesting them from you is likely a scammer trying to steal your funds.

You won’t need to regularly use these seed words. But if/when you need to recover your wallet or move the wallet to a different computer then everything can be rebuilt using these 25 words.

Click “OPEN WALLET” and you will be brought to the main wallet page discussed earlier.

Receiving funds for the first time

When purchasing oxen from an exchange or requesting funds from another person you will need to provide your wallet address. From the main page your wallet address is the 95 character text starting with “L”. This is shown in the red box below:

If you click the “Copy Address” button to the right of the address (Shown in the green box) your wallet address will be copied to the clipboard and you can simply paste it using Ctrl-V.

When receiving funds from an exchange there will generally be some processing time from the exchange (This time varies depending on the exchange) then a transfer will occur on the blockchain which your wallet will recognise.

The wallet scans the blockchain to find transfers that belong to you, when it finds one it will be added to the transaction list at the bottom and your balance will be updated. If the wallet is not detecting your transfers the most common reason is due to the wallet not being fully synced yet.

Down the bottom of the application there is a status bar. This should be green and say Status: READY

Wallet is ready

Remote: 946353 refers to the height of the blockchain on the remote daemon. Wallet: 946353 / 946353 (100.0%) refers to how much of the blockchain the wallet has processed when looking for your transactions. The wallet has to scan all transactions on the blockchain when searching for your transactions, so this process does take some time. If the wallet is still syncing the status bar will look like this:

Wallet is still syncing

While Status: SYNCING is in the status bar it is normal and expected that your transactions are not processed and therefore won't be shown in the application. Please wait until the wallet show Status: READY

Both the Remote Daemon and the Wallet need to be fully synced for your wallet to work correctly.

Sending Funds

From the main page in the application click on the “Send” button

Send Button on the Main Wallet Page

From here you will be greeted with the page to enter in your recipients address and the amount you wish to transfer. Key things to not note this page:

  1. Amount: This is the amount of Oxen you wish to transfer, 1 means 1 full oxen transferred

  2. Priority: Blink is our instant transfer technology which is selected by default. Selecting slow will mean the recipient has to wait until the transfer has been confirmed in a block before seeing the payment. Choosing Blink is recommended wherever possible.

  3. Address: The address of the recipient.

  4. Notes: This is an optional field for noting details about the transaction such as: why are you sending it, who are you sending it to etc. This is completely optional.

Send Funds Page

Click “Send” and you will be prompted for the wallet password and then a screen will confirm the transaction details.

Send transaction confirmation

Click Send to broadcast the transaction to the network. Shortly afterwards the bottom of the application will display a green banner saying Transaction Successfully Sent

After this point the transaction will show up in your transaction list and your balance will be reduced by the sent amount.

Installing on macOS

A Guide on how to install Lokinet with the updated GUI

Thanks for downloading Lokinet on MacOS. This guide will help you install Lokinet.

Latest releases can be found and downloaded here https://github.com/oxen-io/lokinet/releases/latest

macOS Monterey

macOS Ventura guide here

Open the .dmg file in your downloads directory (or wherever you downloaded Lokinet).

Select agree to agree to the GNU GPLv3 license agreement.

Drag and drop the Lokinet application into the applications folder.

Start the Lokinet application from the “Applications” folder and click open when prompted.

Once Lokinet is open, press the power button to turn Lokinet on. You will be prompted with a ‘System Extension Blocked’ popup, click ‘Open Security Preferences’.

If you do not see this popup, open System Preferences and navigate to Security & Privacy instead.

With the Security & Privacy settings window open, click the padlock in the bottom left corner.

After the padlock unlocks, click ‘Allow’, allowing Lokinet to load a system extension which is necessary for VPN functionality.

Enter your password and press unlock when prompted.

Once System Preference changes are allowed, a system prompt will appear. Click “Allow” to allow Lokinet to add a VPN Configuration.

Congratulations! You’re all done. Lokinet should now automatically start, if not try pressing the on button again and Lokinet should startup.

You can view, check, or alter the VPN Configuration created by Lokinet by opening System Preferences and navigating to Network.

macOS Ventura

Select agree to agree to the GNU GPLv3 license agreement.

Drag and drop the Lokinet application into the applications folder.

Start the Lokinet application from the “Applications” folder and click open when prompted.

Once Lokinet is open, press the power button to turn Lokinet on. You will be prompted with a ‘System Extension Blocked’ popup, click ‘Open Security Preferences’.

If you do not see this popup, open System Preferences and navigate to Privacy & Security menu instead.

click ‘Allow’, allowing Lokinet to load a system extension which is necessary for VPN functionality.

Enter your password and press unlock when prompted.

Once System Preference changes are allowed, a system prompt will appear. Click “Allow” to allow Lokinet to add a VPN Configuration.

Congratulations! You’re all done. Lokinet should now automatically start, if not try pressing the on button again and Lokinet should startup.

You can view, check, or alter the VPN Configuration created by Lokinet by opening System Preferences and navigating to Network.

CLI Wallet setup (macOS)

This guide covers installing and configuring the Oxen CLI (Command Line Interface) Wallet on macOS.

If you are new to console or terminal commands and/or would prefer a wallet with buttons and Oxen branding, we suggest you download the .

Before following the guide below, you'll need to download the CLI Wallet for macOS. This guide assumes you are running the latest version of macOS and have Xcode installed.

Step 1: Opening oxen-wallet-cli and oxend.

To use the oxen-wallet-cli we must first have the daemon, oxend, up and running. The oxend is your node which the oxen-wallet-cli broadcasts through. Without the node running the oxen-wallet-cli will not be able to operate.

Open up the oxend file in the folder you extracted the release from. In most cases you will have the following security dialog box pop up.

If the dialog box opens up you will need to allow the oxend to open by moving your cursor to the top-left of your screen, clicking the apple logo, and then clicking on system preferences.

Once in System Preferences, click on the Security & Privacy button, check in this new screen that the oxend file was blocked, if it was you should be confident to click “Open Anyway”.

Keep clicking open and allow to give the software permission to run.

Once the software has permission a terminal window should pop up and say the following text:

Let the daemon run until the node is completely synced, you will know the node is synced once the terminal outputs the following text:

Now the daemon is synced we can run the oxen-wallet-cli file.

Step 2: Setting up your oxen-wallet-cli account.

If this is your first time opening the oxen-wallet-cli it will request for you to specify a wallet name. For the purposes of this user guide we will use the example name MyWallet

Because this is the first time we have used the name MyWallet the following text will appear in our terminal. Type in Y or Yes to confirm your wallet name.

The oxen-wallet-cli has now generated us a wallet called MyWallet and is now prompting us for a password for our generated wallet.

Please note:

  • When typing the password, the characters will not appear. It will seem as if you are typing and no text is appearing however the terminal is logging every character your clicking including if it is capitalised or lowercase.

  • Write down your wallet name and password on a piece of paper as this information will be required every time we want to enter our wallet.

  • Use a password with uppercase letters, lowercase letters, numbers, symbols and make the password at least 9 characters long.

Now once we have chosen our password for the wallet we must choose our language. For the purposes of this user guide I suggest you use English by typing 1 and clicking enter.

The oxen-wallet-cli will generate and spit out several lines of text. Some of the information that was outputted will only ever show once, therefore it is very important to do this next section properly otherwise we may lose access to our account, thus losing access to our funds.

Let’s take a close look at each section of the newly generated wallet:

The text after Generated new wallet shows your public address. This address can be shared and will be used to receive $OXEN to your wallet. All Oxen public addresses start with an L.... and are followed with a string of characters. The public address shown will be your primary address however multiple public addresses can be generated from this primary address.

You do not need to write down the public address, the command address will re-display it whenever required.

The View key address is not to be shared unless you want to show the transactions received to the public address connected to this wallet. You do not need to write down the view key as it can be re-displayed with the command viewkey.

The next few lines of text show how to navigate the oxen-wallet-client.

The next section with the random 25 words is your mnemonic seed. The seed is used to easily back-up and restore your wallet without needing any other information. At this stage, grab a pen and paper and write down your 25 words in order (having these words out of order will not restore your wallet) and store the piece of paper in a safe and secure place. If your words are stored in a text file on your computer or stored online, you increase your risk of someone else getting control of your account.

The last of the outputs are the account balance, because your wallet does not have any $OXEN in it currently the balance is showing 0.

Once we receive a transaction of $OXEN into our wallet the balance will appear as soon as the transaction is confirmed in one block (usually less than 2 minutes). Once the transaction has been confirmed over 10 blocks the balance will show in unlocked balance.

The unlocked balance is the $OXEN available to be spent/sent to other addresses.

**********************************************************************

The daemon will start synchronizing with the network. This may take a long time to complete.

You can set the level of process detailization through "set_log <level|categories>" command,

where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING).

Use the "help" command to see the list of available commands.

Use "help <command>" to see a command's documentation.

**********************************************************************
**********************************************************************

You are now synchronized with the network. You may now start oxen-wallet-cli.

Use the "help" command to see the list of available commands.

**********************************************************************
Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created.

Wallet file name (or Ctrl-C to quit): MyWallet
No wallet found with that name. Confirm creation of new wallet named: MyWallet

(Y/Yes/N/No): Yes
Generating new wallet...

Enter a new password for the wallet:

Confirm password:
List of available languages for your wallet's seed:

If your display freezes, exit blind with ^C, then run again with --use-english-language-names

0 : Deutsch

1 : English

2 : Español

3 : Français

4 : Italiano

5 : Nederlands

6 : Português

7 : русский язык

8 : 日本語

9 : 简体中文 (中国)

10 : Esperanto

11 : Lojban

Enter the number corresponding to the language of your choice: 1
Generated new wallet: LAXk6eS3Ng98QxDTdC47eNdfCXttJycKraXxfsw9cMVngGUqP3kiSE6cwXoApU6gjzSXVX1ASAPAi1MSXA935XUs1MWEcv9
View key: 97d3c27e20818e5e23a6548458b50d4f128a2709c55eb7f9518d0e957a5d2e0d
This user guide will look into more detail the commands that can be used within the loki-wallet-client further in the guide.

Your wallet has been generated!

To start synchronizing with the daemon, use the "refresh" command.

Use the "help" command to see the list of available commands.

Use "help <command>" to see a command's documentation.

Always use the "exit" command when closing loki-wallet-cli to save

your current session's state. Otherwise, you might need to synchronize

your wallet again (your wallet keys are NOT at risk in any case).
NOTE: the following 25 words can be used to recover access to your wallet. Write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.

ponies innocent oyster whale autumn knapsack jostle elapse

inroads joining doorway ticket drying obnoxious algebra tutor

biplane sack alpine zinger huge duets refer rigid inroads
Starting refresh...

Refresh done, blocks received: 0

Untagged accounts:

Account Balance Unlocked balance Label

* 0 LAXk6e 0.000000000 0.000000000 Primary account

----------------------------------------------------------------------------------

Total 0.000000000 0.000000000

Currently selected account: [0] Primary account

Tag: (No tag assigned)

Balance: 0.000000000, unlocked balance: 0.000000000

Background refresh thread started”
GUI Wallet

Network infrastructure

Foundations

At its core, Session is built on the Oxen Service Node network, so it's important to understand how the Oxen network functions to support Session's mission of enabling decentralised anonymous communications.

The Oxen network

Many projects have attempted to establish decentralised permission-less networks. These projects have often found themselves struggling with a ‘tragedy of the commons’ of sorts, wherein public servers, required for the operation of the network, are under-resourced and overused. This inadvertently causes the network to provide poor service to users, which discourages further use or expansion of the network.

Conversely, those projects which are able to create large, public permissionless networks find themselves constantly facing questions about the parties that contribute to running that infrastructure. This can be especially damaging when the operation of that infrastructure can adversely affect the privacy, security, or user experience of an application. For example, the Tor network faces constant questions about evidence of Sybil attacks from unknown parties attempting to run large sections of of the public routing network, which could be used to de-anonymise users .

Session seeks to avoid these issues through using a different type of public access network: a staked routing and storage network called the Oxen Service Node network. This network is based on the Oxen blockchain, which itself is based on the CryptoNote protocol. Through the integration of a blockchain network, Session creates a financial precondition for anyone wishing to host a server on the network (and thus participate in Session’s message storage and routing architecture).

Authorisation for a server to operate on the network is attained through the server operator conducting a special staking transaction, which requires that an operator provably lock an amount of Oxen cryptocurrency assigned to their node (previously, this staking requirement was algorithmically adjusted over time; it is now fixed at 15,000 $OXEN).

This staking system provides a defense against Sybil attacks by limiting attackers based on the amount of financial resources they have available. The staking system also achieves two other goals which further reduce the likelihood of a Sybil attack.

Firstly, the need for attackers to buy or control $OXEN to run service nodes creates a feedback loop of increasing price for anyone attempting to run large portions of the network. That is, as the attacker buys or acquires more $OXEN and locks it, removing it from the circulating supply, the supply of Oxen is decreased and the demand from the attacker must be sustained. This causes the price of any remaining Oxen to increase, furthering the feedback loop of increasing prices. Secondly, the staking system binds an attacker to their stake, meaning if they are found to be performing active attacks, the underlying value of their stake can sharply decline as users lose trust in the network, or could be destroyed or locked by the network, in any case increasing the attackers sunken costs.

The other main advantage of a staked blockchain network is that service nodes earn rewards for the work they do. Service nodes are rewarded with a portion of the block reward minted upon the creation of each new block. This system makes Session distinct from altruistic networks like Tor and I2P by providing an incentive linked directly with the performance of a service node. Honest node behaviour and the provision of a minimum standard of operation is ensured through a consensus-based testing suite. Misbehaving nodes face the threat of having their staked capital locked, while the previously-mentioned cryptocurrency rewards function as the positive incentive for nodes to behave honestly and provide at least a minimum standard of service to the network.

Onion requests

The other foundational component of Session is an onion routing protocol, referred to as onion requests, which enables Session clients to obfuscate their IP addresses by creating a 3-hop randomised path through the Oxen Service Node network. Onion requests use a straightforward onion routing protocol which successively encrypts each request for each of the three hops, ensuring the first service node only knows the IP address of the client and the IP address of the middle service node, the middle service node only knows the IP address of the first and last service nodes, and the last service node only knows the IP address of the middle service node and the final destination IP address for the request.

Each Session client establishes a path on start-up, and once established, all requests for messages, attachments and meta information are sent through this path. Session clients establish a path by selecting three random nodes from their service node list (see bootstrapping), which contains each service node’s IP address, storage server port, and X25519 key. Clients use this information to create an onion, with each layer being encrypted with the X25519 key of its respective service node. This onion is sent to the first service node’s storage server; this service node then decrypts its layer of the onion. When a service node unwraps a layer, the destination key for the next node is revealed. The first service node decrypts its layer and initialises a ZMQ connection with the specified downstream node. When the onion reaches the final node in the path, that node sends a path build success message backwards through the path, which indicates a successful path built upon its receipt by the client.

Upon receiving the path build success message, the client will encrypt their messages with the X25519 keys of the final destination, be that a service node, file server, open group server, or client. The client also includes an ephemeral X25519 key in their request. When the destination server or client receives the request, they decrypt it and generate a response. This response is then sent back down the previously-established path, encrypted for the initial sender’s (the client’s) ephemeral key, so that the client can decrypt the response upon receiving it.

Building on foundations

Onion requests provide a straightforward anonymous networking layer, and the Oxen Service Node network provides an incentivised, self-regulating network of remote servers which provide bandwidth and storage space. A number of services have been built on this foundation in order to give Session features commonly expected of modern messaging applications.

Storage

Message storage is an essential feature for any chat application aiming to provide a good user experience. When a user sends a message, they expect the recipient to receive that message even if the recipient's device goes offline or is turned off after the message has been sent. Users also expect the user on the other end to receive the message when their device wakes up or reconnects from an offline state. Apps that run on decentralised networks typically cannot provide this experience, because of the lack of incentive structures and, consequently, the ephemeral nature of clients and servers on such a network. Session is able to provide message storage through the incentivised service node network and its usage of swarms.

Swarms

Although the Oxen blockchain incentivises correct service node behaviour through rewards and punishments, these incentive models cannot prevent nodes going offline unexpectedly due to operator choice, software bugs, or data centre outages. Therefore, for redundancy, a secondary logical data storage layer must be built on top of the service node network to ensure reliable message storage and retrieval.

This secondary logical layer is created by replicating stored messages across small groupings of service nodes called swarms. The swarm a service node initially joins is determined at the time of that service node’s registration, with the service node having minimal influence over which swarm it joins. This protects against swarms being entirely made up of malicious or non-performant nodes, which is important to maintain the network’s self-regulating properties.

Composition of each swarm inevitably changes as the networks evolves: some nodes leave the network and the newly registered nodes take their place. If a swarm loses a large number of nodes it may additionally "steal" a node from some other, larger swarm. In the unlikely event that the network has no swarms to steal from (i.e., every swarm is at Nmin=5 nodes), the ‘starving’ swarm (a swarm with fewer than Nmin nodes) will be dissolved and its nodes will be redistributed among the remaining swarms. Conversely, when a large number of nodes enter the network that would oversaturate existing swarms (i.e., every swarm is already at max capacity Nmax=10), a new swarm is created from a random selection of Ntarget=7 excess nodes. Note that Nmin < Ntarget < Nmax to ensure that a newly generated swarm doesn’t get dissolved shortly after and that there is still room for growth.

The outcome of this algorithm is the creation and, when necessary, rebalancing of swarms of around Nmin⁠–Nmax service nodes which store and serve Session clients’ messages. The goal of the swarm algorithm is to ensure that no swarm is controlled by a single entity and that the network is resilient enough to handle both small and large scale events where service nodes are no longer contactable, ensuring data integrity and privacy in both cases.

The following set of simple rules ensure that service nodes within swarms remain synchronised as the composition of swarms changes:

When a node joins a new swarm, existing swarm members recognise this and push the swarm’s data records to the new member. When a node leaves a swarm, its existing records can be safely erased, with the exception of when the node is migrating from a dissolving swarm. In this case, the migrating node determines the swarms responsible for its records and distributes them accordingly.

Identity and long-term keys

The majority of popular messaging applications require the user to register with an email or phone number in order to use the service. This provides some advantages, including account verification, for purposes of spam protection, and social network discoverability. However, such requirements also create some major privacy and security issues for users.

The use of a phone number as the basis for ownership of an identity key/long-term key pair weakens security against user accounts being compromised, such as in the cases of popular applications like Signal and WhatsApp. This weakness primarily stems from the fact that phone numbers are managed by centralised service providers (i.e. telecommunications service providers) who can circumvent user control, allowing these providers to assume direct control of specific users’ numbers. Widespread legislation already exists to compel service providers to take this kind of action. Additionally, methods such as SIM swapping attacks, service provider hacking, and phone number recycling can all be exploited by lower-level actors .

Signal and Whatsapp put forward varying degrees of protection against these types of attacks. Signal and WhatsApp both send a 'Safety numbers have changed' warning to a user's contacts if identity keys are changed. In practice, however, users rarely verify these details out-of-band .

Both Signal and WhatsApp also allow users to set a "registration PIN lock" . This protection means that an attacker (including a service provider or state-level actor) needs access to both the phone number and the registration PIN code to modify identity keys. However, this feature is off by default, difficult to find in the settings menu, and automatically disabled after periods of user inactivity. These factors all significantly reduce the efficacy of registration PIN locks as a protective measure against the security risks of phone number-linked accounts.

Using phone numbers as the basis for account registration also greatly weakens the privacy achievable by an average user. In most countries, users must provide personally identifiable information such as a passport, drivers' license or identity card to obtain a phone number — permanently mapping users’ identities to their phone numbers. These identity mappings are kept in private databases that can be queried by governments or the service providers that own them. There are also a number of web scrapers and indexers that automatically scrape phone numbers associated with individuals. These scrapers may target sources such as leaked databases, public social media profiles, and business phone numbers to link people to their phone numbers. Since the only method of initiating contact with a user in Signal, WhatsApp, or similar application is to know the user’s phone number, this immediately strips away user anonymity — a significant concern for whistleblowers, activists, protestors and other such users.

Account systems based on phone numbers also limit the potential for the establishment of multiple identities by a single user. These systems also prevent high-risk users without access to a phone number from accessing these services.

Session does not use email addresses or phone numbers as the basis of its account system. Instead, user identity is established through the generation of X25519 public-private key pairs. These key pairs are not required to be linked with any other identifier, and new key pairs can be generated on-device in seconds. This means that each key pair (and thus, each account) is pseudonymous, unless intentionally linked with an individual identity by the user through out-of-band activity.

Restoration

Because Session does not have a central server to keep records of user identities, the commonly expected user experience of being able to recover or log back into an account using a username and password is not possible. Instead, users are prompted to write down their long-term private key (represented as a mnemonic seed, referred to within Session as a recovery phrase) upon account generation. A user can use this backup key to recover their account if their device is lost or destroyed, and the user's contacts will be able to continue contacting that same user account, rather than having to re-initiate contact with a new key.

Run a secure Mumble server over Lokinet

Mumble is a fantastic open-source voice chat platform known for its reliability and ease of use.

And Lokinet is a cutting-edge onion routing network that offers unparalleled security and anonymity potential.

In this guide, we’re going to show you how to run a Mumble server over Lokinet, combining Mumble’s ease of use with Lokinet’s security and anonymity to create the ultimate secure voice chat service. With just 15 minutes of your time and $3 a month, you or your organisation can create one of the most secure voice chat platforms possible.

A Mumble server running over Lokinet on a server you control gives you absolute certainty that your voice conversations, associated metadata, and other Mumble activity cannot be stored or recorded, because no computer ever knows who is talking to whom — not even the Mumble server itself. So long as you trust the device that you run the Mumble server on (which you can, because it’s yours), you can be certain that no one else on earth can eavesdrop on your conversation — or even know that you’re connected to the server at all.

If this is your first time using SSH and the Linux command line, don’t stress. We’ll walk you through every step! With that, let’s get to it.

Step 1: Rent a VPS

The first thing you’ll want to do is rent yourself a VPS (Virtual Private Server) to host your Mumble voice chat server. You could run the Mumble server from your own computer instead, but if you want the server to stay up 24/7, without having to leave your own PC on all the time, a VPS is the way to go. Mumble’s chat server has extremely low system requirements, so a VPS with any amount of storage and at least 512MB RAM will do the trick — you can find VPSs that meet these requirements for around US$3 a month.

Try https://www.hetzner.com/cloud, or https://evolution-host.com/vps-hosting.php if you want to pay in $OXEN! When ordering, select Ubuntu 22.04 or Debian 11 as the operating system.

Step 2: Prepare your VPS

Once you have access to your new VPS, you’re almost ready to install Lokinet, but there’s a little bit of preparatory work to do first. Start by opening a command prompt on your local machine (Terminal on macOS, any command prompt on Linux, or PowerShell on Windows 10). SSH into (get remote access to) your VPS with this command:

ssh root@[VPS IP address]

Replacing [VPS IP address] with the IP of your VPS. It’ll prompt you for a password which will usually be provided to you by the VPS host. More advanced users can and should disable root password access and instead use SSH keys, but if that sounds hard, don’t worry about it for now. As you learn more about Linux, you’ll get more familiar with these best practices.

Once you’ve logged in, we’re ready to roll. First, we’ll update our package lists to make sure our VPS sees the most recent versions of all available packages. Type:

sudo apt update

You’ll see a bunch of package lists being downloaded. Once this command completes, run the following command to upgrade any outdated packages currently installed on the VPS:

sudo apt upgrade

We’ll also need to make sure the curl command is installed before we proceed. Run this command:

which curl

It should output the location of your installed curl command. If you get an error, install curl:

sudo apt install curl

Then run which curl again to make sure curl is installed.

Success? Congrats, you’re ready to move on to the next step:

Step 3: Install Lokinet

To install Lokinet, we need to add the Lokinet repository. Run the following command to install the public key used by the Lokinet dev team to sign Lokinet binaries:

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg

Then run the following command to tell apt where to find the Lokinet packages:

echo "deb https://deb.oxen.io $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/oxen.list

Next, update your repository package lists again with:

sudo apt update

And now, install Lokinet:

sudo apt install lokinet

Congrats, Lokinet is now installed and running in the background. We’re nearly there.

Step 4: Installing the Mumble server

Run this command:

sudo apt install mumble-server

That’s it. The Mumble server is now installed. On to Step 5:

Step 5: Setting up a persistent keyfile

This step is a bit more involved. We need to set up Lokinet to always generate a keyfile in the same directory, so it will work consistently. Linux servers don’t have a graphical interface, but they do ship with some in-terminal text editors. We need to edit a file now, so start by opening your lokinet.ini file with this command:

sudo nano /etc/loki/lokinet.ini

Using the arrow keys, move the cursor down to the [network] section of the file. Remove the # from before the “keyfile=” line, then add the following after the = symbol:

/var/lib/lokinet/mumble.private

Then hit Ctrl+X. Type “Y” (for yes) when asked if you want to save your changes, then press Enter to save and exit.

Now that you’ve exited nano, you’re back in the terminal. Restart Lokinet to generate a keyfile for Mumble:

sudo systemctl restart lokinet

Step 6: Binding the Mumble server to Lokinet

Now we need to make sure your Mumble server is using Lokinet for all traffic. Start with this command to grab the IP address we need to bind Mumble to:

dig @127.3.2.1 +short localhost.loki

This command will output 2 strings of text: a long string of random letters and numbers ending in .loki, and an IP address (a number in the format xxx.xx(x).x.x).

Select and copy (Ctrl+C on Windows or Linux; Cmd+C on macOS) the IP address. Some SSH clients allow you to copy by highlighting the text and right-clicking on it as well.

Now, we need to point the Mumble server to that IP address. Use this command to open the configuration file for the Mumble server:

nano /etc/mumble-server.ini

Using the arrow keys, navigate down to the line “;host=” under the section Specific IP or hostname to bind to. Delete the ; from the start of the line, then paste the IP address we copied earlier after the = symbol. Hit Ctrl+X to exit. Type “Y” when asked if you want to save your changes, then press Enter to save and exit.

Back at the command line, restart the Mumble server to apply changes:

systemctl restart mumble-server

Step 7: Done!

Congrats! A Mumble server is now up and running on your VPS, and all its traffic is being routed through Lokinet. All that’s left is to grab the Lokinet address of the Mumble server and give it to anyone you want to be able to connect. In case you missed it, run this command to find the Lokinet address of the Mumble server:

dig @127.3.2.1 +short localhost.loki

This is the same command we ran earlier, but this time, pay attention to the long string of characters ending in .loki (be sure to include the .loki part!). This is the Lokinet address of your secure, onion-routed Mumble server.

Copy this address and provide it to anyone you want to be able to connect to the server — all they have to do is paste the address into the Address field of the Add Server dialog in the Mumble client, add a username and label to identify the server, hit OK, and connect!

Mumble can be downloaded for free on all major platforms. Anyone that wants to access your secret Mumble server will also need to have Lokinet installed and running. To download and install Lokinet, just head to https://lokinet.org/. Additional Lokinet guides can be found back at the Lokinet guide hub here on Oxen Docs.

And that’s it! Only 15 minutes and $3 later, you can now have completely surveillance-free conversations over the internet. We hope to integrate voice features into Session to make it even easier to access secure voice channels with this level of privacy and security.

In the meantime, though, this Mumble/Lokinet setup is perhaps the most secure voice channel option available. This unique combination of services is just one example of the power of the Oxen tech stack — stay tuned for more guides and articles about what Oxen’s tech can do.

Have fun!

Session Open Group server video guide

Pulse: Deep dive

This page provides a more in-depth look at the technical side of Pulse, Oxen's PoS consensus mechanism

The Oxen Network has transitioned to the Session Network. More information here.

Introduction

Pulse is Oxen's Proof of Stake (PoS) scheme. There are various reasons this scheme was implemented in favour of the more popular blockchain consensus mechanism, Proof of Work (Pow).

Pulse makes Oxen more secure, more sustainable, and more powerful.

Overview

Every 120 seconds, an active Oxen Service Node is chosen to create a new candidate block. This one true service node creates a candidate block and sends it to 11 randomly chosen validators.

Validators are service nodes tasked with independently assessing the candidate block and ensuring it does not contain any duplicate transactions (or any other malicious activitiy). If 7 of the 11 validators verify the block's legitimacy, it can be published to the network as a valid block.

This process is then repeated to create the next block.

Security

Thanks to Pulse, it is both difficult and unprofitable to attempt an attack on the Oxen network. At the core of any blockchain's security is its consensus mechanism. There are a few critical attacks that blockchains must be secured against, which Proof of Stake consensus schemes excel at thwarting — making sure the value stored on the Oxen blockchain is safe.

Increasing the resource investment needed to attack Oxen

In a Proof of Work blockchain, double spending a token requires an attacker to secretly produce an alternate blockchain with more cumulative difficulty, reverse a previously spent transaction, and then create a new transaction with the same token(s).

Unless the attacker is using sophisticated attacks — such as selfish mining or cartels — this requires the miner to obtain 51% of the entire network's hash power.

Hash power is generally equivalent to computing power — more computing power, more hash power. This means the attacker only needs to acquire enough computing power relative to the size of the network to perform a 51% attack.

Performing the same attack against a PoS blockchain like Oxen's is a little different. Without considering more sophisticated attacks, the attacker would need to gain control of half of the nodes in the network to pull off a 51% attack.

Because Oxen is a finite resource, and its availability is reduced with each node that is created, conducting this attack would be many, many times more expensive than the equivalent attack on a PoW blockchain.

Increasing sunken cost of an attack on Oxen

The resources required to attack a PoW blockchain retain their value after the attack — that is, the computing power purchased to complete the attack can be used again to attack another blockchain, used to complete other computing tasks, or sold.

However, the same assault on a PoS blockchain requires you to purchase the token associated with that specific network. Assuming a successful attack would devalue the token, anyone hoping to attack a PoS blockchain will likely have trouble recouping the cost of their attack.

Checkpointing

Checkpointing provides additional 🛡 defence on top of Pulse. Every four blocks, the Oxen blockchain records a checkpoint — taking a snapshot of everything before it on the blockchain. Nothing transactions older than 2 checkpoints (also known as 8 blocks) can ever be changed.

This means that even if Pulse was somehow compromised, the Oxen blockchain would still be protected.

Checkpointing also provides additional protection against more sophisticated (and luck-dependent) attacks.

Sustainability

As the blockchain space grows, we have to start seriously considering whether our current models are sustainable — higher sustainability, more scope for long-term growth.

Environmental and economic sustainability are becoming increasingly pertinent issues in the tech world, and this is especially true in blockchain.

Power consumption

PoW consensus, while serviceable for securing the blockchain, has an inescapable flaw — it is extremely inefficient, and this problem becomes worse as the network scales.

Bitcoin, which uses PoW, consumes over 100 TWh per year, more than the consumption of entire countries like the Netherlands and the Phillipines — and that's just one blockchain! No one blockchain should have all that power.

PoS means a sustainable future for blockchain technology. Instead of relying on power-intensive computation, the blockchain is secured through the cooperation of service nodes, which is much more energy efficient — say goodbye to the wasteful ways of PoW.

Power

Lots of major players in the blockchain world have thrown their weight behind PoS — most notably, Ethereum.

This is largely because PoS is more scaleable, more flexible, and easier to participate in. PoS is what will finally bring blockchain to the masses.

Of course, the nodes that maintain the Oxen blockchain do a lot more than just create and validate blocks — they form the backbone range of services and applications, like Session and Lokinet. This is just the beginning of what Oxen can do with its powerful network of service nodes.

Implementation

This is the nitty-gritty of exactly how Pulse works. If you're only interested in the why of Pulse, all the information you need is above, but for the how, read on.

Proposal round

A single leader is sequentially chosen from the Oxen Service Node list, as well as a group of 11 validators chosen deterministically using a random value included in the previous block.

The leader scans the transaction pool and collects valid transactions into a block.With this information, the leader creates a candidate block.

The leader is rewarded according to the service node coinbase formula, and receives all transaction fees included in the block.

The leader then signs this candidate block and sends it to all 11 validators.

Each validator also sends the candidate block to 3 other validators, ensuring all validators successfully receive it.

Commit round

Every validator now generates a 128 bit integer, and sends a hash of that integer to all other validators.

Reveal round

Validators will then reveal the pre-image of the hash — which in is the random integer they hashed during the commit round — to all other validators. All validators should now have a subset of the revealed values, which they can combine to produce a new random value.

Validators add this value to the candidate block, signing the resultant block.

This signature is then sent to all other validators.

Block submission

Each validator is then able to check the validity of each of the other validator's signatures, ensuring they are all signing both the same candidate block and the same combined random integer.

Once signatures have been validated, any validator in the quorum may submit a block to the network which includes at least 7 validator signatures.

Key properties of Pulse

  • 120 second block time

  • Cannot be significantly biased by any one member of the quorum

  • Tolerates failure or malfeasance of up to ~45% of service nodes

Fault tolerance

Failures

There is only ever one way Pulse can fail: a timeout.

Timeouts and swap blocks

A timeout occurs when a valid block is not produced after 120 seconds.

As soon as the next leader realises there has been a timeout, they can immediately start building and distributing their own candidate block — containing a special “swap” tag.

If this block is signed by the validators, the swap tag will indicate that there was a quorum failure to both newly syncing nodes and nodes which have been offline.

Demerits and de-registrations

Validators in a quorum can submit intent to demerit messages at any stage for their leader or any peer validator(s) they feel haven't followed the protocol.

For example, if a leader never publishes a candidate block, any validator in the quorum may send an intent to demerit message to their other peers. If this message is signed by the majority of other validators it may be submitted to the network as a demerit point message.

This message is not a transaction, and simply propagates through the p2p layer.

Common failure cases

To get a better understanding of Pulse, it is worth discussing what happens in some common failure cases.

  • The leader doesn't submit a candidate block

  • Not enough validators participate in the commit or reveal rounds

  • Validators sign two different blocks

  • Validators are unable to submit a block due to differences in revealed values

Leader doesn't submit a candidate block

If a leader fails to construct and send a candidate block, the validators will be triggered to submit an intent to demerit message.

If this message is signed by a simple majority of the quorum, a demerit point is be applied to the leader and the next leader creates a swap block.

Not enough validators participate in the commit or reveal rounds

Although all Oxen Service Nodes are incentivised to cooperate in order to avoid demerits, some participants may either act maliciously or simply fail.

The protocol should be able to tolerate the failure of 6 of 11 validator nodes during the commit reveal stage.

As above, any validator that doesn't participate in a commit round, a reveal round, or reveals a different value from their commitment can be flagged by other validators with an intent to demerit message. If this message is signed by a majority of nodes, this message is submitted to the network as evidence of a node’s non-performance in a block creation quorum.

If more than 6 of 11 nodes don't participate in the commit or reveal round, the quorum will not be able to create a block — which means the next quorum can take over block creation once a timeout occurs.

Validators are unable to submit a block due to differences in revealed values

There may be a number of cases where not all of the service nodes correctly receive all of the committed or revealed values. This will result in differing final random integers being calculated by the validators.

As with other errors, the scheme will progress normally as long as the revealed values for 7 of the 11 validators match. Nodes with invalid revealed values can query the other validators in their quorum again to receive any values they missed during the two rounds.

If more than 7 nodes disagree on the final revealed value, then the scheme will fail after once a timeout occurs and the next leader produces a swap block.

Validator signs two different blocks

Any service node, including a validator or leader, may submit a deregistration transaction if they can produce signatures from any other service node that signs multiple blocks which compete for the same height or signs a competing chain once more than two checkpoints have been applied.

This means any node that signs blocks indiscriminately in block creation quorums will be immediately removed from the network with their funds locked.

Traditional PoS attacks

Stake grind attacks

Stake grinding usually refers to a class of attacks where a validator or leader can iterate values to bias the selection of the next chosen validator. Since validators are chosen by using a collaboratively generated random integer in each block, it is possible to bias the results of the scheme. However, the only way to actually do this is for a validator to chooses to hide the value they shared during the commit round.

In the context of Oxen Service Node selection for the next quorum, this biasing is extremely weak, and the action of committing but failing to reveal a value leads to a demerit message being submitted for the validator, making this attack infeasible.

Long range attacks

Long range attacks target nodes that are syncing the chain, or that are offline for a period of time — attempting to convince them of an alternate chain state.

This is possible because old service nodes can use previously held service node keys to re-sign blocks that appear as alternate chains.

The Oxen blockchain already provides a solution for online nodes through service node checkpointing. This prevents service nodes from altering blocks that have received more than 2 checkpoints.

However, tackling the problem of nodes which go offline and miss more than two checkpoints in a row or nodes who are syncing for the first time is more difficult.

Syncing nodes or partially offline nodes

When a node has no previous state of the blockchain, or has been offline long enough to miss enough checkpoints that it is infeasible for it to validate the non alteration of blocks, it must use an external trusted source to correctly identify the main chain. This is usually referred to as weak subjectivity.

The easiest way to solve this issue is to allow syncing service nodes, and service nodes which have been offline to refer to the seed nodes and ascertain which is the true chain. To implement weak subjectivity for Pulse, seed nodes should provide a list of the latest checkpoints, so that when a client is syncing they can ensure they're syncing to the correct chain — and not being segmented onto a network with valid but altered signatures.

Nothing at stake

The ‘nothing at stake’ problem references a validator’s tendency to sign or authorise multiple competing blocks in a Proof of Stake system. They are incentivised to do this because they can’t be sure which chain will become the true chain in the long term, thereby they should sign competing blocks to ensure they don't miss rewards.

With Pulse, the ‘nothing at stake’ problem is prevented by allowing nodes in the network to submit evidence of double signed blocks. If this evidence can be validated, the offending node can be deregistered from the network, providing a punishment for nodes who do not effectively choose a single block to sign.

DDOS attacks

All service nodes in the Oxen network maintain a public IP address so they are reachable by other service nodes and Lokinet/Session users. These IP addresses are held in a distributed list that anyone can access. This opens the service node network and especially block producing quorums to DDoS attacks. For example, an attacker could wait for a block to be successfully published and immediately identify the members of the next quorum who will produce a block. With this information, they could launch a DDoS attack aimed to interrupt the communication between validators, or between the leader and validators. If successful, they would prevent a new block from being produced and could continue this attack on successive quorums.

Although individual service nodes have incentives to prevent DDoS attacks (so they can earn rewards and avoid demerit points), there are some protections we can offer in the Oxen software suite which can be deployed in the case that the previous block has failed to be produced. The most trivial protection is that after a failure in block creation, service nodes in the next selected quorum should ignore any connections from IP addresses which do not belong to another service node. This limits the scope of the attacker’s DDoS to only service nodes — which are costly to operate and far less numerous than a botnet-like DDoS attack. service node operators could also reasonably rate limit other service nodes on a per key basis, choosing not to respond to service nodes who put undue strain on their own networks.

Considerations

Safety of commit reveal schemes

Collaborative commit reveal schemes for generating random values are well studied, and limitations on such schemes are well known. The primary downside to using this type of scheme is that although committed values cannot be changed after they have been committed, a contributor to the scheme may bias the results by not revealing their committed value at all.

For example, say a block creation quorum produces a value between 0 and 10 each block, and Alice wants to run an online casino which uses this random integer to flip a coin, with bets being placed on heads or tails. Alice’s casino algorithm reads the random integer from the blockchain and if the random value is between 0-4 then the coin is tails, and if it's between 5-10 it’s heads.

A possible attack on this application would be for an Oxen Service Node operator, let’s call her “Mallory”, to wait to become a validator in a quorum, act honestly, and commit to a random value. Once she has committed to the scheme, she waits for the other validators to reveal their original integers. She can now calculate the shared random result for those validators that have revealed. Let’s suppose their combined final value will be 3. Using this information and whatever deterministic algorithm that is used to combine each validators contribution, Mallory can now decide whether or not she wants to reveal her result and add her contribution to this data.

If Mallory bets on tails and realises revealing her commitment would change the overall result to heads, then she should not reveal her commitment. If her commitment (when combined with the other commitments) still selects a number under 3, then she can reveal her committed value. Of course, the cost of not revealing a commitment is demerit points being applied to Mallory’s service node which will lead to deregistration in the event that Mallory has not revealed her commitments consistently. However, as long as Mallory’s winnings are more than the cost of being deregistered from the service node network, her dishonest actions are financially incentivised.

It should be clear from this example that service nodes can significantly bias the results of decisions which have few available outcomes, like a coin toss. So applications should not use the random integer we are creating for these type of use cases! The Oxen blockchain, however, does not use the source of randomness in this way. We use the randomness to choose service nodes in a service node list, where biasing the results has an insignificant effect as the possible outcomes are far more numerous. With Pulse, the randomness seeds an algorithm that chooses a combination of 11 nodes out of currently about 620 nodes. Mallory, in this case, would be able to choose between two (and only two) different random samples of 11 nodes from the selection of 620, but this single extra choice is highly unlikely to provide a notable benefit in terms of opportunistic selection.

Block times

Pulse targets a predictable block time of 120 seconds — excluding the rare case where block creation fails. In this case, a block would be created in the subsequent 120 seconds. This means that in a majority of cases users won't be left wondering when the next block is coming like on PoW blockchains, since blocks are be predictability created every 120 seconds.

Conclusion

Pulse is a robust yet simple scheme for block creation and transaction ordering in the Oxen network. Pulse does all this while increasing security and decreasing the need to use energy intensive PoW. Additionally, it's better aligned with existing incentive structures to reward those who do the most work to create order, and secure the network — service nodes.

Hosting SNApps

Depending on the nature of the application or service which you want to make accessible over Lokinet, you may want to only run a temporary SNApp, or a SNApp that continues to persistently use the same .loki pubkey.

A temporary SNApp is a service accessible over Lokinet that does not have a permanent address. This means that the address you supply to others will not work once the server hosting the SNApp is restarted.

If you want users to be able to access your application or service over an extended period of time, a temporary SNApp is not recommended.

If you only want to host a temporary SNApp, jump to Step 2.

Note: This guide assumes you are running a standard Debian or Ubuntu Linux distribution on the machine on which you'll be hosting the SNApp and that you have Lokinet installed and running on this machine, if not please follow the guide here to get Lokinet running. This guide also assumes you are relatively familiar with using the command line.

Step 1: Preparing your Lokinet address

Start by opening your lokinet.ini file and adding a path to where your SNApp key files will be stored.

If you have installed Lokinet from Deb packages, you can open your lokinet.ini file in the nano text editor with the following command:

sudo nano /etc/loki/lokinet.ini

Otherwise, if you have built Lokinet from source, your lokinet.ini file will be in the folder ~/.lokinet/lokinet.ini, and can be opened in nano with the following command:

sudo nano ~/.lokinet/lokinet.ini

With lokinet.ini open in the text editor, scroll down to your [network] section and add the following line:

keyfile=/var/lib/lokinet/snappkey.private

Alternatively, you can set the filepath to wherever you want your SNApp private key to be stored.

Now, when you restart Lokinet, it will generate your snappkey.private file in the directory you have set.

sudo systemctl restart lokinet

Step 2: Finding your SNApp's Lokinet address

You can find your SNApp's current address using a host lookup tool:

nslookup -type=cname localhost.loki 127.0.0.1

You can also use the host command (the .loki address to query is the same, but the resolver uses the address 127.3.2.1 as to not conflict with other resolvers you may have installed):

host -t cname localhost.loki 127.3.2.1

Step 3: Install nginx

Install a proper web server:

sudo apt install nginx

Step 4: Configure nginx

Setup a Lokinet exclusive SNApp

If you want your SNApp to be accessible only via Lokinet and not via your IP address or domain name then you will need to configure nginx to run only on the lokinet interface.

First we will need to set the Lokinet interface IP range, we can do this by accessing our Lokinet config file as we did in Step 1 and adding this line in the [network]section:

ifaddr=10.67.0.1/16

this can go underneath your existing network config changes, after this change is made restart Lokinet using:

sudo systemctl restart lokinet

Once Lokinet is restarted run the following command to open your nginx default configuration file, we are going to make a few changes here.

sudo nano /etc/nginx/sites-enabled/default

change any listen directives to use the lokinet IP 10.67.0.1 remove any IPV6 listen directives and replace the .loki address after server_name with the Lokinet address you discovered in Step 2

This should leave your default file in sites available looking something like this:

server {
        listen 10.67.0.1:80;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name 73qqjm7ju98g6obua8bprce1tjyyphnotknnijhpn8mypwumqs8o.loki;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

}

save the changes and exit the file. Once this step is complete you can reload nginx with the following command:

systemctl reload nginx

Proceed to Step 6

Setup a clearnet and Lokinet accessible SNApp

If you want your SNApp to be accessible via Lokinet and your clearnet IP/Domain name then fewer changes are required. First open /etc/nginx/sites-enabled/default using:

sudo nano /etc/nginx/sites-enabled/default

Then add your .loki address (which you discovered in Step 2) as a server_name, after the changes your nginx default file should look something like this:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _ 73qqjm7ju98g6obua8bprce1tjyyphnotknnijhpn8mypwumqs8o.loki;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

Proceed to Step 6

Nginx Tips:

TIP: By default, you can drop files into /var/www/html to serve them as a SNApp. Make sure they are accessible via the www-data user (or whichever user nginx runs as.

TIP: You can make nginx generate a directory listing of files by adding autoindex on; on a new line into the location block in the nginx config file.

Step 5. Security (Optional)

Make sure no services bind to all interfaces.

Suggested UFW firewall settings when using nginx:

# change me to the range used by lokinet
LOKINET_RANGE=10.0.0.0/16

# drop all from lokinet
ufw deny from $LOKINET_RANGE

# allow tcp 80 from lokinet
ufw allow 80/tcp from $LOKINET_RANGE

Step 6: All done!

Congratulations! Your SNApp should now be accessible over Lokinet. Use the Lokinet address you discovered in Step 2, to access your SNApp

Oxen Name Service for Session

Namespaces

The ONS namespace is broken up into two distinct sections. One section is responsible for all Lokinet names, referred to as .loki names, and the other section is responsible for Wallet and Session usernames.

Names

Each ONS name can resolve to a Session public key, Wallet address or .loki address. Session and Wallet names are within the same namespace. When purchasing a Session record, the Wallet record is automatically added to your possession. Lokinet names are in their own namespaces. For example, when purchasing ‘KeeJef’ in the Session namespace, you can assign a Session public key. Additionally you can update the wallet record under a 2nd transaction.

So when a user looks up ‘KeeJef’ they are returned both a Account ID and Wallet address:

AccountID: 053b6b764388cd6c4d38ae0b3e7492a8ecf0076e270c013bb5693d973045f45254 
Wallet Address: LBMTVEK8WRiC9rmfoKEjyrZSRje6PdiTU6926LjMkGMUdzyApMvXUbH4LswHnLjMjMPLUbDKiL3RCRQe5XFiobWb8jQrApR

It is also possible to purchase ‘KeeJef.loki’ in the Lokinet namespace that is unique from the Session and Wallet namespace.

Depending on which context the name is being used, the application will automatically use the relevant mapping.

Rules

Both namespaces (Session/Wallet and Lokinet) have restrictions on the characters allowed in a name. All names are case-insensitive.

For Session (or Wallet), the name has to:

  • start with an alphanumeric character or underscore

  • consist of alphanumeric, hyphens or underscores in between

  • end with an alphanumeric character or underscore

Users may register names with special characters or emojis by using the equivalent Punycode representation. The name must be at least 1 character long, and at most, 64 characters long.

For Lokinet, the domain must:

  • start with an alphanumeric character

  • contain alphanumeric characters or hyphens

The character before the domain suffix .loki must be alphanumeric followed by the suffix .loki. Users may register names with special characters or emojis by using the equivalent Punycode representation. The domain name must be at most 253 characters long, including the .loki suffix.

Time

By default all mappings in the Session/Wallet namespace will be preserved forever. This is important to ensure that wallet mappings don't change when a user wants to send money to a name. The .loki namespace will have re-registration periods to deter domain squatting and release names if the keys that registered them are lost.

Ownership, transfer, updates and management

By default names are owned by the wallet address that purchased the name. However, names can also be purchased on behalf of another user. Up to 2 wallet addresses may be specified as the owners of a name. This means up to 2 wallets can update and or transfer ownership of the record.

Once a name it can be transferred to another user's Oxen wallet by specifying the address of that wallet and paying the standard transaction fee to transfer the ownership.

Updates to mappings can be made at any time by the owner, at the cost of the standard transaction fee to include the new mapping in the blockchain.

Initially, management of all owned names will be possible through the Oxen Desktop Wallet; however we aim to add functionality to register and manage names to Session clients directly in the future.

Cost

Names in the Session/Wallet namespace cost 7 $OXEN to register. We will try to update this cost per hardfork to continue targeting the $5-10 USD range.

Privacy

It is up to each user to choose which information they map publicly. If you don’t want to map your Account ID or Wallet address to your real world identity you might want to choose a different alias instead of something related to your name. Basic encryption is employed to mask publicity of data on the surface level, but please do not rely on this for critical privacy requirements.

All wallet sub-addresses generated via account new are supported as owners.

Technical documentation

Record encryption/decryption

ONS records stored in the blockchain undergo basic encryption and decryption to deter monitoring of the chain. This does not provide strong guarantees for privacy and should not be relied on for situations with critical privacy requirements.

At its core, a typical ONS record from the database looks like:

  • name_hashed

  • encrypted_value

  • register_height

  • owner

  • backup_owner

  • txid

  • prev_txid

  • register_height

  • more fields (implementation details, see oxen_name_system.h)

Of which the name_hashed and encrypted_value fields use some form of encryption or decryption.

name_hashed

  • Human readable name is hashed with blake2b with the following parameters

    • Key Length: 0 bytes

    • Hash Length: 32 bytes

  • Name hash converted to base64 for storage into the sqlite3 database (this provides optimal lexicographic lookup as a key).

    hash32 = Blake2B(name, key=0)
    name_hash = Base64Encode(hash32)

encrypted_value

  • Generate the secret key for decryption/encryption using the unhashed name with Argon2ID v1.3 and the following parameters as of Valiant Vidar v7.1.X

    • Iterations: 3

    • Memory: 268_435_456 bytes

    • Salt Length: 0 bytes

    • Key Length: 32 bytes

  • Decrypt/encrypt the value represented in binary with XSalsa20Poly1305 and the following parameters as of Valiant Vidar v7.1.X

    • Nonce: 0 bytes

    key32 = Argon2ID(iterations=3, memory=268435436, salt=0)
    encrypted_value = XSalsa20Poly1305Encrypt(value, key32, nonce=0)
    decrypted_value = XSalsa20Poly1305Decrypt(encrypted_value, key32, nonce=0)

Owners

In ONS, an owner of a record has the ability to update information about the record by making a transaction on the Oxen blockchain. Owners are specified when buying a record and in ONS we support 2 types. A standard Ed25519 keypair and an Oxen Wallet address.

By default, the wallet is configured to assign itself as the owner of the mapping when purchased.

Record updating

ONS records can be updated by getting the owner of the record to generate a signature that authorises the protocol to update fields in the record.

The following fields can be updated in a record

Value
Owner
Backup Owner
  • Copy the fields to update into a buffer

  • Copy the TXID into the buffer that last updated the record (which can be retrieved by querying the mapping).

  • Hash the buffer with blake2b with the following parameters

    • Key Length: 0 bytes

    • Hash Length: 32 bytes

  • Sign the hashed buffer

    • If the current owner (or backup owner) is a wallet address, it must be signed with the current owner's (or backup owner's) wallet secret spend key.

    • If the current owner (or backup owner) is a ed25519 key, it must be signed with the current owner's (or backup owner's) ed25519 secret key.

    // *If value is specified, copy the value to the buffer, otherwise skip.
    buffer[] = {*binary_value, *owner, *backup_owner, prev_txid}
    hash32 = Blake2B(buffer, key=0)

    if (monero)
        signature = generate_signature(hash32, spend_pkey, spend_skey)
    else
        signature = ed25519_signature(hash32, ed25519_skey)

Exit nodes

Lokinet's exit node functionality allows you to browse the normal Internet (the 'clearnet') with all the privacy and security protections Lokinet provides. To use an exit node, all you need is a working Lokinet client and an exit node address (the OPTF is currently operating a test exit node available at exit.loki, suitable for basic web browsing).

Using exit nodes with the Lokinet GUI client

Using exit nodes with the Lokinet GUI client is as easy as 1, 2, 3!

Step 1: Enter your exit node address

Open the Lokinet Control Panel and enter the address of the exit node you'd like to use (e.g. exit.loki) in the Exit Node box:

Step 2: Enter your exit node auth code (if applicable)

Some exit nodes may require an authentication code (password) to use (note: exit.lokidoes not require an authentication code). If the exit node you're using requires an authentication code, enter it in the Auth Code box:

Step 3: Enable!

With your exit address and auth code (if applicable) entered, all you need to do is click the switch next to Enable Exit:

Now turn on Lokinet (if not already on) with the big green power button, and you're ready to browse the internet with all the privacy protections of Lokinet.

Using exit nodes with the Lokinet CLI client

To begin browsing from an exit node, use the following command, replacing EXITNODEADDRESS.loki with the address of your desired exit node:

lokinet-vpn --up --exit EXITNODEADDRESS.loki --token authcodegoeshere

To disable exit node functionality:

lokinet-vpn --down

Full service node setup guide

This guide will walk you through the complete process of setting up, staking, and running an Oxen Service Node. The guide targets non-experts, so even if you're new to Linux or the command line, you should be able to follow the text without any difficulty.

You can run the Oxen Service Node software on any device running a supported operating system, but for the purposes of this guide, we'll assume you will be setting up a Service Node on a remote Ubuntu or Debian server. If you're new to Linux or running servers in general, this is the most straightforward approach. If you're more experienced and would prefer to run your Service Node on a different operating system, you'll need to modify the syntax of some commands to suit your system of choice.

Running an Oxen Service Node: Requirements

These are the current basic requirements for running a Service Node as of October 2021. They will almost certainly increase in the future as the technologies powered by the Oxen network grow in popularity, so keep an eye on the Oxen blog and join either our Telegram community or Session open group for all the latest updates.

Spec
Requirement

Latest Oxen Service Node software

Latest Service Node .deb packages (installed via the steps below) or latest

Server operating system

Ubuntu 20.04+ (latest LTS recommended) or Debian 11+ (latest stable recommended)

Storage

40GB or more

RAM

4-8GB (4GB absolute minimum)

Connectivity

100Mb or faster

Traffic

1TB per month or more

Power

Redundant with remote cycling ability, as found in most data centres

Note: It is possible for an experienced system administrator to run a Service Node on a server running an operating system other than Ubuntu or Debian. However, this requires additional work to start up and manage the required services, and is beyond the scope of this guide.

Table of Contents

  • Oxen Service Nodes in a nutshell

  • Set-up for new users

    • Step 1: Obtaining a server

    • Step 2: Preparing your server

    • Step 3: Initial repository set-up

    • Step 4: Service Node installation and operation

    • Step 5: Service Node registration

    • Step 6: Service Node status check

    • Step 7: Unlocking your stake

  • Keeping your binaries up to date

  • Monitoring

  • Back-ups

  • Conclusion

Oxen Service Nodes in a nutshell

  • A Service Node starts as a full node on the Oxen network.

  • The full node becomes a Service Node when the owner locks the required amount of $OXEN (see below) and submits a registration transaction.

  • Once accepted by the network, the Service Node starts performing node operations and becomes eligible to receive periodic block rewards in the form of $OXEN.

  • Multiple participants can stake into one Service Node and can have the reward automatically distributed among them.

Service Node functionality

Service Nodes:

  • Receive, store, and forward encrypted Session messages

  • Route Lokinet traffic

  • Monitor other Service Nodes and vote on their performance

  • Are called into quorums that give them authority over Blink transactions

  • Produce new blocks for the network via Pulse PoS

Service Node set-up for new users

Step 1: Obtaining a server

Choosing where to set up your Service Node is the first and most critical decision you will face in setting up and running your node. There are a number of factors to consider. Because you will be locking up funds as part of operating your Service Node, you will want to ensure, at a minimum, that your server meets the technical requirements given above.

Your aim is to provide a stable, reliable server with good network connectivity, so that data can be efficiently routed to and from your node. An underpowered or poorly connected node will have a poor response time and add latency to the network for all users whose traffic passes through it, resulting in a less than optimal experience.

Additionally, you should consider the following factors. The more weight you attach to these factors when deciding where to run your node, the more value you will provide to the network.

Firstly, please consult the node distribution panel of the Oxen Dashboard, where you will find a breakdown of the current Service Node network by country and network owner.

Here, you will see that some countries and network operators are currently overrepresented on the Service Node network. In other words, a relatively small number of countries and network operators account for the majority of the network. This is bad for decentralisation.

To be robust against disparate forms of attack, a distributed network must pursue diversity at multiple levels:

  • Geographical diversity: distribution across multiple, disparate regions to minimise the effect of natural disasters

  • Sociopolitical diversity: distribution across multiple countries and legal jurisdictions to minimise the effects of unrest, legislation, coercion and espionage

  • Network diversity: distribution across multiple tier 1 and tier 2 network providers to minimise the effects of fire, flooding, network splits, equipment failure, cable rupture, bankruptcy, industrial espionage and rogue employees

  • Software diversity: multiple operating systems, distributions and release variants to minimise the effects of events that target or otherwise afflict a particular system, such as a zero-day vulnerability or the push of a buggy package.

You can make a significant contribution to decentralisation and provide greater value to the network by taking the above factors into account when choosing where to run your node. Take care, however, not to compromise on the core requirements of a node when trying to satisfy these goals.

If your server goes down while staked, your Service Node could be deregistered from the network and your funds locked for 30 days (without receiving rewards).

For this reason, we strongly recommend against running a Service Node from home. Most consumer internet connections have poor upstream bandwidth (Service Nodes require a high speed connection for both uploading and downloading data) and typically don't provide a static IP address, which is essential for a Service Node. Connection speed and support aside, transient power and network outages are a relatively common occurrence with consumer-grade connections and can easily disrupt home servers.

Typically, the simplest and cheapest way to host a server such as an Oxen Service Node is to lease a Virtual Private Server (VPS). There are literally hundreds of options when it comes to VPS providers, but some of the more commonly chosen companies and products are listed below.

Hosting Provider
Product Name
Cost Per Month ($USD)

Netcup

VPS 1000 G8

10.50

Evolution Host

STARTER

5.50

Online.net

Start-2-S-SSD

13.99

Scaleway

START1-M

9.33

OVH

VPS SSD 2

7.61

Leaseweb

Virtual Server XL

34.45

Digital Ocean

4 GB, 2 vCPUs

20 (24 from 22-07-0

Linode

4 GB, 2 vCPUs

20

Feral Hosting

Neon Capability

19.68

Trabia

VDS-8G

38.54

Hetzner

EX41-SSD (30 TB)

39.71

Note: We do not endorse any of these providers. The above list is merely a selection of some of the popular options at the time of writing. Of course, this popularity comes at the expense of decentralisation. To provide even greater value to the network, please consider running a node in a country and/or on a network with few or even no nodes according to the OXEN Dashboard. A useful resource in choosing a less common VPS provider is ExoticVM. Another good one is Server Hunter.

In any case, do not just settle on the first provider you encounter. No two are alike. Do your own research and choose a provider that seems professional, reputable and fits your budget.

The better ones will utilise KVM virtualisation technology. In particular, you should steer clear of VPSes that use OpenVZ. This is an incomplete form of virtualisation that allows VPS capacity to be oversold, and is usually incompatible with the service node software. Virtual machines created with it often lack a /dev/tun device, and even those that have this can still cause insurmountable problems for Lokinet.

A good VPS provider will also allow you to monitor your machine's resource consumption, seamlessly upgrade to a more powerful server at a later date, remotely reboot the host if it becomes unresponsive, and even recover or rebuild the system using out-of-band access if, for example, a bad configuration change results in lost network access.

When selecting your VPS’ operating system, please choose the latest Ubuntu LTS release or latest Debian stable release (currently 22.04 and 12, respectively) if you want to be able to follow the steps below verbatim. If you feel more confident and/or wish to run your server on another Linux distribution, the commands in this guide will still apply, but may need to be modified to suit your chosen operating system. In most cases, beginners and experts alike will be best served by sticking closely to this guide.

Step 2: Preparing your server

Every provider has a slightly different way of issuing you access to your new VPS. Most will send an email with the IP address, root username, and a root password to the VPS.

To access your server, you will need an SSH client for your operating system. Because we’re on Windows today, we’ll download PuTTY. Mac users can also use PuTTY. If you’re a Linux user, you probably don’t need us to tell you where to get an SSH client.

To connect to your VPS, you'll need to paste the provided IP address into the SSH client’s “Host Name (or IP address)” input box and click the “Open” button. The Port number can usually just be left as 22.

A terminal window will now appear, prompting you for your log-in details, username (root) and password, as provided by your VPS provider. When entering your password, characters will not appear in the terminal. This is normal. Hit enter after typing or pasting your password, and you should be logged in to your VPS.

Note: After logging in for the first time, the VPS may prompt you for a new password for the root account. The terminal will require you to enter the new password twice before you can start running commands. If you aren't prompted for a new root password but want to change it anyway, type sudo passwd. Choose something very secure!

2.1: Hot tips for using the console on Windows

Consoles don't quite work like the rest of your computer. Here are some basic tips for navigating your way around the command line!

  • Don't try copying something by using the usual Ctrl + C hotkey! If you want to copy something, do so by highlighting text and then right clicking it and selecting Copy. Pasting works by right clicking a blank area in the console and selecting Paste.

  • If you want to kill a process or stop something from running, press Ctrl + C. (This is why you shouldn't try copying something with this hotkey!)

  • You can always check the directory you are in by typing pwd, and you can list its contents by typing ls.

  • You can always return to your home directory by typing cdand pressing Enter.

  • You can move into a given directory by typing cd <name> or move back up one level by typing cd ...

  • PuTTY allows you to easily duplicate or restart a session by right clicking the top of the window. Handy if you’re trying to do a few things at once.

2.2: Server preparation continued

Next, update your package lists (the lists that tell your server which software is available for install or upgrade). The following command downloads package lists from their respective package repositories and "updates" them to get information on the newest versions of packages and their dependencies. It will do this for all repositories and PPAs.

sudo apt update

You'll notice a bunch of package lists were downloaded. Once this is complete run the below command to fetch new versions of any packages that came preinstalled on the system.

sudo apt upgrade

You'll be prompted to authorise the use of disk space. Type y and Enter to authorise.

If you are prompted during the upgrade that a new version of any file is available then click the up and down arrows until you are hovering over install the package maintainer’s version and click enter.

Alright, good to go. Our server is now set up, up to date, and is not running as root. On to the fun part!

2.3: Firewall Configuration

If you are using a firewall then ensure that the following ports are open/reachable

  • Port 22020 (storage server connectivity; requires both TCP and UDP)

  • Port 22021 (client to storage server)

  • Port 22022 (blockchain syncing)

  • Port 22025 (Service Node to Service Node)

  • Port 1090 (Lokinet router data; UDP only)

Step 3: Initial repository setup

You only need to do this step the first time you want to set up the Oxen repository; when you've done it once, the repository will automatically update whenever you fetch new system updates.

To add the apt repository, run the following commands.

This first command installs the public key used to sign the Oxen Service Node packages:

sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg

The second command tells apt where to find the packages. Note: Replace <DISTRO>with the appropriate value to match your operating system. If your VPS is running Ubuntu 22.04 as recommended for this guide, replace <DISTRO> with jammy.

Otherwise, to check your <DISTRO> , run the following command: lsb_release -sc

Alternatively, your <DISTRO> can be found by using the following list:

  • bookworm (Debian 12)

  • bullseye (Debian 11)

  • buster (Debian 10)

  • jammy (Ubuntu 22.04)

  • focal (Ubuntu 20.04)

  • bionic (Ubuntu 18.04)

We also have repositories for Debian testing (trixie or testing) and unstable (sid or unstable), and typically support the latest or upcoming Ubuntu non-LTS release (mantic, as of writing). Note, however, that none of these distribution versions are recommended for production service nodes.

echo "deb https://deb.oxen.io <DISTRO> main" | sudo tee /etc/apt/sources.list.d/oxen.list

Then resync your package repositories with:

sudo apt update

Step 4: Oxen Service Node installation and operation

To install the software needed to run a Service Node, simply install the oxen-service-node package:

sudo apt install oxen-service-node

This will detect your public IP (or allow you to enter it yourself) and automatically update the /etc/oxen/oxen.conf configuration file with the necessary additional settings to run a Service Node.

Note: This process can take up to 6 hours for the blockchain to fully sync.

If you encounter an error during the syncing process due to a 15000 millisecond ping, you can run this command to fix it:

sudo systemctl restart oxen-node.service

Alternatively, the blockchain can be typically be downloaded in a fraction of the time required to sync it via the network, using the following command:

sudo oxend-download-lmdb https://public.loki.foundation/loki/data.mdb

4.1: Interacting with the running oxend

If you run the oxend command with an appended oxend command (note that sudo is not required!), the oxend command forwards this instruction to the running oxend. So, for example, to get the current oxend status you can run you would run:

oxend status

oxend print_sn_status

To see the output log of your node you can run the following command:

journalctl -u oxen-node -af

This is useful to see if your node is syncing with the blockchain and to see other diagnostic messages that may come up from time to time. (Press Ctrl-C to stop watching the log).

For a full list of supported commands run:

oxend help

You can also get basic statistics (such as uptime proof and ping times) on the running daemons from the systemctl status commands:

systemctl status oxen-node
systemctl status oxen-storage-server
systemctl status lokinet-router

Step 5: Service Node registration

This section of the guide is split into two parts:

  • If you are an individual staker and do not require any other contributors to run your Service Node, jump into the Individual staking section.

  • If you want to run a pooled Service Node, jump into Setting up a pooled Service Node.

5.0.1: Retrieving your wallet address

You'll need your wallet address to register your Service Node. Copy your primary address from the Oxen GUI wallet, or run the address command from within the Oxen CLI wallet, and copy the output.

Note: Do not use subaddresses for staking. Subaddresses are currently unsupported for staking in the Oxen wallet.

5.1: Individual staking

To run a Service Node as the sole contributor, you'll need:

  • A fully synchronized, up-to-date Oxen daemon running on your Service Node

  • An Oxen wallet with at least 15,000 $OXEN in it (to meet the staking requirement to register your Service Node)

5.1.1: Preparing your node for registration

Log in (if not already logged in) to the VPS running the Service Node, then run the following command:

oxend prepare_registration

The daemon will output the current staking requirement and prompt you with an input to clarify whether you are an individual staker or you will be running a pool. Type y and click enter, as you will be the sole staker.

The daemon will now prompt you for the operator's (your) Oxen address — this is the address saved in Step 5. Retrieve this address, copy it, then paste it into the terminal and press Enter.

The daemon will now ask for a final confirmation. If you agree with the information provided, type y and click enter.

The daemon will output a command which looks similar to:

register_service_node 4294967292 T6TCCyDgjjbddtzwNGryRJ5HntgGYvqZTagBb2mtHhn7WWz7i5JDeqhFiHqu7ret56411ZJS7Thfeis718bVteBZ2UA6Y7G2d 4294967292 100.000000000 1535677391 ec3895ea70a4a91b5ec4b5e1df96a45e07046f1fb0123c754d98fb2d70f4529d 5bb35d7b8ab1acb943bc47913ada8f9d2e6d6e22264e57484a04c1bbfd461f0ee2e5435454cd9b7059b221eb506ce9ea4537ddd9faf1f1757e0ef611a41c0609

NOTE: You must run the command which your daemon outputs, and not the command shown above.

5.1.2: Registering your Service Node

To stake and register your Service Node, open your Oxen GUI wallet (with a balance of at least 15,000 $OXEN). Navigate to the Service Nodes tab, then the Registration subsection. Paste the register_service_node command from Step 5.1.1 above, and click Register Service Node.

If you're using the Oxen CLI wallet, simply paste the registration command directly into the CLI wallet prompt and hit Enter.

Well done! Continue to Step 6: Service Node check to make sure your Service Node is running properly.

5.2: Setting up a pooled Service Node

Minimum contribution rules

The Service Node staking requirement is fixed at 15,000 $OXEN. Service Nodes accept at most 10 contributions, meaning the minimum contribution to a Service Node is <Remaining Staking Requirement> ➗ <Number of Remaining Contributors>.

When setting up reserved spots in a pooled Service Node, the node administrator (you) must ensure the reserved stake amounts each meet the minimum staking requirement; contributors then simply stake their reserved amounts.

5.2.1: Pool operator

The operator (you) is the individual who will be hosting the pool and running the server hosting the Service Node, thus incurring the operating expenses involved in running a node.

To be an operator, you'll need to have:

  • A server running a fully synchronized, up-to-date oxend

  • An Oxen wallet with at least 3750 $OXEN (to meet the minimum Service Node operator staking requirement)

  • 1-3 other contributors who also have an Oxen wallet (either the CLI or GUI wallet) with enough $OXEN to meet their portion of the total stake

  • If the operator wants to reserve contribution spots for specific contributors, the operator will need the addresses of the contributors and the amounts the 1-3 contributors will stake.

If you have the above ready, we can now prepare the Service Node.

Log in (if not already logged in) to the VPS running the Service Node, then run the following command:

oxend prepare_registration

oxend will prompt you to specify if you will contribute the entire stake. Because you're running a pooled Service Node, type n and press Enter.

Next, oxend will request input for your desired operator fee. This value, which can be between 0-100, represents the percentage of the reward the operator will receive before the reward is distributed to all shareholders (including you!). For example, if you want to set up a 10% operator cut, you would type 10 and press Enter.

For example, imagine a Service Node with 4 contributors, including the operator, all staking equal amounts (25%). If the operator specified a 10% fee at this step, they would automatically receive 10% of the Service Node rewards, and the remaining 90% would then be split equally between the operator and the other 3 contributors.

The terminal will now display the minimum reserve the operator can contribute, and request input for the amount (in Oxen) you, as the operator, wish to contribute. Type your desired <operator contribution> and click return.

Once you've set your desired stake amount, you'll be prompted to either reserve spots for individuals that have already agreed to stake into the Service Node, or leave the pool open for anyone to contribute.

Option one: Reserved pool

If you want to reserve spots for specific contributors, type y at this prompt and click return.

The terminal will now prompt you for the number of additional contributors you've organised to stake into this Service Node. Type in the number of reserved contributors, not including yourself, and press Enter.

The daemon will now prompt you for the operator's (your) Oxen address — this is the address saved in Step 5. Retrieve this address, copy it, then paste it into the terminal and press Enter.

Next, you need to input the amount of Oxen each contributor will stake, and the Oxen Walled Address of the specific contributor(s).

NOTE: It is possible to reserve only some of the required total stake for specific contributors, while leaving the remaining staking amount open for other contributors.

The daemon will display a summary of the information you've entered. This is your chance for a final check over to make sure the correct information has been entered. To confirm the information is correct, type y and press Enter.

Option two: Open pool

If the operator wishes to leave their pool complete open to contributions they should type n at the reservation prompt and type Enter. The terminal will prompt you to input your address. Once your address has been entered, the terminal will display the remaining portion that needs to be contributed by others. If you agree, click y and hit return.

The daemon will display a summary of the information you've entered. This is your chance for a final check over to make sure the correct information has been entered. To confirm the information is correct, type y and press Enter.

Step 5.2.2: Registering your shared Service Node

Regardless of which option (closed or open) you've gone with, the daemon will output a command which looks similar to:

register_service_node 4294967292 T6TCCyDgjjbddtzwNGryRJ5HntgGYvqZTagBb2mtHhn7WWz7i5JDeqhFiHqu7ret56411ZJS7Thfeis718bVteBZ2UA6Y7G2d 4294967292 100.000000000 1535677391 ec3895ea70a4a91b5ec4b5e1df96a45e07046f1fb0123c754d98fb2d70f4529d 5bb35d7b8ab1acb943bc47913ada8f9d2e6d6e22264e57484a04c1bbfd461f0ee2e5435454cd9b7059b221eb506ce9ea4537ddd9faf1f1757e0ef611a41c0609

NOTE: You must run the command which your daemon outputs, and not the command shown above.

Copy the whole line of text in your daemon and paste it into your notepad, as you'll need to run this command from within your Oxen GUI (or CLI) wallet.

You have 2 weeks from the moment of registering the Service Node to run the register_service_node command, however it is advised to do it as soon as possible.

Before you disconnect from your VPS, run the following command:

oxend print_sn_key

This will output a bunch of information about your Service Node, but there's one part we're interested in at this stage: the long string of random letters and numbers after the characters SN: . This string is your Service Node's public key, used to identify your Service Node on the list of registered and operational Service Nodes. Select and copy the public key (do not copy any of the surrounding information).

On your local machine, open your Oxen GUI or CLI wallet and make sure your wallet contains at least 3750 $OXEN to meet the Service Node staking requirement. Once you're in your wallet and have checked the balance, run the command which was provided above when you ran the prepare_registration command. The wallet will prompt you to confirm your password, then the amount of $OXEN to stake. Confirm this by typing y and clicking enter.

Once this command completes, your staking transaction will be sent to be included on the blockchain. It may take a few minutes for the transaction to be mined into a block; you can check the status using the following command:

oxend print_sn_status

You can also check your node's status by looking for your <Service Node Public Key> in the "Service Nodes Awaiting Contributions" section on the Oxen block explorer.

Once the Service Node registration is received, you can send the <Service Node Public Key> to your contributors, along with the amount of $OXEN they are required to stake.

At this point, you'll need to wait until all contributors have staked before the Service Node activates and becomes eligible to begin receiving rewards.

Staking to a shared node as a contributor

For a guide on staking to a shared Oxen Service Node as a contributor, see here.

Step 6: Service Node status check

After you've staked to your Service Node (or after all contributors have staked, if you're running a shared node), you'll need to check if your Service Node's public key is on the list of Service Nodes which are operational on the network. This will prove that your Service Node is running, recognised, and eligible to receive rewards.

Connect to the VPS where the Service Node is running and run the following command to retrieve your Service Node's public key:

oxend print_sn_key

This will output a long string of letters and numbers: your Service Node's public key. This public key is used to identify your Service Node on the list of registered and operational Service Nodes. Select and copy the public key.

You can now jump onto oxen.observer, open the full list of active Service Nodes, and use Cmd+F/Ctrl+F to check if your Service Node's public key appears in the list.

Step 7: Unlocking your stake

Service Nodes will continually receive block rewards indefinitely until a stake is unlocked or the Service Node becomes deregistered. To unlock your stake, simply open the Oxen GUI Wallet and navigate to the Service Nodes > My Stakes tab. You can then click Unlock for any stake you wish to unlock:

You can also unlock your stake by running the following command from the Oxen Command Line Interface (CLI) Wallet:

request_stake_unlock <service node key>

The Service Node will expire 15 days (10800 blocks) after the unlock is requested, and your staked $OXEN will then become unlocked after expiry.

For pooled nodes, any contributor can submit an unlock request. This will schedule the Service Node for expiration. All locked stakes in that Service Node will be unlocked 15 days (10800 blocks) after the unlock is requested. Once an unlock is requested, this process can not be undone or prolonged. Service Node participants will continue receiving rewards until the node expires.

Deregistrations can be issued at any point during the active lifecycle of a Service Node, including during the period after requesting an unlock. Deregistration removes your Service Node from the network, and your stake(s) become locked and unspendable for 30 days (21600 blocks) from the block in which the Service Node was deregistered.

Receiving a deregistration after participant(s) have already requested an unlock overrides the 15-day (10800-block) stake unlock time, and sets the unlock time to 30 days (21600 blocks).

print_locked_stakes

Keeping your binaries up to date

When a new release is available, upgrading is as simple as syncing with the repository:

sudo apt update

Then installing updates using:

sudo apt upgrade

Note that this will install both updated oxend packages and any available system updates (this is generally a good thing!).

During the upgrade, all instances of oxend will be restarted if they are currently running in order to switch to the updated oxend.

If for some reason you want to install only Oxen package upgrades but not other system package updates, then instead of the sudo apt upgrade you can use:

sudo apt install oxen-storage-server oxend lokinet-router

Monitoring

We highly recommend setting up monitoring for your Service Node. This is as simple as calling on the services of our Telegram or Discord bot. Contact @OxenSNBot on Telegram or OxenSNBot#5812 on Discord and type /start or $help respectively to get started.

Another helpful tool is Konstantin Ullrich's Oxen Service Node Operator app for Android.

Back-ups

You should immediately make a back-up of your Service Node's secret key. This will allow you to recover from a disaster or to migrate your node to a different network service provider, should that prove necessary in the future.

The command to reveal the secret key is:

oxen-sn-keys show /var/lib/oxen/key_ed25519

And the command to restore it is:

oxen-sn-keys restore /var/lib/oxen/key_ed25519

Alternatively, you can use a tool like scp to copy the file off-host for safekeeping.

Note that for older service nodes (installed before Oxen 8.x) the server will have two keys: the above, plus a legacy /var/lib/oxen/key. You must additionally back up and restore this legacy key to restore such a service node, using:

oxen-sn-keys show /var/lib/oxen/key

to show the key, and if you need to restore it (note the "legacy" added to the command):

oxen-sn-keys restore-legacy /var/lib/oxen/key

If you are planning on unlocking and re-registering an older node with two keys, it is recommended to remove the legacy /var/lib/oxen/key after the registration expires, restart the oxen/lokinet/storage server services, and then register using the new, single key: this will leave you with just one key to back up and restore. IMPORTANT: Never remove any keys on an active, registered service node!

Conclusion

Well done! Your Service Node is configured, operational, and will now begin receiving rewards.

For tips and tricks to maintain your Service Node, check out Service Node tools and upkeep.

Having trouble? Just head to our Support section.

binaries

Session

Session is an open-source encrypted messenger powered by Oxen, designed to provide both security and anonymity through metadata minimisation, fully anonymous signup, and secure encryption and networking protocols. Session uses the Oxen Service Node network to route and temporarily store messages.

Why Session?

The past decade has seen a massive increase in the number of people using — and relying on — instant messengers for everything from chatting with friends to mission-critical business tasks. The most widely-used messengers have amassed more than a billion users. However, these popular messengers have some serious privacy and security shortfalls that make them completely unsuitable for anyone concerned about their online privacy.

Some messengers, such as WhatsApp, have deployed end-to-end encryption in an attempt to alleviate user concerns about privacy and security. However, simply encrypting the contents of user messages doesn't fix the wider underlying issue: the companies that operate these services can still see massive amounts of metadata about their users' messaging activities. This metadata can include user IP addresses and phone numbers, the time and #️quantity of sent messages, and the relationship each account has with other accounts. Increasingly, it is the existence and analysis of this metadata that poses a significant privacy risk to journalists, human rights activists, and other groups with a real need for private communications.

Session is, in large part, a response to this growing risk. Session is built to minimise metadata creation and leakage at every step of the messaging process. Through its fully anonymous signup process, decentralised networking infrastructure, and encryption and onion routing protocols, Session ensures that users send messages — not metadata.

Download Session

You can download Session for Windows, macOS, Linux, iOS, or Android on the Session website, where you can also find more information about the app, including details about its encryption protocol and more.

Register a Session name

Looking to register a permanent name for your Account ID? Head over to Using Oxen Name Service.

CLI Wallet commands

Oxen CLI Wallet commands

The Oxen CLI wallet is based on wallet first developed by Monero. The Oxen wallet includes additional commands on top of the standard monero-wallet-cli commands, and this document goes through all the Oxen and Monero CLI commands available within oxen-wallet-cli.

Displaying commands

The oxen-wallet-cli has multiple commands to conduct different operations on the Oxen Blockchain. Typing help and pressing Enter after loading your wallet will bring up the commands that can be used.

1 Accounts

1.1 Creating new account

When a wallet is generated, it will automatically have an account labelled Primary account with index 0. If at any time you wish to create an additional account use the command:

account new <label text with white spaces allowed>

This command will create a subaddress which is labelled with a tag and index number. This subaddress will share the same seed as your Primary address. To ensure this new account is displayed you must type exit to save your session.

You will note that there is now an asterisk to the left of index 1. The asterisks show us the account in which the commands we run will apply to.

Note: Restoring your wallet from your seed will not restore your accounts as the index of your subaddress data is stored on your computer within your wallet file. All the funds stored in your additional accounts will be shown in your Primary account if you need to restore your wallet from scratch.

[wallet L9LnR2]: account new Secondary account
[wallet L9LnR2]: Untagged accounts:
[wallet L9LnR2]: Account Balance Unlocked balance Label
[wallet L9LnR2]: 0 L9LnR2 0.000000000 0.000000000 Primary account
[wallet L9LnR2]: * 1 LY5J5W 0.000000000 0.000000000 Secondary account
[wallet L9LnR2]: Total 0.000000000 0.000000000

1.2 Switching account

When transferring out or receiving to a specific account we need to make sure that the account we are performing the action is the one the CLI is currently connected to. An asterisk will show which account we are connected to. In the below example the asterisk is shown to the left of Secondary account so any operations will be associated with that account.

Each of the accounts connected to your Primary address will have an index associated with them. The index number will be shown to the left of the Account column. By default, index “0” is your Primary account.

[wallet L9LnR2]: account new Secondary account
[wallet L9LnR2]: Untagged accounts:
[wallet L9LnR2]: Account Balance Unlocked balance Label
[wallet L9LnR2]: 0 L9LnR2 0.000000000 0.000000000 Primary account
[wallet L9LnR2]: * 1 LY5J5W 0.000000000 0.000000000 Secondary account
[wallet L9LnR2]: Total 0.000000000 0.000000000

To switch between the accounts you have created run the command:

account switch <index>

After running the command a similar output shown below will be on your terminal.

[wallet L9LnR2]: account switch 0
[wallet L9LnR2]: Currently selected account: [0] Primary account
[wallet L9LnR2]: Balance: 0.000000000, unlocked balance: 0.000000000

1.3 Changing account labels

To change the label name connected to a specific Oxen Primary or Sub-address use the command:

account label <index> <label text with white spaces allowed>

Replacing <index> with the index number associated with the account you wish to relabel, and replacing <label text with white spaces allowed> with the new label you would like to name the specified account.

Below shows the current accounts and labels for a specific wallet.

[wallet LCmjSH]: Untagged accounts:
[wallet LCmjSH]: Account Balance Unlocked balance Label
[wallet LCmjSH]: * 0 LCmjSH 0.000000000 0.000000000 Primary account
[wallet LCmjSH]: 1 LTLgNy 0.000000000 0.000000000 Secondary
[wallet LCmjSH]: Total 0.000000000 0.000000000

Using the command account label 0 My Account we have changed the label connected to our Primary address from “Primary account” to “My Account”.

[wallet LCmjSH]: account label 0 My Account
[wallet LCmjSH]: Untagged accounts:
[wallet LCmjSH]: Account Balance Unlocked balance Label
[wallet LCmjSH]: * 0 LCmjSH 0.000000000 0.000000000 My Account
[wallet LCmjSH]: 1 LTLgNy 0.000000000 0.000000000 Secondary
[wallet LCmjSH]: Total 0.000000000 0.000000000

1.4 Tagging and untagging accounts:

The oxen-wallet-cli allows you to group accounts by tagging or untagging them.

Below shows a wallet with 4 accounts, Dog, Kid 1 and Kid 2.

[wallet LVP3bv]: Untagged accounts:
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 0 LAXk6e 0.000000000 0.000000000 My Account
[wallet LVP3bv]: 1 LRDvY6 0.000000000 0.000000000 Dog
[wallet LVP3bv]: 2 LVJDwN 0.000000000 0.000000000 Kid 1
[wallet LVP3bv]: * 3 LVP3bv 0.000000000 0.000000000 Kid 2
[wallet LVP3bv]: Total 0.000000000 0.000000000

We can tag a single account with the following command:

account tag <tag_name> <account_index>
[wallet LVP3bv]: account tag Pets 1
[wallet LVP3bv]: Accounts with tag: Pets
[wallet LVP3bv]: Tag's description:
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 1 LRDvY6 0.000000000 0.000000000 Dog
[wallet LVP3bv]: Total 0.000000000 0.000000000

When needing to perform multiple tags we can do it through one command:

account tag <tag_name> <account_index_1> [<account_index_2> ...]
[wallet LVP3bv]: account tag Family 2 3
[wallet LVP3bv]: Accounts with tag: Family
[wallet LVP3bv]: Tag's description:
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 2 LVJDwN 0.000000000 0.000000000 Kid 1
[wallet LVP3bv]: * 3 LVP3bv 0.000000000 0.000000000 Kid 2
[wallet LVP3bv]: Total 0.000000000 0.000000000

Similarly we can untag accounts by running the following command:

account untag <account_index_1> [<account_index_2> ...]

Using the above exampled wallet we will remove our “Dog” account from “Pets”.

[wallet LVP3bv]: account untag 1
[wallet LVP3bv]: Accounts with tag: Family
[wallet LVP3bv]: Tag's description:
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 2 LVJDwN 0.000000000 0.000000000 Kid 1
[wallet LVP3bv]: * 3 LVP3bv 0.000000000 0.000000000 Kid 2
[wallet LVP3bv]: Total 0.000000000 0.000000000
[wallet LVP3bv]:
[wallet LVP3bv]: Untagged accounts:
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 0 LAXk6e 0.000000000 0.000000000 My Account
[wallet LVP3bv]: 1 LRDvY6 0.000000000 0.000000000 Dog
[wallet LVP3bv]: Total 0.000000000 0.000000000

1.5 Adding Tag descriptions

If you require additional information attached to a specific tag you can add a description with the following command:

account tag_description <tag_name> <description>

For example:

[wallet LVP3bv]: account tag_description Family This is my family.
[wallet LVP3bv]: Accounts with tag: Family
[wallet LVP3bv]: Tag's description: This is my family.
[wallet LVP3bv]: Account Balance Unlocked balance Label
[wallet LVP3bv]: 2 LVJDwN 0.000000000 0.000000000 Kid 1
[wallet LVP3bv]: * 3 LVP3bv 0.000000000 0.000000000 Kid 2
[wallet LVP3bv]: Total 0.000000000 0.000000000

2 Balance

To check the balance of your wallet you can run one of two commands:

balance or balance detail

Running the command balance will generated a simple output showing your balance and unlocked balance of the specific account you are in. For example:

Currently selected account: [0] Primary account
Tag: (No tag assigned)
Balance: 172286.035054991, unlocked balance: 172086.338373771

While running the command balance detail will generate a more detailed output, showing the account number, first few characters of the address, balance, unlocked balance, Outputs and the Label of the account. For example:

[wallet T6TmZX]: balance detail
Currently selected account: [0] Primary account
Tag: (No tag assigned)
Balance: 172286.035054991, unlocked balance: 172086.338373771
Balance per address:
Address Balance Unlocked balance Outputs Label
0 T6TmZX 172286.035054991 172086.338373771  3347 Primary account

There are other commands that will also output the balance which have been covered by this guide, such as the account command.

3 Getting the Block Height

To show the blockchain height run the command:

bc_height

4 Blackballing Transactions

Blackballing transactions allows you to ignore others' outputs (containers of money) that are known to be spent in a certain transaction.

For example let’s imagine that txid: 4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542 is known to be fake and if this txid is seen within a RingCT transaction the network can assume it is fake, therefore an actor has a better chance of deducing the real transaction within the RingCT.

By blackballing the above txid we remove the chance of it being used within our RingCT.

To do this we will use the following command:

blackball <output public key> | <filename> [add]

For example:

[wallet LAXk6e]: blackball 4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542

To check if the txid was added to our list of txids not to use we can use the following command:

blackballed <output public key>

If the txid is on our list the following will output:

[wallet LAXk6e]: blackballed 4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542
[wallet LAXk6e]: Blackballed: <4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542>

Alternatively if the txid is not on our list the following will output:

[wallet LAXk6e]: blackballed 4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542
[wallet LAXk6e]: not blackballed: <4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542>

To unblackball a txid use the following command:

unblackball <output public key>

For example:

[wallet LAXk6e]: unblackball 4f4b371a0da8858bbeab8a40ff37de1f6ff33e64a616e5ced8239062570b7542

5 Reserve Proof

Reserve Proofs are used to generate a signature proving that you own an amount of $OXEN, with the option to sign the reserve proof with a key.

For example let’s imagine you see a car for sale but they will accept $OXEN as payment, however they have advised in their online listing that they are only interested in serious buyers and require you to prove you have the $OXEN. Luckily we can use Reserve Proof commands for this proof.

5.1 Generate Reserve Proof

To begin we will need to run the get_reserve_proof command to generate our proof.

get_reserve_proof (all|<amount>) [<message>]

If the individual you are sending this proof to requires you to prove you have 1000 $OXEN you will need to replace the section (all|<amount>) with a 1000, otherwise replace it with the amount you need to prove you have reserved. If you want to put an extra layer of encryption over the file replace [<message>] with a password.

Your command will similar to the below command:

get_reserve_proof 1000 Car

The CLI will request your wallet password and once your password is entered it will tell you it generated a signature file.

[wallet T6TmZX]: get_reserve_proof 1000 Car
Wallet password:
signature file saved to: oxen_reserve_proof

This signature file oxen_reserve_proof will be saved in your Oxen folder, where your daemon and wallet keys are. Keep in mind every time you run the get_reserve_proof command it will overwrite youroxen_reserve_proof file.

You will want to send this file to the person who requires the proof. You can upload the oxen_reserve_proof file through https://transfer.sh/ by running the command within the folder of your signature file:

curl --upload-file ./oxen_reserve_proof https://transfer.sh/oxen_reserve_proof`

The terminal will then print out a link to your signature file which you can then provide to the individual performing the check.

https://transfer.sh/QhoC7/oxen_reserve_proof

Make sure you provide the following to the individual who will be checking your reserve proof:

  • The oxen_reserve_proof file through the transfer.sh link.

  • The Oxen address you are proving has $OXEN in it.

  • The <message> if you encrypted the file.

5.2 Checking Reserve Proof

To check a reserve proof we need to first have the oxen_reserve_proof file in our Oxen folder.

If you do not have the oxen_reserve_proof file in your Oxen folder request the individual sending the file to you to use https://transfer.sh/, once they send you the link to their oxen_reserve_proof you can use the following command to download it.

curl <link> -o oxen_reserve_proof

Replacing <link> with the link to download the oxen_reserve_proof.

Now that the oxen_reserve_proof is in our folder we can run the following command:

check_reserve_proof <address> <signature_file> [<message>]

Where <address> is the address of the wallet where the command get_reserve_proof was ran. <signature_file> is the file that was received from the individual sending you the reserve proof, normally generated as oxen_reserve_proof and <message> is the key set by the individual who sent you the reserve proof.

Therefor for the previous example where we created a reserve proof for 1000 $OXEN and signed with “car”, we would run the command:

check_reserve_proof T6TmZX8EzZVjS9zNg7zAsrEQFDgcVC2qV2ZMyoWsbyK4SNB2SwMHZtMhPSsFyTmRBQUaGVF5k3qy5CMFM6Lvj7gi3AeszDag7 oxen_reserve_proof Car

If all goes well, the terminal will output the following:

Good signature -- total: 1014.862440831, spent: 0.000000000, unspent: 1014.862440831

You may note that it shows a reserve proof which is greater than 1000, this is because the command is adding up all the transactions into the address specified until it is greater than the reserve proof set.

6 Spend Proof

Spend Proofs are used to generate a signature proving that you generated a TXID, with the option to sign the spend proof with a key.

For example let’s imagine you have bought a car from a dealership with $OXEN and have sent 1000 $OXEN to the seller. Unfortunately the dealer does not know which transaction is yours as he has received 5 transactions of 1000 $OXEN in the same block for 5 different cars. He knows the txid’s but wants you to prove that you have generate one of the txid’s in his list. Luckily we can prove we generated the txid by using the get_spend_proof command.

6.1 Generate Spend Proof

To begin we will first need to find the txid associated with our transaction. To do this run the following command in our wallet:

show_transfers

The terminal will output a list of transactions in and out of your address. You should have a transaction in your list with the amount you spent to the dealership. Copy the txid(by highlighting) associated with this transaction and save it in a notepad for later.

We can now run the get_spend_proof command to generate our proof.

get_spend_proof <txid> [<message>]

Replacing <txid> with the txid of our transfer out and replacing <message> if we want to add a password to the proof. If all went well the terminal will output the following text:

signature file saved to: oxen_spend_proof

This signature file oxen_spend_proof will be saved in your Oxen folder, where your daemon and wallet keys are. Keep in mind every time you run the get_spend_proof command it will overwrite your oxen_spend_proof file.

You will want to send this file to the person who requires the proof. You can upload the oxen_spend_proof file through https://transfer.sh/ by running the command within the folder of your signature file:

curl --upload-file ./oxen_spend_proof https://transfer.sh/oxen_spend_proof

The terminal will then print out a link to your signature file which you can then provide to the individual performing the check. For example:

https://transfer.sh/QhoC7/oxen_spend_proof

Make sure you provide the following to the individual who will be checking your reserve proof:

  • The oxen_spend_proof file through the transfer.sh link.

  • The $OXEN transaction txid associated with the transaction you are proving you generated.

  • The <message> if you encrypted the file.

6.2 Checking Spend Proof

To check a spend proof we need to first have the oxen_spend_proof file in our Oxen folder and the txid associated with the transaction being proved.

If you do not have the oxen_spend_proof file in your Oxen folder request the individual sending the file to you to use https://transfer.sh/, once they send you the link to their oxen_spend_proof you can use the following command to download it.

curl <link> -o oxen_spend_proof

Replacing <link> with the link to download the oxen_spend_proof.

Now that the oxen_spend_proof is in our folder we can run the following command:

check_spend_proof <txid> <signature_file> [<message>]

Where <txid> is the txid associated with the transaction that is being proved. <signature_file> is the file that was received from the individual sending you the spend proof, normally generated as oxen_spend_proof and <message> is the key set by the individual who sent you the spend proof.

An example would look like the following command

check_spend_proof 20eb3b5545d6587e5a379feb2fc69b43d4f8b6b825bb7eff78e263d4e7e8eaa9 oxen_spend_proof car

If all goes well, the terminal will output the following:

Good signature

If you receive a Good signature message that should be a good proof that the txid you are checking was generated from the sender. Keep in mind however that this can potentially not always be the case, considering someone could get access to someone else's computer thus having access to this file.

7 TX Proof

TX Proofs are used to generate a signature file proving that you generated a TXID, with the option to sign the spend proof with a key. TX proofs work similar to Reserve Proof’s and Spend Proofs however they show more detailed information.

For example let’s imagine you have bought a car from a dealership with $OXEN and have sent 1000 $OXEN to the seller. Unfortunately the dealer does not know which transaction is yours as he has received 5 transactions of 1000 $OXEN in the same block for 5 different cars. He knows the txid’s but wants you to prove that you have generate one of the txid’s in his list. Luckily we can prove we generated the txid by using the get_tx_proof command.

7.1 Generate Spend Proof

To begin we will first need to find the txid associated with our transaction. To do this run the following command in our wallet:

show_transfers

The terminal will output a list of transactions in and out of your address. You should have a transaction in your list with the amount you spent to the dealership. Copy the txid(by highlighting) associated with this transaction and save it in a notepad for later.

We can now run the get_tx_proof command to generate our proof.

get_tx_proof <txid> <address> [<message>]

Replacing <txid> with the txid of our transfer out, <address> with the receiver's address, and replacing <message> if we want to add a password to the proof. If all went well the terminal will output the following text:

signature file saved to: oxen_tx_proof

This signature file oxen_tx_proof will be saved in your Oxen folder, where your daemon and wallet keys are. Keep in mind every time you run the get_tx_proof command it will overwrite your oxen_tx_proof file.

You will want to send this file to the person who requires the proof. You can upload the oxen_tx_proof file through https://transfer.sh/ by running the command within the folder of your signature file:

curl --upload-file ./oxen_tx_proof https://transfer.sh/oxen_tx_proof

The terminal will then print out a link to your signature file which you can then provide to the individual performing the check. For example:

https://transfer.sh/QhoC7/oxen_tx_proof

Make sure you provide the following to the individual who will be checking your reserve proof:

  • The oxen_tx_proof file through the transfer.sh link.

  • The $OXEN transaction txid associated with the transaction you are proving you generated.

  • The receiver's Oxen address.

  • The <message> if you encrypted the file.

7.2 Checking tx Proof

To check a tx proof we need to first have the oxen_tx_proof file in our Oxen folder, the receiver's address and the txid associated with the transaction being proved.

If you do not have the oxen_tx_proof file in your Oxen folder request the individual sending the file to you to use https://transfer.sh/, once they send you the link to their oxen_tx_proof you can use the following command to download it.

curl <link> -o oxen_tx_proof

Replacing <link> with the link to download the oxen_tx_proof.

Now that the oxen_tx_proof is in our folder we can run the following command:

check_tx_proof <txid> <address> <signature_file> [<message>]

Where <txid> is the txid associated with the transaction that is being proved, <address> is the receiver’s address and <signature_file> is the file that was received from the individual sending you the tx proof, normally generated as oxen_tx_proof and <message> is the key set by the individual who sent you the tx proof.

An example would look like the following command:

check_tx_proof 3f8c62b4d83100ff4f89b44a96350e65aeaa83a9b4273c31f94b9aa12e713044 TRrEpWMLd3rRuirYqsjg1iaNsukAAojWjFDhJ2kK2o4uM6tkcjMerA4SZNat6QHEYe1SoGCFQddVPgRqmkA8kARX1ffU1Wcjc oxen_tx_proof

If all goes well, the terminal will output the following:

Good signature
TRrEpWMLd3rRuirYqsjg1iaNsukAAojWjFDhJ2kK2o4uM6tkcjMerA4SZNat6QHEYe1SoGCFQddVPgRqmkA8kARX1ffU1Wcjc received 40000.000000 in txid <3f8c62b4d83100ff4f89b44a96350e65aeaa83a9b4273c31f94b9aa12e713044>
This transaction has 1 confirmations

If you receive a Good signature message that should be a good proof that the txid you are checking was generated from the sender. Keep in mind however that this can potentially not always be the case, considering someone could get access to someone else's computer thus having access to this file.

8 TX key

A TX key is a private key associated with a TXid. Only the wallet that has sent the transaction can generate a TX key from the TXID that both parties can see. A TX key can be used to validate a transaction on a case by case basis. In essence, you can provide the tx key, txid and the receiver address to someone to prove you had generate that transaction.

8.1 View TX key

To view the TX key of a specific transaction you have generate you will need to run the command:

get_tx_key <txid>

Where <txid> is the transaction id associated with the transfer out you are proving is yours.

The terminal will prompt the user for the wallet's password and then print out the tx key, which will look similar to:

[wallet T6TmZX]: get_tx_key d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f
Wallet password:
Tx key: 5dfc4d677e2707317f306219b6aa445feaab4c652927237c012f7e72cb41bf0e

Provide the <tx key> with the <txid> and <receiving address> to the individual who will run the validation, thus this will prove you generated the transaction.

8.2 Validate transaction with TX key

Once we have a <tx key>, <txid> and <receiving address> from a specific transaction we can use the following command to prove they are all associated:

check_tx_key <txid> <txkey> <address>

For the previous example we would run the following command from any Oxen wallet:

check_tx_key d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f 5dfc4d677e2707317f306219b6aa445feaab4c652927237c012f7e72cb41bf0e T6TZ2VaG1p9PQkDgdVCYwnjoxYSU7ErXX56etGsqHLugAGqynFwBvP4dnN7wvYCcJfMa9LPgtYu8UEUqyc4xsxmx2ZTyMp4U3

The terminal will show text of how much $OXEN the address received. It will also show how many confirmations the transaction has received from the blockchain. For example:

[wallet T6TZ2V]: check_tx_key d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f 5dfc4d677e2707317f306219b6aa445feaab4c652927237c012f7e72cb41bf0e T6TZ2VaG1p9PQkDgdVCYwnjoxYSU7ErXX56etGsqHLugAGqynFwBvP4dnN7wvYCcJfMa9LPgtYu8UEUqyc4xsxmx2ZTyMp4U3  
T6TZ2VaG1p9PQkDgdVCYwnjoxYSU7ErXX56etGsqHLugAGqynFwBvP4dnN7wvYCcJfMa9LPgtYu8UEUqyc4xsxmx2ZTyMp4U3 received 10000.000000000 in txid <d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f>
This transaction has 10 confirmations

9 Tx Notes

The oxen-wallet-cli allows you to add notes to specific txid’s, however this note does not get stored on the blockchain, rather it is stored on client side, on the device that generates the tx_note.

9.1 Set tx note

To set a tx note we will need a the <txid> and the <message> you want to add to the txid. For instance, if you want to add a note to a txid that is connected to your wallet run the following command to show your transactions in/out with their <txid>’s:

show_transfers

To set the note to the <txid> run the following command:

set_tx_note <txid> [free text note]

Where <txid> is the transaction id associated to the transaction you are adding the [free text note] too. Your command will look similar to the following example:

[wallet T6TmZX]: set_tx_note d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f This is a tx note example.

9.2 View tx note

To view a note connected to a txid run the following command:

get_tx_note <txid>

Where <txid> is the transaction id that has the note connected to it. For example, if we run the command on the previous <txid> mentioned, the terminal will display the following text:

[wallet T6TmZX]: get_tx_note d5fb415aad43f4e45bc72566d5ad4c8f12629db1f924d953efc2521c137a987f
note found: This is a tx note example.

You can also view a tx note by running the show_transfers command, each transaction that has a note connected to it will display the text to the right of each transfer.

10 Changing wallet password

Changing the wallet password is only client side(locally), and if the password is forgotten the wallet can always be restored with the mnemonic seed. If you know the password to the wallet and want to change it you can run the following command:

password

Once the command has been run the terminal will prompt you for the current password and the new password twice. If entered correctly the terminal will go back to receiving inputs, otherwise the terminal will output an error such as Passwords do not match! Please try again or Error: invalid password.

11 Encrypting seed phrase

Your seed passphrase is a 25 word phrase which is used to recover access to your wallet on a client or gui and is. The command encrypted_seed allows your to add an additional password, or encryption layer, to your 25 word mnemonic seed. Encrypting your seed will stop others from recovering access to your wallet if they somehow gain access to your 25 word mnemonic seed as they will not have the passphrase that decrypts them. This means, your passphrase should not be written or saved in the same location as your encrypted 25 word mnemonic seed phrase.

To encrypt your seed run the following command:

encrypted_seed

Initially the CLI wallet will prompt you to enter your wallet password. Next it will request for your seed encryption passphrase, enter in your desired password/passphrase once, click enter, then type the passphrase in again.

The wallet will output your mnemonic seed which is a 25 word passphrase. It is generally best practice to write these 25 words down and store them somewhere safe and securely, write your passphrase down(which is the phrase you used to encrypt the 25 words) and store this somewhere else. Storing the 25 words with the passphrase in a file on your computer that is not encrypted is giving others easier access to your mnemonic seed.

Daemon 📞 RPC calls

Introduction

This is a list of the oxend daemon RPC calls, their inputs and outputs, and examples of each.

Many RPC calls use the daemon's JSON RPC interface while others use their own interfaces, as demonstrated below.

Note: "atomic units" refer to the smallest fraction of 1 $OXEN according to the oxend implementation. 1 $OXEN = 1e12 atomic units.

JSON RPC Methods:

  • get_block_count

  • on_get_block_hash

  • get_block_template

  • submit_block

  • get_last_block_header

  • get_block_header_by_hash

  • get_block_header_by_height

  • get_block_headers_range

  • get_block

  • get_connections

  • get_info

  • hard_fork_info

  • set_bans

  • get_bans

  • flush_txpool

  • get_output_histogram

  • get_version

  • get_coinbase_tx_sum

  • get_fee_estimate

  • get_alternate_chains

  • relay_tx

  • get_txpool_backlog

  • get_output_distribution

Other RPC Methods:

  • /get_height

  • /get_blocks.bin

  • /get_blocks_by_height.bin

  • /get_hashes.bin

  • /get_o_indexes.bin

  • /get_outs.bin

  • /get_transactions

  • /get_alt_blocks_hashes

  • /is_key_image_spent

  • /send_raw_transaction

  • /save_bc

  • /get_peer_list

  • /set_log_hash_rate

  • /set_log_level

  • /set_log_categories

  • /get_transaction_pool

  • /get_transaction_pool_hashes.bin

  • /get_transaction_pool_stats

  • /stop_daemon

  • /get_info (not JSON)

  • /get_limit

  • /set_limit

  • /out_peers

  • /in_peers

  • /start_save_graph

  • /stop_save_graph

  • /get_outs

  • /update

JSON RPC Methods

The majority of oxend RPC calls use the daemon's json_rpc interface to request various bits of information. These methods all follow a similar structure, for example:

IP=127.0.0.1
PORT=18081
METHOD='get_block_header_by_height'
ALIAS='getblockheaderbyheight'
PARAMS='{"height":912345}'
curl \
    -X POST http://$IP:$PORT/json_rpc \
    -d '{"jsonrpc":"2.0","id":"0","method":"'$METHOD'","params":'$PARAMS'}' \
    -H 'Content-Type: application/json'

Some methods include parameters, while others do not. Examples of each JSON RPC method follow.

get_block_count

Look up how many blocks are in the longest chain known to the node.

Alias: getblockcount.

Inputs: None.

Outputs:

  • count - unsigned int; Number of blocks in longest chain seen by the node.

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block_count"}' -H 'Content-Type: application/json'  

{  
  "id": "0",  
  "jsonrpc": "2.0",  
  "result": {  
    "count": 993163,  
    "status": "OK"  
  }  
}

on_get_block_hash

Look up a block's hash by its height.

Alias: on_getblockhash.

Inputs:

  • block height (int array of length 1)

Outputs:

  • block hash (string)

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"on_get_block_hash","params":[912345]}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6"
}

get_block_template

Get a block template on which mining a new block.

Alias: getblocktemplate.

Inputs:

  • wallet_address - string; Address of wallet to receive coinbase transactions if block is successfully mined.

  • reserve_size - unsigned int; Reserve size.

Outputs:

  • blocktemplate_blob - string; Blob on which to try to mine a new block.

  • blockhashing_blob - string; Blob on which to try to find a valid nonce.

  • difficulty - unsigned int; Difficulty of next block.

  • expected_reward - unsigned int; Coinbase reward expected to be received if block is successfully mined.

  • height - unsigned int; Height on which to mine.

  • prev_hash - string; Hash of the most recent block on which to mine the next block.

  • reserved_offset - unsigned int; Reserved offset.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block_template","params":{"wallet_address":"44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns","reserve_size":60}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "blockhashing_blob": "070786a498d705f8dc58791266179087907a2ff4cd883615216749b97d2f12173171c725a6f84a00000000fc751ea4a94c2f840751eaa36138eee66dda15ef554e7d6594395827994e31da10",
    "blocktemplate_blob": "070786a498d705f8dc58791266179087907a2ff4cd883615216749b97d2f12173171c725a6f84a0000000002aeab5f01fff2aa5f01e0a9d0f2f08a01028fdb3d5b5a2c363d36ea17a4add99a23a3ec7935b4c3e1e0364fcc4295c7a2ef5f01f912b15f5d17c1539d4722f79d8856d8654c5af87f54cfb3a4ff7f6b512b2a08023c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1755090c809421d69873c161e7969b8bf33cee3b451dd4859bfc244a705f0b4900498f804b6023e13fa023a0fb759e8b7c9a39506a21442bc47077beeedc6b78d34c4ebdae91bd96097ccc9a882bc5056568b0d2f1f06559368fea4acba8e745444e883e53156d5083c1fd260edf05292934c8b40c098b81fe4e261720bdd272b209e317247a1d2c55dc4718891af0d16273c5a610f36f382a3bf50f54808aaa6a508e51d4601dd0d8fbf8b3b1685066ce121666a1409e8ac7a4d673c1cc36d10b825f764af647441f53230518e4d2efbcf8791c6060912c76e90db4982a66d51bbd96290bbb34db8080b216c2940cec407260bf5e2c3a5ee280835f15298f0801e9d98c4d414792282fbc2c28c3e20bc0fcb1829b5c3ad8f8d20847be8fdb2a949fd96f0205fbd6d271c880c5d8c83e9813606cd803a44d377fdeae45bfa67112132af601e9b3b0613ba7dff2ec3d4b935c447b47bfe39f7b950981b2f4c66c0d853e2218f1f69229a9b608c3d98be09b6d4d640a9f6ff0e920dbacf7e58b59554c0b398b1ae4b1d497104b4e4e745d850eed7eddb8aa93437427bf442ae5beb22cbf10a8fa738ea38cfa5d86dfd30675d4be11a38016e36936fd5601e52643e8b8bc433702ea7ae6149309c95b898cc854850e73fe0b95c5b8879b7325ecd4",
    "difficulty": 61043624293,
    "expected_reward": 4771949057248,
    "height": 1561970,
    "prev_hash": "f8dc58791266179087907a2ff4cd883615216749b97d2f12173171c725a6f84a",
    "reserved_offset": 129,
    "status": "OK",
    "untrusted": false
  }
}

submit_block

Submit a mined block to the network.

Alias: submitblock.

Inputs:

  • Block blob data - array of strings; list of block blobs which have been mined. See get_block_template to get a blob on which to mine.

Outputs:

  • status - string; Block submit status.

In this example, a block blob which has not been mined is submitted:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"submit_block","params":["0707e6bdfedc053771512f1bc27c62731ae9e8f2443db64ce742f4e57f5cf8d393de28551e441a0000000002fb830a01ffbf830a018cfe88bee283060274c0aae2ef5730e680308d9c00b6da59187ad0352efe3c71d36eeeb28782f29f2501bd56b952c3ddc3e350c2631d3a5086cac172c56893831228b17de296ff4669de020200000000"]' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "error": {
    "code": -7,
    "message": "Block not accepted"
  }
}

get_last_block_header

Block header information for the most recent block is easily retrieved with this method. No inputs are needed.

Alias: getlastblockheader.

Inputs: None.

Outputs:

  • block_header - A structure containing block header information.

    • block_size - unsigned int; The block size in bytes.

    • depth - unsigned int; The number of blocks succeeding this block on the blockchain. A larger number means an older block.

    • difficulty - unsigned int; The strength of the Oxen network

    • hash - string; The hash of this block.

    • height - unsigned int; The number of blocks preceding this block on the blockchain.

    • major_version - unsigned int; The major version of the Oxen protocol at this block height.

    • minor_version - unsigned int; The minor version of the Oxen protocol at this block height.

    • nonce - unsigned int; a cryptographic random one-time number used in mining a $OXEN block.

    • num_txes - unsigned int; Number of transactions in the block, not counting the coinbase tx.

    • orphan_status - boolean; Usually false. If true, this block is not part of the longest chain.

    • prev_hash - string; The hash of the block immediately preceding this block in the chain.

    • reward - unsigned int; The amount of new generated in this block and rewarded to the miner. Note: 1 $OXEN = 1e12 atomic units.

    • timestamp - unsigned int; The unix time at which the block was recorded into the blockchain.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

In this example, the most recent block (1562023 at the time) is returned:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_last_block_header"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "block_header": {
      "block_size": 62774,
      "depth": 0,
      "difficulty": 60097900840,
      "hash": "3a289b8fa88b10e2163826c230b45d79f2be37d14fa3153ee58ff8a427782d14",
      "height": 1562023,
      "major_version": 7,
      "minor_version": 7,
      "nonce": 3789681204,
      "num_txes": 5,
      "orphan_status": false,
      "prev_hash": "743e5d0a26849efe27b96086f2c4ecc39a0bc744bf21473dad6710221aff6ac3",
      "reward": 4724029079703,
      "timestamp": 1525029411
    },
    "status": "OK",
    "untrusted": false
  }
}

get_block_header_by_hash

Block header information can be retrieved using either a block's hash or height. This method includes a block's hash as an input parameter to retrieve basic information about the block.

Alias: getblockheaderbyhash.

Inputs:

  • hash - string; The block's sha256 hash.

Outputs:

  • block_header - A structure containing block header information. See get_last_block_header.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

In this example, block 912345 is looked up by its hash:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block_header_by_hash","params":{"hash":"e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6"}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "block_header": {
      "block_size": 210,
      "depth": 649717,
      "difficulty": 815625611,
      "hash": "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6",
      "height": 912345,
      "major_version": 1,
      "minor_version": 2,
      "nonce": 1646,
      "num_txes": 0,
      "orphan_status": false,
      "prev_hash": "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78",
      "reward": 7388968946286,
      "timestamp": 1452793716
    },
    "status": "OK",
    "untrusted": false
  }
}

get_block_header_by_height

Similar to get_block_header_by_hash above, this method includes a block's height as an input parameter to retrieve basic information about the block.

Alias: getblockheaderbyheight.

Inputs:

  • height - unsigned int; The block's height.

Outputs:

  • block_header - A structure containing block header information. See get_last_block_header.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

In this example, block 912345 is looked up by its height (notice that the returned information is the same as in the previous example):

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block_header_by_height","params":{"height":912345}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "block_header": {
      "block_size": 210,
      "depth": 649721,
      "difficulty": 815625611,
      "hash": "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6",
      "height": 912345,
      "major_version": 1,
      "minor_version": 2,
      "nonce": 1646,
      "num_txes": 0,
      "orphan_status": false,
      "prev_hash": "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78",
      "reward": 7388968946286,
      "timestamp": 1452793716
    },
    "status": "OK",
    "untrusted": false
  }
}

get_block_headers_range

Similar to get_block_header_by_height above, but for a range of blocks. This method includes a starting block height and an ending block height as parameters to retrieve basic information about the range of blocks.

Alias: getblockheadersrange.

Inputs:

  • start_height - unsigned int; The starting block's height.

  • end_height - unsigned int; The ending block's height.

Outputs:

  • headers - array of block_header (a structure containing block header information. See get_last_block_header).

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

In this example, blocks range from height 1545999 to 1546000 is looked up (notice that the returned informations are ascending order and that it is at the April 2018 network upgrade time):

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block_headers_range","params":{"start_height":1545999,"end_height":1546000}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "headers": [{
      "block_size": 301413,
      "depth": 16085,
      "difficulty": 134636057921,
      "hash": "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a",
      "height": 1545999,
      "major_version": 6,
      "minor_version": 6,
      "nonce": 3246403956,
      "num_txes": 20,
      "orphan_status": false,
      "prev_hash": "0ef6e948f77b8f8806621003f5de24b1bcbea150bc0e376835aea099674a5db5",
      "reward": 5025593029981,
      "timestamp": 1523002893
    },{
      "block_size": 13322,
      "depth": 16084,
      "difficulty": 134716086238,
      "hash": "b408bf4cfcd7de13e7e370c84b8314c85b24f0ba4093ca1d6eeb30b35e34e91a",
      "height": 1546000,
      "major_version": 7,
      "minor_version": 7,
      "nonce": 3737164176,
      "num_txes": 1,
      "orphan_status": false,
      "prev_hash": "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a",
      "reward": 4851952181070,
      "timestamp": 1523002931
    }],
    "status": "OK",
    "untrusted": false
  }
}

get_block

Full block information can be retrieved by either block height or hash, like with the above block header calls. For full block information, both lookups use the same method, but with different input parameters.

Alias: getblock.

Inputs (pick one of the following):

  • height - unsigned int; The block's height.

  • hash - string; The block's hash.

Outputs:

  • blob - string; Hexadecimal blob of block information.

  • block_header - A structure containing block header information. See get_last_block_header.

  • json - json string; JSON formatted block details:

    • major_version - Same as in block header.

    • minor_version - Same as in block header.

    • timestamp - Same as in block header.

    • prev_id - Same as prev_hash in block header.

    • nonce - Same as in block header.

    • miner_tx - Miner transaction information

      • version - Transaction version number.

      • unlock_time - The block height when the coinbase transaction becomes spendable.

      • vin - List of transaction inputs:

        • gen - Miner txs are coinbase txs, or "gen".

          • height - This block height, a.k.a. when the coinbase is generated.

      • vout - List of transaction outputs. Each output contains:

        • amount - The amount of the output, in atomic units.

        • target -

          • key -

      • extra - Usually called the "transaction ID" but can be used to include any random 32 byte/64 character hex string.

      • signatures - Contain signatures of tx signers. Coinbased txs do not have signatures.

    • tx_hashes - List of hashes of non-coinbase transactions in the block. If there are no other transactions, this will be an empty list.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Look up by height:

In the following example, block 912345 is looked up by its height. Note that block 912345 does not have any non-coinbase transactions. (See the next example for a block with extra transactions):

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block","params":{"height":912345}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "blob": "0102f4bedfb405b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff786e0600000195d83701ffd9d73704ee84ddb42102378b043c1724c92c69d923d266fe86477d3a5ddd21145062e148c64c5767700880c0fc82aa020273733cbd6e6218bda671596462a4b062f95cfe5e1dbb5b990dacb30e827d02f280f092cbdd080247a5dab669770da69a860acde21616a119818e1a489bb3c4b1b6b3c50547bc0c80e08d84ddcb01021f7e4762b8b755e3e3c72b8610cc87b9bc25d1f0a87c0c816ebb952e4f8aff3d2b01fd0a778957f4f3103a838afda488c3cdadf2697b3d34ad71234282b2fad9100e02080000000bdfc2c16c00",
    "block_header": {
      "block_size": 210,
      "depth": 649772,
      "difficulty": 815625611,
      "hash": "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6",
      "height": 912345,
      "major_version": 1,
      "minor_version": 2,
      "nonce": 1646,
      "num_txes": 0,
      "orphan_status": false,
      "prev_hash": "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78",
      "reward": 7388968946286,
      "timestamp": 1452793716
    },
    "json": "{\n  \"major_version\": 1, \n  \"minor_version\": 2, \n  \"timestamp\": 1452793716, \n  \"prev_id\": \"b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78\", \n  \"nonce\": 1646, \n  \"miner_tx\": {\n    \"version\": 1, \n    \"unlock_time\": 912405, \n    \"vin\": [ {\n        \"gen\": {\n          \"height\": 912345\n        }\n      }\n    ], \n    \"vout\": [ {\n        \"amount\": 8968946286, \n        \"target\": {\n          \"key\": \"378b043c1724c92c69d923d266fe86477d3a5ddd21145062e148c64c57677008\"\n        }\n      }, {\n        \"amount\": 80000000000, \n        \"target\": {\n          \"key\": \"73733cbd6e6218bda671596462a4b062f95cfe5e1dbb5b990dacb30e827d02f2\"\n        }\n      }, {\n        \"amount\": 300000000000, \n        \"target\": {\n          \"key\": \"47a5dab669770da69a860acde21616a119818e1a489bb3c4b1b6b3c50547bc0c\"\n        }\n      }, {\n        \"amount\": 7000000000000, \n        \"target\": {\n          \"key\": \"1f7e4762b8b755e3e3c72b8610cc87b9bc25d1f0a87c0c816ebb952e4f8aff3d\"\n        }\n      }\n    ], \n    \"extra\": [ 1, 253, 10, 119, 137, 87, 244, 243, 16, 58, 131, 138, 253, 164, 136, 195, 205, 173, 242, 105, 123, 61, 52, 173, 113, 35, 66, 130, 178, 250, 217, 16, 14, 2, 8, 0, 0, 0, 11, 223, 194, 193, 108\n    ], \n    \"signatures\": [ ]\n  }, \n  \"tx_hashes\": [ ]\n}",
    "miner_tx_hash": "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30",
    "status": "OK",
    "untrusted": false
  }
}

Look up by hash:

In the following example, block 993056 is looked up by its hash. Note that block 993056 has 3 non-coinbase transactions:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block","params":{"hash":"510ee3c4e14330a7b96e883c323a60ebd1b5556ac1262d0bc03c24a3b785516f"}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "blob": "0102a3978cb7050ea4af6547c05c965afc8df6d31509ff3105dc7ae6b10172521d77e09711fd6df407000001dcce3c01ffa0ce3c049da8bece070259e9d685b3484886bc7b47c133e6099ecdf212d5eaa16ce19cd58e8c3c1e590a80d88ee16f024c5e2f542d25513c46b9e3b7d40140a22d0ae5314bfcae492ad9f56fff8185f080d0b8e1981a0213dd8ffdac9e6a2f71e327dad65328198dc879a492d145eae72677c0703a351580c0f9decfae010262bda00341681dccbc066757862da593734395745bdfe1fdc89b5948c86a5d4c2b01b691851cf057b9c302a3dbca879e1cba4cc45061ca55aaa6e03cdc67ab9e455002080000000c617fdf160379c6b9f00db027bde151705aafe85c495883aae2597d5cb8e1adb2e0f3ae1d07d715db73331abc3ec588ef07c7bb195786a4724b08dff431b51ffa32a4ce899bb197066426c0ed89f0b431fe171f7fd62bc95dd29943daa7cf3585cf1fdfc99d",
    "block_header": {
      "block_size": 3981,
      "depth": 569068,
      "difficulty": 964985344,
      "hash": "510ee3c4e14330a7b96e883c323a60ebd1b5556ac1262d0bc03c24a3b785516f",
      "height": 993056,
      "major_version": 1,
      "minor_version": 2,
      "nonce": 2036,
      "num_txes": 3,
      "orphan_status": false,
      "prev_hash": "0ea4af6547c05c965afc8df6d31509ff3105dc7ae6b10172521d77e09711fd6d",
      "reward": 6932043647005,
      "timestamp": 1457720227
    },
    "json": "{\n  \"major_version\": 1, \n  \"minor_version\": 2, \n  \"timestamp\": 1457720227, \n  \"prev_id\": \"0ea4af6547c05c965afc8df6d31509ff3105dc7ae6b10172521d77e09711fd6d\", \n  \"nonce\": 2036, \n  \"miner_tx\": {\n    \"version\": 1, \n    \"unlock_time\": 993116, \n    \"vin\": [ {\n        \"gen\": {\n          \"height\": 993056\n        }\n      }\n    ], \n    \"vout\": [ {\n        \"amount\": 2043647005, \n        \"target\": {\n          \"key\": \"59e9d685b3484886bc7b47c133e6099ecdf212d5eaa16ce19cd58e8c3c1e590a\"\n        }\n      }, {\n        \"amount\": 30000000000, \n        \"target\": {\n          \"key\": \"4c5e2f542d25513c46b9e3b7d40140a22d0ae5314bfcae492ad9f56fff8185f0\"\n        }\n      }, {\n        \"amount\": 900000000000, \n        \"target\": {\n          \"key\": \"13dd8ffdac9e6a2f71e327dad65328198dc879a492d145eae72677c0703a3515\"\n        }\n      }, {\n        \"amount\": 6000000000000, \n        \"target\": {\n          \"key\": \"62bda00341681dccbc066757862da593734395745bdfe1fdc89b5948c86a5d4c\"\n        }\n      }\n    ], \n    \"extra\": [ 1, 182, 145, 133, 28, 240, 87, 185, 195, 2, 163, 219, 202, 135, 158, 28, 186, 76, 196, 80, 97, 202, 85, 170, 166, 224, 60, 220, 103, 171, 158, 69, 80, 2, 8, 0, 0, 0, 12, 97, 127, 223, 22\n    ], \n    \"signatures\": [ ]\n  }, \n  \"tx_hashes\": [ \"79c6b9f00db027bde151705aafe85c495883aae2597d5cb8e1adb2e0f3ae1d07\", \"d715db73331abc3ec588ef07c7bb195786a4724b08dff431b51ffa32a4ce899b\", \"b197066426c0ed89f0b431fe171f7fd62bc95dd29943daa7cf3585cf1fdfc99d\"\n  ]\n}",
    "miner_tx_hash": "372395aeac5e5ad2c40b4c546b0bad00c4242fb2bd88e2e25f4e43231876f81e",
    "status": "OK",
    "tx_hashes": ["79c6b9f00db027bde151705aafe85c495883aae2597d5cb8e1adb2e0f3ae1d07","d715db73331abc3ec588ef07c7bb195786a4724b08dff431b51ffa32a4ce899b","b197066426c0ed89f0b431fe171f7fd62bc95dd29943daa7cf3585cf1fdfc99d"],
    "untrusted": false
  }
}

get_connections

Retrieve information about incoming and outgoing connections to your node.

Alias: None.

Inputs: None.

Outputs:

  • connections - List of all connections and their info:

    • address - string; The peer's address, actually IPv4 & port

    • avg_download - unsigned int; Average bytes of data downloaded by node.

    • avg_upload - unsigned int; Average bytes of data uploaded by node.

    • connection_id - string; The connection ID

    • current_download - unsigned int; Current bytes downloaded by node.

    • current_upload - unsigned int; Current bytes uploaded by node.

    • height- unsigned int; The peer height

    • host - string; The peer host

    • incoming - boolean; Is the node getting information from your node?

    • ip - string; The node's IP address.

    • live_time - unsigned int

    • local_ip - boolean

    • localhost - boolean

    • peer_id - string; The node's ID on the network.

    • port - string; The port that the node is using to connect to the network.

    • recv_count - unsigned int

    • recv_idle_time - unsigned int

    • send_count - unsigned int

    • send_idle_time - unsigned int

    • state - string

    • support_flags - unsigned int

Following is an example of get_connections and it's return:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_connections"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "connections": [{
      "address": "173.90.69.136:62950",
      "avg_download": 0,
      "avg_upload": 2,
      "connection_id": "083c301a3030329a487adb12ad981d2c",
      "current_download": 0,
      "current_upload": 2,
      "height": 1562127,
      "host": "173.90.69.136",
      "incoming": true,
      "ip": "173.90.69.136",
      "live_time": 8,
      "local_ip": false,
      "localhost": false,
      "peer_id": "c959fbfbed9e44fb",
      "port": "62950",
      "recv_count": 259,
      "recv_idle_time": 8,
      "send_count": 24342,
      "send_idle_time": 8,
      "state": "state_normal",
      "support_flags": 0
    },{
    ...
    }],
    "status": "OK"
  }
}

get_info

Retrieve general information about the state of your node and the network.

Alias:

  • /get_info

  • /getinfo

See other RPC Methods /get_info (not JSON)

Inputs: None.

Outputs:

  • alt_blocks_count - unsigned int; Number of alternative blocks to main chain.

  • block_size_limit - unsigned int; Maximum allowed block size

  • block_size_median - unsigned int; Median block size of latest 100 blocks

  • bootstrap_daemon_address - string; bootstrap node to give immediate usability to wallets while syncing by proxying RPC to it. (Note: the replies may be untrustworthy).

  • cumulative_difficulty - unsigned int; Cumulative difficulty of all blocks in the blockchain.

  • difficulty - unsigned int; Network difficulty (analogous to the strength of the network)

  • free_space - unsigned int; Available disk space on the node.

  • grey_peerlist_size - unsigned int; Grey Peerlist Size

  • height - unsigned int; Current length of longest chain known to daemon.

  • height_without_bootstrap - unsigned int; Current length of the local chain of the daemon.

  • incoming_connections_count - unsigned int; Number of peers connected to and pulling from your node.

  • mainnet - boolean; States if the node is on the mainnet (true) or not (false).

  • offline - boolean; States if the node is offline (true) or online (false).

  • outgoing_connections_count - unsigned int; Number of peers that you are connected to and getting information from.

  • rpc_connections_count - unsigned int; Number of RPC client connected to the daemon (Including this RPC request).

  • stagenet - boolean; States if the node is on the stagenet (true) or not (false).

  • start_time - unsigned int; Start time of the daemon, as UNIX time.

  • status - string; General RPC error code. "OK" means everything looks good.

  • target - unsigned int; Current target for next proof of work.

  • target_height - unsigned int; The height of the next block in the chain.

  • testnet - boolean; States if the node is on the testnet (true) or not (false).

  • top_block_hash - string; Hash of the highest block in the chain.

  • tx_count - unsigned int; Total number of non-coinbase transaction in the chain.

  • tx_pool_size - unsigned int; Number of transactions that have been broadcast but not included in a block.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

  • was_bootstrap_ever_used - boolean; States if a bootstrap node has ever been used since the daemon started.

  • white_peerlist_size - unsigned int; White Peerlist Size

Following is an example get_info call and its return:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_info"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "alt_blocks_count": 6,
    "block_size_limit": 600000,
    "block_size_median": 129017,
    "bootstrap_daemon_address": "",
    "cumulative_difficulty": 14121125493385685,
    "difficulty": 60580751777,
    "free_space": 138758750208,
    "grey_peerlist_size": 4998,
    "height": 1562168,
    "height_without_bootstrap": 1562168,
    "incoming_connections_count": 2,
    "mainnet": true,
    "offline": false,
    "outgoing_connections_count": 8,
    "rpc_connections_count": 2,
    "stagenet": false,
    "start_time": 1524751757,
    "status": "OK",
    "target": 120,
    "target_height": 1562063,
    "testnet": false,
    "top_block_hash": "7a7ba647080844073fdd8e3a069e00554c773d6e6863354dba1dec45a43f5592",
    "tx_count": 2759894,
    "tx_pool_size": 755,
    "untrusted": false,
    "was_bootstrap_ever_used": false,
    "white_peerlist_size": 1000
  }
}

hard_fork_info

Look up information regarding hard fork voting and readiness.

Alias: None.

Inputs: None.

Outputs:

  • earliest_height - unsigned int; Block height at which hard fork would be enabled if voted in.

  • enabled - boolean; Tells if hard fork is enforced.

  • state - unsigned int; Current hard fork state: 0 (There is likely a hard fork), 1 (An update is needed to fork properly), or 2 (Everything looks good).

  • status - string; General RPC error code. "OK" means everything looks good.

  • threshold - unsigned int; Minimum percent of votes to trigger hard fork. Default is 80.

  • version - unsigned int; The major block version for the fork.

  • votes - unsigned int; Number of votes towards hard fork.

  • voting - unsigned int; Hard fork voting status.

  • window - unsigned int; Number of blocks over which current votes are cast. Default is 10080 blocks.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"hard_fork_info"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "earliest_height": 1009827,
    "enabled": false,
    "state": 2,
    "status": "OK",
    "threshold": 0,
    "version": 1,
    "votes": 7277,
    "voting": 2,
    "window": 10080
  }
}

set_bans

Ban another node by IP.

Alias: None.

Inputs:

  • bans - A list of nodes to ban:

    • host - string; Host to ban (IP in A.B.C.D form - will support I2P address in the future).

    • ip - unsigned int; IP address to ban, in Int format.

    • ban - boolean; Set true to ban.

    • seconds - unsigned int; Number of seconds to ban node.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Examples:

banning by host

In the following example, host is banned with its IP address string-formatted as A.B.C.D:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_bans","params":{"bans":[{"host":"192.168.1.51","ban":true,"seconds":30}]}}' -H  'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "status": "OK"
  }
}

banning by ip

In the following example, integer-formatted IP is banned:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_bans","params":{"bans":[{"ip":838969536,"ban":true,"seconds":30}]}}' -H  'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "status": "OK"
  }
}

get_bans

Get list of banned IPs.

Alias: None.

Inputs: None.

Outputs:

  • bans - List of banned nodes:

    • host - string; Banned host (IP in A.B.C.D form).

    • ip - unsigned int; Banned IP address, in Int format.

    • seconds - unsigned int; Local Unix time that IP is banned until.

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_bans"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "bans": [{
      "host": "102.168.1.51",
      "ip": 855746662,
      "seconds": 22
    },{
      "host": "192.168.1.50",
      "ip": 838969536,
      "seconds": 28
    }],
    "status": "OK"
  }
}

flush_txpool

Flush tx ids from transaction pool

Alias: None.

Inputs:

  • txids - array of strings; Optional, list of transactions IDs to flush from pool (all tx ids flushed if empty).

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"flush_txpool","params":{"txids":["dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308",""]}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "status": "OK"
  }
}

get_output_histogram

Get a histogram of output amounts. For all amounts (possibly filtered by parameters), gives the number of outputs on the chain for that amount. RingCT outputs counts as 0 amount.

Inputs:

  • amounts - list of unsigned int

  • min_count - unsigned int

  • max_count - unsigned int

  • unlocked - boolean

  • recent_cutoff - unsigned int

Outputs:

  • histogram - list of histogram entries, in the following structure:

    • amount - unsigned int; Output amount in atomic units

    • total_instances - unsigned int;

    • unlocked_instances - unsigned int;

    • recent_instances - unsigned int;

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_output_histogram","params":{"amounts":[20000000000]}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "histogram": [{
      "amount": 20000000000,
      "recent_instances": 0,
      "total_instances": 381458,
      "unlocked_instances": 0
    }],
    "status": "OK",
    "untrusted": false
  }
}

get_coinbase_tx_sum

Get the coinbase ammount and the fees ammount for n last blocks starting at particular height

Alias: None.

Inputs:

  • height - unsigned int; Block height from which getting the amounts

  • count - unsigned int; number of blocks to include in the sum

Outputs:

  • emission_amount - unsigned int; amount of coinbase reward in atomic units

  • fee_amount - unsigned int; amount of fees in atomic units

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_coinbase_tx_sum","params":{"height":1563078,"count":2}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "emission_amount": 9387854817320,
    "fee_amount": 83981380000,
    "status": "OK"
  }
}

get_version

Give the node current version

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

  • version - unsigned int;

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_version"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "status": "OK",
    "untrusted": false,
    "version": 65555
  }
}

get_fee_estimate

Gives an estimation on fees per kB.

Alias: None.

Inputs:

  • grace_blocks - unsigned int; Optional

Outputs:

  • fee - unsigned int; Amount of fees estimated per kB in atomic units

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_fee_estimate"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "fee": 187610000,
    "status": "OK",
    "untrusted": false
  }
}

get_alternate_chains

Display alternative chains seen by the node.

Alias: None.

Inputs: None.

Outputs:

  • chains - array of chains, the following structure:

    • block_hash - string; the block hash of the first diverging block of this alternative chain.

    • difficulty - unsigned int; the cumulative difficulty of all blocks in the alternative chain.

    • height - unsigned int; the block height of the first diverging block of this alternative chain.

    • length - unsigned int; the length in blocks of this alternative chain, after divergence.

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_alternate_chains"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "chains": [{
      "block_hash": "697cf03c89a9b118f7bdf11b1b3a6a028d7b3617d2d0ed91322c5709acf75625",
      "difficulty": 14114729638300280,
      "height": 1562062,
      "length": 2
    }],
    "status": "OK"
  }
}

relay_tx

Relay a list of transaction IDs.

Alias: None.

Inputs:

  • txids - array of string; list of transaction IDs to relay

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"relay_tx","params":{"txids":[9fd75c429cbe52da9a52f2ffc5fbd107fe7fd2099c0d8de274dc8a67e0c98613]}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "status": "OK"
  }
}

sync_info

Get synchronisation informations

Alias: None.

Inputs: None.

Outputs:

  • height - unsigned int;

  • peers - array of peer structure, defined as follows:

    • info - structure of connection info, as defined in get_connections

  • spans - array of span structure, defined as follows (optional, absent if node is fully synced):

    • connection_id - string; Id of connection

    • nblocks - unsigned int; number of blocks in that span

    • rate - unsigned int; connection rate

    • remote_address - string; peer address the node is downloading (or has downloaded) than span from

    • size - unsigned int; total number of bytes in that span's blocks (including txes)

    • speed - unsigned int; connection speed

    • start_block_height - unsigned int; block height of the first block in that span

  • status - string; General RPC error code. "OK" means everything looks good.

  • target_height - unsigned int; target height the node is syncing from (optional, absent if node is fully synced)

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sync_info"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "height": 1563543,
    "peers": [{
      "info": {
        "address": "70.109.53.128:60064",
        "avg_download": 0,
        "avg_upload": 5,
        "connection_id": "204067223b9b3415c265dd25ad29ee48",
        "current_download": 0,
        "current_upload": 1,
        "height": 1559975,
        "host": "70.109.53.128",
        "incoming": true,
        "ip": "70.109.53.128",
        "live_time": 38,
        "local_ip": false,
        "localhost": false,
        "peer_id": "96b8545dbc7a8866",
        "port": "60064",
        "recv_count": 1580,
        "recv_idle_time": 28,
        "send_count": 203603,
        "send_idle_time": 8,
        "state": "state_normal",
        "support_flags": 1
      }
    },{
      "info": {
        ...
      }
    },{
      ...
    },{
      ...
    },{
      ...
    }],
    "status": "OK",
    "target_height": 1564067
  }
}

get_txpool_backlog

Get all transaction pool backlog

Alias: None.

Inputs: None.

Outputs:

  • backlog: array of structures tx_backlog_entry (in binary form):

    • blob_size - unsigned int (in binary form)

    • fee - unsigned int (in binary form)

    • time_in_pool - unsigned int (in binary form)

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_txpool_backlog"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "backlog": "...Binary...",
    "status": "OK",
    "untrusted": false
  }
}

get_output_distribution

Alias: None.

Inputs:

  • amounts - array of unsigned int; amounts to look for

  • cumulative - boolean; (optional, default is false) States if the result should be cumulative (true) or not (false)

  • from_height - unsigned int; (optional, default is 0) starting height to check from

  • to_height - unsigned int; (optional, default is 0) ending height to check up to

Outputs:

  • distributions - array of structure distribution as follows:

    • amount - unsigned int

    • base - unsigned int

    • distribution - array of unsigned int

    • start_height - unsigned int

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_output_distribution","params":{"amounts":[628780000],"from_height":1462078}}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "distributions": [{
      "amount": 2628780000,
      "base": 0,
      "distribution": "",
      "start_height": 1462078
    }],
    "status": "OK"
  }
}

Other Daemon RPC Calls

Not all daemon RPC calls use the JSON_RPC interface. This section gives examples of these calls.

The data structure for these calls is different than the JSON RPC calls. Whereas the JSON RPC methods were called using the /json_rpc extension and specifying a method, these methods are called at their own extensions. For example:

IP=127.0.0.1
PORT=18081
METHOD='gettransactions'
PARAMS='{"txs_hashes":["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408"]}'
curl \
  -X POST http://$IP:$PORT/$METHOD \
  -d $PARAMS \
  -H 'Content-Type: application/json'

Note: It is recommended to use JSON RPC where such alternatives exist, rather than the following methods. For example, the recommended way to get a node's height is via the JSON RPC methods get_info or get_last_block_header, rather than getheight below.

For calls that end with .bin, the data is exchanged in the form of binary, serialized objects, as defined in the Core RPC Server.

/get_height

Get the node's current height.

Alias: /getheight.

Inputs: None.

Outputs:

  • height - unsigned int; Current length of longest chain known to daemon.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

$ curl -X POST http://127.0.0.1:18081/get_height -H 'Content-Type: application/json'

{
  "height": 1564055,
  "status": "OK",
  "untrusted": false
}

/get_blocks.bin

Get all blocks info. Binary request.

Alias: /getblocks.bin.

Inputs:

  • block_ids - binary array of hashes; first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block

  • start_height - unsigned int

  • prune - boolean

Outputs:

  • blocks - array of block complete entries

  • current_height - unsigned int

  • output_indices - structure as follows:

    • indices - array of tx output indices, structure as follows:

      • indices - array of unsigned int

  • start_height - unsigned int

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/get_blocks_by_height.bin

Get blocks by height. Binary request.

Alias: /getblocks_by_height.bin.

Inputs:

  • heights - array of unsigned int; list of block heights

Outputs:

  • blocks - array of block complete entries

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/get_hashes.bin

Get hashes. Binary request.

Alias: /gethashes.bin.

Inputs:

  • block_ids - binary array of hashes; first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block

  • start_height - unsigned int

Outputs:

  • current_height - unsigned int

  • m_block_ids - binary array of hashes; see block_ids above.

  • start_height - unsigned int

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/get_o_indexes.bin

Get global outputs of transactions. Binary request.

Alias: None.

Inputs:

  • txid - binary txid

Outputs:

  • o_indexes - array of unsigned int; List of output indexes

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/get_outs.bin

Get outputs. Binary request.

Alias: None.

Inputs:

  • outputs - array of structure get_outputs_out as follows:

    • amount - unsigned int;

    • index - unsigned int;

Outputs:

  • outs - array of structure outkey as follows:

    • amount - unsigned int;

    • height - unsigned int; block height of the output

    • key - the public key of the output

    • mask

    • txid - transaction id

    • unlocked - boolean; States if output is locked (false) or not (true)

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/get_transactions

Look up one or more transactions by hash.

Alias: /gettransactions.

Inputs:

  • txs_hashes - string list; List of transaction hashes to look up.

  • decode_as_json - boolean; Optional (false by default). If set true, the returned transaction information will be decoded rather than binary.

  • prune - boolean; Optional (false by default).

Outputs:

  • missed_tx - array of strings. (Optional - returned if not empty) Transaction hashes that could not be found.

  • status - General RPC error code. "OK" means everything looks good.

  • txs - array of structure entry as follows:

    • as_hex - string; Full transaction information as a hex string.

    • as_json - json string; List of transaction info:

      • version - Transaction version

      • unlock_time - If not 0, this tells when a transaction output is spendable.

      • vin - List of inputs into transaction:

        • key - The public key of the previous output spent in this transaction.

          • amount - The amount of the input, in atomic units.

          • key_offsets - A list of integer offets to the input.

          • k_image - The key image for the given input

      • vout - List of outputs from transaction:

        • amount - Amount of transaction output, in atomic units.

        • target - Output destination information:

          • key - The stealth public key of the receiver. Whoever owns the private key associated with this key controls this transaction output.

      • extra - Usually called the "payment ID" but can be used to include any random 32 bytes.

      • signatures - List of signatures used in ring signature to hide the true origin of the transaction.

    • block_height - unsigned int; block height including the transaction

    • block_timestamp - unsigned int; Unix time at chich the block has been added to the blockchain

    • double_spend_seen - boolean; States if the transaction is a double-spend (true) or not (false)

    • in_pool - boolean; States if the transaction is in pool (true) or included in a block (false)

    • output_indices - array of unsigned int; transaction indexes

    • tx_hash - string; transaction hash

  • txs_as_hex - string; Full transaction information as a hex string (old compatibility parameter)

  • txs_as_json - json string; (Optional - returned if set in inputs. Old compatibility parameter) List of transaction as in as_json above:

Example 1: Return transaction information in binary format.

$ curl -X POST http://127.0.0.1:18081/get_transactions -d '{"txs_hashes":["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408"]}' -H 'Content-Type: application/json'

{
  "status": "OK",
  "txs": [{
    "as_hex": "...",
    "as_json": "",
    "block_height": 993442,
    "block_timestamp": 1457749396,
    "double_spend_seen": false,
    "in_pool": false,
    "output_indices": [198769,418598,176616,50345,509],
    "tx_hash": "d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408"
  }],
  "txs_as_hex": ["..."],
  "untrusted": false
}

Example 2: Decode returned transaction information in JSON format. Note: the "vin", "vout" and "signatures" list have been truncated in the displayed return for space considerations.

$ curl -X POST http://127.0.0.1:18081/get_transactions -d '{"txs_hashes":["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408"],"decode_as_json":true}' -H 'Content-Type: application/json'

{
  "status": "OK",
  "txs": [{
    "as_hex": "...",
    "as_json": "{\n  \"version\": 1, \n  \"unlock_time\": 0, \n  \"vin\": [ {\n      \"key\": {\n        \"amount\": 9999999999, \n        \"key_offsets\": [ 691\n        ], \n        \"k_image\": \"6ebee1b651a8da723462b4891d471b990ddc226049a0866d3029b8e2f75b7012\"\n      }\n    }, {\n      \"key\": {\n        \"amount\": 9000000000000, \n        \"key_offsets\": [ 175760\n        ], \n        \"k_image\": \"200bd02b70ee707441a8863c5279b4e4d9f376dc97a140b1e5bc7d72bc508069\"\n      }\n    }, ... \n  ], \n  \"vout\": [ {\n      \"amount\": 60000000000, \n      \"target\": {\n        \"key\": \"8c792dea94dab48160e067fb681edd6247ba375281fbcfedc03cb970f3b98e2d\"\n      }\n    }, {\n      \"amount\": 700000000000, \n      \"target\": {\n        \"key\": \"1ab33e69737e157d23e33274c42793be06a8711670e73fa10ecebc604f87cc71\"\n      }\n    }, ... \n  ], \n  \"extra\": [ 1, 3, 140, 109, 156, 205, 47, 148, 153, 9, 17, 93, 83, 33, 162, 110, 152, 1, 139, 70, 121, 19, 138, 10, 44, 6, 55, 140, 242, 124, 143, 219, 172\n  ], \n  \"signatures\": [ \"fd82214a59c99d9251fa00126d353f9cf502a80d8993a6c223e3c802a40ab405555637f495903d3ba558312881e586d452e6e95826d8e128345f6c0a8f9f350e\", \"8c04ef50cf34afa3a9ec19c457143496f8cf7045ed869b581f9efa2f1d65e30f1cec5272b00e9c61a34bdd3c78cf82ae8ef4df3132f70861391069b9c255cd08\", ... ]\n}",
    "block_height": 993442,
    "block_timestamp": 1457749396,
    "double_spend_seen": false,
    "in_pool": false,
    "output_indices": [198769,418598,176616,50345,509],
    "tx_hash": "d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408"
  }],
  "txs_as_hex": ["..."],
  "txs_as_json": ["{\n  \"version\": 1, \n  \"unlock_time\": 0, \n  \"vin\": [ {\n      \"key\": {\n        \"amount\": 9999999999, \n        \"key_offsets\": [ 691\n        ], \n        \"k_image\": \"6ebee1b651a8da723462b4891d471b990ddc226049a0866d3029b8e2f75b7012\"\n      }\n    }, {\n      \"key\": {\n        \"amount\": 9000000000000, \n        \"key_offsets\": [ 175760\n        ], \n        \"k_image\": \"200bd02b70ee707441a8863c5279b4e4d9f376dc97a140b1e5bc7d72bc508069\"\n      }\n    }, ... \n  ], \n  \"vout\": [ {\n      \"amount\": 60000000000, \n      \"target\": {\n        \"key\": \"8c792dea94dab48160e067fb681edd6247ba375281fbcfedc03cb970f3b98e2d\"\n      }\n    }, {\n      \"amount\": 700000000000, \n      \"target\": {\n        \"key\": \"1ab33e69737e157d23e33274c42793be06a8711670e73fa10ecebc604f87cc71\"\n      }\n    }, ... \n  ], \n  \"extra\": [ 1, 3, 140, 109, 156, 205, 47, 148, 153, 9, 17, 93, 83, 33, 162, 110, 152, 1, 139, 70, 121, 19, 138, 10, 44, 6, 55, 140, 242, 124, 143, 219, 172\n  ], \n  \"signatures\": [ \"fd82214a59c99d9251fa00126d353f9cf502a80d8993a6c223e3c802a40ab405555637f495903d3ba558312881e586d452e6e95826d8e128345f6c0a8f9f350e\", \"8c04ef50cf34afa3a9ec19c457143496f8cf7045ed869b581f9efa2f1d65e30f1cec5272b00e9c61a34bdd3c78cf82ae8ef4df3132f70861391069b9c255cd08\", ... ]\n}"],
  "untrusted": false
}

Example 3: Returned a missed (unexisting) transaction.

curl -X POST http://127.0.0.1:18081/get_transactions -d '{"txs_hashes":["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090409"]}' -H 'Content-Type: application/json'

{
  "missed_tx": ["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090409"],
  "status": "OK",
  "untrusted": false
}

/get_alt_blocks_hashes

Get the known blocks hashes which are not on the main chain.

Alias: None.

Inputs: None

Outputs:

  • blks_hashes - array of strings; list of alternative blocks hashes to main chain

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/get_alt_blocks_hashes -H 'Content-Type: application/json'

{
  "blks_hashes": ["9c2277c5470234be8b32382cdf8094a103aba4fcd5e875a6fc159dc2ec00e011","637c0e0f0558e284493f38a5fcca3615db59458d90d3a5eff0a18ff59b83f46f","6f3adc174a2e8082819ebb965c96a095e3e8b63929ad9be2d705ad9c086a6b1c","697cf03c89a9b118f7bdf11b1b3a6a028d7b3617d2d0ed91322c5709acf75625","d99b3cf3ac6f17157ac7526782a3c3b9537f89d07e069f9ce7821d74bd9cad0e","e97b62109a6303233dcd697fa8545c9fcbc0bf8ed2268fede57ddfc36d8c939c","70ff822066a53ad64b04885c89bbe5ce3e537cdc1f7fa0dc55317986f01d1788","b0d36b209bd0d4442b55ea2f66b5c633f522401f921f5a85ea6f113fd2988866"],
  "status": "OK",
  "untrusted": false
}

/is_key_image_spent

Check if outputs have been spent using the key image associated with the output.

Alias: None.

Inputs:

  • key_images - string list; List of key image hex strings to check.

Outputs:

  • spent_status - unsigned int list; List of statuses for each image checked. Statuses are follows: 0 = unspent, 1 = spent in blockchain, 2 = spent in transaction pool

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/is_key_image_spent -d '{"key_images":["8d1bd8181bf7d857bdb281e0153d84cd55a3fcaa57c3e570f4a49f935850b5e3","7319134bfc50668251f5b899c66b005805ee255c136f0e1cecbb0f3a912e09d4"]}' -H 'Content-Type: application/json'

{
  "spent_status": [1,2],
  "status": "OK"
  "untrusted": false
}

/send_raw_transaction

Broadcast a raw transaction to the network.

Alias: /sendrawtransaction.

Inputs:

  • tx_as_hex - string; Full transaction information as hexidecimal string.

  • do_not_relay - boolean; Stop relaying transaction to other nodes (default is false).

Outputs:

  • double_spend - boolean; Transaction is a double spend (true) or not (false).

  • fee_too_low - boolean; Fee is too low (true) or OK (false).

  • invalid_input - boolean; Input is invalid (true) or valid (false).

  • invalid_output - boolean; Output is invalid (true) or valid (false).

  • low_mixin - boolean; Mixin count is too low (true) or OK (false).

  • not_rct - boolean; Transaction is a standard ring transaction (true) or a ring confidential transaction (false).

  • not_relayed - boolean; Transaction was not relayed (true) or relayed (false).

  • overspend - boolean; Transaction uses more money than available (true) or not (false).

  • reason - string; Additional information. Currently empty or "Not relayed" if transaction was accepted but not relayed.

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

  • too_big - boolean; Transaction size is too big (true) or OK (false).

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example (No return information included here.):

$ curl -X POST http://127.0.0.1:18081/send_raw_transaction -d '{"tx_as_hex":"de6a3...", "do_not_relay":false}' -H 'Content-Type: application/json'

/save_bc

Save the blockchain. The blockchain does not need saving and is always saved when modified, however it does a sync to flush the filesystem cache onto the disk for safety purposes against Operating System or Harware crashes.

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

Example:

$ curl -X POST http://127.0.0.1:18081/save_bc -H 'Content-Type: application/json'

{
  "status": "OK"
}

/get_peer_list

Get the known peers list.

Alias: None.

Inputs: None.

Outputs:

  • gray_list - array of offline peer structure as follows:

    • host - unsigned int; IP address in integer format

    • id - string; Peer id

    • ip - unsigned int; IP address in integer format

    • last_seen - unsigned int; unix time at which the peer has been seen for the last time

    • port - unsigned int; TCP port the peer is using to connect to Oxen network.

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

  • white_list - array of online peer structure, as above.

Example (truncated lists):

$ curl -X POST http://127.0.0.1:18081/get_peer_list -H 'Content-Type: application/json'

{
  "gray_list": [{
    "host": "640304833",
    "id": 5345237316225602120,
    "ip": 640304833,
    "last_seen": 1525540510,
    "port": 18080
  },{
    "host": "2183731038",
    "id": 14955030573998424430,
    "ip": 2183731038,
    "last_seen": 1525540499,
    "port": 28080
  }, ...
  ],
  "status": "OK",
  "white_list": [{
    "host": "1221637955",
    "id": 10354694710033118926,
    "ip": 1221637955,
    "last_seen": 1525540511,
    "port": 18080
  },{
    "host": "1780407354",
    "id": 17193661050352240890,
    "ip": 1780407354,
    "last_seen": 1525540510,
    "port": 18080
  }, ...
  ]
}

/set_log_hash_rate

Set the log hash rate display mode.

Alias: None.

Inputs:

  • visible - boolean; States if hash rate logs should be visible (true) or hidden (false)

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

Example while mining:

$ curl -X POST http://127.0.0.1:18081/set_log_hash_rate -d '{"visible":true}' -H 'Content-Type: application/json'

{
  "status": "OK"
}

Error while not mining:

$ curl -X POST http://127.0.0.1:18081/set_log_hash_rate -d '{"visible":true}' -H 'Content-Type: application/json'

{
  "status": "NOT MINING"
}

/set_log_level

Set the daemon log level. By default, log level is set to 0.

Alias: None.

Inputs:

  • level - integer; daemon log level to set from 0 (less verbose) to 4 (most verbose)

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

Example:

$ curl -X POST http://127.0.0.1:18081/set_log_level -d '{"level":1}' -H 'Content-Type: application/json'

{
  "status": "OK"
}

/set_log_categories

Set the daemon log categories. Categories are represented as a comma separated list of <Category>:<level> (similarly to syslog standard <Facility>:<Severity-level>), where:

  • Category is one of the following:

    • * - All facilities

    • default

    • net

    • net.http

    • net.p2p

    • logging

    • net.throttle

    • blockchain.db

    • blockchain.db.lmdb

    • bcutil

    • checkpoints

    • net.dns

    • net.dl

    • i18n

    • perf

    • stacktrace

    • updates

    • account

    • cn

    • difficulty

    • hardfork

    • miner

    • blockchain

    • txpool

    • cn.block_queue

    • net.cn

    • daemon

    • debugtools.deserialize

    • debugtools.objectsizes

    • device.ledger

    • wallet.gen_multisig

    • multisig

    • bulletproofs

    • ringct

    • daemon.rpc

    • wallet.simplewallet

    • WalletAPI

    • wallet.ringdb

    • wallet.wallet2

    • wallet.rpc

    • tests.core

  • Level is one of the following:

    • FATAL - higher level

    • ERROR

    • WARNING

    • INFO

    • DEBUG

    • TRACE - lower level A level automatically includes higher level. By default, categories are set to *:WARNING,net:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO. Setting the categories to "" prevent any logs to be outputed.

Alias: None.

Inputs:

  • categories - string; Optional, daemon log categories to enable

Outputs:

  • categories - string; daemon log enabled categories

  • status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.

Example to set all facilities to Security Level Info:

$ curl -X POST http://127.0.0.1:18081/set_log_categories -d '{"categories": "*:INFO"}' -H 'Content-Type: application/json'

{
  "categories": "*:INFO",
  "status": "OK"
}

Example without input to set the default categories:

$ curl -X POST http://127.0.0.1:18081/set_log_categories -H 'Content-Type: application/json'

{
  "categories": "*:WARNING,net:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO",
  "status": "OK"
}

/get_transaction_pool

Show information about valid transactions seen by the node but not yet mined into a block, as well as spent key image information for the txpool in the node's memory.

Alias: None.

Inputs: None.

Outputs:

  • spent_key_images - List of spent output key images:

    • id_hash - string; Key image.

    • txs_hashes - string list; tx hashes of the txes (usually one) spending that key image.

  • status - string; General RPC error code. "OK" means everything looks good.

  • transactions - List of transactions in the mempool are not in a block on the main chain at the moment:

    • blob_size - unsigned int; The size of the full transaction blob.

    • double_spend_seen - boolean; States if this transaction has been seen as double spend.

    • do_not_relay; boolean; States if this transaction should not be relayed

    • fee - unsigned int; The amount of the mining fee included in the transaction, in atomic units.

    • id_hash - string; The transaction ID hash.

    • kept_by_block - boolean; States if the tx was included in a block at least once (true) or not (false).

    • last_failed_height - unsigned int; If the transaction validation has previously failed, this tells at what height that occured.

    • last_failed_id_hash - string; Like the previous, this tells the previous transaction ID hash.

    • last_relayed_time - unsigned int; Last unix time at which the transaction has been relayed.

    • max_used_block_height - unsigned int; Tells the height of the most recent block with an output used in this transaction.

    • max_used_block_hash - string; Tells the hash of the most recent block with an output used in this transaction.

    • receive_time - unsigned int; The Unix time that the transaction was first seen on the network by the node.

    • relayed - boolean; States if this transaction has been relayed

    • tx_blob - unsigned int; Hexadecimal blob represnting the transaction.

    • tx_json - json string; JSON structure of all information in the transaction:

      • version - Transaction version

      • unlock_time - If not 0, this tells when a transaction output is spendable.

      • vin - List of inputs into transaction:

        • key - The public key of the previous output spent in this transaction.

          • amount - The amount of the input, in atomic units.

          • key_offsets - A list of integer offets to the input.

          • k_image - The key image for the given input

      • vout - List of outputs from transaction:

        • amount - Amount of transaction output, in atomic units.

        • target - Output destination information:

          • key - The stealth public key of the receiver. Whoever owns the private key associated with this key controls this transaction output.

      • extra - Usually called the "transaction ID" but can be used to include any random 32 bytes.

      • rct_signatures - Ring signatures:

        • type

        • txnFee

        • ecdhInfo - array of Diffie Helman Elipctic curves structures as follows:

          • mask - String

          • amount - String

        • outPk

      • rctsig_prunable

        • rangeSigs - array of structures as follows:

          • asig

          • Ci

        • MGs - array of structures as follows:

          • ss - array of arrays of two strings.

          • cc - String

Example (Note: Some lists in the returned information have been truncated for display reasons):

$ curl -X POST http://127.0.0.1:18081/get_transaction_pool -H 'Content-Type: application/json'

{
  "spent_key_images": [{
    "id_hash": "a2af919609db4ff5ab8d4ba18502e647d521760e1cbc30288f06fa87bf9a0c1c",
    "txs_hashes": ["1ee6a4873b638711795fc3b0b73fc7146505a09a7f4749534fd408d571a273cf"]
  },{
    "id_hash": "02d5f6559e9bca5ae5a335130aeeb05df2db518ab9837fa64ebbab276c100792",
    "txs_hashes": ["531aacc0ceb8514cdde5f104285202ccc3e969c77584e3c6fa614c987c583965"]
  },
  ...],
  "status": "OK",
  "transactions": [{
    "blob_size": 13193,
    "do_not_relay": false,
    "double_spend_seen": false,
    "fee": 9694360000,
    "id_hash": "f8fb875cfc9e2e59bcf96a42474c79e01d50b69e6548d445d45984f7db66e50f",
    "kept_by_block": false,
    "last_failed_height": 0,
    "last_failed_id_hash": "0000000000000000000000000000000000000000000000000000000000000000",
    "last_relayed_time": 1525615049,
    "max_used_block_height": 1564924,
    "max_used_block_id_hash": "4bae7856979f46c7de31f3fb58cac36d4dfd2765bf33f876edf33d0e05ebb4a7",
    "receive_time": 1525615049,
    "relayed": true,
    "tx_blob": " ... ",
    "tx_json": "{\n  \"version\": 2, \n  \"unlock_time\": 0, \n  \"vin\": [ {\n      \"key\": {\n        \"amount\": 0, \n        \"key_offsets\": [ 2630347, 594429, 1047509, 758973, 464501, 61971, 22268\n        ], \n        \"k_image\": \"0731363c58dd4492f031fa20c82fe6ddcb9cc070d73938afe8a5f7f77897f8b4\"\n      }\n    }\n  ], \n  \"vout\": [ {\n      \"amount\": 0, \n      \"target\": {\n        \"key\": \"f3b3dd09483616e343b9866eed50a0ce01d5c0d0f2612ce2c4d0e9cce5c218cd\"\n      }\n    }, {\n      \"amount\": 0, \n      \"target\": {\n        \"key\": \"9796f2d477a696b6282bf3cb1a41cefba0c4604eedcc2e7a44904d7033643e0e\"\n      }\n    }\n  ], \n  \"extra\": [ 1, 25, 228, 80, 5, 214, 117, 150, 9, 125, 98, 17, 113, 208, 89, 223, 242, 227, 188, 197, 141, 190, 135, 140, 152, 117, 240, 150, 21, 93, 62, 108, 124\n  ], \n  \"rct_signatures\": {\n    \"type\": 1, \n    \"txnFee\": 9694360000, \n    \"ecdhInfo\": [ {\n        \"mask\": \"645f06a2816aecf83d5041c3320eb31092b994fb2733bb74c8c47e288d452c04\", \n        \"amount\": \"3908f14d39dcb3831331cb255eeadc5b0aea0143645b9cd3034abf613995740d\"\n      }, {\n        \"mask\": \"0785b5df0a994b14d59da810503a022721d8f629720f526e15bd848ad3c2c509\", \n        \"amount\": \"fbd81cf2368dcd742905ded5287457030467aaf5bc9939e13f1d6bf8d4c8ca09\"\n      }], \n    \"outPk\": [ \"c19f5fa052859126e0eed0e3c860aadab049677b2b3dd14cc74d02f92f1d013f\", \"1581ef6368de1608ea366566b88272db220479cf215f6d88d7b60ec221d11e0a\"]\n  }, \n  \"rctsig_prunable\": {\n    \"rangeSigs\": [ {\n        \"asig\": \" ... \", \n        \"Ci\": \" .. \"\n      }, {\n        \"asig\": \" ... \", \n        \"Ci\": \" ... \"\n      }], \n    \"MGs\": [ {\n        \"ss\": [ [ \"218a10a29e0f66e5a324af67b7734708a8a4cc8f16b28acd8cda538aaa495a02\", \"b368b4e956df5808c5c257f0dc3f7eff8c28463d0bb20759d19977fa02d6f205\"], [ \"f741d2c96bc23b362b4155a03fb6f1351ab5bf4445a43b3e52ba776f526af305\", \"a10ad1ee80dce3f311dd3dc141803daeecaa4d2a25a390cd9c35e4161b7c9e0c\"],
    ...], \n        \"cc\": \"e93801b707261ca76e146fdf2085abae71ad9203a00edc843c74f4ead8a39601\"\n      }]\n  }\n}"
  },
  ...]
}

/get_transaction_pool_hashes.bin

Get hashes from transaction pool. Binary request.

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

  • tx_hashes - binary array of transaction hashes.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/get_transaction_pool_hashes.bin -H 'Content-Type: application/json'

{
  "status": "OK",
  "tx_hashes": " ... ",
  "untrusted": false
}

/get_transaction_pool_stats

Get the transaction pool statistics.

Alias: None.

Inputs: None.

Outputs:

  • pool_stats - Structure as follows:

    • bytes_max - unsigned int; Max transaction size in pool

    • bytes_med - unsigned int; Median transaction size in pool

    • bytes_min - unsigned int; Min transaction size in pool

    • bytes_total - unsigned int; total size of all transactions in pool

    • histo - structure txpool_histo as follows:

      • txs - unsigned int; number of transactions

      • bytes - unsigned int; size in bytes.

    • histo_98pc unsigned int; the time 98% of txes are "younger" than

    • num_10m unsigned int; number of transactions in pool for more than 10 minutes

    • num_double_spends unsigned int; number of double spend transactions

    • num_failing unsigned int; number of failing transactions

    • num_not_relayed unsigned int; number of non-relayed transactions

    • oldest unsigned int; unix time of the oldest transaction in the pool

    • txs_total unsigned int; total number of transactions.

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/get_transaction_pool_stats -H 'Content-Type: application/json'

{
  "pool_stats": {
    "bytes_max": 47222,
    "bytes_med": 13290,
    "bytes_min": 13092,
    "bytes_total": 449511,
    "fee_total": 289715320000,
    "histo": "\t▒'▒5▒4▒\/▒▒▒$3",
    "histo_98pc": 0,
    "num_10m": 18,
    "num_double_spends": 1,
    "num_failing": 17,
    "num_not_relayed": 0,
    "oldest": 1525457001,
    "txs_total": 26
  },
  "status": "OK",
  "untrusted": false
}

/stop_daemon

Send a command to the daemon to safely disconnect and shut down.

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/stop_daemon -H 'Content-Type: application/json'

{
  "status": "OK"
}

/get_info (not JSON)

This method is a convenient backward support and should not be used anymore. See get_info JSON RPC for details.

Alias:

  • /getinfo

  • get_info

/get_limit

Get daemon bandwidth limits.

Alias: None.

Inputs: None.

Outputs:

  • limit_down - unsigned int; Download limit in kBytes per second

  • limit_up - unsigned int; Upload limit in kBytes per second

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

Example:

$ curl -X POST http://127.0.0.1:18081/get_limit -H 'Content-Type: application/json'

{
  "limit_down": 8192,
  "limit_up": 128,
  "status": "OK",
  "untrusted": false
}

/set_limit

Set daemon bandwidth limits.

Alias: None.

Inputs:

  • limit_down - signed int; Download limit in kBytes per second (-1 reset to default, 0 don't change the current limit)

  • limit_up - signed int; Upload limit in kBytes per second (-1 reset to default, 0 don't change the current limit)

Outputs:

  • limit_down - unsigned int; Download limit in kBytes per second

  • limit_up - unsigned int; Upload limit in kBytes per second

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/set_limit -d '{"limit_down": 1024}' -H 'Content-Type: application/json'

{
  "limit_down": 1024,
  "limit_up": 128,
  "status": "OK"
}

/out_peers

Limit number of Outgoing peers.

Alias: None.

Inputs:

  • out_peers - unsigned int; Max number of outgoing peers

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/out_peers -d '{"out_peers": 3232235535}' -H 'Content-Type: application/json'

{
  "status": "OK"
}

/in_peers

Limit number of Incoming peers.

Alias: None.

Inputs:

  • in_peers - unsigned int; Max number of incoming peers

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/out_peers -d '{"in_peers": 3232235535}' -H 'Content-Type: application/json'

{
  "status": "OK"
}

/start_save_graph

Obsolete. Conserved here for reference.

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/start_save_graph -H 'Content-Type: application/json'

{
  "status": "OK"
}

/stop_save_graph

Obsolete. Conserved here for reference.

Alias: None.

Inputs: None.

Outputs:

  • status - string; General RPC error code. "OK" means everything looks good.

Example:

$ curl -X POST http://127.0.0.1:18081/stop_save_graph -H 'Content-Type: application/json'

{
  "status": "OK"
}

/get_outs

Get outputs.

Alias: None.

Inputs:

  • outputs array of get_outputs_out structure as follows:

    • amount - unsigned int;

    • index - unsigned int;

Outputs:

  • outs - array of structure outkey as follows:

    • height - unsigned int; block height of the output

    • key - String; the public key of the output

    • mask - String

    • txid - String; transaction id

    • unlocked - boolean; States if output is locked (false) or not (true)

  • status - string; General RPC error code. "OK" means everything looks good.

  • untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced (false).

/update

Update daemon.

Alias: None.

Inputs:

  • command - String; command to use, either check or download

  • path - String; Optional, path where to download the update.

Outputs:

  • auto_uri - string;

  • hash - string;

  • path - String; path to download the update

  • status - string; General RPC error code. "OK" means everything looks good.

  • update - boolean; States if an update is available to download (true) or not (false)

  • user_uri - string;

  • version - string; Version available for download.

Example:

$ curl -X POST http://127.0.0.1:18081/update -d '{"command":"check"}' -H 'Content-Type: application/json'

{
  "auto_uri": "",
  "hash": "",
  "path": "",
  "status": "OK",
  "update": false,
  "user_uri": "",
  "version": ""
}

Sources:

Reworked from GetMonero.org RPC calls for Oxen under their copyright license.

Wallet 📞 RPC calls

Introduction

This is a list of the oxen-wallet-rpc calls, their inputs and outputs, and examples of each. The program oxen-wallet-rpc replaced the rpc interface that was in simplewallet and then oxen-wallet-cli.

All oxen-wallet-rpc methods use the same JSON RPC interface. For example:

If the oxen-wallet-rpc was executed with the --rpc-login argument as username:password, then follow this example:

Note: "atomic units" refer to the smallest fraction of 1 $OXEN according to the oxend implementation. 1 $OXEN = 1e9 atomic units.

Index of JSON RPC Methods:

  • get_balance

  • get_address

  • get_address_index

  • create_address

  • label_address

  • get_accounts

  • create_account

  • label_account

  • get_account_tags

  • tag_accounts

  • untag_accounts

  • set_account_tag_description

  • get_height

  • transfer

  • transfer_split

  • sign_transfer

  • submit_transfer

  • sweep_dust

  • sweep_all

  • sweep_single

  • relay_tx

  • store

  • get_payments

  • get_bulk_payments

  • incoming_transfers

  • query_key

  • make_integrated_address

  • split_integrated_address

  • stop_wallet

  • rescan_blockchain

  • set_tx_notes

  • get_tx_notes

  • set_attribute

  • get_attribute

  • get_tx_key

  • check_tx_key

  • get_tx_proof

  • check_tx_proof

  • get_spend_proof

  • check_spend_proof

  • get_reserve_proof

  • check_reserve_proof

  • get_transfers

  • get_transfer_by_txid

  • sign

  • verify

  • export_outputs

  • import_outputs

  • export_key_images

  • import_key_images

  • make_uri

  • parse_uri

  • get_address_book

  • add_address_book

  • delete_address_book

  • refresh

  • rescan_spent

  • start_mining

  • stop_mining

  • get_languages

  • create_wallet

  • open_wallet

  • close_wallet

  • change_wallet_password

  • is_multisig

  • prepare_multisig

  • make_multisig

  • export_multisig_info

  • import_multisig_info

  • finalize_multisig

  • sign_multisig

  • submit_multisig

  • get_version

JSON RPC Methods:

get_balance

Return the wallet's balance.

Alias: getbalance.

Inputs:

  • account_index - unsigned int; Return balance for this account.

  • address_indices - array of unsigned int; (Optional) Return balance detail for those subaddresses.

Outputs:

  • balance - unsigned int; The total balance of the current Oxen-wallet-rpc in session.

  • unlocked_balance - unsigned int; Unlocked funds are those funds that are sufficiently deep enough in the Oxen blockchain to be considered safe to spend.

  • multisig_import_needed - boolean; True if importing multisig data is needed for returning a correct balance.

  • per_subaddress - array of subaddress information; Balance information for each subaddress in an account.

    • address_index - unsigned int; Index of the subaddress in the account.

    • address - string; Address at this index. Base58 representation of the public keys.

    • balance - unsigned int; Balance for the subaddress (locked or unlocked).

    • unlocked_balance - unsigned int; Unlocked balance for the subaddress.

    • label - string; Label for the subaddress.

    • num_unspent_outputs - unsigned int; Number of unspent outputs available for the subaddress.

Example:

get_address

Return the wallet's addresses for an account. Optionally filter for specific set of subaddresses.

Alias: getaddress.

Inputs:

  • account_index - unsigned int; Return subaddresses for this account.

  • address_index - array of unsigned int; (Optional) List of subaddresses to return from an account.

Outputs:

  • address - string; The 95-character hex address string of the oxen-wallet-rpc in session.

  • addresses array of addresses informations

    • address string; The 95-character hex (sub)address string.

    • label string; Label of the (sub)address

    • address_index unsigned int; index of the subaddress

    • used boolean; states if the (sub)address has already received funds

Example:

get_address_index

Get account and address indexes from a specific (sub)address

Alias: None.

Inputs:

  • address - String; (sub)address to look for.

Outputs:

  • index - subaddress informations

    • major unsigned int; Account index.

    • minor unsigned int; Address index.

Example:

create_address

Create a new address for an account. Optionally, label the new address.

Alias: None.

Inputs:

  • account_index - unsigned int; Create a new address for this account.

  • label - string; (Optional) Label for the new address.

Outputs:

  • address - string; Newly created address. Base58 representation of the public keys.

  • address_index - unsigned int; Index of the new address under the input account.

Example:

label_address

Label an address.

Alias: None.

Inputs:

  • index - subaddress index; JSON Object containing the major & minor address index:

    • major - unsigned int; Account index for the subaddress.

    • minor - unsigned int; Index of the subaddress in the account.

  • label - string; Label for the address.

Outputs: None.

Example:

get_accounts

Get all accounts for a wallet. Optionally filter accounts by tag.

Alias: None.

Inputs:

  • tag - string; (Optional) Tag for filtering accounts.

Outputs:

  • subaddress_accounts - array of subaddress account information:

    • account_index - unsigned int; Index of the account.

    • balance - unsigned int; Balance of the account (locked or unlocked).

    • base_address - string; Base64 representation of the first subaddress in the account.

    • label - string; (Optional) Label of the account.

    • tag - string; (Optional) Tag for filtering accounts.

    • unlocked_balance - unsigned int; Unlocked balance for the account.

  • total_balance - unsigned int; Total balance of the selected accounts (locked or unlocked).

  • total_unlocked_balance - unsigned int; Total unlocked balance of the selected accounts.

Example:

create_account

Create a new account with an optional label.

Alias: None.

Inputs:

  • label - string; (Optional) Label for the account.

Outputs:

  • account_index - unsigned int; Index of the new account.

  • address - string; Address for this account. Base58 representation of the public keys.

Example:

label_account

Label an account.

Alias: None.

Inputs:

  • account_index - unsigned int; Apply label to account at this index.

  • label - string; Label for the account.

Outputs: None.

Example:

get_account_tags

Get a list of user-defined account tags.

Alias: None.

Inputs: None.

Outputs:

  • account_tags - array of account tag information:

    • tag - string; Filter tag.

    • label - string; Label for the tag.

    • accounts - array of int; List of tagged account indices.

Example:

tag_accounts

Apply a filtering tag to a list of accounts.

Alias: None.

Inputs:

  • tag - string; Tag for the accounts.

  • accounts - array of unsigned int; Tag this list of accounts.

Outputs: None.

Example:

untag_accounts

Remove filtering tag from a list of accounts.

Alias: None.

Inputs:

  • accounts - array of unsigned int; Remove tag from this list of accounts.

Outputs: None.

Example:

set_account_tag_description

Set description for an account tag.

Alias: None.

Inputs:

  • tag - string; Set a description for this tag.

  • description - string; Description for the tag.

Outputs: None.

Example:

get_height

Returns the wallet's current block height.

Alias: getheight.

Inputs: None.

Outputs:

  • height - unsigned int; The current oxen-wallet-rpc's blockchain height. If the wallet has been offline for a long time, it may need to catch up with the daemon.

Example:

transfer

Send $OXEN to a number of recipients.

Alias: None.

Inputs:

  • destinations - array of destinations to receive $OXEN:

    • amount - unsigned int; Amount to send to each destination, in atomic units.

    • address - string; Destination public address.

  • account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0)

  • subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0)

  • priority - unsigned int; Set a priority for the transaction. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority.

  • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).

  • ring_size - unsigned int; Number of outputs to mix in the transaction (this output + N decoys from the blockchain).

  • unlock_time - unsigned int; Number of blocks before the $OXEN can be spent (0 to not add a lock).

  • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.

  • get_tx_key - boolean; (Optional) Return the transaction key after sending.

  • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the Oxen network. (Defaults to false)

  • get_tx_hex - boolean; Return the transaction as hex string after sending (Defaults to false)

  • get_tx_metadata - boolean; Return the metadata needed to relay the transaction. (Defaults to false)

Outputs:

  • amount - Amount transferred for the transaction.

  • fee - Integer value of the fee charged for the txn.

  • multisig_txset - Set of multisig transactions in the process of being signed (empty for non-multisig).

  • tx_blob - Raw transaction represented as hex string, if get_tx_hex is true.

  • tx_hash - String for the publically searchable transaction hash.

  • tx_key - String for the transaction key if get_tx_key is true, otherwise, blank string.

  • tx_metadata - Set of transaction metadata needed to relay this transfer later, if get_tx_metadata is true.

  • unsigned_txset - String. Set of unsigned tx for cold-signing purposes.

Example:

transfer_split

Same as transfer, but can split into more than one tx if necessary.

Alias: None.

Inputs:

  • destinations - array of destinations to receive $OXEN:

    • amount - unsigned int; Amount to send to each destination, in atomic units.

    • address - string; Destination public address.

  • account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0)

  • subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0)

  • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).

  • ring_size - unsigned int; Sets ringsize to n (mixin + 1).

  • unlock_time - unsigned int; Number of blocks before the $OXEN can be spent (0 to not add a lock).

  • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.

  • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.

  • priority - unsigned int; Set a priority for the transactions. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority.

  • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the Oxen network. (Defaults to false)

  • get_tx_hex - boolean; Return the transactions as hex string after sending

  • new_algorithm - boolean; True to use the new transaction construction algorithm, defaults to false.

  • get_tx_metadata - boolean; Return list of transaction metadata needed to relay the transfer later.

Outputs:

  • tx_hash_list - array of: string. The tx hashes of every transaction.

  • tx_key_list - array of: string. The transaction keys for every transaction.

  • amount_list - array of: integer. The amount transferred for every transaction.

  • fee_list - array of: integer. The amount of fees paid for every transaction.

  • tx_blob_list - array of: string. The tx as hex string for every transaction.

  • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.

  • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).

  • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.

Example:

sign_transfer

Sign a transaction created on a read-only wallet (in cold-signing process)

Alias: None.

Inputs:

  • unsigned_txset - string. Set of unsigned tx returned by "transfer" or "transfer_split" methods.

  • export_raw - boolean; (Optional) If true, return the raw transaction data. (Defaults to false)

Outputs:

  • signed_txset - string. Set of signed tx to be used for submitting transfer.

  • tx_hash_list - array of: string. The tx hashes of every transaction.

  • tx_raw_list - array of: string. The tx raw data of every transaction.

In the example below, we first generate an unsigned_txset on a read only wallet before signing it:

Generate unsigned_txset using the above "transfer" method on read-only wallet:

Sign tx using the previously generated unsigned_txset

submit_transfer

Submit a previously signed transaction on a read-only wallet (in cold-signing process).

Alias: None.

Inputs:

  • tx_data_hex - string; Set of signed tx returned by "sign_transfer"

Outputs:

  • tx_hash_list - array of: string. The tx hashes of every transaction.

In the example below, we submit the transfer using the signed_txset generated above:

sweep_dust

Send all dust outputs back to the wallet's, to make them easier to spend (and mix).

Alias: sweep_unmixable.

Inputs:

  • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.

  • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the Oxen network. (Defaults to false)

  • get_tx_hex - boolean; (Optional) Return the transactions as hex string after sending. (Defaults to false)

  • get_tx_metadata - boolean; (Optional) Return list of transaction metadata needed to relay the transfer later. (Defaults to false)

Outputs:

  • tx_hash_list - array of: string. The tx hashes of every transaction.

  • tx_key_list - array of: string. The transaction keys for every transaction.

  • amount_list - array of: integer. The amount transferred for every transaction.

  • fee_list - array of: integer. The amount of fees paid for every transaction.

  • tx_blob_list - array of: string. The tx as hex string for every transaction.

  • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.

  • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).

  • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.

Example (In this example, sweep_dust returns nothing because there are no funds to sweep):

sweep_all

Send all unlocked balance to an address.

Alias: None.

Inputs:

  • address - string; Destination public address.

  • account_index - unsigned int; Sweep transactions from this account.

  • subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account.

  • priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee.

  • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).

  • ring_size - unsigned int; Sets ringsize to n (mixin + 1).

  • unlock_time - unsigned int; Number of blocks before the $OXEN can be spent (0 to not add a lock).

  • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.

  • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.

  • below_amount - unsigned int; (Optional) Include outputs below this amount.

  • do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false)

  • get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false)

  • get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false)

Outputs:

  • tx_hash_list - array of: string. The tx hashes of every transaction.

  • tx_key_list - array of: string. The transaction keys for every transaction.

  • amount_list - array of: integer. The amount transferred for every transaction.

  • fee_list - array of: integer. The amount of fees paid for every transaction.

  • tx_blob_list - array of: string. The tx as hex string for every transaction.

  • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.

  • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).

  • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.

Example:

sweep_single

Send all of a specific unlocked output to an address.

Alias: None.

Inputs:

  • address - string; Destination public address.

  • account_index - unsigned int; Sweep transactions from this account.

  • subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account.

  • priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee.

  • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).

  • ring_size - unsigned int; Sets ringsize to n (mixin + 1).

  • unlock_time - unsigned int; Number of blocks before the $OXEN can be spent (0 to not add a lock).

  • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.

  • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.

  • key_image - string; Key image of specific output to sweep.

  • below_amount - unsigned int; (Optional) Include outputs below this amount.

  • do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false)

  • get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false)

  • get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false)

Outputs:

  • tx_hash_list - array of: string. The tx hashes of every transaction.

  • tx_key_list - array of: string. The transaction keys for every transaction.

  • amount_list - array of: integer. The amount transferred for every transaction.

  • fee_list - array of: integer. The amount of fees paid for every transaction.

  • tx_blob_list - array of: string. The tx as hex string for every transaction.

  • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.

  • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).

  • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.

Example:

relay_tx

Relay a transaction previously created with "do_not_relay":true.

Alias: None.

Inputs:

  • hex - string; transaction metadata returned from a transfer method with get_tx_metadata set to true.

Outputs:

  • tx_hash - String for the publically searchable transaction hash.

Example:

store

Save the wallet file.

Alias: None.

Inputs: None.

Outputs: None.

Example:

get_payments

Get a list of incoming payments using a given payment id.

Alias: None.

Inputs:

  • payment_id - string; Payment ID used to find the payments (16 characters hex).

Outputs:

  • payments - list of:

    • payment_id - string; Payment ID matching the input parameter.

    • tx_hash - string; Transaction hash used as the transaction ID.

    • amount - unsigned int; Amount for this payment.

    • block_height - unsigned int; Height of the block that first confirmed this payment.

    • unlock_time - unsigned int; Time (in block height) until this payment is safe to spend.

    • subaddr_index - subaddress index:

      • major - unsigned int; Account index for the subaddress.

      • minor - unsigned int; Index of the subaddress in the account.

    • address - string; Address receiving the payment; Base58 representation of the public keys.

Example:

get_bulk_payments

Get a list of incoming payments using a given payment id, or a list of payments ids, from a given height. This method is the preferred method over get_paymentsbecause it has the same functionality but is more extendable. Either is fine for looking up transactions by a single payment ID.

Alias: None.

Inputs:

  • payment_ids - array of: string; Payment IDs used to find the payments (16 characters hex).

  • min_block_height - unsigned int; The block height at which to start looking for payments.

Outputs:

  • payments - list of:

    • payment_id - string; Payment ID matching one of the input IDs.

    • tx_hash - string; Transaction hash used as the transaction ID.

    • amount - unsigned int; Amount for this payment.

    • block_height - unsigned int; Height of the block that first confirmed this payment.

    • unlock_time - unsigned int; Time (in block height) until this payment is safe to spend.

    • subaddr_index - subaddress index:

      • major - unsigned int; Account index for the subaddress.

      • minor - unsigned int; Index of the subaddress in the account.

    • address - string; Address receiving the payment; Base58 representation of the public keys.

Example:

incoming_transfers

Return a list of incoming transfers to the wallet.

Inputs:

  • transfer_type - string; "all": all the transfers, "available": only transfers which are not yet spent, OR "unavailable": only transfers which are already spent.

  • account_index - unsigned int; (Optional) Return transfers for this account. (defaults to 0)

  • subaddr_indices - array of unsigned int; (Optional) Return transfers sent to these subaddresses.

  • verbose - boolean; (Optional) Enable verbose output, return key image if true.

Outputs:

  • transfers - list of:

    • amount - unsigned int; Amount of this transfer.

    • global_index - unsigned int; Mostly internal use, can be ignored by most users.

    • key_image - string; Key image for the incoming transfer's unspent output (empty unless verbose is true).

    • spent - boolean; Indicates if this transfer has been spent.

    • subaddr_index - unsigned int; Subaddress index for incoming transfer.

    • tx_hash - string; Several incoming transfers may share the same hash if they were in the same transaction.

    • tx_size - unsigned int; Size of transaction in bytes.

Example, get all transfers:

Example, get available transfers:

Example, get unavailable transfers:

query_key

Return the spend or view private key.

Alias: None.

Inputs:

  • key_type - string; Which key to retrieve: "mnemonic" - the mnemonic seed (older wallets do not have one) OR "view_key" - the view key

Outputs:

  • key - string; The view key will be hex encoded, while the mnemonic will be a string of words.

Example (Query view key):

Example (Query mnemonic key):

make_integrated_address

Make an integrated address from the wallet address and a payment id.

Alias: None.

Inputs:

  • standard_address - string; (Optional, defaults to primary address) Destination public address.

  • payment_id - string; (Optional, defaults to a random ID) 16 characters hex encoded.

Outputs:

  • integrated_address - string

  • payment_id - string; hex encoded;

Example (Payment ID is empty, use a random ID):

split_integrated_address

Retrieve the standard address and payment id corresponding to an integrated address.

Alias: None.

Inputs:

  • integrated_address - string

Outputs:

  • is_subaddress - boolean; States if the address is a subaddress

  • payment - string; hex encoded

  • standard_address - string

Example:

stop_wallet

Stops the wallet, storing the current state.

Alias: None.

Inputs: None.

Outputs: None.

Example:

rescan_blockchain

Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself. This includes destination addresses, tx secret keys, tx notes, etc.

Alias: None.

Inputs: None.

Outputs: None.

Example:

set_tx_notes

Set arbitrary string notes for transactions.

Alias: None.

Inputs:

  • txids - array of string; transaction ids

  • notes - array of string; notes for the transactions

Outputs: None.

Example:

get_tx_notes

Get string notes for transactions.

Alias: None.

Inputs:

  • txids - array of string; transaction ids

Outputs:

  • notes - array of string; notes for the transactions

Example:

set_attribute

Set arbitrary attribute.

Alias: None.

Inputs:

  • key - string; attribute name

  • value - string; attribute value

Outputs: None.

Example:

get_attribute

Get attribute value by name.

Alias: None.

Inputs:

  • key - string; attribute name

Outputs:

  • value - string; attribute value

Example:

get_tx_key

Get transaction secret key from transaction id.

Alias: None.

Inputs:

  • txid - string; transaction id.

Outputs:

  • tx_key - string; transaction secret key.

Example:

check_tx_key

Check a transaction in the blockchain with its secret key.

Alias: None.

Inputs:

  • txid - string; transaction id.

  • tx_key - string; transaction secret key.

  • address - string; destination public address of the transaction.

Outputs:

  • confirmations - unsigned int; Number of block mined after the one with the transaction.

  • in_pool - boolean; States if the transaction is still in pool or has been added to a block.

  • received - unsigned int; Amount of the transaction.

Example:

get_tx_proof

Get transaction signature to prove it.

Alias: None.

Inputs:

  • txid - string; transaction id.

  • address - string; destination public address of the transaction.

  • message - string; (Optional) add a message to the signature to further authenticate the prooving process.

Outputs:

  • signature - string; transaction signature.

Example:

check_tx_proof

Prove a transaction by checking its signature.

Alias: None.

Inputs:

  • txid - string; transaction id.

  • address - string; destination public address of the transaction.

  • message - string; (Optional) Should be the same message used in get_tx_proof.

  • signature - string; transaction signature to confirm.

Outputs:

  • confirmations - unsigned int; Number of block mined after the one with the transaction.

  • good - boolean; States if the inputs proves the transaction.

  • in_pool - boolean; States if the transaction is still in pool or has been added to a block.

  • received - unsigned int; Amount of the transaction.

In the example below, the transaction has been proven:

In the example below, the wrong message is used, avoiding the transaction to be proved:

get_spend_proof

Generate a signature to prove a spend. Unlike proving a transaction, it does not requires the destination public address.

Alias: None.

Inputs:

  • txid - string; transaction id.

  • message - string; (Optional) add a message to the signature to further authenticate the prooving process.

Outputs:

  • signature - string; spend signature.

Example:

check_spend_proof

Prove a spend using a signature. Unlike proving a transaction, it does not requires the destination public address.

Alias: None.

Inputs:

  • txid - string; transaction id.

  • message - string; (Optional) Should be the same message used in get_spend_proof.

  • signature - string; spend signature to confirm.

Outputs:

  • good - boolean; States if the inputs proves the spend.

In the example below, the spend has been proven:

In the example below, the wrong message is used, avoiding the spend to be proved:

get_reserve_proof

Generate a signature to prove of an available amount in a wallet.

Alias: None.

Inputs:

  • all - boolean; Proves all wallet balance to be disposable.

  • account_index - unsigned int; Specify the account from witch to prove reserve. (ignored if all is set to true)

  • amount - unsigned int; Amount (in atomic units) to prove the account has for reserve. (ignored if all is set to true)

  • message - string; (Optional) add a message to the signature to further authenticate the prooving process.

Outputs:

  • signature - string; reserve signature.

Example:

check_reserve_proof

Proves a wallet has a disposable reserve using a signature.

Alias: None.

Inputs:

  • address - string; Public address of the wallet.

  • message - string; (Optional) Should be the same message used in get_reserve_proof.

  • signature - string; reserve signature to confirm.

Outputs:

  • good - boolean; States if the inputs proves the reserve.

In the example below, the reserve has been proven:

In the example below, all wallet reserve has been proven:

In the example below, the wrong message is used, avoiding the reserve to be proved:

get_transfers

Returns a list of transfers.

Alias: None.

Inputs:

  • in - boolean; (Optional) Include incoming transfers.

  • out - boolean; (Optional) Include outgoing transfers.

  • pending - boolean; (Optional) Include pending transfers.

  • failed - boolean; (Optional) Include failed transfers.

  • pool - boolean; (Optional) Include transfers from the daemon's transaction pool.

  • filter_by_height - boolean; (Optional) Filter transfers by block height.

  • min_height - unsigned int; (Optional) Minimum block height to scan for transfers, if filtering by height is enabled.

  • max_height - unsigned int; (Opional) Maximum block height to scan for transfers, if filtering by height is enabled (defaults to max block height).

  • account_index - unsigned int; (Optional) Index of the account to query for transfers. (defaults to 0)

  • subaddr_indices - array of unsigned int; (Optional) List of subaddress indices to query for transfers. (defaults to 0)

Outputs:

  • in array of transfers:

    • address - string; Public address of the transfer.

    • amount - unsigned int; Amount transferred.

    • confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed).

    • double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before.

    • fee - unsigned int; Transaction fee for this transfer.

    • height - unsigned int; Height of the first block that confirmed this transfer (0 if not mined yet).

    • note - string; Note about this transfer.

    • payment_id - string; Payment ID for this transfer.

    • subaddr_index - JSON object containing the major & minor subaddress index:

      • major - unsigned int; Account index for the subaddress.

      • minor - unsigned int; Index of the subaddress under the account.

    • suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block.

    • timestamp - unsigned int; POSIX timestamp for when this transfer was first confirmed in a block (or timestamp submission if not mined yet).

    • txid - string; Transaction ID for this transfer.

    • type - string; Transfer type: "in"

    • unlock_time - unsigned int; Number of blocks until transfer is safely spendable.

  • out array of transfers (see above).

  • pending array of transfers (see above).

  • failed array of transfers (see above).

  • pool array of transfers (see above).

Example:

get_transfer_by_txid

Show information about a transfer to/from this address.

Alias: None.

Inputs:

  • txid - string; Transaction ID used to find the transfer.

  • account_index - unsigned int; (Optional) Index of the account to query for the transfer.

Outputs:

  • transfer - JSON object containing payment information:

    • address - string; Address that transferred the funds. Base58 representation of the public keys.

    • amount - unsigned int; Amount of this transfer.

    • confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed).

    • destinations - array of JSON objects containing transfer destinations:

      • amount - unsigned int; Amount transferred to this destination.

      • address - string; Address for this destination. Base58 representation of the public keys.

    • double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before.

    • fee - unsigned int; Transaction fee for this transfer.

    • height - unsigned int; Height of the first block that confirmed this transfer.

    • note - string; Note about this transfer.

    • payment_id - string; Payment ID for this transfer.

    • subaddr_index - JSON object containing the major & minor subaddress index:

      • major - unsigned int; Account index for the subaddress.

      • minor - unsigned int; Index of the subaddress under the account.

    • suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block.

    • timestamp - unsigned int; POSIX timestamp for the block that confirmed this transfer (or timestamp submission if not mined yet).

    • txid - string; Transaction ID of this transfer (same as input TXID).

    • type - string; Type of transfer, one of the following: "in", "out", "pending", "failed", "pool"

    • unlock_time - unsigned int; Number of blocks until transfer is safely spendable.

Example:

sign

Sign a string.

Alias: None.

Inputs:

  • data - string; Anything you need to sign.

Outputs:

  • signature - string; Signature generated against the "data" and the account public address.

Example:

verify

Verify a signature on a string.

Alias: None.

Inputs:

  • data - string; What should have been signed.

  • address - string; Public address of the wallet used to sign the data.

  • signature - string; signature generated by sign method.

Outputs:

  • good - boolean;

Example:

export_outputs

Export all outputs in hex format.

Alias: None.

Inputs: None.

Outputs:

  • outputs_data_hex - string; wallet outputs in hex format.

Example:

import_outputs

Import outputs in hex format.

Alias: None.

Inputs:

  • outputs_data_hex - string; wallet outputs in hex format.

Outputs:

  • num_imported - unsigned int; number of outputs imported.

Example:

export_key_images

Export a signed set of key images.

Alias: None.

Inputs: None.

Outputs:

  • signed_key_images - array of signed key images:

    • key_image - string;

    • signature - string;

Example:

import_key_images

Import signed key images list and verify their spent status.

Alias: None.

Inputs:

  • signed_key_images - array of signed key images:

    • key_image - string;

    • signature - string;

Outputs:

  • height - unsigned int;

  • spent - unsigned int; Amount (in atomic units) spent from those key images.

  • unspent - unsigned int; Amount (in atomic units) still available from those key images.

Example:

make_uri

Create a payment URI using the official URI spec.

Alias: None.

Inputs:

  • address - string; Wallet address

  • amount - unsigned int; (optional) the integer amount to receive, in atomicunits

  • payment_id - string; (optional) 16 or 64 character hexadecimal payment id

  • recipient_name - string; (optional) name of the payment recipient

  • tx_description - string; (optional) Description of the reason for the tx

Outputs:

  • uri - string; This contains all the payment input information as a properly formatted payment URI

Example:

parse_uri

Parse a payment URI to get payment information.

Alias: None.

Inputs:

  • uri - string; This contains all the payment input information as a properly formatted payment URI

Outputs:

  • uri - JSON object containing payment information:

    • address - string; Wallet address

    • amount - unsigned int; Decimal amount to receive, in coin units (0 if not provided)

    • payment_id - string; 16 or 64 character hexadecimal payment id (empty if not provided)

    • recipient_name - string; Name of the payment recipient (empty if not provided)

    • tx_description - string; Description of the reason for the tx (empty if not provided)

Example:

get_address_book

Retrieves entries from the address book.

Alias: None.

Inputs:

  • entries - array of unsigned int; indices of the requested address book entries

Outputs:

  • entries - array of entries:

    • address - string; Public address of the entry

    • description - string; Description of this address entry

    • index - unsigned int;

    • payment_id - string;

Example:

add_address_book

Add an entry to the address book.

Alias: None.

Inputs:

  • address - string;

  • payment_id - (optional) string, defaults to "0000000000000000000000000000000000000000000000000000000000000000";

  • description - (optional) string, defaults to "";

Outputs:

  • index - unsigned int; The index of the address book entry.

Example:

delete_address_book

Delete an entry from the address book.

Alias: None.

Inputs:

  • index - unsigned int; The index of the address book entry.

Outputs: None.

Example:

refresh

Refresh a wallet after opening.

Alias: None.

Inputs:

  • start_height - unsigned int; (Optional) The block height from which to start refreshing.

Outputs:

  • blocks_fetched - unsigned int; Number of new blocks scanned.

  • received_money - boolean; States if transactions to the wallet have been found in the blocks.

Example:

rescan_spent

Rescan the blockchain for spent outputs.

Alias: None.

Inputs: None.

Outputs: None.

Example:

get_languages

Get a list of available languages for your wallet's seed.

Alias: None.

Inputs: None.

Outputs:

  • languages - array of string; List of available languages

Example:

create_wallet

Create a new wallet. You need to have set the argument "–wallet-dir" when launching oxen-wallet-rpc to make this work.

Alias: None.

Inputs:

  • filename - string; Wallet file name.

  • password - string; (Optional) password to protect the wallet.

  • language - string; Language for your wallets' seed.

Outputs: None.

Example:

open_wallet

Open a wallet. You need to have set the argument "–wallet-dir" when launching oxen-wallet-rpc to make this work.

Alias: None.

Inputs:

  • filename - string; wallet name stored in –wallet-dir.

  • password - string; (Optional) only needed if the wallet has a password defined.

Outputs: None.

Example:

close_wallet

Close the currently opened wallet, after trying to save it.

Alias: None.

Inputs: None.

Outputs: None.

Example:

change_wallet_password

Change a wallet password.

Alias: None.

Inputs:

  • old_password - string; (Optional) Current wallet password, if defined.

  • new_password - string; (Optional) New wallet password, if not blank.

Outputs: None.

Example:

is_multisig

Check if a wallet is a multisig one.

Alias: None.

Inputs: None.

Outputs:

  • multisig - boolean; States if the wallet is multisig

  • ready - boolean;

  • threshold - unsigned int; Amount of signature needed to sign a transfer.

  • total - unsigned int; Total amount of signature in the multisig wallet.

Example for a non-multisig wallet:

Example for a multisig wallet:

prepare_multisig

Prepare a wallet for multisig by generating a multisig string to share with peers.

Alias: None.

Inputs: None.

Outputs:

  • multisig_info - string; Multisig string to share with peers to create the multisig wallet.

Example:

make_multisig

Make a wallet multisig by importing peers multisig string.

Alias: None.

Inputs:

  • multisig_info - array of string; List of multisig string from peers.

  • threshold - unsigned int; Amount of signatures needed to sign a transfer. Must be less or equal than the amount of signature in multisig_info.

  • password - string; Wallet password

Outputs:

  • address - string; multisig wallet address.

  • multisig_info - string; Multisig string to share with peers to create the multisig wallet (extra step for N-1/N wallets).

Example for 2/2 Multisig Wallet:

Example for 2/3 Multisig Wallet:

export_multisig_info

Export multisig info for other participants.

Alias: None.

Inputs: None.

Outputs:

  • info - string; Multisig info in hex format for other participants.

Example:

import_multisig_info

Import multisig info from other participants.

Alias: None.

Inputs:

  • info - array of string; List of multisig info in hex format from other participants.

Outputs:

  • n_outputs - unsigned int; Number of outputs signed with those multisig info.

Example:

finalize_multisig

Turn this wallet into a multisig wallet, extra step for N-1/N wallets.

Alias: None.

Inputs:

  • multisig_info - array of string; List of multisig string from peers.

  • password - string; Wallet password

Outputs:

  • address - string; multisig wallet address.

Example:

sign_multisig

Sign a transaction in multisig.

Alias: None.

Inputs:

  • tx_data_hex - string; Multisig transaction in hex format, as returned by transfer under multisig_txset.

Outputs:

  • tx_data_hex - string; Multisig transaction in hex format.

  • tx_hash_list - array of string; List of transaction Hash.

Example:

submit_multisig

Submit a signed multisig transaction.

Alias: None.

Inputs:

  • tx_data_hex - string; Multisig transaction in hex format, as returned by sign_multisig under tx_data_hex.

Outputs:

  • tx_hash_list - array of string; List of transaction Hash.

Example:

get_version

Get RPC version Major & Minor integer-format, where Major is the first 16 bits and Minor the last 16 bits.

Alias: None.

Inputs: None.

Outputs:

  • version - unsigned int; RPC version, formatted with Major * 2^16 + Minor(Major encoded over the first 16 bits, and Minor over the last 16 bits).

Example:

Sources:

Reworked RPC calls for Oxen under their .

IP=127.0.0.1
PORT=18082
METHOD="make_integrated_address"
PARAMS="{\"payment_id\":\"1234567890123456789012345678900012345678901234567890123456789000\"}"
curl \
    -X POST http://$IP:$PORT/json_rpc \
    -d '{"jsonrpc":"2.0","id":"0","method":"'$METHOD'","params":'"$PARAMS"'}' \
    -H 'Content-Type: application/json'
IP=127.0.0.1
PORT=18082
METHOD="make_integrated_address"
PARAMS="{\"payment_id\":\"1234567890123456789012345678900012345678901234567890123456789000\"}"
curl \
    -u username:password --digest \
    -X POST http://$IP:$PORT/json_rpc \
    -d '{"jsonrpc":"2.0","id":"0","method":"'$METHOD'","params":'"$PARAMS"'}' \
    -H 'Content-Type: application/json'
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_balance","params":{"account_index":0,"address_indices":[0,1]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "balance": 157443303037455077,
    "multisig_import_needed": false,
    "per_subaddress": [{
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "address_index": 0,
      "balance": 157360317826255077,
      "label": "Primary account",
      "num_unspent_outputs": 5281,
      "unlocked_balance": 157360317826255077
    },{
      "address": "7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o",
      "address_index": 1,
      "balance": 59985211200000,
      "label": "",
      "num_unspent_outputs": 1,
      "unlocked_balance": 59985211200000
    }],
    "unlocked_balance": 157443303037455077
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address","params":{"account_index":0,"address_index":[0,1,4]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    "addresses": [{
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "address_index": 0,
      "label": "Primary account",
      "used": true
    },{
      "address": "7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o",
      "address_index": 1,
      "label": "",
      "used": true
    },{
      "address": "77xa6Dha7kzCQuvmd8iB5VYoMkdenwCNRU9khGhExXQ8KLL3z1N1ZATBD1sFPenyHWT9cm4fVFnCAUApY53peuoZFtwZiw5",
      "address_index": 4,
      "label": "test2",
      "used": true
    }]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address_index","params":{"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "index": {
      "major": 0,
      "minor": 1
    }
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_address","params":{"account_index":0,"label":"new-sub"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "address": "7BG5jr9QS5sGMdpbBrZEwVLZjSKJGJBsXdZLt8wiXyhhLjy7x2LZxsrAnHTgD8oG46ZtLjUGic2pWc96GFkGNPQQDA3Dt7Q",
    "address_index": 5
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"label_address","params":{"index":{"major":0,"minor":5},"label":"myLabel"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_accounts","params":{"tag":"myTag"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "subaddress_accounts": [{
      "account_index": 0,
      "balance": 157663195572433688,
      "base_address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "label": "Primary account",
      "tag": "myTag",
      "unlocked_balance": 157443303037455077
    },{
      "account_index": 1,
      "balance": 0,
      "base_address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
      "label": "Secondary account",
      "tag": "myTag",
      "unlocked_balance": 0
    }],
    "total_balance": 157663195572433688,
    "total_unlocked_balance": 157443303037455077
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_account","params":{"label":"Secondary account"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "account_index": 1,
    "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp"
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"label_account","params":{"account_index":0,"label":"Primary account"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "account_tags": [{
      "accounts": [0,1],
      "label": "",
      "tag": "myTag"
    }]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_account_tags","params":""}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "account_tags": [{
      "accounts": [0],
      "label": "Test tag",
      "tag": "myTag"
    }]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"tag_accounts","params":{"tag":"myTag","accounts":[0,1]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"untag_accounts","params":{"accounts":[1]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_account_tag_description","params":{"tag":"myTag","description":"Test tag"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_height"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "height": 145545
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"destinations":[{"amount":100000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"},{"amount":200000000000,"address":"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"get_tx_key": true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "amount": 300000000000,
    "fee": 86897600000,
    "multisig_txset": "",
    "tx_blob": "",
    "tx_hash": "7663438de4f72b25a0e395b770ea9ecf7108cd2f0c4b75be0b14a103d3362be9",
    "tx_key": "25c9d8ec20045c80c93d665c9d3684aab7335f8b2cd02e1ba2638485afd1c70e236c4bdd7a2f1cb511dbf466f13421bdf8df988b7b969c448ca6239d7251490e4bf1bbf9f6ffacffdcdc93b9d1648ec499eada4d6b4e02ce92d4a1c0452e5d009fbbbf15b549df8856205a4c7bda6338d82c823f911acd00cb75850b198c5803",
    "tx_metadata": "",
    "unsigned_txset": ""
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer_split","params":{"destinations":[{"amount":1000000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"},{"amount":2000000000000,"address":"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"get_tx_key": true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "amount_list": [3000000000000],
    "fee_list": [85106400000],
    "multisig_txset": "",
    "tx_hash_list": ["c8d815f48f27d53fdaf198a74b292a91bfaf87529a9a9a9ee66079a890b3b58b"],
    "unsigned_txset": ""
  }
}
curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"destinations":[{"amount":1000000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"do_not_relay":true,"get_tx_hex":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "amount": 1000000000000,
    "fee": 15202740000,
    "multisig_txset": "",
    "tx_blob": "...long_hex...",
    "tx_hash": "c648ba0a049e5ce4ec21361dbf6e4b21eac0f828eea9090215de86c76b31d0a4",
    "tx_key": "",
    "tx_metadata": "",
    "unsigned_txset": "...long_hex..."
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign_transfer","params":{"unsigned_txset":...long_hex..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signed_txset": "...long_hex...",
    "tx_hash_list": ["ff2e2d49fbfb1c9a55754f786576e171c8bf21b463a74438df604b7fa6cebc6d"]
  }
}
curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"submit_transfer","params":{"tx_data_hex":...long_hex..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "tx_hash_list": ["40fad7c828bb383ac02648732f7afce9adc520ba5629e1f5d9c03f584ac53d74"]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_dust","params":{"get_tx_keys":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "multisig_txset": "",
    "unsigned_txset": ""
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_all","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","subaddr_indices":[4],"ring_size":7,"unlock_time":0,"get_tx_keys":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "amount_list": [9985885770000],
    "fee_list": [14114230000],
    "multisig_txset": "",
    "tx_hash_list": ["ab4b6b65cc8cd8c9dd317d0b90d97582d68d0aa1637b0065b05b61f9a66ea5c5"],
    "tx_key_list": ["b9b4b39d3bb3062ddb85ec0266d4df39058f4c86077d99309f218ce4d76af607"],
    "unsigned_txset": ""
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_single","params":{"address":"74Jsocx8xbpTBEjm3ncKE5LBQbiJouyCDaGhgSiebpvNDXZnTAbW2CmUR5SsBeae2pNk9WMVuz6jegkC4krUyqRjA6VjoLD","ring_size":7,"unlock_time":0,"key_image":"a7834459ef795d2efb6f665d2fd758c8d9288989d8d4c712a68f8023f7804a5e","get_tx_keys":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "amount": 27126892247503,
    "fee": 14111630000,
    "multisig_txset": "",
    "tx_blob": "",
    "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
    "tx_key": "",
    "tx_metadata": "",
    "unsigned_txset": ""
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"relay_tx","params":{"hex":"...tx_metadata..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "tx_hash": "1c42dcc5672bb09bccf33fb1e9ab4a498af59a6dbd33b3d0cfb289b9e0e25fa5"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"store"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_payments","params":{"payment_id":"60900e5603bf96e3"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "payments": [{
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "amount": 1000000000000,
      "block_height": 127606,
      "payment_id": "60900e5603bf96e3",
      "subaddr_index": {
        "major": 0,
        "minor": 0
      },
      "tx_hash": "3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f",
      "unlock_time": 0
    }]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_bulk_payments","params":{"payment_ids":["60900e5603bf96e3"],"min_block_height":"120000"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "payments": [{
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "amount": 1000000000000,
      "block_height": 127606,
      "payment_id": "60900e5603bf96e3",
      "subaddr_index": {
        "major": 0,
        "minor": 0
      },
      "tx_hash": "3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f",
      "unlock_time": 0
    }]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"all","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "transfers": [{
      "amount": 60000000000000,
      "global_index": 122405,
      "key_image": "768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b",
      "spent": true,
      "subaddr_index": 3,
      "tx_hash": "f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b",
      "tx_size": 159
    },{
      "amount": 27126892247503,
      "global_index": 594994,
      "key_image": "7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e",
      "spent": false,
      "subaddr_index": 3,
      "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
      "tx_size": 157
    },{
      "amount": 27169374733655,
      "global_index": 594997,
      "key_image": "e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157",
      "spent": false,
      "subaddr_index": 3,
      "tx_hash": "0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621",
      "tx_size": 158
    }]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"available","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "transfers": [{
      "amount": 27126892247503,
      "global_index": 594994,
      "key_image": "7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e",
      "spent": false,
      "subaddr_index": 3,
      "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
      "tx_size": 157
    },{
      "amount": 27169374733655,
      "global_index": 594997,
      "key_image": "e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157",
      "spent": false,
      "subaddr_index": 3,
      "tx_hash": "0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621",
      "tx_size": 158
    }]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"unavailable","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
{
"id": "0",
"jsonrpc": "2.0",
"result": {
  "transfers": [{
    "amount": 60000000000000,
    "global_index": 122405,
    "key_image": "768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b",
    "spent": true,
    "subaddr_index": 3,
    "tx_hash": "f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b",
    "tx_size": 159
  }]
}
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"view_key"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "key": "0a1a38f6d246e894600a3e27238a064bf5e8d91801df47a17107596b1378e501"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"mnemonic"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "key": "vocal either anvil films dolphin zeal bacon cuisine quote syndrome rejoices envy okay pancakes tulips lair greater petals organs enmity dedicated oust thwart tomorrow tomorrow"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_integrated_address","params":{"standard_address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "integrated_address": "5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn",
    "payment_id": "420fa29b2d9a49f5"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"split_integrated_address","params":{"integrated_address": "5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "is_subaddress": false,
    "payment_id": "420fa29b2d9a49f5",
    "standard_address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"stop_wallet"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"rescan_blockchain"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_tx_notes","params":{"txids":["3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f"],"notes":["This is an example"]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_notes","params":{"txids":["3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f"]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "notes": ["This is an example"]
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_attribute","params":{"key":"my_attribute","value":"my_value"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_attribute","params":{"key":"my_attribute"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "value": "my_value"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_key","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "tx_key": "feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_key","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","tx_key":"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "confirmations": 0,
    "in_pool": false,
    "received": 1000000000000
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"this is my transaction"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signature": "InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"this is my transaction","signature":"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "confirmations": 482,
    "good": true,
    "in_pool": false,
    "received": 1000000000000
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"wrong message","signature":"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "confirmations": 0,
    "good": false,
    "in_pool": false,
    "received": 0
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"this is my transaction"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signature": "SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"this is my transaction","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": true
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"wrong message","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": false
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_reserve_proof","params":{"all":false,"account_index":0,"amount":100000000000}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signature": "ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_reserve_proof","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","signature":"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": true,
    "spent": 0,
    "total": 100000000000
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_reserve_proof","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","message":"I have 10 at least","signature":"...signature..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": true,
    "spent": 0,
    "total": 164113855714662789
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"wrong message","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": false
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_transfers","params":{"in":true,"account_index":1}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "in": [{
      "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
      "amount": 200000000000,
      "confirmations": 1,
      "double_spend_seen": false,
      "fee": 21650200000,
      "height": 153624,
      "note": "",
      "payment_id": "0000000000000000",
      "subaddr_index": {
        "major": 1,
        "minor": 0
      },
      "suggested_confirmations_threshold": 1,
      "timestamp": 1535918400,
      "txid": "c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a",
      "type": "in",
      "unlock_time": 0
    }]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_transfer_by_txid","params":{"txid":"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "transfer": {
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "amount": 300000000000,
      "confirmations": 1,
      "destinations": [{
        "address": "7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o",
        "amount": 100000000000
      },{
        "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
        "amount": 200000000000
      }],
      "double_spend_seen": false,
      "fee": 21650200000,
      "height": 153624,
      "note": "",
      "payment_id": "0000000000000000",
      "subaddr_index": {
        "major": 0,
        "minor": 0
      },
      "suggested_confirmations_threshold": 1,
      "timestamp": 1535918400,
      "txid": "c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a",
      "type": "out",
      "unlock_time": 0
    }
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign","params":{"data":"This is sample data to be signed"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signature": "SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3"
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"verify","params":{"data":"This is sample data to be signed","address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","signature":"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "good": true
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_outputs"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "outputs_data_hex": "...outputs..."
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_outputs","params":{"outputs_data_hex":"...outputs..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "num_imported": 6400
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_key_images"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "signed_key_images": [{
      "key_image": "cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876",
      "signature": "c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00"
    },{
      "key_image": "65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19",
      "signature": "c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c"
    },...]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_key_images", "params":{"signed_key_images":[{"key_image":"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876","signature":"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00"},{"key_image":"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19","signature":"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c"}]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "height": 76428,
    "spent": 62708953408711,
    "unspent": 0
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_uri","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","amount":10,"payment_id":"420fa29b2d9a49f5","tx_description":"Testing out the make_uri function.","recipient_name":"el00ruobuob Stagenet wallet"}}'  -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "uri": "oxen:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function."
  }
}
$ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"parse_uri","params":{"uri":"oxen:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "uri": {
      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
      "amount": 10,
      "payment_id": "420fa29b2d9a49f5",
      "recipient_name": "el00ruobuob Stagenet wallet",
      "tx_description": "Testing out the make_uri function."
    }
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address_book","params":{"entries":[0,1]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "entries": [{
      "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
      "description": "Second account",
      "index": 0,
      "payment_id": "0000000000000000000000000000000000000000000000000000000000000000"
    },{
      "address": "78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j",
      "description": "Third account",
      "index": 1,
      "payment_id": "0000000000000000000000000000000000000000000000000000000000000000"
    }]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"add_address_book","params":{"address":"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j","description":"Third account"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "index": 1
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"delete_address_book","params":{"index":1}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"refresh","params":{"start_height":100000}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "blocks_fetched": 24,
    "received_money": true
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"rescan_spent"}' -H 'Content-Type: application/json'

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_languages"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "languages": ["Deutsch","English","Español","Français","Italiano","Nederlands","Português","русский язык","日本語","简体中文 (中国)","Esperanto","Lojban"]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"mytestwallet","password":"mytestpassword","language":"English"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"open_wallet","params":{"filename":"mytestwallet","password":"mytestpassword"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"close_wallet"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"change_wallet_password","params":{"old_password":"theCurrentSecretPassPhrase","new_password":"theNewSecretPassPhrase"}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"is_multisig"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "multisig": false,
    "ready": false,
    "threshold": 0,
    "total": 0
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"is_multisig"}' -H 'Content-Type: application/json'                  {
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "multisig": true,
    "ready": true,
    "threshold": 2,
    "total": 2
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"prepare_multisig"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "multisig_info": "MultisigV1BFdxQ653cQHB8wsj9WJQd2VdnjxK89g5M94dKPBNw22reJnyJYKrz6rJeXdjFwJ3Mz6n4qNQLd6eqUZKLiNzJFi3UPNVcTjtkG2aeSys9sYkvYYKMZ7chCxvoEXVgm74KKUcUu4V8xveCBFadFuZs8shnxBWHbcwFr5AziLr2mE7KHJT"
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_multisig","params":{"multisig_info":["MultisigV1K4tGGe8QirZdHgTYoBZMumSug97fdDyM3Z63M3ZY5VXvAdoZvx16HJzPCP4Rp2ABMKUqLD2a74ugMdBfrVpKt4BwD8qCL5aZLrsYWoHiA7JJwDESuhsC3eF8QC9UMvxLXEMsMVh16o98GnKRYz1HCKXrAEWfcrCHyz3bLW1Pdggyowop"],"threshold":2}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "address": "55SoZTKH7D39drxfgT62k8T4adVFjmDLUXnbzEKYf1MoYwnmTNKKaqGfxm4sqeKCHXQ5up7PVxrkoeRzXu83d8xYURouMod",
    "multisig_info": ""
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_multisig","params":{"multisig_info":["MultisigV1MTVm4DZAdJw1PyVutpSy8Q4WisZBCFRAaZY7hhQnMwr5AZ4swzThyaSiVVQM5FHj1JQi3zPKhQ4k81BZkPSEaFjwRJtbfqfJcVvCqRnmBVcWVxhnihX5s8fZWBCjKrzT3CS95spG4dzNzJSUcjheAkLzCpVmSzGtgwMhAS3Vuz9Pas24","MultisigV1TEx58ycKCd6ADCfxF8hALpcdSRAkhZTi1bu4Rs6FdRC98EdB1LY7TAkMxasM55khFgcxrSXivaSr5FCMyJGHmojm1eE4HpGWPeZKv6cgCTThRzC4u6bkkSoFQdbzWN92yn1XEjuP2XQrGHk81mG2LMeyB51MWKJAVF99Pg9mX2BpmYFj"],"threshold":2}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "address": "51sLpF8fWaK1111111111111111111111111111111111ABVbHNf1JFWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDkTRgKS",
    "multisig_info": "MultisigxV18jCaYAQQvzCMUJaAWMCaAbAoHpAD6WPmYDmLtBtazD654E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2Sscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskaDKuTAWtdB9VTBGW7iG1cd7Zm1dYgur3CiemkGjRUAj9bL3xTEuyaKGYSDhtpFZFp99HQX57EawhiRHk3qq4hjWX"
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_multisig_info"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "info": "4d6f6e65726f206d756c7469736967206578706f72740105cf6442b09b75f5eca9d846771fe1a879c9a97ab0553ffbcec64b1148eb7832b51e7898d7944c41cee000415c5a98f4f80dc0efdae379a98805bb6eacae743446f6f421cd03e129eb5b27d6e3b73eb6929201507c1ae706c1a9ecd26ac8601932415b0b6f49cbbfd712e47d01262c59980a8f9a8be776f2bf585f1477a6df63d6364614d941ecfdcb6e958a390eb9aa7c87f056673d73bc7c5f0ab1f74a682e902e48a3322c0413bb7f6fd67404f13fb8e313f70a0ce568c853206751a334ef490068d3c8ca0e"
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_multisig_info","params":{"info":["...multisig_info..."]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "n_outputs": 35
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"finalize_multisig","params":{"multisig_info":["MultisigxV1JNC6Ja2oBt5Sqea9LN2YEF7WYZCpHqr2EKvPG89Trf3X4E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2McPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZEKVAQ4HPPyQciSCdNjgwsuFRBzrskMdMUwNMgKst1debYfm37i6PSzDoS2tk4kYTYj83kkAdR7kdshet1axQPd6HQ","MultisigxV1Unma7Ko4zdd8Ps3Af4oZwtj2JdWKzwNfP6s2G9ZvXhMoSscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskMcPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZE1LTpWxLoC3vPMSrqVVcjnmL9LYfdCZz3fECjNZbCEDq3PHDiUuY5jurQTcNoGhDTio5WM9xaAdim9YByiS5KyqF4"]}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "address": "5B9gZUTDuHTcGGuY3nL3t8K2tDnEHeRVHSBQgLZUTQxtFYVLnho5JJjWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDqDx1gV"
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign_multisig","params":{"tx_data_hex":"...multisig_txset..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "tx_data_hex": "...multisig_txset...",
    "tx_hash_list": ["4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d"]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"submit_multisig","params":{"tx_data_hex":"...tx_data_hex..."}}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "tx_hash_list": ["4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d"]
  }
}
$ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_version"}' -H 'Content-Type: application/json'
{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "version": 65539
  }
}
GetMonero.org
copyright license

Token burning

Oxen has a robust token burning scheme designed to keep inflation under control

The Oxen Network has transitioned to the Session Network. More information here.

A crucial consideration for any tokenomics system with an indefinite emissions tail is how to keep inflation under control. In short: How can we keep rewarding service nodes indefinitely without also ending up with so much $OXEN floating around that the token becomes worthless?

$OXEN solves the inflation problem through a robust token burning scheme. This means that the effective net emissions are lower than they may seem, because most routine interactions with the Oxen network, including Blink transactions and ONS name purchases, provably burn a certain amount of $OXEN.

  • Blink fees are 0.05 $OXEN per transaction output, plus a very small per-byte amount of $OXEN; all transactions have at least 2 outputs (recipient(s) and change), so the effective fee is around 0.101 $OXEN for a typical simple transaction

  • Of that fee, 40% goes to the service node that constructs the block validating the transaction (forming part of that service node’s reward), and the remaining 60% (i.e. around 0.06 $OXEN for a typical transaction) is burned

  • Basic ONS registrations burn 7 $OXEN (for Session/Wallet namespace registrations, a registration lasts forever; for Lokinet, a basic registration lasts for 1 year)

  • You can also buy 2, 5, and 10-year Lokinet registrations for 2x, 4x, or 6x the basic fee, respectively

We periodically reevaluate and adjust fees and burn amounts to maintain reasonable levels relative to the price of $OXEN. For example, in the Valiant Vidar hardfork, the Blink fees and burn ratios were adjusted from approx. 0.2 $OXEN fee with 80% burned in a typical transaction to approx. 0.1 $OXEN fee with 60% burned.

You can view the total burned $OXEN in the block explorer.