# Introduction to Peerplays

The code for this documentation portal is on [GitHub](https://github.com/PBSA/Technical-Documents/blob/master/README.md) and we would welcome all contributions from the community.

## What is Peerplays?

Peerplays is the humanizing crypto platform.

Peerplays is a decentralized, global crypto platform, bringing a new paradigm of fairness, transparency, speed, and security. Built with Graphene technology and Gamified Proof of Stake (GPoS), Peerplays provides the fastest, most decentralized blockchain consensus model available today.

## Why Peerplays?

Peerplays is building an ecosystem of decentralized products and apps, offering people a real alternative to untrustworthy and greedy centers of control.

The Peerplays blockchain is a game-changer for people and communities around the world:

1. **Provably Fair** – Every Peerplays software component has been designed to provide a fair experience. And, unlike with traditional platform operators, all Peerplays software is open-source and publicly audit-able. Peerplays sets new standards for provably-fair networking.
2. **100% Real-Time Transparency** – Peerplays publicly broadcasts each transaction as it is executed on the blockchain in real-time. As soon as a transaction is placed, anyone can view the full audit trail of that transaction, marking a step-change in economic standards for transparency.
3. **Fast, Secure, Anonymous Control** – Peerplays integrates with all digital currencies (Bitcoin, ETH, HIVE, etc.) to provide fast, cryptographically-secured deposits and withdrawals, immediate access to funds, and anonymous control over each and every transaction.
4. **Most Trusted** – Peerplays uses GPoS to create a fully decentralized blockchain. This removes third party operators from the equation (traditional firms and exchanges) creating a completely independent platform where 100% trust is built into the core technology. (In the same way, Bitcoin released money from the control of third party financial institutions).
5. **Most Reliable** – Graphene technology gives Peerplays financial markets-grade performance and reliability with years of successful deployment logged via the BitShares blockchain.
6. **Global** – With witness nodes spread across the world, and the capacity to process over 10,000 transactions per second, the Peerplays blockchain scales to deliver a truly global economic platform.

## Who is Behind Peerplays?

A number of different groups and individuals share jurisdiction over the Peerplays blockchain, which ensures no single entity can gain control over the network. These groups and individuals include Witnesses, Advisors, and PPY token holders. For more information on the governance of the Peerplays blockchain, please visit the Governance section of this website.

The Peerplays blockchain software has been developed by the Peerplays Blockchain Standards Association (PBSA), a non-profit organization based in Canada. For more information on PBSA, please visit [pbsa.info](http://www.pbsa.info/).


# Decentralization

## 1. What is Decentralization? <a href="#decentralization" id="decentralization"></a>

You've been hearing the word **decentralized** being thrown around. What does it mean?

Decentralization refers to the transfer of control of an activity or organization to several local offices or authorities rather than one single entity. This can be ambiguous because "several" can refer to anything from as few as three to as many as there are members of an organization (like multiple boards of directors vs. every single member of the organization.) In many organizations, this can create a smoke screen where the perception of freedom is created to hide the real aim of the organization; control for the few. The more decentralized the organization, the greater capacity there is for its members having control. In order to assess the level of control we will have when joining an organization that claims to be decentralized, we must assess the organization’s methods of decentralization.

## 2. Quantifying Decentralization

Examine the level to which the organization has dispersed its control. First, how many modes of power have been decentralized and to what extent has each mode been decentralized? To judge the number of modes, we must understand these modes and the impact that they have on an organization. These modes are decision making, narrative, enforcement, and innovation.

### 2.1. Decision Making

Decision making refers to the ability to choose and implement avenues of change within bounds. This could mean the day-to-day decisions in each department, which has generally been the role of employees and managers within centralized systems. The power to make decisions extends to the highest level of the organization. Decision making determines how money is obtained, how it is distributed, which solutions are attempted, which risks are considered worth taking, how compensation is determined, and so on.

Much of the decision making power in centralized systems have been delegated across departments with a single party or small group of parties responsible for the implementation of suggestions made by each of these departments. For example, a human resources department may assess the compensation needs of all employees based on department and employee generated criteria and then propose a compensation and benefits package that every member of the organization would find fair. If, however, this package were to be vetoed by the CEO of the organization, the implementation of this package would not occur.

In a fully decentralized system, each employee would be asked for input, the suggestions would be compiled into a cohesive package and assessed for feasibility, and implemented once a sustainable agreement was found without the backing of a higher authority. While this may seem time consuming due to the need for negotiation among those providing opinion, ultimately the result of such negotiations allows each member to take ownership, feel valued, and have the opportunity to understand the reasoning for decisions. In this way, discontentment among staff is avoided and the organization has the support of all of its members.

### 2.2. Narrative

The narrative of an organization is the union of several pieces of human generated experience.

* First, it is made of organizational data.
* Second, it is made of the value system, mission statement, and goals of the organization as a whole.
* Third, it is made of the values and goals of each individual member of an organization, including those that are never voiced (For example: plans for furthering education, competition among members, personal problems, etc.)
* Fourth, it is made of communication.

To truly understand narrative and its impact on an organization, it can be helpful to think of Ecological systems theory developed by Urie Bronfenbrenner (see Figure 1 & [Appendix A](/concepts/decentralization#appendix-a)). While Bronfenbrenner’s theory relates to the development of people, an organization will be treated as an individual within public consciousness. Its development must be treated as any other individual, with the understanding that it too is made of individuals.

![Figure 1: Bronfenbrenner's Ecological systems theory. See Appendix A for details.](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-Mhn2vK87bfXWZrn2iZS%2F-MhnEWD6zVr6frOEiE12%2FEcological-systems-theory.jpg?alt=media\&token=58abba93-5dc3-4de1-9f95-612e764bc678)

Both the narrative of each member and the narrative of the organization as a cohesive whole acting as an individual in the public sphere must be taken into account when control is considered. Errors in representation are always made when a group is unable to speak for themselves. The perception of individuals within a group and the group as a whole will come from how those outside the organization receive the narrative. The narrative of the organization as a whole will also create the perception of its members. To control the narrative is to control how you are seen. A negative perception at any level helps no one, and is often a source of much anger, resentment, and embarrassment among those who do not feel accurately represented. Representation matters.

### 2.3. Enforcement

Enforcement is the act of compelling observance of or compliance with a law, rule, culture, or obligation. The control of enforcement must be given careful consideration. In a centralized system, there is always a bottom tier that has no power to enforce, and no one has authority of the top tier outside of state and national law. While those without punitive authority are able to report to those higher or provide feedback to each other, they ultimately do not have the power to ensure that every member of their group is abiding by the established rules and culture. More often than not, only those at the highest level of the authoritative hierarchy are able to set rules and devise the means by which these rules are to be enforced. A lack of enforcement means that a rule is not taken seriously, and is therefore not a rule. Too much enforcement can generate fear and distrust of authority figures, which can negatively impact performance in a variety of ways.

The alternative to this hierarchical approach is to encourage as much organizational ownership as possible to the creation and enforcement of rules and organizational culture as possible. In an article published at [tribeculturechange.com](https://tribeculturechange.com/how-to-make-people-follow-the-rules/), Lizz Fields-Pattinson promotes the idea that "when we have a stake in how we’re supposed to approach the world around us, we feel a sense of social belonging and alignment with the people who share that world-view," so it is beneficial to "involve more people in the decisions which affect rules or codes of conduct from the start, that way you encourage a larger number of engaged advocates to back your cause." This is echoed by Market Business News: "People feel motivated to follow through when they feel that they are part of the program."

While it may still be necessary within an organization to have an authority group that is charged with enforcement, there are ways to decentralize this mode of control so that there is no hierarchy. For example, in the beginning stages of the formation of rules and consequences, all member should be invited to share their vision of the standard by which operations are to be run and what should be the consequence for an individual that does not follow the standard. Once a code of conduct and levels of intervention have been established, a review process can occur within set cycles to ensure that new members have an opportunity to weigh in and necessary changes to the system can be established and implemented. To ensure that all members are held accountable, delegates can be chosen for a disciplinary committee on a rotational basis on which all individuals have the opportunity to serve. Team managers can be chosen based on experience and training criteria, but also be subject to peer review by those they manage. In a system such as this, all members have the opportunity to provide and receive feedback, and no one is in a strictly subordinate role.

### 2.4. Innovation

Innovation refers to the development of something new. This applies to products, but also any idea, method, or procedure at any level within the organization. In general, the control of innovation has everything to do with who is given the authority to try new things and to make suggests. In a typical centralized organization, innovation is reserved for specific departments and the categories of thought are siloed. Consider that human resources, research and development, manufacturing, and marketing often have no need to communicate, yet individuals within every department are affected by the ideas generated by each group. Also consider that individuals may have expertise separate from their job role. For example, a member of the production line may be obtaining a social work degree and therefore generate an idea that could be useful to human resources. If there is no means by which these ideas can easily be shared, they likely will not be. A suggestion box is only useful when the ideas within are actively considered.

## 3. What does this mean for me?

In a centralized system, primary decisions are made by the person or group at the very top of the organization, such as a board of directors or a CEO. To move away from this model, an organization may begin to allow latitudes to "lower" levels of the organization, but maintain functions such as research, development, and records keeping for the highest levels of the organization. So, even if basic decision making is now shared throughout the organization, the upper levels maintain control of innovation and any long-term changes are not easily accessible to those who have the power of basic decision making.

While blended systems such as these seem to allow freedom, those with voting power can only choose those options they believe are available to them. Consider that daily decisions may be short lived and have little impact on the direction of the company. Without the ability to innovate, the future direction of the company is still controlled by a central group. The suggestions leading to innovation will be generated by research and development which, being controlled by a centralized group rather than open to all, are funneled. Any decisions therefore are controlled by a central group.

The same is true for the control of narrative, especially by way of data and information regarding changes within the organization. Consider an organization’s turn over. If those involved in decision making are gradually replaced by others over time, those new to the organization will only know of what has recently come to pass without the ability to access all records. If the records are maintained by a central group, again there is the concern of funneling. When documentation is restricted, openness is jeopardized, as is timeliness. Further, a single copy of historical records is subject to corruption. Any changes made, whether accidental or intentional, will have no basis of comparison. If, however, every person with power of decision were to have their own copy of all documentation records, access will be automatically granted and immediate, and discrepancies will become apparent between copies.

When all aspects of an organization are fully decentralized, there is no limit to its innovative potential. Rather than suggestions being funneled from a centralized viewpoint. Each member is free to make suggestions relative to their perspective within the organization. Each suggestion may be assessed for utility by all those with power of decision and implemented with expediency. There is no need to wait for approval from a centralized power. Majority support cannot be overturned by a single voice. Once accepted and initiated, it will be up to market trends to decide outcomes. Counter-changes can be made just as quickly if market trends show a need. This flexibility in innovation allows for timely adjustments and increases the likelihood for rapid growth and success.

Likewise, the increased access of information allows for better integrity within the organization. Consider the human dynamic within organizations. While no one wants to think the worst of an organization’s members, mistakes will happen and people can give into temptation. In a centralized system of records keeping, it is up to a single group to catch all errors or intentional fudging. When there is no basis of comparison, it can take time to reconcile places where figures do not make sense. The more transactions occur, the longer it can take.  When information is decentralized, however, there is a large basis for comparison and every individual with a copy has the ability to compare with others. Discrepancies are far more noticeable. If a single copy varies from the others, it becomes easier to fix and easier to trace its source. Unless each copy where to be simultaneously corrupted, there would be no way to hide a discrepancy. Since each copy is housed separately, it would be nearly impossible to effect a change across the entirety of records. The contents of the documentation are therefore trustworthy.

It is only when all aspects of an organization are delegated that an organization can truly claim to be decentralized.

## Appendix A

Ecological systems theory was developed by Urie Bronfenbrenner. The six systems described in his theory, and outlined in Figure 1 (above) are as follows:

**Individual** (or Organization): This can represent a member of the organization or the organization itself, depending on the context.

**Microsystem**: Institutions and groups that most immediately and directly impact the individual's development.

**Mesosystem**: Consists of interconnections between the microsystems. For example, interactions between different departments within the organization that will impact the individual.

**Exosystem**: Involves links between social settings that do not involve the individual, yet have an impact on the individual. For example, the experiences of other organizations within the same industry.

**Macrosystem**: Describes the overarching culture that influences the developing individual, as well as the microsystems and mesosystems embedded in those cultures. Cultural contexts can differ based on geographic location, socioeconomic status, poverty, and ethnicity. Members of a cultural group often share a common identity, heritage, and values. Macrosystems evolve across time and from generation to generation.

**Chronosystem** (not pictured): Consists of the pattern of environmental events and transitions over the life course of the individual, as well as changing socio-historical circumstances.


# Consensus Mechanisms Compared

The differences among POW, POS, & POP (and their variations)

## 1. Consensus

In the realm of crypto-economies, consensus is the way decisions are made that impact a whole network despite having no central decision-maker. Systems must be in place to allow everyone to agree on transactions happening in real-time across the globe. This is why the developers of blockchains have carefully crafted mechanisms of consensus to try to preserve decentralization while also maintaining mutual agreement of all members of the network.

Here we will explain the most widely used and well known consensus mechanisms, Proof of Work and Proof of Stake. We will also introduce a new consensus mechanism which serves to be the latest evolution and a paradigm shift to the approach of consensus, Proof of Pulse.

## 2. Proof of Work

### 2.1. The Big Idea

> Competitive: The one with the most computing power wins.

Proof of Work (**POW**) is essentially a puzzle-solving race to determine block creation. Block producers, known in this case as "miners", use ever-increasing levels of computing power to solve more and more difficult puzzles. The first miner to solve the puzzle produces a block on the network, receives a reward, and the process starts again with a new puzzle. Its main goal is to incentivize people to use their computing power to ensure the network continues to run, and the blocks are validated.

### 2.2. Incentivization

Miners are in a competitive race to produce blocks on the network. For every block produced, a reward is given to the producer. The difficulty of the puzzles increases over time to keep the block production at roughly 10 minutes per block (on the Bitcoin chain). The difficultly must increase due to more and more computing power coming online to earn rewards. This has the unfortunate side effect of being horribly inefficient. More and more electricity is being used to fuel the computing power, etc.

### 2.3. Network Security

In POW, the distribution of computing power matters most. If an individual or organization could gain 51% of the network computing resources, they could simply validate any block they wished. In essence, it would be a complete chain take-over. The power of cryptocurrencies comes from the decentralization of its ledger of transactions. If anyone could own 51% of the network resources, they would own the ledger and the network would no longer be decentralized.

## 3. Proof of Stake

### 3.1. The Big Idea

> Competitive: The one with the most tokens wins.

Proof of Stake (**POS**) is another competitive consensus algorithm. But instead of a computing power race, the level of staked tokens is used as the determining factor of who can produce and validate blocks. This method is much more efficient than POW. The more staked tokens an account has, the more priority it is given to produce and validate blocks. Rewards at then given to the producers upon block production.

### 3.2. Incentivization

Block producers, sometimes called "Master Nodes" in POS, store vast amounts of the network's tokens in stakes. Depending on the chain in question, sometimes a certain (usually very high) level of stake is required to be a block producer. Higher stakes means more rights to produce blocks which in turn means more rewards. This translates to a classic "the rich get richer, the poor get poorer" scenario.

### 3.3. Network Security

In POS, the distribution of staked tokens matters most. Much like in POW, If an individual or organization could gain 51% of the staked tokens, they could simply validate any block they wished. Again, it would be a complete chain take-over. The power of cryptocurrencies comes from the decentralization of its ledger of transactions. If anyone could own 51% of the staked tokens, they would own the ledger and the network would no longer be decentralized.

### 3.4. Variations

#### Delegated Proof of Stake

Delegated Proof of Stake (**DPOS**) is a variation of POS in that instead of only the highest levels of stake getting a say, everybody with any amount of stake can participate. Although the same "Master Node" concept applies, anyone can apply their stake to back a Master Node. When the Master Nodes are rewarded, the rewards are shared proportionally with those who backed them up with their stake. It helps to spread the rewards a little, but it's like the blockchain equivalent of "trickle down" economics. It still requires huge stakes to have meaningful rewards.

In some chains, like Graphene based chains, DPOS is implemented more like a vote. Master Nodes ("Witnesses" in Graphene) are voted on by applying your stake as a vote for someone else's node. The winners of the vote are then the active block producers.

#### Gamified Proof of Stake

Gamified Proof of Stake (**GPOS**) is a further improvement on DPOS. Voting for Witnesses with staked tokens occurs like with other Graphene chains, but in this case the rewards given to the voters diminishes over time. Voters must periodically vote again to maintain their rewards income. This requires the voters to be more actively engaged in the network governance to reap the full benefits of their stake.

GPOS is where we start to see a major paradigm shift:

* We're moving from **competitive** consensus to **cooperative** consensus.
* The rewards shift from paying those that **own capital** (expensive computers, vast sums of tokens) to paying those that **do work** (node operators providing services).
* People go from being **passive users** of a network to **engaged participants** in network governance.
* The incentives shift from the **extrinsic**, "What can the network do for me?" to the **intrinsic**, "How can we improve the network for everyone?".

## 4. Proof of Pulse

### 4.1. The Big Idea

> Cooperative: Everyone contributes to incremental network improvement.

Proof of Pulse (**POP**) generates network consensus spontaneously from the outcomes of continuous, randomized, and incremental voting. Every hour a round of voting, a **"pulse"**, begins:

1. First, a random subset of accounts are selected across the network.
2. These accounts are each given one random item to vote on. (Fees, node operators, etc.)
3. Each chosen account is notified, and there is a limited time to make their vote.
   1. Votes can only be: Up (in favor), Down (against), or Stay (no change).
   2. Votes are weighted by voting power of the account.
4. The votes are tallied per item and the winning vote is how that particular item will change.
5. The impact of the pulse will expire after 60 days.

This method ensures that, while everyone has a voice, it's the will of the collective whole that moves the network along.

### 4.2. Incentivization

The POP consensus mechanism relies on the intrinsic motivation of individuals who genuinely wish to improve the state of the network. There are no monetary rewards for casting votes or participating in blockchain governance. Node operators are paid for the work they perform for the network. One of the decisions of consensus is how much a node operator will be paid for their services.

Another form of income is to stake tokens to supply liquidity pools to enable instant token swaps. In this case, staked tokens will earn rewards from the transaction fees of the token swaps they are backing. Once again, the transaction fees are changed through decisions of consensus.

Note that in POP, rewards are only paid when some form of work is done. If you are a node operator, you are running software to provide a service. If you stake to a liquidity pool, people are using your tokens to make swaps in the exchange.

### 4.3. Network Security

#### The Attacker's Dilemma

An attacker's goal is to gain as much control over the network parameters as possible. This is usually done by using overwhelming resources to gain the majority of voting power or ability to edit the chain itself. In a POP system, an attacker has to make a decision:

* Concentrate all of their voting power on one account...
  * but severely limit their chances of being included in the vote they wish to control!
* Open hundreds of accounts to give themselves a much greater chance of being randomly assigned the votes they wish to control...
  * but spread their voting power too thin to actually control the vote!

As you can see, it's a bad situation for an attacker. They cannot simultaneously have "whale" levels of voting power and also guarantee they'll be assigned the votes they want to control. But it gets even worse for an attacker. Even if they hold massive voting power in their account, and get lucky enough to be randomly assigned the vote they want, they can't **set** chain parameters. Votes are only for incremental changes from the existing parameter levels. And on top of that, the effects of votes drop off over time. That is to say, a vote outcome today will not have an effect on the chain parameters after 60 days. So they would have to have absurd luck, again and again, to dominate the chain.

Proof of Pulse was designed specifically for consensus of the whole network.

## 5. Future of Consensus

Consensus is about agreement. That's why it's important to rethink the mechanisms we create to form consensus in this new decentralized world. Competitive structures don't seek agreement. Instead we can use cooperation to build a system that benefits everyone. We can use incentives to get work done rather than to pay those who are already at the top. We can build more human centered networks. This is what the Proof of Pulse consensus mechanism is all about.


# Peerplays Technical Summary

## Introducing Peerplays

Peerplays is a decentralized, global crypto platform, built on the most advanced blockchain technology available today. Peerplays brings a new paradigm of fairness, speed, transparency, and security to the global economy.

Peerplays’ decentralization is based on the Delegated Proof of Stake (DPoS) consensus model, meaning that blocks are produced by a group of "Witness" nodes which are elected by stake-weighted token holder voting.&#x20;

In addition to the Witnesses and the Advisors, a group of blockchain accounts, likewise elected by token holder voting, which vote to specify configurable blockchain parameters, and vote to include or reject proposed new features and other modifications to the consensus protocol.

Peerplays is a smart contracting platform specifically targeted at humanizing crypto economies.&#x20;

{% hint style="warning" %}
Peerplays is not a *Turing complete* smart contracting platform, meaning that Peerplays does not support arbitrary, user-defined smart contracts; rather, it provides a well-defined set of officially maintained, built-in contracts. This is in contrast to *Turing complete* smart contracting platforms like EOS or Ethereum, which provide few to no official contracts, but allow users to define and share contracts without any formally defined quality or correctness verification.
{% endhint %}

This document is intended to give new Peerplays developers an introduction to the Peerplays architecture and software. Readers are expected to be familiar with C++ software development in general, but not with Peerplays specifically.

This document will walk readers through the code repository structure and how to build the software; describe the individual libraries and executables and their purposes; and examine how the smart contracts work and discuss how to create or modify Peerplays smart contracts.

## Graphene

Graphene is the underlying technology behind the Peerplays blockchain. It's an open-source blockchain technology, mainly written in C++. The Graphene source is available in numerous variations, as it has been forked and adapted many times.

There is no other known blockchain like Graphene that can even try to compete in the processing such a high number of transactions this blockchain already can.&#x20;

Graphene-based coins can do something Bitcoin was never capable of, and will never be. And that is being a real-time value exchange system that will get mass adoption, with great apps built upon it.&#x20;

A few of the advantages of Graphene are:

* Can push over 10,000 transactions per second (TPS), versus Bitcoin, currently at around 7 transactions per second - this could mean Bitcoin payments hanging for 3-4 days!
* Best-in-class block production and transaction finality at three seconds compared to Bitcoin at 10 minutes.
* Supports payments with zero commission. Users can transfer coins from one account to another absolutely free of charge.
* Uses the Delegated Proof of Stake (DPOS) algorithm instead of Proof of work (POW).
* The possibility of working with several tokens in one system at once.

The key Graphene resources can be found here and are a very good starting point for anyone wanting to understand the Peerplays blockchain.

{% embed url="<https://github.com/cryptonomex/graphene>" %}

## DPOS and GPOS

Peerplays is based on the Delegated Proof of Stake (DPOS) consensus mechanism, where the number of Witnesses are selected, via continuous voting by the PPY token holders, to produce blocks.&#x20;

{% hint style="warning" %}
**Note**: The number of block producing (active) Witnesses has to be an odd number.
{% endhint %}

Only these Witnesses produce the blocks in their respective time slots until the next maintenance interval. After the maintenance interval, the algorithm chooses the next set of Witnesses based on the voting results. Furthermore:

* Only token holders can participate in the voting process.
* Token holders can vote multiple times, for multiple Witnesses.

Apart from Witnesses, the token holders also elect Advisors who have the privilege of proposing changes to the network parameters. These changes range from something as simple as transaction fees – to the number of elected Witnesses.&#x20;

Under DPOS the administrative authority rests in the hands of the users, just like a democracy. But unlike Witnesses, the Advisors are not compensated for retaining their positions.

Building on the success of the DPOS consensus mechanism, Peerplays introduced a unique enhancement called **Gamified Proof of Stake (GPOS)**.

The original intent of Peerplays was to operate as a Decentralized Autonomous Cooperative (DAC) where DPOS enabled the voting collective of core token holders to determine who would act as Advisors, Witness, and Proposals within Peerplays. However, the challenges of voter turnout continued to plague Peerplays like other DPOS based blockchains.&#x20;

GPOS made a protocol change such that PPY token holders now receive a 'participation reward' based on their voting performance and how many PPY they have vested or 'staked'.

This is a significant change from the original DPOS protocol where token holders were rewarded with their share of a 'rake', taken from a percentage of the blockchain fees, and then distributed to token holders relative to their token holdings, regardless of any voting participation.

The importance of voter participation of the PPY token holders is paramount to the security of the blockchain. The introduction of GPOS ensures that token holders will take an active interest in the operation and governance of Peerplays.

## Peerplays Repository

The official Peerplays repository can be found at:

{% embed url="<https://github.com/peerplays-network/peerplays>" %}

This repository uses git submodules, so be sure to fetch the submodules when cloning. This can be done by passing the `--recursive` flag when cloning:

```
$ git clone https://github.com/peerplays-network/peerplays --recursive
```

The most significant subdirectories in the repository are `libraries`, `programs`, and `tests`. The Peerplays implementation is almost entirely defined within various libraries, which are located in the `libraries` subdirectory.&#x20;

The `programs` subdirectory contains small wrappers around these libraries, exposing their functionality as executable binaries.

&#x20;The `tests` subdirectory contains various tests to verify that essential blockchain features and functionality are working, and to detect regressions should they occur during development.

We'll now look at each of the three subdirectories in greater detail.

### The Peerplays Libraries

Peerplays is implemented in several `libraries` within the libraries sub directory of the repository. A high level description of each of the libraries is as follows:

* `app` contains the `application` class, which implements the heart of a Peerplays node
* `chain` contains the bulk of the blockchain implementation, including all Peerplays specific functionality
* `db` contains the database functionality, implementing the in-memory database as well as the persistence layer
* `egenesis` is a small library which embeds the genesis block data into the binary
* `fc` is a library implementing many utility functionalities, including serialization, RPC, concurrency, etc.
* `net` contains the peer-to-peer networking layer of Peerplays
* `plugins` contains several plugin libraries which can be utilized within a Peerplays node
* `utilities` contains code and data necessary to Peerplays’ implementation, but not critical to the core functionality
* `wallet` contains the reference command-line wallet implementation

Of these libraries, the bulk of development activity occurs within the `chain` library, and sometimes `fc`. The other libraries remain reasonably stable, seeing comparatively small updates and modifications.

### The Peerplays Programs

Peerplays contains several programs, but only two of these are relevant to modern Peerplays development: `witness_node` and `cli_wallet.` In addition, the code within these folders exists just to expose library functionality in an executable, and is rarely updated.&#x20;

The `witness_node` program is the only maintained Peerplays node executable. The name `witness_node` is something of a misnomer, as this executable is really just a full node, but it can provide witness (i.e., block producer) functionality by loading the `witness` plugin.&#x20;

{% hint style="info" %}
**Tip**: If you wish to sync with the Peerplays blockchain network and maintain a database of the current chain state, this is the program to do it with.
{% endhint %}

The `cli_wallet` program implements a command-line wallet for Peerplays. It requires a network connection to a running `witness_node` to provide chain state information to it. This program provides a basic UI for all Peerplays functionality.

### The Peerplays Tests

Peerplays uses the Boost testing framework for its tests. Most of the Peerplays tests use the `database_fixture`, defined in `tests/common/database_fixture.hpp`, as the basis of the tests. This file also defines many macros and functions to reduce the boilerplate of test writing.

The bulk of the tests are written in the `tests/tests` folder, and are run by the `chain_test` binary. All tests of core functionality should be included in this directory and binary.

## Peerplays Smart Contracts

This section provides a high-level overview of the architecture of smart contracts in Peerplays, how they work, and how they are created.

At its essence, a Peerplays smart contract is comprised of three main types of object:&#x20;

* `operation`
* `evaluator`&#x20;
* `object`&#x20;

The Peerplays protocol defines a set of actions a user can take within the blockchain ecosystem, called `operation` s. All interactions with the blockchain take place through `operation` s, and in a sense, they are the blockchain’s API.&#x20;

Each `operation` has an `evaluator`, which implements that operation’s functionality within the Peerplays software implementation. Thus an `operation` is like a function prototype, whereas an `evaluator` is the function definition.&#x20;

Finally, all data persistently stored by the blockchain is contained within database `object` s. Each `object` defines a group of fields, analogous to columns of a relational database table.

### Operations

All `operation` s charge a fee to execute, and each must specify an account to pay the fee. This account’s ID must be returned by the `fee_payer()` method on the `operation`. Each `operation` must also provide a stateless consistency check which examines the `operation`’s fields and throws an exception if anything is invalid.&#x20;

Finally, `operation` s must provide a `calculate_fee()` method which examines the `operation` and calculates the fee to execute it. This method may not reference blockchain state, however, each `operation` defines a `fee_parameters_type` struct containing settings for the fee calculation defined at runtime, and an instance of this struct is passed to the `calculate_fee()` method.

All `operation` s automatically require the authorization of their fee paying account, but an `operation` may additionally specify other accounts which must authorize their execution by defining the `get_required_active_authorities()` and/or `get_required_owner_authorities()` methods.&#x20;

{% hint style="warning" %}
**Note**: If a transaction contains an `operation` which requires a given account’s authorization, signatures sufficient to satisfy that account’s authority must be provided on the transaction.
{% endhint %}

### Evaluators

Each `operation` has an `evaluator` which implements that `operation`’s modifications to the blockchain database. Each `evaluator` most provide two methods: `do_evaluate()` and `do_apply()`.&#x20;

The evaluate step examines the `operation` with read-only access to the database, and verifies that the `operation` can be applied successfully. The apply step then modifies the database.&#x20;

Each `evaluator` must also define a type alias, `evaluator::operation_type`, which aliases the specific `operation` implemented by that evaluator.

### Objects

The Peerplays software implementation utilizes a custom, in-memory relational-style database to track the blockchain state as new blocks and transactions are applied, containing `operation` s which modify the database.&#x20;

This database is implemented in the `libraries/db` folder, and it provides persistence to disk as well as undo functionality allowing the rewinding of changes, such as when a partially-applied transaction fails to execute, or blocks are popped due to a chain reorganization (i.e. when switching forks).

The Peerplays database tracks various `object` types, each of which defines the columns of a table. The rows of this table represent the individual object instances in the database. Along with each `object` type is an index type, which, in relational database terms, defines the primary and secondary keys, which can be used to look up object instances.&#x20;

The primary key is always an `object_id` type, a unique numerical ID for each object instance known to the blockchain. All `objects` inherit an `id` field from their base class which contains this ID. This field is set by the database automatically and does not need to be modified manually.

### Summary

Peerplays smart contracts are defined as a set of `operation` s which are analogous to API calls provided by the contract.&#x20;

These `operation` s are implemented by `evaluator` s, which provide code to verify that the operation can execute successfully, and then to perform the requisite modifications to database `object` s.&#x20;

All `object` s specify an index, which defines keys which can be used to look up an object instance within the database.

## Peerplays API(s)

Since Peerplays is a Graphene based blockchain it supports the Graphene API at its core.

For more information on the Graphene API go to:

{% embed url="<https://docslocalcoinis.readthedocs.io/en/latest/api/index.html>" %}

To make access to the API easier for developers there are two Python libraries that can be used.

### python-peerplays (pypeerplays)

This is a communications library which allows interface with the Peerplays blockchain directly and without the need for a cli\_wallet. It provides a wallet interface and can construct any kind of transactions and properly sign them for broadcast.

The repository can be found here:

{% embed url="<https://github.com/peerplays-network/python-peerplays>" %}

The purpose of `pypeerplays` is to simplify development of products and services that use the Peerplays blockchain. It comes with:

* It’s own (bip32-encrypted) wallet
* RPC interface for the Blockchain backend
* JSON-based blockchain objects (accounts, blocks, events, etc)
* A simple to use yet powerful API
* Transaction construction and signing
* Push notification API
* *and more*

### peerplaysjs-lib

This is Javascript API for interacting with the Peerplays Blockchain. This is more commonly used for connecting dApps to the blockchain.&#x20;

The repository can be found here:

{% embed url="<https://github.com/peerplays-network/peerplaysjs-lib>" %}

### Interfacing With Graphene

The APIs are separated into two categories:

* the **Blockchain API** which is used to query blockchain data (account, assets, trading history, etc.)
* the **CLI Wallet API** which has your private keys loaded and is required when interacting with the blockchain with new transactions.

The set of available calls depends on whether you connect to a full node (`witness_node`) or the wallet (`cli_wallet`). Both support RPC-JSON. The full node also supports the websocket protocol with notifications.

Which blockchain network you connect to depends on the configuration of the full node and the wallet.&#x20;

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-LwEjhkzu6zw_t-CCZHV%2F-LwEkfswgRa4k65FpRxp%2FScreen%20Shot%202019-12-16%20at%201.27.55%20PM.png?alt=media\&token=74e7dad0-203f-4506-a205-38c36f8a7b72)

{% hint style="info" %}
**Tip**: If you run a full node, we recommend you connect your wallet to your local full node even though it could be connected to any other public full node as well.
{% endhint %}

#### Blockchain API

The blockchain API (as provided by the `witness_node` application) can be used to obtain any kind of data stored in the blockchain. Besides data stores in the blockchain itself (blocks, transactions, etc. ..), higher level objects (such as accounts, balances, etc. …) can be retrieved through the full node’s database.

It is not required to run a local full node if you want to query a particular blockchain or database, but you can also query any existing public node for information.

{% hint style="danger" %}
**Important**: The blockchain API doesn't know about private keys, and cannot sign transactions for you. All it does is validate and broadcast transactions to the P2P network.
{% endhint %}

#### CLI Wallet API

The cli-wallet api, as provided by the `cli_wallet` binary, allows you to create and sign transactions and broadcast them.

{% embed url="<https://github.com/peerplays-network/peerplaysjs-lib>" %}


# Intro to Peerplays Tokens

A brief guide to the various tokens of Peerplays.

## 1. Overview

Cryptocurrency (crypto) tokens represent tradable assets or utilities that reside on a blockchain. There are many uses for these tokens and their usefulness is growing in scope and scale at a remarkable pace. For example, just some of the things tokens are used for today:

* a store of value, like fiat currency
* fundraising via crowd sales
* decentralized financial instruments (called DeFi)
* digital intellectual property
* digital objects (in-game items, etc.)
* digital records (certifications, college degrees, etc.)
* supply chain management

The Peerplays blockchain has its own set of tokens which enable the various features of the network. Each type of token brings more versatility to benefit everyone who enjoys Peerplays.

## 2. Token Types

Many different types of tokens exist in the world of crypto. Peerplays uses the following types to facilitate the transactions on the network.

{% hint style="info" %}
Tokens are sometimes called "assets". The terms are pretty much interchangeable, at least for the purposes of this document.
{% endhint %}

### 2.1. Native Assets (coins)

The native assets within Peerplays are the coins which provide voting power when staked. The native asset of the Peerplays network itself is PPY. Communities within the Peerplays network may also have their own native asset. In this case, when the community native asset is staked, you would gain voting power for the governance of that community.

### 2.2. NFTs

NFTs, or Non-Fungible Tokens, are tokens that typically represent virtual objects. Such objects are indivisible by nature. A visual example of an NFT would be art prints. Many prints of a single piece of art can exist, but each print itself can't be divided. NFTs are often used for artwork because of this quality.

Another defining feature of NFTs is their ability to be verified thanks to blockchain technology. All NFTs are unique. Going back to the art prints example, it's possible to know exactly which print you own from a given set. You might have print number 6 out of 200 and this can be verified on the blockchain. Additionally, you can find all the transactions related to that NFT since its creation.

The Peerplays network allows you to create, exchange, and buy/sell NFTs. They're also used in Peerplays for token staking, governance, rewards, and countless uses within dApps.

### 2.3. Community Tokens

Community tokens (also called Fan tokens) are tokens which have been created to serve a particular community within the Peerplays network. Communities can have their own core token to provide voting power for the governance of that community. Other community tokens can exist to serve specific purposes within that community as well. The uses of community tokens are only limited by the imagination.

### 2.4. Sidechain Tokens

Sidechain tokens are assets which have originated off-chain that have been transferred onto the Peerplays chain through the services of Peerplays SONs. These sidechain assets include Peerplays versions of BTC, HIVE, or ETH and even Peerplays versions of NFTs living on the Ethereum chain. The external assets are backed by their counterparts, locked in a Peerplays controlled account on their native chains.

The sidechain tokens are prefixed with a "p" to denote that it is a Peerplays version of the token. For example, pBTC is Peerplays-Bitcoin and having a balance of 1 pBTC would mean having it backed by 1 BTC in a Peerplays controlled wallet. In this way, BTC can be deposited, withdrawn, and used across Peerplays as easily as any native token.

This means that tokens like BTC can be exchanged using the Peerplays Dex, staked to Peerplays liquidity pools, used in Peerplays based dApps, and to purchase NFTs.

## 3. Peerplays Tokens

### 3.1. PPY

PPY (Peerplays coin) is the native asset of the Peerplays network. Staking this asset provides voting power for voting on witnesses, SONs, advisors, and more. In addition, all exchanges that take place in the Peerplays Dex are based on exchanging assets with PPY. Currently a portion of all transaction fees within Peerplays is redistributed back to PPY holders as rewards, based on their amount of staked PPY.

PPY is the main store of value in Peerplays and is used to pay for transaction fees on the network.

### 3.2. BTFUN

BTFUN (BitFun) is the token created for BookiePro. BTFUN is used to place bets with a valueless token. It's used just for fun!

### 3.3. Peerplays NFTs

NFTs can be created on the Peerplays network for a wide variety of uses. DApp developers can issue NFTs to represent digital items, certificates, shares of ownership, and much more.


# Intro to Peerplays Liquidity Pools

A brief overview of the Peerplays Liquidity Pools.

## 1. Liquidity Pools

Liquidity pools (LPs) are designed to enable the instant swapping of various crypto assets, coins or tokens, at a price which is based on the available supply of each asset. LPs give those who are looking for an opportunity to earn rewards with the assets they own a way to do so. These asset owners supply the liquidity by staking their assets into the pool.

### 1.1. What is a liquidity pool?

In Peerplays, a liquidity pool is a network controlled asset address which is used to store the assets which have been staked to the pool. This pool is then used to facilitate the exchange of assets between interested traders. A small fee is charged to execute an exchange using the pool. The fees are then given to the people who staked to the pool in proportion to the amount of assets they have staked as rewards.

### 1.2. Get rewards by staking

When you stake assets to an LP, you receive an NFT in return. The NFT (non-fungible token) stores and tracks certain info about your stake:

* the pool you staked to
* the number of assets that you staked
* the length of time you chose to lock the assets for
* the total rewards which have been earned
* the amount of claimed rewards so far
* and more

The NFT represents your claim on the amount of rewards that have been generated by the staked assets.

## 2. Asset Staking

Staking your assets to an LP (known as an asset **Power Up**) helps to sustain the health of the Peerplays exchange. More assets staked to an LP means greater liquidity in the market. And greater liquidity in the market has many benefits to all participants. Staking your assets provides perks to you as well. In addition to generating rewards over time, the NFT you receive for staking can also grant you voting power.

### 2.1. The stake NFT perks

When you decide to stake your assets to an LP, first you'll choose which pool to support. Then you can choose how long to lock the assets into the pool. Once your assets are staked, you'll receive your stake NFT.

**Rewards** - Rewards will be generated over time based on the amount of assets you staked and the length of the locking period you chose for the stake. You can claim the available rewards at any time and in any asset you like. The NFT tracks the total rewards earned and the total amount you claimed. This is important information because you can buy and sell stake NFTs in the NFT marketplace. You can also power down the NFT to get your assets back (minus claimed rewards).

**Voting Power** - Your voting power is determined by the amount you stake as well as how long you choose to stake your assets for. Higher stakes and longer locking periods will grant more voting power. Though you *won't get all the voting power all at once*. To prevent people with large amounts of assets from dominating voting, voting power is generated over time.

**Supporting Communities** - Staking assets that are created by communities on the Peerplays network will help to support those communities. People will be able to easily exchange their assets for the community's assets and you can participate in the governance of that community.

### 2.2. The freedom of your stake NFT

Your stake NFT isn't bound to your account. You have the freedom to sell your NFT or to put it up for auction. You can send it to another account or you can choose to power it down.

**Buying and Selling** - One of the quickest ways to gain the perks of a stake NFT is to simply buy one from the NFT marketplace. The NFT will be sent to your account where it will generate rewards and voting power for you. The previous owner of the NFT may or may not have already claimed some of the rewards. Anything that remains unclaimed when you buy the NFT is then yours to claim. Similarly you will gain the voting power that the NFT has accrued over its life so far.

Because of the time dependant values explained above, you can sell aged NFTs at a premium. This is a great way to get some assets back. Selling the NFT keeps the assets in the LPs so liquidity is maintained in the market.

**NFT Power Down** - Another option for reclaiming your staked assets is to Power Down (burn) your stake NFT. If the NFT has matured, the locking period has elapsed, you can claim the remaining rewards that have accrued and then receive **all** of your staked assets from the pool.

If the locking period has not elapsed when the NFT is powered down, you will receive your staked assets from the pool minus the amount of claimed rewards. Essentially, you'll get the full amount of what you had initially staked, but no rewards. This is true for any stake NFT you own, even if you bought it from the NFT marketplace.

**Flow of Voting Power** - Stake NFTs will generate voting power over time until they reach their maximum voting power value. The voting power is granted to whoever owns the NFT. If you buy an NFT from the marketplace that has some voting power, that voting power is now yours and the previous owner of the NFT loses the voting power. (vice versa if you sell!)

The only way that voting power is destroyed is when a stake NFT is powered down. Not only does this remove liquidity from the market, it also removes voting power from the network. This is something to consider before powering down a stake NFT, even a mature NFT.

## 3. Asset Swapping

Liquidity pools were built to support instant asset swaps. This exchange of assets differs in many ways from the traditional approach of order book trading. There are pros and cons to each and both are beneficial in their own way. Peerplays offers asset swapping based on liquidity pools and fully decentralized order book trading. The best of both worlds!

### 3.1. Swapping vs. Order Books

The table below contrasts the trading methods of swapping and order book trading.

|                                                                    Swapping                                                                    |                     vs.                    |                                                                                         Order Books                                                                                        |
| :--------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|                   The price is set by an algorithm based on the difference in supply between the two assets being exchanged.                   |          **How is the price set?**         |                                                          Traders using the exchange set prices at which they're willing to trade.                                                          |
| Whenever you make a swap, you're making an exchange with an automated market-maker on the network. "Orders" don't exist, just pools of assets. |    **Who is involved in the exchange?**    | When you place an order, your order may match another trader's order or perhaps several orders. These orders then fill for the buyer on one side of the trade and the seller on the other. |
|                              Swaps can happen between any two assets which have an existing LP. (PPY, pBTC, pHIVE)                             | **What assets are available to exchange?** |                                                            Markets exist for any network-asset in Peerplays. (PPY, pBTC, pHIVE)                                                            |
|                                             Only the market price exists so swaps occur instantly.                                             |   **What kind of exchanges can be made?**  |                                                                               Market, Limit, Stop-limit, etc.                                                                              |
|                                                                    Instantly                                                                   |    **How quickly do exchanges happen?**    |                                     This depends on the type of order. Market orders are almost instant. Limit orders can be set to last until filled.                                     |
|                                                   Peerplays asset swapping is decentralized.                                                   |   **Are these exchanges decentralized?**   |                                                                       Peerplays order book trading is decentralized.                                                                       |

### 3.2. How can I swap assets?

Peerplays asset swapping is one of the fastest ways to exchange one asset for another. Once you visit the Peerplays DEX and sign in, you have the ability to deposit assets to your Peerplays account. Then on the swap tab, you'll be able to select the assets you'd like to exchange.

## 4. Liquidity Pools Flow Diagram

The diagram below shows the essence of Liquidity Pools. A more detailed liquidity pool diagram with use case examples can be [found here](/technology/staking-in-peerplays).

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MglzVqIe1lK8hdtimKX%2F-Mgm5AAt5gRn56SwQuE4%2Flps-basic-diagram.png?alt=media\&token=3d61bf3f-48eb-44af-8613-94265052beb9)

### 4.1. Downloads

The Diagram in PDF form to easily view and share:

{% file src="/files/-Mgm5NwN5bezcDOwFi7f" %}
Liquidity Pools Diagram (PDF)
{% endfile %}

The Diagram in Draw\.io's XML format. You can edit the diagram using this file in Draw\.io:

{% file src="/files/-Mgm5azg7ECfI4UxADOg" %}
Liquidity Pools Diagram (Draw\.io XML)
{% endfile %}


# Service Infrastructure Pools

A specialized asset pool for Peerplays communities.

Service Infrastructure Pools (SIPs) are a special type of asset pool with their own purpose. SIPs exist to support the sustained growth of Peerplays communities. Where normal liquidity pools (LPs) enable asset swapping on the Peerplays chain, SIPs in contrast provide funding and rewards to the community they belong to.

## 1.1. Comparison of LPs and SIPs

The following table shows the similarities and differences between liquidity pools and service infrastructure pools.

|                                                           Liquidity Pools                                                          |                              vs.                             |                                                                                          Service Infrastructure Pools                                                                                         |
| :--------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|                                LPs provide the liquidity of assets so they can be instantly swapped.                               |                    **What's the purpose?**                   |                                              Communities use SIPs as a steady stream of income for decentralized proposal funds and to reward community members.                                              |
|                                           Anyone can! LPs exist for any Peerplays asset.                                           |                   **Who can stake to it?**                   |                                                            Communities can stake to SIPs automatically through the sale of their community tokens.                                                            |
|                                It's your choice. You can choose a locking period of up to 10 years.                                | **How long are assets staked? (What's the locking period?)** |                                                               Staking into a SIP is permanent. The staked assets will remain in the SIP forever.                                                              |
| You'll receive an NFT which represents your stake. This NFT will grant you voting power, and the right to claim rewards over time. |                **What do I get for staking?**                | Instead of staking directly to a SIP, the community will do so with the income it receives from selling a community token. So you receive some community token when you buy them directly from the community. |
|                          Your stake NFT is mature and you can Power Down the NFT to claim your stake back.                         |     **What happens when the locking period is reached?**     |                                                                                There is no locking period for staking in SIPs.                                                                                |

## 1.2. How does a SIP work?

When you buy a community token directly from the community the assets you used to purchase those tokens get automatically staked into that community's SIP. The community will receive a special stake NFT to a community governance controlled rewards fund account. This special NFT cannot be traded, sold, sent, transferred, or otherwise moved from the account. It also cannot be Powered Down and has no locking period. It is completely permanent on that account.

The NFT represents that community's stake in its SIP. This guarantees a steady income to the community through its (now permanent) stake in income generating DeFi rewards pools. Depending on the assets received for the sales of their community token, the SIPs can be stakes of Peerplays assets like PPY or even off-chain assets like HIVE. Since these stakes are permanent and are executed on the community level, the special NFTs do not generate voting power like normal stake NFTs do for staking in LPs.

Through community governance, the community decides what to do with the rewards received from its SIP. The community could decide to create a decentralized proposal fund to make continual improvements. Or the community could decide to simply pass the rewards on to its members. The community could even decide to do both and set the rate of each. Communities in Peerplays are empowered to self-govern.

## 1.3. SIP flow diagram

The diagram below shows the essence of Service Infrastructure Pools.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MgkimMAQhlfPHJUC1AG%2F-MglyEkkszm2n-zEI3w_%2Fsip-basic-diagram.png?alt=media\&token=acbcab0b-0ad7-4398-ada7-3b6931c1f996)

### Downloads

The Diagram in PDF form to easily view and share:

{% file src="/files/-MglyKiBLErD12iNwLF-" %}
Service Infrastructure Pools Diagram (PDF)
{% endfile %}

The Diagram in Draw\.io's XML format. You can edit the diagram using this file in Draw\.io:

{% file src="/files/-MglyUyECpKYwmE81BgQ" %}
Service Infrastructure Pool Diagram (Draw\.io XML)
{% endfile %}


# Staking (PowerUp) in Peerplays

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MgS3niFHjdm7ZBt5G59%2F-MgS48mdv6CdaJs9f77R%2FNFT-Staking.png?alt=media\&token=50e1a4f5-913b-4879-ac45-b4492d416559)

## Downloads

The Diagram in PDF form to easily view and share:

{% file src="/files/-MgS4e5cYDUHuDYWNXLt" %}
Staking (PowerUp) in Peerplays - PDF
{% endfile %}

The Diagram in Draw\.io's XML format. You can edit the diargam using this file in Draw\.io:

{% file src="/files/-MgS52RWFh\_fsdZE1RoH" %}
Staking (PowerUp) in Peerplays - XML
{% endfile %}


# Gamified User Namespaces and Subject Matter Expert Committees

A brief introduction to GUNs and SMECs using the SPK network as an example.

## 1. Gamified User Namespaces

SPK network, a Peerplays community, will have its own namespace when users register that will always end with `.SPK`. Under this authority, dapp protocols will automatically whitelist these users for various operations relating to community governance. The gamified user namespace (GUN) will provide a means of onboarding new user accounts at little to no cost and will gamify the process of becoming a full user.

1. Registration > `randomname.SPK` - keys (no fee)
2. Deposit Funds > option to choose `username.SPK` (fee set by a Subject Matter Expert Committee, or SMEC)
3. Engagement via Rewards Engine Parameter > option to choose `username.SPK`  (fee set by SMEC)

The user accounts that operate under `.SPK` will have special switches which are associated with SPK network SMEC which will allow them to be able to vote on the rate of fees for operations. Before voting these operations will be whatever the current rate on Peerplays stands. Voting capabilities will be available only to the holders of SPK-NFTs, BRONCA-NFTs, or LARNIX-NFTs depending on what works best for the SPK network.

There will be many random sources which will be shared for account registration due to the faucets being built into network infrastructure nodes.

## 2. SKP Network NFTs Backed by Liquid Staking

SPK-NFTs are created by staking SPK and will have the capability to lock for up to 10 years (can be longer if set in the token parameters). If no period is selected they will, by default, stay locked with an inverse time to withdraw. This means if they stay locked for 30 days, it would take 30 days to withdraw if they initiated this on the 30th day to get their SPK out of the NFT. The NFT is then burned.

An alternative to destroying the NFTs would be to sell them on the NFT Marketplace and get access to their SPK or any other asset they want to sell it for instantly without the SPK needing to be unlocked from the NFT for whatever staking period may have been selected.

The staked SPK goes into the SPK Liquidity Pool with AMM DEX to power liquidity in SPK markets. The SPK market fees then flow back to all the SPK-NFT holders proportionally. The SPK-NFT that gets issued will have a PowerUP rating associated with the amount of SPK that was used to stake into the NFT. This gets used as the measure for rewards they receive. This means that the longer term someone commits to the staking period, the greater the rewards they will receive. When rewards are paid out they must be claimed by the user account and can be in the asset of their choosing supported in Peerplays. This means they could get SPK, BTC, PPY, HIVE, or any other assets available. If this is not desired, limited options can be made available in user interfaces.

These NFTs will be governed by dynamic properties while at the same time being capable of having custom "skins" for users preferences which can have additional gamification benefits.

For more information on Staking and Liquidity Pools, see here.

## 3. Subject Matter Expert Committees (SMECs)

Based on the SPK-NFT PowerUP, the user will be able to cast voting in various matters relating to the network.

Voting power is determined by the length of time the NFT has existed and the staked length. A linear scale starting from zero to the period staked provides that amount of weight multiplier the voter carries. This means someone who stakes for 10 years will not get the full weight multiplier on their stake, but instead will have it added to their account over the period of the stake with each coinday. Likewise, someone who has decided to stake by default with accumulating locking will experience the same multiplier effect over time. However, the staker of 10 years will have their weight increase from day one, as their multiplier has been predetermined by the 10 year commit.

This ensures that long term actors are the ones who will be able to carry more influence, but they will only have that influence accumulate over time. The only way for new people to gain this added vote power would be to accumulate SPK-NFTs from the marketplace which have been aged, thus increasing the subjective value of the SPK-NFTs.

Using the SPK-NFT the user can vote on the parameters of the network to determine what rates should be paid for fees on various operations. Some operations may be the rewards earned for holding SPK-NFTs that are generated from the DEX/AMM Liquidity Pools. These come from parameters set in the SPK market which will only be able to be controlled via voting among `username.SPK` accounts, and SPK-NFTs.

Another element which `username.SPK` users will be able to use are the operations of the SMEC which enables the users to vote for a committee of members which can be funded through various mechanisms. The SMEC do not have direct access to the funding pool but instead must approve proposals which should be used for their mission intent. Effectively the SMEC acts as a manager, and the ones who are doing the work are being paid by the proposal. Payouts for the funds only occur monthly when the SMEC publishes a progress report on the activity so as to provide concise communication feedback to the community at large.

Multiple SMECs can be created by the `username.SPK` community for any number of reasons beyond just funded work. Typically SMECs might include, but are not limited to, marketing, sales, development, legal, and payment gateways. The `SPK.SMEC` could also be configured so that the SPK market fees can flow to the `SPK.SMEC` for funding.


# Peer-to-Peer Autonomous Organizations: Flow Diagram

## Flow Diagram

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FrBZRk4JMeidfHUwNlHxQ%2FPAO%20Flow%20Diagram.png?alt=media\&token=9b2fa700-9f15-451d-b833-37e824408e8a)

## Downloads

### PDF

{% file src="/files/sQw907lC53tLcuAtVsvo" %}

### XML

{% file src="/files/MTGXoIYqkQWvmGCK8GNE" %}


# Gamified Proof of Stake (GPOS)

## Introduction

Building on the success of the DPOS consensus mechanism, Peerplays introduced a unique enhancement called Gamified Proof of Stake (GPOS). This idea was first proposed as [Peerplays Improvement Proposal (PIP) #2](https://github.com/peerplays-network/pips/blob/master/pip-0002.md) in January 2019.

The original intent of Peerplays was to operate as a Decentralized Autonomous Cooperative (DAC) where DPOS enables the voting collective of core token holders to determine who would act as Advisors, Witness, and Proposals within Peerplays. However, like other DPOS based blockchains, the challenges of voter turnout continue to plague Peerplays.

## What Makes GPOS Different?

GPOS made a protocol change such that PPY token holders now receive a *participation reward* based on their voting performance and how many PPY they have vested or *staked*.

This is a significant change from the original protocol where token holders were rewarded with their share of a rake, taken from a percentage of the blockchain fees, and then distributed to token holders relative to their token holdings, regardless of any voting participation.

Put simply, this means that each PPY token holder needs to vest some, or close to all, of their PPY balance towards GPOS and then once a month vote for either Witnesses, Advisors or Proxies.

## Why is GPOS Important?

Being a DPOS consensus blockchain, the importance of voter participation from the PPY token holders is paramount to the security of the blockchain. The introduction of GPOS ensures that token holders will take an active interest in the operation and governance of Peerplays.

Each vote cast impacts the people behind the successful operation of Peerplays, in particular the Witnesses. A Witness receiving high votes is much more likely to be elected as a block producing (active) Witness.

Under DPOS the Witness position is more secure because a lot less token holders are voting and subsequently it might just take one or two major PPY token holders to influence the election of a Witness. Under GPOS all token holders should participate making it a much more democratic process, and also receive rewards for voting.

## Participation Rewards

Participation rewards combined with voting performance are what makes the Peerplays consensus mechanism *gamified.*

The rewards are calculated as follows:

### **Qualified Reward %**

This is the percentage of a user's maximum possible reward received based on their voting performance. This reward *decays* at a rate of 16.67% per month. For example, if a token holder doesn't vote for a month the qualified reward percentage drops to 83.33% and if the token holder doesn't vote for six consecutive months the reward will be 0%.

{% hint style="warning" %}
**Note**: Complete decay was set at six consecutive months to coincide with the dividend distribution periods.

Below are the some of the key GPOS parameters that are currently set on mainnet.

GPOS period = 6 months(180 days)

GPOS sub-period = 30 days

GPOS lock-in period = 30 days

Vesting fee = 1PPY

Withdrawal fee = 0.01PPY
{% endhint %}

### **Estimated Rake Reward %**

This is the potential percentage reward a user could receive based on the [qualified reward percentage](/technology/gamified-proof-of-stake-gpos#qualified-reward), the amount of PPY they have vested and their share of the total GPOS balance.

So the estimated rake reward is calculated as:

GPOS balance = b\
Total GPOS balance on blockchain = TB\
Qualified reward % = q

Estimated Rake Reward% = (b / TB) \* q

**For example:**

A user has a GPOS balance of 1,000PPY and is entitled to 100% of their reward based on voting performance. The total GPOS balance on the blockchain is 4,000,000PPY.

The user would receive the following percentage of the rake:

(1,000 / 4,000,000) \* 100% = 0.025%

So if the total (month) rake was 100,000PPY then the user would receive 25PPY.

## GPOS related cli\_wallet commands

**create\_vesting\_balance account amount asset\_symbol vesting\_type broadcast**

Creates vesting balance of GPOS type, enables user to participate in GPOS

Example:

```
create_vesting_balance account_name 50 PPY gpos true
```

**vote\_for\_witness account witness approve broadcast**

Cast or withdraw vote for a witness by given account. To keep user vesting performance, it is best for user to vote in each GPOS subperiod

Example:

```
# Cast a vote for a witness
vote_for_witness account_name witness_name true true

# Withdraw a vote for a witness
vote_for_witness account_name witness_name false true
```

**withdraw\_GPOS\_vesting\_balance account amount asset\_symbol broadcast**

Once the vesting period expires, user is able to collect his reward with withdraw\_GPOS\_vesting\_balance command. User is not allowed to withdraw his balance before vesting period expires. Default GPOS vesting period is 30 days.

Example:

```
withdraw_GPOS_vesting_balance account_name 10 PPY true
```

**How to retrieve GPOS info**

Some GPOS info is stored in global properties object. Retrieve GPO and inspect the following values - gpos\_period, gpos\_subperiod, gpos\_period\_start and gpos\_vesting\_lockin\_period.

Example:

```
# Output is shortened, check out "extensions" section
get_global_properties 
{
  "id": "2.0.0",
  "parameters": {
...
    "maximum_tournament_start_delay": 604800,
    "maximum_tournament_number_of_wins": 100,
    "extensions": {
      "sweeps_distribution_percentage": 200,
      "sweeps_distribution_asset": "1.3.0",
      "sweeps_vesting_accumulator_account": "1.2.0",
      "gpos_period": 15552000,                   <----- Length of GPOS period (180 days)
      "gpos_subperiod": 2592000,                 <----- Length of GPOS subperiod (30 days)
      "gpos_period_start": 1609376400,           <----- Epoch time of last GPOS subperiod start (2020-12-31 1:00:00)
      "gpos_vesting_lockin_period": 2592000,     <----- GPOS Vesting period (30 days)
      "rbac_max_permissions_per_account": 5,
      "rbac_max_account_authority_lifetime": 15552000,
      "rbac_max_authorities_per_permission": 15,
      "account_roles_max_per_account": 20,
      "account_roles_max_lifetime": 31536000,
...
    }
  },
...
}
```

**How to check account's last voting time**

Account's last voting time is stored in account's statistic object. To retrieve the account statistic object, user needs account statistic object id, which is stored in account object.

Example:

```
# Get the account object first, and retrieve statistic object id
get_account account_name
{
  "id": "1.2.20",
  "membership_expiration_date": "1970-01-01T00:00:00",
  "registrar": "1.2.18",
  "referrer": "1.2.18",
  "lifetime_referrer": "1.2.18",
  "network_fee_percentage": 2000,
  "lifetime_referrer_fee_percentage": 3000,
  "referrer_rewards_percentage": 0,
  "name": "account_name",
  ...
  "statistics": "2.6.20",          <--- HERE IT IS!!!
  "whitelisting_accounts": [],
  "blacklisting_accounts": [],
  "whitelisted_accounts": [],
  "blacklisted_accounts": [],
  "owner_special_authority": [
    0,{}
  ],
  "active_special_authority": [
    0,{}
  ],
  "top_n_control_flags": 0
}

# Retrieve the account's statistic object
get_object 2.6.20
[{
    "id": "2.6.20",
    "owner": "1.2.20",
    "name": "account_name",
    "most_recent_op": "2.9.0",
    "total_ops": 0,
    "removed_ops": 0,
    "total_core_in_orders": 0,
    "core_in_balance": "5000000000000",
    "has_cashback_vb": false,
    "is_voting": false,
    "lifetime_fees_paid": 0,
    "pending_fees": 0,
    "pending_vested_fees": 0,
    "last_vote_time": "1970-01-01T00:00:00"     <--- HERE IT IS
  }
]
```


# Wallet User Guide

Version 1.5 of the Peerplays Core Wallet added the GPOS functionality for the first time; this document will step you through the new features it implements to ensure you qualify for maximum participation rewards.

{% content-ref url="/pages/-M-uV17BlxhuwC5jqL\_S" %}
[GPOS Panel](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-panel)
{% endcontent-ref %}

{% content-ref url="/pages/-M-uVlUOD1HEY25SS4n7" %}
[GPOS Landing Page](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page)
{% endcontent-ref %}

{% content-ref url="/pages/-M-uenWPwDOziBUBqucw" %}
[Power Up](/technology/gamified-proof-of-stake-gpos/user-guide/power-up)
{% endcontent-ref %}

{% content-ref url="/pages/-M-ujM87SJsdPr3gHRE-" %}
[Power Down](/technology/gamified-proof-of-stake-gpos/user-guide/power-down)
{% endcontent-ref %}

{% content-ref url="/pages/-M-uuS\_iq18zhckWaeFr" %}
[Vote](/technology/gamified-proof-of-stake-gpos/user-guide/vote)
{% endcontent-ref %}

{% content-ref url="/pages/-M-v1nYD8CnWkc5Ezg5n" %}
[Thank you for voting!](/technology/gamified-proof-of-stake-gpos/user-guide/thank-you-for-voting)
{% endcontent-ref %}


# GPOS Panel

## The GPOS Panel

The home page of the wallet now includes a panel to display your GPOS status.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zCDGgKXNNKxNxaHQ_%2F-M-zp0x1JxAqmWi2_tBK%2FScreen%20Shot%202020-02-13%20at%202.33.27%20PM.png?alt=media\&token=d52232f9-2ec3-480f-9c15-e4bfbb068818)

The features of the panel are:

### GPOS Balance

This is the total amount of PPY that has been vested. In the above example the amount is zero which is  reflected in the Voting Performance as well.

### Voting Performance

Voting performance is calculated based on the last time you voted for either Witnesses, Advisors or Proxies. The text and colour of the caption indicates your performance according to the following table:

| Reward %      | Text          | Colour                                      |
| ------------- | ------------- | ------------------------------------------- |
| 0             | No rewards    | Dark Red                                    |
| 1- 16.68      | Critical low  | Red                                         |
| 16.69 - 33.33 | Lower rewards | Orange                                      |
| 33.34 - 50    | Low rewards   | Yellow                                      |
| 50.01 - 66.66 | OK rewards    | Blue                                        |
| 66.67 - 83.33 | Good rewards  | Dark Green                                  |
| 83.34 < 100   | Great rewards | Green                                       |
| 100           | Max rewards   | <p>Same colour as </p><p>other captions</p> |

### Get Started

Clicking on the `GET STARTED` button will begin the GPOS vesting process.

If you have a zero GPOS balance, which will always be the case if this is the first time you are using it, the button text will be `Get Started`. However, the text on the button will change to `PATICIPATE` once a balance is vested. See[ Power Up](/technology/gamified-proof-of-stake-gpos/user-guide/power-up)

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zp5lQxwSrzVJCngUn%2F-M-zpAqe9wo4zapFFYnT%2FScreen%20Shot%202020-02-13%20at%202.24.36%20PM.png?alt=media\&token=da4fa770-b040-4280-b213-20d751a105f7)

### Participate

As mentioned, this option is only available once you have a GPOS balance.

Clicking on `PARTICIPATE` will take you to the GPOS Landing Page as before, except this time both the `Power Down` and `Vote` buttons will be enabled.


# GPOS Landing Page

The landing page is the entry point to use the different GPOS features.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-uVE-7j2ik0yKVyZag%2F-M-uW87nOB51FJFEMSx3%2FScreen%20Shot%202020-02-12%20at%201.47.42%20PM.png?alt=media\&token=fe24e87d-9250-4682-aa79-375c21d5f5c5)

## Power Up

Clicking on `Power Up` will take you to the deposit screen where you can vest PPY towards GPOS and in turn, add to your participation rewards.&#x20;

You can click `Power Up` at any time since you are free to come back and vest more PPY at your discretion.

## Power Down

Clicking on `Power Down` is very similar to `Power Up` except this time you'll be taken to the withdraw screen.

You can withdraw form your GPOS balance at any time up to the value of your balance.

{% hint style="danger" %}
**Important**: If you have a GPOS balance of zero the `Power Down` button will be disabled
{% endhint %}

## Vote

For anybody familiar with earlier versions of the Peerplays wallet, the voting section is much the same as before. Only the steps to go through to access this feature have changed.

{% hint style="danger" %}
**Important**: If you have a GPOS balance of zero the `Vote` button will be disabled
{% endhint %}


# Power Up

After clicking on the `Power Up` button on the [GPOS landing page](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page) you'll be taken to the Power Up screen; from here you can add to your GPOS balance.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zpDjN_ZLSsWC3oQUx%2F-M-zpmyPcv4rDy6GnbYz%2FScreen%20Shot%202020-02-13%20at%202.27.10%20PM.png?alt=media\&token=584276bc-552a-426a-96ac-baab4fe0dad9)

The functionality of this screen is very straightforward. Simply select an amount of PPY to vest by either entering it in the Deposit field, or scroll the amount up and down using the `+` and `-` buttons.

{% hint style="danger" %}
**Important**: You might think you can vest 100% of your PPY balance to get the maximum participation rewards. However, each time you create a vested balance there is a 1PPY transaction fee. This means that you must leave at least this amount in your balance in order to perform the Power Up.
{% endhint %}

In the example above the user has no vested balance. If an amount of 80PPY is vested the New GPOS Balance will be 80PPY and if the user power's up again the Opening GPOS Balance will be 80PPY as will the New GPOS Balance.

Click on the `CANCEL` button to leave this screen without saving any changes. Or click on `SUBMIT` to save changes and return to the [GPOS Landing Page.](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page)

{% hint style="warning" %}
**Note**: Creating a GPOS balance doesn't yet qualify you to receive participation rewards, you must still [vote](/technology/gamified-proof-of-stake-gpos/user-guide/vote).
{% endhint %}


# Power Down

If you have a GPOS balance then you can access the Power Down screen from the [GPOS Landing Page](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page).

After clicking on the `Power Down` button you'll be taken to the Power Down screen; from here you can withdraw from your GPOS balance.

Unsurprisingly the Power Down screen follows a very similar format to [Power Up](/technology/gamified-proof-of-stake-gpos/user-guide/power-up); you just use it to withdraw from your GPOS balance, instead of adding to it.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zpq7B3gwyCW1x5zm2%2F-M-zpvMl4qrH1N5TnANg%2FScreen%20Shot%202020-02-13%20at%202.28.19%20PM.png?alt=media\&token=c3172384-7a27-4600-b261-bcf15efad690)

And just like the [Power Up](/technology/gamified-proof-of-stake-gpos/user-guide/power-up) screen you can select an amount by scrolling up and down using the `+` and `-` buttons. The amount you select will be shown in the Withdraw field and reflected in your New GPOS Balance.

You can withdraw up to the total amount of your Opening GPOS Balance.

{% hint style="warning" %}
**Note**: There is a transaction fee of 0.01PPY each time a withdrawal is made.
{% endhint %}

In the example above the user has no vested balance. If an amount of 80PPY is vested the New GPOS Balance will be 80PPY and if the user power's up again the Opening GPOS Balance will be 80PPY as will the New GPOS Balance.

### GPOS Balance Holding Period

In the example above note that although the Opening GPOS Balance is 80PPY the Available GPOS Balance is zero. This is because there is a 30 day holding period on new deposits. In this example  the deposit was made the same day as the requested withdrawal.

The main reasons for having a holding period are:

* It's in your best interest to maintain a GPOS balance, withdrawing from the balance will effect your participation rewards.
* Withdrawing all the balance before 30 days could also effect your reward percentage by stopping you from voting.
* There are fees associated with creating a balance and withdrawing from it. A holding period protects you from 'experimenting' with vesting and incurring unexpected fees.

Click on the `CANCEL` button to leave this screen without saving any changes. Or click on `SUBMIT` to save changes and return to the [GPOS Landing Page.](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page)


# Vote

If you have a GPOS balance then you can access the Vote screen from the [GPOS Landing Page](/technology/gamified-proof-of-stake-gpos/user-guide/gpos-landing-page).

After clicking on the `Vote` button you'll be taken to the Vote screen from where you can vote for Witnesses, Advisors and Proxies.

The voting functionality hasn't changed from previous versions of the Peerplays Wallet so will only be documented briefly here.

## Proxy

Proxy voting allows you to select another token holder to vote on your behalf. As far as GPOS goes this still constitutes participation as you have made a commitment to the operation of the blockchain.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-uyGDJcX2XVQekq5Kn%2F-M-v0IVbciK8dBYCtRaF%2FScreen%20Shot%202020-02-12%20at%203.56.47%20PM.png?alt=media\&token=36b54553-b8fa-4cab-9d25-3c47764a694e)

However, since there are participation rewards at stake, and penalties for poor voting performance, if you use this option make sure you proxy your vote(s) to someone reliable!

## Witness

Voting for a Witness is probably the most common use of a vote. By voting for a Witness you are playing an important role in the governance of Peerplays.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zq2qndXMbGcKXVF2T%2F-M-zq8IP5CI_VnnvYgL9%2FScreen%20Shot%202020-02-13%20at%202.30.33%20PM.png?alt=media\&token=95e9222c-f867-4384-b352-4a3f73406cfa)

You can select one or more Witnesses from the list, or search for them, and then click `ADD` to add them to your approved list. Click `PUBLISH CHANGES` to cast your vote.

## Advisors

The Peerplays Advisors are a committee that makes decisions on software changes to Peerplays and attributes and parameters of the blockchain. They are an important part of a DPOS consensus mechanism.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-zq2qndXMbGcKXVF2T%2F-M-zqBxNszNEEwOHQT8J%2FScreen%20Shot%202020-02-13%20at%202.31.36%20PM.png?alt=media\&token=c224a6f3-13ef-4467-b913-cd22c210457e)

Selecting an Advisor works exactly the same way as selecting a Witness.

{% hint style="danger" %}
**Important**: Whether voting for Witnesses, Advisors or Proxies you must first click on`PUBLISH` `CHANGES` before you'll be able to click on`FINISH`.
{% endhint %}

Click on `CANCEL` to return to the GPOS Landing Page without voting, or click on `FINISH` to go to the [Thank you for voting! ](/technology/gamified-proof-of-stake-gpos/user-guide/thank-you-for-voting)screen.


# Thank you for voting!

You made it this far; now you qualify for participation rewards for contributing to the governance of Peerplays.

After you vote you'll see the following screen:

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-M-v4eFTqCRc2poKF_0G%2F-M-v56pM-adV1EKcZ28o%2FScreen%20Shot%202020-02-12%20at%204.08.08%20PM.png?alt=media\&token=3a2879f9-607a-47d1-b9f2-4724686b7c6f)

So like the avatar says, go and share your experience with your friends, family and the Peerplays community.


# FAQ

{% content-ref url="/pages/-M-vEZo9ZU20s193Ytkc" %}
[General](/technology/gamified-proof-of-stake-gpos/faq/general)
{% endcontent-ref %}

{% content-ref url="/pages/-M-vEc48ulgY7B7EGp5A" %}
[GPOS Panel](/technology/gamified-proof-of-stake-gpos/faq/gpos-panel)
{% endcontent-ref %}

{% content-ref url="/pages/-M-vEjPHZyNu063bamQs" %}
[Power Up & Power Down](/technology/gamified-proof-of-stake-gpos/faq/power-up-and-power-down)
{% endcontent-ref %}

{% content-ref url="/pages/-M-vErxJWESOixYh8s81" %}
[Voting](/technology/gamified-proof-of-stake-gpos/faq/voting)
{% endcontent-ref %}

{% content-ref url="/pages/-M-vEw97UzCNBalURbRH" %}
[Participation Rewards](/technology/gamified-proof-of-stake-gpos/faq/participation-rewards)
{% endcontent-ref %}


# General

### What is GPOS?

GPOS is short for Gamified Proof of Stake which is an advanced implementation of the DPOS consensus mechanism.

GPOS gives voting weight and rewards to all token holders that commit some of their PPY balance as a vested GPOS balance. For more information see [Gamified Proof of Stake](/technology/gamified-proof-of-stake-gpos).

### What is a vested balance?

The best way to understand this is to compare it to the difference between stock options and shares. If you hold stock options you have a stake in the company, but the options have no value unless you can profit from them and to do this the options have to first be vested as shares.

GPOS works the same way, instead of all token holders being entitled to dividends just by virtue of holding tokens (shares), token holders now have a PPY balance (options) that they only profit from when they are vested in GPOS (become shares).

### Are there any fees associated with GPOS?

Yes, there is a fee of 1PPY for Powering Up (depositing) and a nominal fee of 0.01PPY for Powering Down (withdrawing).

### What happens to the fees?

The fees are 'burned', that is to say they return to the reserve. The reserve can then be drawn on for block rewards for the block producers.

### Did I just lose some share of the Peerplays rake?

No, in fact far from it. GPOS gives you every opportunity to not just receive the same dividends as before but actually get higher dividends if there are token holders that don't vote. Just remember to vest a GPOS balance and then vote at least once a month.

### Why is GPOS better for Peerplays?

GPOS encourages all PPY token holders to take a much bigger interest, and say, in the governance of the blockchain. This will strengthen the democratic process that goes into electing the operators of   Peerplays, and make them much more accountable.&#x20;

Before GPOS token holder voting was poor and that opened up the opportunity for one or two major token holders to influence the operation of the blockchain. Full participation by token holders in the voting process will mitigate this risk and keep the blockchain secure.


# GPOS Panel

### What is the difference between Qualified Reward and Estimated Rake Reward?

Qualified Reward is the percentage your maximum possible reward based on voting performance. This reward *decays* at a rate of 16.67% per month.

Estimated Rake Reward is the potential percentage reward you could receive based on the Qualified Reward percentage, the amount of PPY you have vested and your share of the total GPOS balance.&#x20;

For more information see [Participation Rewards.](/technology/gamified-proof-of-stake-gpos#participation-rewards)

### Why does the panel say I only qualify for 50% rewards even though I voted?

Voting qualifies you for participation rewards but the actual amount you qualify for is also based on the percentage of your PPY balance you've vested.

### Why does my PPY balance show as 19.99PPY when it should be 20PPY?

Every time you withdraw from you GPOS balance there is a transaction fee of 0.01PPY.

### &#x20;My voting performance is 'OK Rewards', how do I improve this?

Basically, vote more often!

The performance rating is based on voting performance, to have a rating of 'OK' would mean that you've missed voting for about three months.


# Power Up & Power Down

### Why can't I vest my entire balance?

There as a 1PPY fee every time you power up (deposit) to your GPOS balance. So you must make sure you have enough PPY left to cover the transaction fee.

### What would be a sensible amount to vest?

There's no hard and fast rule, it's going to depend on how active you are as a Peerplays wallet user and other factors. It's certainly beneficial to vest as much as you can as you're total participation rewards are based on how much you vest.&#x20;

But you should note that as all wallet operations incur a small fee, vesting too much could actually stop you from withdrawing PPY from GPOS until you deposit more PPY to your wallet.

### Why is the Power Down button disabled?

You can't power down until you have powered up for the first time, or if you've withdrawn from your GPOS balance leaving it at zero.

### Why can't I withdraw any of my GPOS balance?

It's theoretically possible for this to happen if you don't have enough available PPY to pay the withdrawal fee. But the most likely reason is because there is a 30 day holding period on GPOS deposits before they can be withdrawn. For more information see [GPOS Balance Holding Period](/technology/gamified-proof-of-stake-gpos/user-guide/power-down#gpos-balance-holding-period).


# Voting

### Does GPOS affect how I vote?

Yes and no. The functionality of the voting feature in the Peerplays wallet hasn't changed in the newest version, only the steps you go through to vote have changed.

But GPOS will effect your voting habits as it requires regular participation.

### What happens if I don't vote?

Simply put, you'll lose a percentage of your qualifying rewards for every month that you don't vote. If after six months you still haven't voted you won't qualify for any participation rewards.

### Can I vote more than once a month?

Yes, you can vote as many times as you'd like to, and you can vote for more than one Witness or Advisor at the same time.

### Why can't I vote for the same Witness twice?

Once a Witness or Advisor has been voted for and is in your approved list you can't currently re-select that person for voting again without first un-voting them. This is a known issue that will be fixed in the next release.

### Will my voting performance go back to 100% once I vote?

Yes, regardless of your level of voting performance as soon as you vote it'll return to 100%. It will however, start to decay again if you don't vote regularly.

### Can I just vote for a proxy and then let them manage my account?

Yes, this is the role of the proxy ... but if you do this make sure your proxy is reliable as your voting performance is in their hands, and you still need to vote once a month.


# Participation Rewards

### How are participation rewards different from traditional dividend payments?

GPOS introduces a number of significant changes to the old method of dividing the Peerplays rake between all token holders relative to how many tokens they hold.

The biggest change is that the percentage of the rake is based on the total of all **GPOS vested balances**, and not the cumulative value of all PPY in circulation. This gives the opportunity for regular voters to get a larger share of the rake than before by virtue of other unreliable voters.

### I'm confused, just how exactly are my rewards calculated?

At first the new formula for calculating your estimated reward percentage can be a bit confusing; this example should help:

If you have a GPOS balance of 1,000PPY, and have voted recently, so you have qualified for a 100% reward, and the total GPOS balance on the blockchain is 4,000,000PPY when the rake is distributed, then your percentage of the rake would be:

(1,000 / 4,000,00) \* 0.025%

What you'll actually receive as a dividend is based on the monthly rake, so if the rake is 100,000PPY then you'd receive 100,000 \* 0.025% = 25PPY.


# Sidechain Operator Nodes (SONs)

*Sidechain Operator Nodes* - SONs facilitate the transfer of off-chain assets (like Bitcoin, Hive, or Ethereum tokens) between the Peerplays chain and the asset's native chain. These nodes often run the Peerplays node software and node software of other chains.

{% hint style="info" %}
The software used to run Witness, API (full), Seed, and SON nodes is named `witness_node`. All these node types are run with the same software. What makes these nodes different is how that software is configured and how it's used.

SONs will also require the use of software supplied by other chains, like Bitcoin Core for example.

BOS nodes use a collection of software known as the Bookie Oracle Suite.
{% endhint %}


# New to SONs?

Here's everything you need to know about how the Peerplays SONs work? what are the problems they solve?

Bitcoin and Ethereum are slow and expensive to use.

Currently, Bitcoin can process only 4.6 transactions per second. The average confirmation time for a BTC payment is about 10 minutes. For context, Visa does around 1,700 transactions per second on average. On the other hand, Ethereum fees are extremely expensive and through the roof. Scalability is a serious issue for both networks.

Is there any way to overcome these problems? Sidechains may provide a solution.

If you’re new to Sidechains, then this is the perfect place to start.


# What are Sidechain Operating Nodes?

In order to improve the performance of Bitcoin and Ethereum, a unique mechanism is required. Sidechains can help move tokens, perform transactions faster and cheaper.

Sidechains provide the [decentralized ](/concepts/decentralization)way to seamlessly transfer value between multiple blockchains and to operate Sidechain SONs node are used.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FH8CNIxBGupLUGJt67Co1%2F1.JPG?alt=media\&token=2a3deb9b-864b-4cfb-b888-69ae732a0f6d)

Sidechain Operating Nodes (SONs) means a lot to the blockchain world. SONs provide a way for blockchains to interact with each other. Those nodes are in harmony with each other like a handshake which ease the process of transferring tokens from Peerplays blockchain to and from another blockchain.

Sidechains solve a problem known as Inter-Blockchain Communication (IBC). This problem takes place when blockchains have different protocol types (also called consensus mechanisms, like Proof of Work, Proof of Stake, Delegated Proof of Stake, etc.)

Peerplays SONs are decentralized, trustless, and elective.


# How do SONs Work?

Hinted through their names, these Sidechains run alongside a root or “parent chain.” When you transfer funds, they're locked on the parent chain and then released onto their respective sidechain. You can then move them around at will until you decide to return them back to their original chain.

Anyone can enable a Sidechain Operating Node. However, that is not enough to run a SON. You must be an ‘active participant’ in the Peerplays community and receive votes in order to qualify to become a SON. Since Peerplays blockchain is Gamified Proof of Stake, this incentivizes voting for those who run SONs.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F2AhAvwmE7PbaprWjVRKV%2F2.JPG?alt=media\&token=892ef1c3-c816-48d1-ac55-93e290055481)

Once a SON finds a particular transaction which is signed by 2/3rd of other SONs, that SON will post the transaction to the Peerplays blockchain. Upon receiving the transaction, the SON will verify the transaction details with the appropriate blockchain. If the data on the source blockchain sidechain seems to be intact, the SON will sign the transaction and publish it. This helps prevent any SON from malicious transactions.


# Why are SONs important?

SONs help the blockchains scale and develop more quickly. Blockchains like Bitcoin or Ethereum have to validate every new transaction on their own. But SONS only have to periodically refresh information from the root chain with updates about transactions. Which means massive scalability without sacrificing security or decentralization!

The problem with blockchains out there that offer inter-blockchain communications like Cosmos and Polkadot is that they ‘talk’ only with other blockchains that are identical like them. This doesn’t really solve the problem of blockchains interacting with one another. It creates a situation where a ‘foreign’ blockchain must switch over to another blockchain that is able to communicate with a blockchain that is ‘compatible’ with Polkadot or Cosmos.

That’s why Peerplays SONs technology is an innovative, elegant solution.


# How do SONs impact me?

You can think of SONs as a two-way street. The value of two blockchain tokens is going back and forth safely and smoothly.

To paint a picture, let’s imagine you’re sending your bitcoin from an address to a sidechain. This bitcoin is then represented on the other side of the new blockchain. You are then able to move this represented bitcoin without touching your original bitcoin.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fv77NvHMVZ2LDkotHnK5C%2F3.JPG?alt=media\&token=5441cc5f-1e5f-4569-a431-a888416b2d1f)

This offers scalability for bitcoin. For example, let’s say another blockchain can perform 50,000 transactions per second. Now Imagine being able to operate your bitcoin at that speed. This opens up endless possibilities about the applications Bitcoin could be used in.

It could really be the answer for worldwide adoption.


# SON Fees & Performance Requirements

SONs get paid out from a daily reward pool for signing transactions and the weight of voting. Both the transactions they approve and reject are counted in. Bitcoin transactions in Peerplays blockchain get validated to ensure they originated from the SONs.

When a SON changes, their private key on the bitcoin address gets replaced with the private keys of the new incoming SON.

The performance of SONs is also tracked. Their errors, uptime, missed blocks, and similar errors provide historical performance data for voters. Witnesses have the power to freeze a SON or blacklist them if necessary.


# Peerplays SONs

Bitcoin and Ethereum are slow, expensive to use, and not scalable enough for mass adoption and usability. They can’t support high transaction throughput.

SONs provide an alternative way for blockchains to communicate with each other, which opens up new possibilities in terms of scalability and interoperability.

Peerplays SONs are decentralized, trustless, and elective. The side chains are as secure as they can get. They can keep the scalability trilemma at bay (security, decentralization, and scalability).

Public open decentralized blockchains are the way to go forward. We here at Peerplays are committed to making sure whatever we create is not centralized and can’t be manipulated.


# FAQ

## 1. What is the transaction finality time for withdrawals and deposits of BTC?

Six transaction confirmations are the recommended value for transaction finality on the Bitcoin blockchain and thus its recommended to set the value at 6 confirmations for Bitcoin SONs. (reference: <https://web.archive.org/web/20210218094358/http://bitcoins.net/guides/bitcoin-confirmations>)

## 2. What is the daily reward pool set at right now for sons nodes?

Funds equivalent of 200 PPY is set aside and its distributed among SONs proportional to their performance. This value can be changed by the committee.

## 3. I have also noticed that my server is running at 100% at all times. Is it trying to mine test btc?

No, when you are connected to SONs network as a seed or a SON itself, you won't be doing any PoW mining. SONs just listens on the Bitcoin network for any incoming transfers to Peerplays BTC addresses.


# NFTs and Marketplace


# NFT marketplace in Python

Describing here the steps to verify the Marketplace\_python on local or server machine.

&#x20;**Machine configuration** : Local or server machine.

#### &#x20;**Step 1:** Clone Marketplace\_python binaries on machine

**Project Url :**

```
https://gitlab.com/PBSA/PeerplaysIO/tools-libs/python-peerplays/-/tree/nft
```

#### Clone binaries on Machine:

```
git clone https://gitlab.com/PBSA/PeerplaysIO/tools-libs/python-peerplays.git
```

#### &#x20;**Step: 2** Install virtual env on machine

#### Go to projec&#x74;**:**

```
cd python-peerplays
```

#### Ru&#x6E;**:**

```
virtualenv -p python3 env
```

&#x20;

####

#### **Step: 3** Install python requirements

**Run:**

```
source env/bin/activate
```

**And then:**

```
pip3 install -r requirements.txt
```

**then:**

```
pip3 install -r requirements-test.txt
```

&#x20;

**Step: 4 Run unit tests**

**Run:**

```
python -m unittest tests/test_market_place.py
```

&#x20;**Expected result should be as below:**

```
(env) ubuntu@ip-172-31-13-101:~/python-peerplays$ python -m unittest tests/test_market_place.py
Not broadcasting anything!
Not broadcasting anything!
create_off Success!
Not broadcasting anything!
create_bid Success!
Not broadcasting anything!
cancel_offer Success!
All tests successful!
.
----------------------------------------------------------------------
Ran 1 test in 2.270s
OK
(env) ubuntu@ip-172-31-13-101:~/python-peerplays$
```


# NFT Operations in Python

Describing the steps to verify the NFT\_python on local or server machine below. <br>

**Machine configuration** : Local or server machine.<br>

####

#### **Step 1:** Clone NFT\_python binaries on machine

#### **Project Url :**

```
https://gitlab.com/PBSA/PeerplaysIO/tools-libs/python-peerplays/-/tree/nft
```

#### **Clone binaries on Machine :**&#x20;

```
git clone https://gitlab.com/PBSA/PeerplaysIO/tools-libs/python-peerplays.git
```

#### **Step: 2** Install virtual env on machine

**Go to project :**&#x20;

```
cd python-peerplays
```

**Run:**

```
virtualenv -p python3 env
```

#### **Step: 3** Install python requirements

**Run:**

```
source env/bin/activate
```

**then,**&#x20;

```
pip3 install -r requirements.txt
```

**And then,**&#x20;

```
pip3 install -r requirements-test.txt
```

#### **Step: 4** Run unit tests

**Run:**

```
python3 -m unittest tests/test_nft.py
```

&#x20;

**Expected result should be as below:**

```
(env) ubuntu@ip-172-31-13-101:~/python-peerplays$ python3 -m unittest tests/test_nft.py
Not broadcasting anything!
nft_metadata_create Success!
Not broadcasting anything!
nft_metadata_update Success!
Not broadcasting anything!
nft_mint Success!
Not broadcasting anything!
nft_safe_transfer_from Success!
Not broadcasting anything!
nft_approve Success!
Not broadcasting anything!
nft_set_approval_for_all Success!
All tests successful!
.
----------------------------------------------------------------------
Ran 1 test in 3.449s

OK
(env) ubuntu@ip-172-31-13-101:~/python-peerplays$


```

Cheers, all unit tests are passed and you successfully verify the NFT\_python


# NFT, Marketplace, HRP, and RBAC related Commands/Use Cases

Here we learn some commands and use cases related to NFT, Marketplace, HRP, and RBAC.

#### **1. NFT Metadata Creation** <a href="#id-1.-nft-metadata-creation" id="id-1.-nft-metadata-creation"></a>

```
nft_metadata_create(string owner_account_id_or_name, string name, string symbol, string base_uri, optional<string> revenue_partner, optional<uint16_t> revenue_split, bool is_transferable, bool is_sellable, optional<account_role_id_type> role_id, bool broadcast)
```

Example NFT metadata create command without permissions,

```
nft_metadata_create account01 "AVALON NAME" "AVALON SYMBOL" "AVALON BASE URI" account02 100 false true null true
```

* **account01** is the owner account of the metadata
* **“AVALON NAME”** is the name of the NFT types created from the NFT metadata being created
* **“AVALON SYMBOL”** is the symbol of the NFT types created from the NFT metadata being created. The symbol is reserved for future use.
* **“AVALON BASE URI”** is the URI of the NFT types. Eg: `avalonmeta.com`
* **account02** is the revenue partner, this can be owner as well. Whenever the minted NFT is sold in the marketplace a split of the selling price goes to the revenue partner. The split can be specified in **revenue\_split** parameter.
* **100** is the revenue\_split on the scale of 10000 being 100 percent. i.e. 100 is 1%
* is\_transferable specifies if the minted NFTs can be transferred by the owner of the NFT to other accounts
* is\_sellable specifies if the minted NFTs can be sold in the marketplace.
* role\_id is the resource permissions specifying the whitelisting accounts among which the NFTs can either be transferred or sold on marketplace.
* broadcast either true or false, keeping it true will include the transaction in the upcoming block on the chain.

#### Example NFT metadata create command with permissions <a href="#example-nft-metadata-create-command-with-permissions" id="example-nft-metadata-create-command-with-permissions"></a>

First create a permission:

```
create_account_role(string owner_account_id_or_name, string name, string metadata, flat_set<int> allowed_operations, flat_set<account_id_type> whitelisted_accounts, time_point_sec valid_to, bool broadcast)
```

Example Permission:

```
create_account_role account01 "Avalon Permissions1" "Permission Metadata" [88,89,90,95] [1.2.40, 1.2.41] "2020-11-04T13:43:39" true
```

* **account01** is the owner of the permission being created which can be attached to NFT metadata.
* **“Avalon Permissions1”** is the name of the resource permission being created.
* **“Permission Metadata”** is the metadata, can be a JSON as well.
* **\[88,89,90,95]** is the list of operations this permission whitelists for accounts.\
  88 - List Offer operation in marketplace\
  89 - Bid operation in marketplace\
  90 - Cancel Offer operation in marketplace\
  95 - Safe transfer from owner to another NFT
* **\[1.2.40, 1.2.41]** List of accounts whitelisted for the above operations. Offer, bid and transfer operations can only be among the whitelisted accounts.
* `"2020-11-04T13:43:39"` Expiry date of the permission
* `true` broadcast, keep it true to include the transaction in upcoming block.

Example NFT metadata create command with permissions:

```
nft_metadata_create account01 "AVALON NAME" "AVALON SYMBOL" "AVALON BASE URI" account02 100 false true 1.32.0 true
```

* 1.32.0 This is specified in the metadata create operation to attach permissions to all the NFTs created from this metadata.

#### **NFT creation** <a href="#nft-creation" id="nft-creation"></a>

NFT is always minted by the owner of the metadata object this NFT is based on. The fees associated with minting this NFT is just the transaction fee + storage fee which are both collected in core PPY token. After the NFT has been minted this can be sold on marketplace in any token of NFT owner’s choice.

Syntax:

```
nft_create(string metadata_owner_account_id_or_name, nft_metadata_id_type metadata_id, string owner_account_id_or_name, string approved_account_id_or_name, string token_uri, bool broadcast)
```

Example NFT creation based on the metadata created above:

```
nft_create account01 1.30.0 account02 account02 "AVALON NFT URI" true
```

* **account01** is the owner of the metadata this NFT is based on
* **1.30.0** is the metadata ID of the metadata object this NFT is based on ( Currently this works on best guess method by doing get\_object 1.30.0, 1.30.1, 1.30.2 …. so on, in future a new cli command will be introduced that can list all the metadata objects by owner account ).
* **account02** is the owner of the NFT, can be one of the user of the Avalon App.
* **account02** is the approved account of the NFT, can be the owner as well.
* `"AVALON NFT URI"`is the URI that has additional information about this NFT.

#### **NFT Safe Transfer from owner to other account** <a href="#nft-safe-transfer-from-owner-to-other-account" id="nft-safe-transfer-from-owner-to-other-account"></a>

```
nft_safe_transfer_from(string operator_account_id_or_name, string from_account_id_or_name, string to_account_id_or_name, nft_id_type token_id, string data, bool broadcast)
```

Example command:

Note that NFTs can be transferred only when `is_transferableflag` is set to true, also if permissions are enabled both from and to accounts have to be whitelisted.

```
nft_safe_transfer_from account02 account02 account03 1.31.0 "Enjoy my NFT" true
```

* **account02** operator or owner account
* **account02** from account
* **account03** to account
* **1.31.0** Id of the NFT
* "Enjoy my NFT"is the metadata of the transfer
* **true** is broadcast option mentioned above.<br>

#### **Create Market Listing Offer** <a href="#create-market-listing-offer" id="create-market-listing-offer"></a>

```
create_offer(set<nft_id_type> item_ids, string issuer_accound_id_or_name, asset minimum_price, asset maximum_price, bool buying_item, time_point_sec offer_expiration_date, optional<memo_data> memo, bool broadcast)
```

Example command:

Note that is\_sellable of NFT metadata should be true to make listing of the NFTs created from the metadata.&#x20;

Only owner of the NFT can create a listing in auction.

```
create_offer ["1.31.0","1.31.1"] account02 {"amount":100,"asset_id":"1.3.0"} {"amount":10000,"asset_id":"1.3.0"} false "2020-08-18T11:05:39" null true 
```

* `["1.31.0","1.31.1"]` - List of NFTs to sell or buy
* **account02** is the owner of the NFTs
* `{"amount":100,"asset_id":"1.3.0"}` minimum bid price expected
* `{"amount":10000,"asset_id":"1.3.0"}` maximum bid price expected
* `false` buying\_item denotes if this is an auction or reverse auction
* `"2020-08-18T11:05:39"` Listing expiry date
* `null` Optional metadata, if not null assign a string value
* `true` broadcast value mentioned above

#### **Create Bid Offer** <a href="#create-bid-offer" id="create-bid-offer"></a>

```
create_bid(string bidder_account_id_or_name, asset bid_price, offer_id_type offer_id, bool broadcast)
```

Example bid command:

```
create_bid account04 {"amount":10000,"asset_id":"1.3.0"} 1.29.0 true
```

* **account04** is the bidder
* `{"amount":10000,"asset_id":"1.3.0"}` bid price
* `1.29.0` Offer listing objected created from create\_offer command
* `true` broadcast value mentioned above

#### **Cancel Offer** <a href="#cancel-offer" id="cancel-offer"></a>

```
cancel_offer(string issuer_account_id_or_name, offer_id_type offer_id, bool broadcast)
```

Example cancel offer command:

```
cancel_offer account02 1.29.0 true
```

* **account02** is the creator of the listing
* `1.29.0` is the offer object
* `true` broadcast value mentioned above

#### **List Offers** <a href="#list-offers" id="list-offers"></a>

Returns all the sell and buy listings offer objects in the marketplace.

```
list_offers(uint32_t limit, optional<offer_id_type> lower_id)
```

Example command:

```
list_offers 100 1.29.0
```

* `100` Number of items per fetch (pagination)
* `1.29.0` Index to start the search for. (pagination)

Example command without pagination:

```
list_offers 100 null
```

#### **List Sell Offers** <a href="#list-sell-offers" id="list-sell-offers"></a>

Returns all the sell listing offer objects in the marketplace.

```
list_sell_offers(uint32_t limit, optional<offer_id_type> lower_id)
```

Example command:

```
list_sell_offers 10 1.29.6
```

* `10` Number of items per fetch (pagination)
* `1.29.6` Index to start the search for. (pagination)

Example command without pagination:

```
list_sell_offers 10 null
```

#### **List Buy Offers** <a href="#list-buy-offers" id="list-buy-offers"></a>

Returns all the buy listing offer objects in the marketplace. (Reverse Auction offer objects).

```
list_buy_offers(uint32_t limit, optional<offer_id_type> lower_id)
```

Example command:

```
list_buy_offers 10 1.29.6
```

* `10` Number of items per fetch (pagination)
* `1.29.6` Index to start the search for. (pagination)

Example command without pagination:

```
list_buy_offers 10 null
```

#### **List Offer History** <a href="#list-offer-history" id="list-offer-history"></a>

Returns all the closed auction and reverse auction listings. (offers)

```
list_offer_history(uint32_t limit, optional<offer_history_id_type> lower_id)
```

Example command:

```
list_offer_history 10 2.24.2
```

* `10`Number of items per fetch (pagination)
* `2.24.2`Index to start the search for. (pagination)

Example command without pagination:

```
list_offer_history 10 null
```

#### Get Offers by Issuer <a href="#get-offers-by-issuer" id="get-offers-by-issuer"></a>

Returns all the offers listed by an account.

```
get_offers_by_issuer(string issuer_account_id_or_name, uint32_t limit, optional<offer_id_type> lower_id)
```

Example command:

```
get_offers_by_issuer account02 10 1.29.0
```

* `account02` issuer
* `10` Number of items per fetch (Pagination)
* `1.29.0` Index to start the search for. (pagination)

Example command without pagination:

```
get_offers_by_issuer account02 10 null
```

#### Get Offers by NFT Item <a href="#get-offers-by-nft-item" id="get-offers-by-nft-item"></a>

```
get_offers_by_item(const nft_id_type item, uint32_t limit, optional<offer_id_type> lower_id)
```

Example command:

```
get_offers_by_item 1.31.0 10 1.29.1
```

* `1.31.0` NFT Id
* `10` Number of items per fetch (Pagination)
* `1.29.1` Index to start the search for. (pagination)

Example command without pagination:

```
get_offers_by_item 1.31.0 10 null
```

#### Get Offer History by Issuer <a href="#get-offer-history-by-issuer" id="get-offer-history-by-issuer"></a>

```
get_offer_history_by_issuer(string issuer_account_id_or_name, uint32_t limit, optional<offer_history_id_type> lower_id)
```

Example command:

```
get_offer_history_by_issuer account06 10 2.24.1
```

* account06 Issuer
* 10 Number of items per fetch (Pagination)
* 2.24.1 Index to start the search for. (pagination)

Example command without pagination:

```
get_offer_history_by_issuer account06 10 null
```

#### Get Offer History by NFT Item <a href="#get-offer-history-by-nft-item" id="get-offer-history-by-nft-item"></a>

```
get_offer_history_by_item(const nft_id_type item, uint32_t limit, optional<offer_history_id_type> lower_id)
```

Example Command:

```
get_offer_history_by_item 1.31.0 10 2.24.1
```

* `1.31.0` NFT Id
* `10` Number of items per fetch (Pagination)
* `2.24.1` Index to start the search for. (pagination)

Example command without pagination:

```
get_offer_history_by_item 1.31.0 10 null
```

#### Get Offer History by Bidder <a href="#get-offer-history-by-bidder" id="get-offer-history-by-bidder"></a>

```
get_offer_history_by_bidder(string bidder_account_id_or_name, uint32_t limit, optional<offer_history_id_type> lower_id)
```

Example Command:

```
get_offer_history_by_bidder account07 10 2.24.1
```

* account07 Bidder
* 10 Number of items per fetch (Pagination)
* 2.24.1 Index to start the search for. (pagination)<br>

Example command without pagination:

```
get_offer_history_by_bidder account07 10 null
```

## HRP User Authorities

> Hierarchical role based permissions is a feature of Peerplays blockchain which helps in increasing the security of user accounts.
>
> Users don’t have to use their active and owner keys for everything they do on the chain.
>
> They can create role based custom permissions and map them to different keys other than active and owner keys.
>
> They can then use these custom keys to sign transactions.

#### Create Custom Permissions <a href="#create-custom-permissions" id="create-custom-permissions"></a>

```
 create_custom_permission(string owner, string permission_name, authority auth, bool broadcast)
```

* owner Owner of the account who is creating the custom permission
* permission\_name Permission name, eg. `nftcreatepermission`
* auth authority is account authority, more info at [permissions](https://peerplays.atlassian.net/wiki/spaces/EP/pages/197466275/Reverse+Engineering+-+Peerplaysjs-lib), [public/private keys](https://peerplays.atlassian.net/wiki/spaces/EKB/pages/197460303), [multi authority](https://peerplays.atlassian.net/wiki/spaces/PROJECTS/pages/66519041/Compare+of+Master5050+and+Hardfork+Code)

Example Command:

```
create_custom_permission account01 perm1 { "weight_threshold": 1,  "account_auths": [["1.2.52",1]], "key_auths": [["TEST71ADtL4fzjGKErk9nQJrABmCPUR8QCjkCUNfdmgY5yDzQGhwto",1]], "address_auths": [] } true
```

`{ "weight_threshold": 1, "account_auths": [["1.2.52",1]], "key_auths": [["TEST71ADtL4fzjGKErk9nQJrABmCPUR8QCjkCUNfdmgY5yDzQGhwto",1]], "address_auths": [] }`

> This represents an authority structure, `account_auths` represent the amount of weight each accounts have on our account, in this example 1.2.52 has weight 1
>
> `key_auths` represent the amount of weight each public key has on this account, in this example `TEST71ADtL4fzjGKErk9nQJrABmCPUR8QCjkCUNfdmgY5yDzQGhwto` has weight 1
>
> `Weight_threshold` represent the required weight for a transaction to be signed successfully.
>
> In this example either `1.2.52` can sign with his active key or `TEST71ADtL4fzjGKErk9nQJrABmCPUR8QCjkCUNfdmgY5yDzQGhwto` can be used to sign a transaction successfully.

#### Get Custom Permissions <a href="#get-custom-permissions" id="get-custom-permissions"></a>

```
get_custom_permissions(string owner)
```

Example Command,

```
get_custom_permissions account01
```

#### Update Custom Permissions <a href="#update-custom-permissions" id="update-custom-permissions"></a>

```
update_custom_permission(string owner, custom_permission_id_type permission_id, fc::optional<authority> new_auth, bool broadcast)
```

Example Command:

```
update_custom_permission account01 1.27.0 { "weight_threshold": 1,  "account_auths": [["1.2.53",1]], "key_auths": [], "address_auths": [] } true
```

Here we removed the `key_auths` and added `1.2.53` with weight 1, which is equal to `weight_threshold` , so `1.2.53` can alone sign the transaction successfully.

#### Create Custom Account Authority <a href="#create-custom-account-authority" id="create-custom-account-authority"></a>

> Creating custom authority maps the created custom permissions with the actual operations present on the blockchain.
>
> It also has expiry time by when this custom permission is no more valid on any given account and operation combination.

```
create_custom_account_authority(string owner, custom_permission_id_type permission_id, int operation_type, fc::time_point_sec valid_from, fc::time_point_sec valid_to, bool broadcast)
```

Example Command:

```
create_custom_account_authority account01 1.27.0 0 "2020-11-02T17:53:25" "2020-12-03T17:53:25" true
```

`account01` is the owner of the account and the one who created a permission `1.27.0`

`1.27.0` is the custom permission created

`0` is the operation number, refer to operations at [operations](https://devs.peerplays.tech/supporting-and-reference-docs/operation-ids-list), here `0` is `transfer_operation`

`"2020-11-02T17:53:25"` valid from timestamp

`"2020-12-03T17:53:25"` valid to timestamp

`true` broadcast

Basically this represents a full HRP where transfer operation on `account01` can be done by authorities present in `1.27.0` instead of account owner `account01`

#### Update Custom Account Authority <a href="#update-custom-account-authority" id="update-custom-account-authority"></a>

Can be used to update existing `valid_from` and `valid_to` times,

```
update_custom_account_authority(string owner, custom_account_authority_id_type auth_id, fc::optional<fc::time_point_sec> new_valid_from, fc::optional<fc::time_point_sec> new_valid_to, bool broadcast)
```

Example command:

```
update_custom_account_authority account01 1.28.0 "2020-06-02T17:52:25" "2020-06-03T17:52:25" true
```

#### Delete Custom Permission <a href="#delete-custom-permission" id="delete-custom-permission"></a>

Used to delete the existing custom permission, this will delete all the custom account authorities linked to this permission as well.( cascading delete )

```
delete_custom_permission(string owner, custom_permission_id_type permission_id, bool broadcast)
```

Example command:

```
delete_custom_permission account01 1.27.0 true
```

#### Delete Custom Account Authority <a href="#delete-custom-account-authority" id="delete-custom-account-authority"></a>

Used to delete an account authority attached to a permission.

```
delete_custom_account_authority(string owner, custom_account_authority_id_type auth_id, bool broadcast)
```

Example command:

```
delete_custom_account_authority account01 1.28.0 true
```

### Resource Permissions ( Account Roles ) <a href="#resource-permissions-account-roles" id="resource-permissions-account-roles"></a>

As opposed to HRP mentioned above, resource permissions are controlled by an owner of a resource (eg. NFT metadata is a resource).

These are similar to IAM permissions in AWS Cloud environment.

#### Create Account Role <a href="#create-account-role" id="create-account-role"></a>

Used to create an account role.

```
create_account_role(string owner_account_id_or_name, string name, string metadata, flat_set<int> allowed_operations, flat_set<account_id_type> whitelisted_accounts, time_point_sec valid_to, bool broadcast)
```

`owner_account_id_or_name` resource owner Eg. account creating an NFT Metadata resource

`name` name of the account role Eg. Movie Interstellar Permissions

`metadata` metadata for additional info Eg. Some JSON struct or an external URL with info

`allowed_operations` allowed operations that `whitelisted_accounts` can perform on this resource.

`whitelisted_accounts` All the accounts that can perform any `allowed_operations` on a resource

`valid_to` exports time of the account role, valid from is the time of creation of the account role

`broadcast` broadcast mentioned above

Currently valid `allowed_operations` are

`offer_operation`**(88),** Checks if the user who is listing an NFT for sale is in `whitelisted_accounts` , if not the user can’t list the NFTs in marketplace.

`bid_operation`**(89),** Checks if the user who is bidding for an NFT on sale is in `whitelisted_accounts` , if not the user can’t bid / buy the NFT from marketplace.

&#x20;`nft_safe_transfer_from_operation` **(95),** Checks if the user who transferring i.e. owner is in `whitelisted_accounts`, if yes it checks the to-account is also in the `whitelisted_accounts`. If any of the two checks fail, the transfer fails.

More operations like NFT Lottery, RNG are to be attached to account roles.

Example Command:

```
create_account_role account01 ar1 ar1 [89,95] [1.2.40, 1.2.41, 1.2.43] "2020-09-04T13:43:39" true
```

This command effectively limits any NFT to be sold or transferred between only three accounts, `1.2.40, 1.2.41, 1.2.43`

For attaching NFT metadata to an account role, please refer to the above NFT sections.

#### Get Account Roles <a href="#get-account-roles" id="get-account-roles"></a>

```
get_account_roles_by_owner(string owner_account_id_or_name)
```

Example command:

```
get_account_roles_by_owner account01
```

#### Update Account Role <a href="#update-account-role" id="update-account-role"></a>

As a resource owner, one can update the operations and whitelisted accounts present in an account role.

This helps in blacklisting any users from selling or transferring NFTs or any resources.

```
update_account_role(string owner_account_id_or_name, account_role_id_type role_id, optional<string> name, optional<string> metadata, flat_set<int> operations_to_add, flat_set<int> operations_to_remove, flat_set<account_id_type> accounts_to_add, flat_set<account_id_type> accounts_to_remove, optional<time_point_sec> valid_to, bool broadcast)
```

`operations_to_add` new operations to add to the account role

`operations_to_remove` existing operations to remove from the account role

`accounts_to_add` new accounts to add to the whitelist

`accounts_to_remove` existing accounts to remove from the whitelist

Example command:

```
update_account_role account01 1.32.0 null null [88] [95] [1.2.42] [1.2.40] "2020-09-04T13:52:38" true
```

`88` `offer_operation`**`(88)`** is added

`95` `nft_safe_transfer_from_operation` is removed

`1.2.42` account to the whitelist

`1.2.40` account removed from the whitelist

#### Delete Account Role <a href="#delete-account-role" id="delete-account-role"></a>

Once account role is deleted, restrictions on resource access no longer work.

```
delete_account_role(string owner_account_id_or_name, account_role_id_type role_id, bool broadcast)
```

Example command:

```
delete_account_role account01 1.32.0 true
```

### Fee Considerations <a href="#fee-considerations" id="fee-considerations"></a>

**PPY** is the core token of peerplays blockchain. Blockchain users can issue their own tokens with a conversion rate to core token.

In the Peerplays blockchain, every operation executed has a fee associated with it. The majority of these fees go as payments to witnesses that run the blockchain. These fees are called transaction fees and are collected in core (PPY) tokens only.

There is also a fee for storing any data on the blockchain like metadata or names.

Currently for the operations related to **NFT, Marketplace, HRP, and Account Roles:**

```
 ID     Operation Name                              Fees (in PPY)
 82	custom_permission_create_operation__________0.005 + 0.01 per Kb data
 83	custom_permission_update_operation__________0.005
 84	custom_permission_delete_operation__________0.005
 85	custom_account_authority_create_operation___0.005 + 0.01 per Kb data
 86	custom_account_authority_update_operation___0.005
 87	custom_account_authority_delete_operation___0.005
 88	offer_operation_____________________________0.001 + 0.01 per Kb data
 89	bid_operation_______________________________0.001
 90	cancel_offer_operation______________________0.001
 91	finalize_offer_operation____________________0.0 (Free!)
 92	nft_metadata_create_operation_______________0.1  + 0.01 per Kb data
 93	nft_metadata_update_operation_______________0.1
 94	nft_mint_operation__________________________0.01 + 0.01 per Kb data
 95	nft_safe_transfer_from_operation____________0.01 + 0.01 per Kb data
 96	nft_approve_operation_______________________0.005
 97	nft_set_approval_for_all_operation__________0.005
 98	account_role_create_operation_______________1.0  + 1.00 per Kb data
 99	account_role_update_operation_______________1.0  + 1.00 per Kb data
 100	account_role_delete_operation_______________1.0
```

{% hint style="warning" %}
These values are subject to change by committee members.
{% endhint %}

### NFT Notes <a href="#nft-notes" id="nft-notes"></a>

* In order to create an NFT, a metadata has to be created first.
* Only the owner of the metadata can mint NFTs
* These NFTs can be assigned to any user of metadata owner’s choice.
* **NFT Metadata owner** is the owner of the metadata that mints the NFTs, **NFT owner** is the one who is assigned an NFT by metadata owner after minting.
* User who is not the metadata owner cannot mint NFTs to himself
* `is_transferable` and `is_sellable` flags configured on metadata control the transfer and selling properties of all the NFTs minted from the metadata.
* If `is_transferable` is false and `is_sellable` is true, then the NFT owner can only list it in marketplace and sell it. He can’t transfer to another user.
* If `is_transferable` is true and `is_sellable` is false, then the NFT owner cannot list it in marketplace and he can freely transfer it to other users.
* If `is_transferable` is false and `is_sellable` is false, then the NFT owner can neither be transfer nor sell the NFT. It remains with him forever.

### Marketplace Notes <a href="#marketplace-notes" id="marketplace-notes"></a>

* Peerplays blockchain operates the marketplace through `offer_operation`, `bid_operation`, `cancel_offer_operation`, `finalize_offer_operation` operations/smart contracts.
* Offers operate as an auction where max bid before the expiry time owns the NFT
* If max\_price is equal to min\_price in offer\_operation it acts as normal listing. Whoever bids the max\_price gets the NFT instantly.
* For a successful bid, `revenue_partner` gets the `revenue_split` percent of the bid. This is configured during NFT metadata creation. So for all the NFT sales that are based on the metadata, `revenue_partner` gets the cut.
* Currently peerplays stakeholders don’t get the cut, this will be implemented in the future.
* Currently there is only one marketplace i.e. Peerplays blockchain is providing a marketplace where any owner can sell his NFT based on the configuration of the parent metadata.
* Metadata owner can customize this marketplace in the UI to show only the NFTs minted from his own metadata to his DAPP users.
* So there are no multiple marketplaces on peerplays blockchain at the moment, only UI customization are possible.
* Price can be set in terms of custom assets (tokens) in market place. In this case both offers and bids should be in the same asset (token). Eg. Offer price is in XCOIN token, then bid price should also be in XCOIN token.

### Use Cases <a href="#usecases" id="usecases"></a>

#### Movie Tickets (For Blockchain Savvy Users) <a href="#movie-tickets-for-blockchain-savvy-users" id="movie-tickets-for-blockchain-savvy-users"></a>

* I’m the owner of a movie theater where there is a premiere show for a movie Interstellar.
* I create NFT metadata for Interstellar movie that has basic info about the genre, running time, movie posters etc
* To maximize my profit and take a cut from the black market ticket sales, I created the metadata of the movie `is_transferable` to false and `is_sellable` to true
* I accept payment on the blockchain in multiple currencies namely PPY, XCOIN and BTC (or some off chain mechanism in FIAT currencies like USD)
* I mint the tickets as NFTs to the users who sent me the amount in the above currencies. Users can gain entry to the movie only with these NFT tickets.
* Users cannot transfer the tickets among themselves, they can only list them on marketplace.
* As the demand for tickets increase, listing price increase, so I get more cut for every ticket sold.

#### NFT Lottery with Geolocation restrictions (Account Roles/ Resource Permission use case) <a href="#nft-lottery-with-geolocation-restrictions-account-roles-resource-permission-use-case" id="nft-lottery-with-geolocation-restrictions-account-roles-resource-permission-use-case"></a>

* I’m the issuer of the lottery which has geo restrictions saying the lottery can only be sold to residents of the state New South Wales(NSW) in Australia.
* I do the KYC check off chain and list down all the users on the blockchain that are residents of the state.
* While creating NFT metadata I attach the account roles with the whitelist of users along with `is_transferable` to true and `is_sellable` to false.
* I create a smart contract for minting NFTs from the metadata created.
* This smart contract accesses the account role associated with the metadata.
* If any user is not whitelisted he can’t purchase the NFT lottery ticket from the smart contract.
* If the user is whitelisted and minted a lottery ticket, he can’t transfer it to non-whitelisting users who are not residents of NSW.
* I create a draw and declare the owner of NFT as winner.

#### University Degrees <a href="#university-degrees" id="university-degrees"></a>

* I’m the university issuing degrees to students that complete masters degree in two streams science and arts.
* I create two NFT metadata one each for both Science and Arts.
* I make both `is_transferable` to false and `is_sellable` to false.
* I mint NFT accordingly based on the stream to each student.
* Each NFT (degree) has the info about the student grades, courses etc.
* These NFTs (degrees) stays with the students (users) forever, they can’t be transferred or sold.

#### Minting NFTs (For not so Blockchain Savvy Users) <a href="#minting-nfts-for-not-so-blockchain-savvy-users" id="minting-nfts-for-not-so-blockchain-savvy-users"></a>

* I’m the owner of an NFT Metadata and my DAPP users are not blockchain savvy.
* I mint the NFTs to my account itself.
* I modify the URI of NFTs accordingly off chain to denote the ownership.

### Example NFT creation <a href="#example-nft-creation" id="example-nft-creation"></a>

Core coin : PPY for fee

Purchase/Sell/Transaction token for NFTs : ava-token

PPY:ava-token = 1:10000


# NFT command reference

### **Step: 1** Create Metadata

**Command used** : `nft_metadata_create <<account_name>> <<metadata_name>> <<metadata_symbol>> <<base_uri>> true true true`

**For example :** `nft_metadata_create account01 sknft sknft sknft null null true true true`<br>

### **Step:2** Update Metadata

**Command used** : `nft_metadata_update <<account_name>> <<metadata_id>> <<new_name>> <<new_symbol>> <<new_base_uri>> null null true true true`

**For Example :**`nft_metadata_update account01 1.30.1 sknft01 sknft01 sknft01 null null true true true`\ <br>

### **Step: 3** Create NFT

**Command used** : `nft_create <<account_name>> <<metadata_id>> <<Owner_account_name>> <<approve_aacount_name>> <<token_uri>> true`

**For Example** : `nft_create account01 1.30.0 account03 account03 sknftmint true`<br>

### **Step:4** Get NFT balance

**Command used** : `nft_get_balance <<account_name>>`

**For Example :** `nft_get_balance account01`\ <br>

### **Step:5** To verify the owner of created NFT

**Command used** : `nft_owner_of <<nft_id>>`

**For Example :** `nft_owner_of 1.31.1`\ <br>

### **Step:6** Safe NFT transfer

**Command Used :** `nft_safe_transfer_from <<Operator_account_name>> <<transfer_from_account_name>> <<transfer_to_account_name>> <<nft_id>> true true`

**For Example** : `nft_safe_transfer_from account01 account01 aaccount02 1.31.1 true true`\ <br>

### **Step: 7** NFT Transfer

**Command used :** `nft_transfer_from <<Operator_account_id>> <<From_account_id>> <<To_account_id>> <<nft_id>> true`

**For Example** : `nft_transfer_from 1.2.31 1.2.31 1.2.28 1.31.37 true`\ <br>

### **Step:8** NFT Approve

**Command used** : `nft_approve <<new_operator_account_id>> <<new_account_id>> <<ndt_id>> true`

**For Example** : `nft_approve 1.2.19 1.2.19 1.31.1 true`\ <br>

### **Step : 9** To approve all NFTs at once

**Command used:** `nft_set_approval_for_all <<Owner_account_id>> <<Operator_account_id>> true true`

**For example** : `nft_set_approval_for_all 1.2.21 1.2.21 true true`\ <br>

### **Step: 10** To see the approved account details

**Command used** : `nft_get_approved <<approve_nft_id>>`

**For Example:** `nft_get_approved 1.31.0`\ <br>

### **Step:11** Approved for all

**Command used:** `nft_is_approved_for_all <<owner_account_id>> <<operator_account_id>>`

**For Example :** `nft_is_approved_for_all 1.2.21 1.2.21`\ <br>

### **Step :12** Get list of all created NFT

**Command used** : `nft_get_all_tokens`

With this - all the created NFTs are listed on the machine.


# Peerplays DEX

A brief overview of the Peerplays decentralized exchange.

## 1. Decentralized Asset Exchanges

In the cryptocurrency space, a decentralized exchange (DEX) is a place to trade crypto assets while maintaining ownership of your private keys and thereby keeping control of your assets. There is no third party or broker in the DEX. Instead, the trading is managed by an impartial (and therefore trustworthy) automatic market-making algorithm.

## 2. The Peerplays DEX

The user can perform the following tasks using Peerplays DEX:

* use it as a wallet to manage your assets.
* monitoring the market activity of any trading pair.
* swap assets using the Peerplays PPY.&#x20;
* cast votes and participate in blockchain governance.
* manage your Peerplays account.
* register your Bitcoin, Hive, and Ethereum accounts to send and receive BTC, HIVE, and ETH.

## 3. Peerplays account

The user has to log in to Peerplays DEX to manage the Peerplays account. The user can monitor activities such as selling/buying assets, monitoring market activities, order history, profile setting, and voting in their account. Use the below document to create one,

{% embed url="<https://peerplays.gitbook.io/peerplays-infrastructure-docs/~/changes/0IXXeM79c2vnSTcZBjuH/the-basics/how-to-create-a-peerplays-account>" %}

## 4. Peerplays wallet

There is a built-in wallet for each account through which the user can trade the asset, receive the asset from BTC/HIVE/ETHEREUM, and maintain ownership. &#x20;

#### Deposits and withdrawals

You can deposit Bitcoin and Hive to your Peerplays wallet to use in the Peerplays DEX. Peerplays SONs (Sidechain Operator Nodes) enable off-chain assets to be deposited and withdrawn from Peerplays accounts. More chains will be added over time to bring the most popular assets to Peerplays.

When these assets are on the Peerplays chain, they benefit from the 3-second blocks of the Peerplays network. They can be traded, swapped, or staked like any other Peerplays asset. And they can be withdrawn back to their original chains as well. When these off-chain assets are on the Peerplays chain, they are always backed by an equal amount on their original chain.

#### Sending assets

Assets that you own can easily be sent to any other Peerplays account. When on the Peerplays chain, Bitcoin and Hive can be sent to other Peerplays accounts or addresses on their original chains.

## 5. Asset staking (PowerUp)

Staking your assets using the PowerUp option in the DEX will earn you rewards and voting power over time. Your staked assets supply liquidity pools used for asset swapping. In return, you'll receive an NFT that represents and tracks your stake in the liquidity pools.

The NFT reaches maturity when its locking period (which you choose) expires. At this point, you can PowerDown the NFT to retrieve your assets from the pool. At any time along the way, you can claim the rewards that have been accruing based on the size of your stake and the length of the locking period you chose. But beware, powering down the NFT means losing the voting power that has also been accruing.

Another option you have is to sell the NFT in the NFT marketplace. Especially if you have an aged NFT, you can fetch a premium price for your NFT.

## 6. GPOS - Voting

Transfer the PPY to GPOS balance to participate in the voting for best witnesses, advisors, SONS, and proposals. To increase the participation rewards, the user has to transfer more PPY into the GPOS balance and share Peerplays with others. Peerplays remains the most secure provably fair blockchain globally with Decentralized Autonomous Cooperative (DAC).&#x20;

Using Powerup, the user can participate in the DAC with which the user can become a big part globally, earn participant rewards, stake PPY while participating, bragging rights, and help secure Peerplays Blockchain.

## 7. Asset swapping

From the Peerplays account, using PPY asset swapping can be done with ease. The swapping mechanism is simple and quick compared with the traditional order book exchange. The exchange rate is calculated based on the available supply of each asset rather than set by traders seeking the best price.

## 8. The exchange

The Peerplays DEX provides a decentralized order book trading experience for those who prefer to set their own prices on trades. The DEX supports market, limit, and stop-limit orders. The exchange is where you can speculatively trade various markets. Since the Peerplays DEX keeps your private keys in your hands and is both a decentralized exchange and your wallet, there's no need to store your assets off the DEX. This means you can always be ready to trade in any market condition without the worry of hackers, exit scams, government takeovers, or bankruptcies (like what happens to centralized exchanges.)

## 9. Blockchain governance

The DEX is the place to cast your votes on important blockchain issues. You can help direct the blockchain and strengthen it by voting for the best node operators. Votes will also occur for setting fees for all the blockchain operations, how many node operators should run the network, which node operators are active, and network proposals. The voting happens on a continuous cycle so the blockchain can grow in the direction the voters wish to take it.


# User Guide

The user guide helps user to understand the various functionalities of NEX application. The below section guides the user to perform desired operations,

## 1. Account Creation

This section helps the new user in account creation. It also explains the existing user login operation. Click the below link to learn about this in details,

{% content-ref url="/pages/Tepl90YkI5KpjVm7u2AI" %}
[Account Creation](/technology/peerplays-dex/user-guide/account-creation)
{% endcontent-ref %}

## 2. Dashboard

The dashboard has four different operations and it is the home page of NEX application. The dashboard provide the options such as Deposit, withdraw, swap and market functions. Click the below link to learn more,

{% content-ref url="/pages/f9hLyIflaEhu2TAaci5Z" %}
[Dashboard](/technology/peerplays-dex/user-guide/dashboard)
{% endcontent-ref %}

## 3. Market Activity

The market activity page helps the user to choose the trading pair to perform sell/buy operations. It's one of the important page which helps the user to learn about the activities such as performance, history, order history, and open orders of any selected trading pair. Click the belwo link to learn in detail,

{% content-ref url="/pages/gm41vZKj9kqtFWWdglPW" %}
[Market Activity](/technology/peerplays-dex/user-guide/market-activity)
{% endcontent-ref %}

## 4. Peerplays Blocks

Blockchain represents the detailed list of block, time, supply (PPY), and ID. The user can switch between witnesses, sons and committees to learn more about each in details. The fees section provide list of all activities and respective fees involved. Click the below link to learn more in detail,

{% content-ref url="/pages/u8BKKxWn0UBHi6kUPkCC" %}
[Peerplays Blocks](/technology/peerplays-dex/user-guide/peerplays-blocks)
{% endcontent-ref %}

## 5. Settings

The settings page helps the user to alter any existing feature based on preferences. It provides option to setup language, generate keys and membership. Click below to learn more about the setting operation,

{% content-ref url="/pages/b9j1tIx0VbBSGUmJLTIu" %}
[Settings](/technology/peerplays-dex/user-guide/settings)
{% endcontent-ref %}

## 6. Wallet

Wallet page show the list of assets, asset send & receive option which helps user to perform any operations at ease. Click the below link learn the wallet operation in detail,

{% content-ref url="/pages/xvopMxdoMpMJDRxVrX6w" %}
[Wallet](/technology/peerplays-dex/user-guide/wallet)
{% endcontent-ref %}

## 7. Profile

The profile page has the option to check the activities of the user such as open orders, order history, activities, and notification in the account. Click the below link to learn more in detail,

{% content-ref url="/pages/SA9vNW6S3pOobkmhaZX0" %}
[Profile](/technology/peerplays-dex/user-guide/profile)
{% endcontent-ref %}

## 8. GPOS - Voting

The voting page helps the user to verify any desired account and perform voting operation. The sections are classified as witness, sons and committee. The user also has the option to choose  proxy account. Click the below link to learn in detail,

{% content-ref url="/pages/Wego5mGkYzyrokARvLWI" %}
[GPOS - Voting](/technology/peerplays-dex/user-guide/gpos-voting)
{% endcontent-ref %}

## 9. Logout

Click the below link to learn about the options to perform logout operation.

{% content-ref url="/pages/4qv4AUSM9Bx3bZK7Wui5" %}
[Logout](/technology/peerplays-dex/user-guide/logout)
{% endcontent-ref %}


# Account Creation

The page to create login for new users

## Creating an Account

1. Navigate to [PeerplaysDEX](https://swap.peerplays.com/) dashboard.
2. Click on **Create account** to create a new login.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FHBZH67rxhvhcUyUdnkWj%2FCreate-account.JPG?alt=media&amp;token=a0607d92-5f38-4170-ad04-c97372416f16" alt=""><figcaption><p>Fig-1: Dashboard Page</p></figcaption></figure>

3\. Enter the desired Username.&#x20;

{% hint style="info" %}
The user name should start with **lowercase.**

The user name should not contain,

* Capital Letter
* Special Characters
* Only digits
  {% endhint %}

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FSwI8XmjDJJGZauPpREOR%2F1.JPG?alt=media&amp;token=38577138-a76b-4fb1-b33f-b63f7c699c2d" alt=""><figcaption><p>Fig-2: Login creation</p></figcaption></figure>

4\. For the first time, the password is auto-generated. Copy that password and paste it into the "**re-enter your auto-generated master password**" box.

5\. Click **"Download Recovery password file here"** option to download the Keys to use for future login.

6\.   Enable the checkboxes and click on **create account.**&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F53Z6MHl3lZqA5NCxWXjo%2F3.JPG?alt=media&amp;token=784a77ae-fd41-4559-afc1-6ffb79f52459" alt=""><figcaption><p>Fig-3: Create account page</p></figcaption></figure>

7\. After successful login, the following screen will be displayed.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Frq1JK7NdLZ5QHWLlbLeN%2F5.JPG?alt=media&amp;token=2e6283fa-0fcf-4250-b9ed-150f858eb8e1" alt=""><figcaption><p>Fig-4: Login Creation Success</p></figcaption></figure>


# Dashboard

The first screen on the NEX page

There are 4 tabs in the dashboard section,

1. Deposit
2. Withdraw
3. Swap
4. Market

## 1. Deposit

This section helps the user to deposit assets into the account. The current version supports three assets BTC, HIVE, and ETH.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fa6UC73bCr2YaG1sZeLlR%2FDeposit-1.jpg?alt=media&amp;token=c6f18d8d-edf2-471e-9bf1-5b28fc1977bc" alt=""><figcaption><p>Fig-1 Deposit option</p></figcaption></figure>

### BTC Deposit

To deposit Bitcoin, select BTC from the drop-down list and click on **Generate Bitcoin address**. This prompts you to enter the password to confirm the validation.&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fa4WXvGlk1952N2TPO4xz%2Fbitcoin-deposit.JPG?alt=media&amp;token=c7af3f3f-36df-4741-b883-8f98ce9b61b5" alt=""><figcaption><p>Fig-2: Bitcoin Deposit</p></figcaption></figure>

Please follow the steps in the below link for any Bitcoin transaction,

{% embed url="<https://community.peerplays.com/~/changes/8PhtH7T32e0eFNJI7WpX/technology/peerplays-dex-1/user-guide/dashboard/bitcoin-transaction>" %}

## HIVE Deposit

To deposit HIVE/HBD, select HIVE from the drop-down menu. It instructs to send funds to son-account on hive blockchain with memo as account name.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F6msO3e37x1ISuleKPrX0%2FHBD-deposit.JPG?alt=media&amp;token=1e9f6bbe-58ad-4c77-ad86-09d0ceab4af8" alt=""><figcaption><p>Fig-3: Hive Deposit</p></figcaption></figure>

### Ethereum Deposit

To deposit Ethereum, first, the user should add the Ethereum deposit address,

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F1T8XLHh0fNwLhcH3plrJ%2Feth-deposit.JPG?alt=media&amp;token=e6452c28-247d-41a6-9f00-00a4434d98c2" alt=""><figcaption><p>Fig-4: Add Ethereum address</p></figcaption></figure>

## 2. Withdraw

To withdraw the desired asset choose withdraw tab in the dashboard. There are two assets supported in this version BTC and HIVE.

## BTC Withdraw

1. Select BTC from the list of options in the drop-down list.
2. Enter the required amount of BTC to be withdrawn.
3. Enter the Compressed withdraw public key & address from the keys text file.
4. The Estimated fee, total transaction, and time will be calculated based on the withdrawal amount.
5. Click on the **Withdraw** button to initiate the transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fd75JuaJ6V2JLAbdgCHyu%2Fbitcoin-withdraw.JPG?alt=media&amp;token=bddde2f2-f94d-4fa6-a450-8c929c60be29" alt=""><figcaption><p>Fig-5: BTC withdraw</p></figcaption></figure>

## HIVE Withdraw

1. Select **HIVE** from the list of options available in the drop-down list
2. Enter the amount to be withdrawn from the account
3. Enter the HIVE account withdrawal address in the text box
4. The Fees, total transaction, and time will be calculated based on the withdrawal amount.
5. Click on **Withdraw** to initiate the transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FggjmsTtnlrChdOinC3IZ%2Fhive-withdraw.JPG?alt=media&amp;token=478e99d4-139e-4edd-8205-e97e4d84553b" alt=""><figcaption><p>Fig-6: Hive Withdraw</p></figcaption></figure>

## Ethereum Withdraw

1. Select **ETH** from the list of options available in the drop-down list.
2. Enter the amount to be withdrawn from the account.
3. Enter the **ETH account address** withdrawal address in the text box.
4. The Fees, total transaction, and time will be calculated based on the withdrawal amount.
5. Click on **Withdraw** to initiate the transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FY8soFike7i8DU1AHCJTR%2FEth-witdraw-page.JPG?alt=media&amp;token=fd6bc527-72ce-4219-a8e4-e20a9dfb837f" alt=""><figcaption><p>Fig-7: ETH Withdraw</p></figcaption></figure>

## 3. Swap

The swap functionality is a quick way to exchange the asset. The assets that can be exchanged with each other are Bitcoin(BTC), Hive (HBD), and Peerplays (PPY).

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FLsDAlI80QgUOmWMXuqMY%2FSwap-asset.jpg?alt=media&amp;token=c9888ab2-10f8-4c26-8d41-8e5091b92f62" alt=""><figcaption><p>Fig-8: Asset options</p></figcaption></figure>

1. Select the asset from which the amount has to be swapped and enter the amount to be transferred.
2. Select the asset to which the amount has to be received. The amount will be calculated based on the transfer amount.
3. The fees and type of transaction will be displayed.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FO4aCrKee9RveDckdX9tf%2Fswapping-asset.JPG?alt=media&amp;token=5c34bfc9-cb05-45d6-b126-405eaee499de" alt=""><figcaption><p>Fig-9: Coin swap</p></figcaption></figure>

4\. Click on the **Swap Coins** button to initiate the swap which prompts you to enter the password for validation.

5\. The swap order will be displayed. Click on **Confirm** button to complete the swap.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FX9WUSGetT49oBCjgHBeT%2Fswap-order.JPG?alt=media&amp;token=64768aba-f44a-405b-8d98-31a46dc39656" alt=""><figcaption><p>Fig-10: Swap order transaction</p></figcaption></figure>

6\. After successful swapping, the success message will be displayed.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FI7bfC5mCMQ3mMGkBIqmw%2Fswap-order-complete.JPG?alt=media&amp;token=0aecea4e-6839-4060-b3d5-04549e46b0df" alt=""><figcaption><p>Fig-11: Transaction confirmation</p></figcaption></figure>

&#x20;7\. Click Done to reflect the changes in the dashboard.

## 4. Market

The Market tab is the shortcut way to choose the Trading pair for any transaction. The trading pairs will be listed in blocks, hover over the blocks to click any option.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FeVFlQZlXSBQTjwg9759a%2FDashboard-marketpage.JPG?alt=media&amp;token=6d4efeac-8b61-4c20-87c2-65a04de83bad" alt=""><figcaption><p>Fig-12: Market page</p></figcaption></figure>

On clicking the desired block, it will direct to the Market tab to display all the activities of the Trading pair in detail.&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FY9iztxFFUYSi0d9bmBhP%2FMarket-page.JPG?alt=media&amp;token=4b41e69a-736a-4cab-b2b9-9cfeeb1f3fe8" alt=""><figcaption><p>Fig-13: Market-page Trading pair</p></figcaption></figure>

The Market page can also be chosen from the list of options available from the menu.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FMIcVtn41Vh92lcKsLXEL%2FMarket-other-option.jpg?alt=media&amp;token=3bf5572b-58a2-4268-8cee-e1f88efecdf9" alt=""><figcaption><p>Fig-14: Menu selection-Market page</p></figcaption></figure>


# Bitcoin Transaction

An example to get the bitcoin address

Depending on the wallet that you’re using, you may have to use a tool like [bitaddress.org](https://www.bitaddress.org/) to find your Public Key if it’s not already displayed in your wallet.

Wasabi Wallet, for example, displays your Public key.&#x20;

But wallets like [Trust Wallet](https://growfollowing.com/trust-wallet-private-key/) and Exodus require you to use external tools like [bitaddress.org](https://www.bitaddress.org/) to find your Public Key.

In this example, we’ll be using Wasabi Wallet as the Deposit address and Exodus as the withdrawal address.

As you can see in the image below, the Deposit Address (Wasabi Wallet) is bc1qhlu97p4ehnvt2274na5xqra5n8a8cnumavatn3

The Deposit Public Key is 02d5a014ec94974a01b5b81550bbcf6a629715140d38e7da5f1c2c71ccdcd8b61c

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FioXRv1OjxJZrd16X84xx%2Fstep4.webp?alt=media&amp;token=535e7123-d1ce-4dbb-a91d-6e6b7723794f" alt=""><figcaption></figcaption></figure>

The Withdraw Address (Exodus Wallet) is bc1qrk768lztvrjduama2ruuut9eweamtz5ru4vmhl

But we must find the Withdraw Private Key.. Here’s how:

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fqew8aOV7n29v6hfWAGWB%2Fstep5.webp?alt=media&amp;token=46524acf-9896-49cb-9179-3b285f3f0827" alt=""><figcaption></figcaption></figure>

Open your wallet. As seen in the image above, click on the three dotted lines and click “View Private Keys.” Then Click ”Yes, I’m sure.”

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FFupqu350Yt8VW2H2pFhe%2Fstep6.webp?alt=media&amp;token=8b85c1ca-c6ee-48f0-b30f-af6052a19e41" alt=""><figcaption></figcaption></figure>

Next, type your account password.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F8lhic25UyyBCzOTRXxQU%2Fstep7.webp?alt=media&amp;token=9898a09e-868d-4c39-9ac2-c40a1ef0b9fb" alt=""><figcaption></figcaption></figure>

And now you’ll see your Bitcoin deposit Address as well as your Private Key. Copy the address that starts with bc1 and it’s Private key.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fe165wzYBIsnmS4dx3wQ0%2Fstep8.webp?alt=media&amp;token=1dd4e98e-ba69-4a0a-895c-cde289dab998" alt=""><figcaption></figcaption></figure>

The Withdraw Private Key is L5896NkkABQ9PCcWHQiM1tAyFWoPtaEf1uLRQ5eG7nTvzXeXY29g

We will now use the Private Key to find out our Public Key. Simply head over to [bitaddress.org](https://www.bitaddress.org/). Then, click “Wallet Details”.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FUjE4PIT0kx5TWfKUmbqU%2Fstep9.webp?alt=media&amp;token=caf4cb40-b9e7-40ad-bf67-6bb707f68795" alt=""><figcaption></figcaption></figure>

Paste your Private Key and click “View Details.”

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FuJF0VGpZ0vHuTlCNP7OC%2Fstep10.webp?alt=media&amp;token=6ff81208-4b1e-404b-b977-0aba4dbba3e1" alt=""><figcaption></figcaption></figure>

You will find your Public Key over here. Make sure you copy and paste the compressed, 66 characters \[0-9A-F] and **NOT** the 130 Characters key.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FY00C7W6dngXAV9OQUUTy%2Fstep11.webp?alt=media&amp;token=6354029f-f113-4b58-9683-b91190b140ee" alt=""><figcaption></figcaption></figure>

We now have the Deposit Public Key, the Withdraw Public Key, and the Withdraw Address.&#x20;

**Deposit Public Key (Wasabi Wallet – already displayed):** 02d5a014ec94974a01b5b81550bbcf6a629715140d38e7da5f1c2c71ccdcd8b61c

**Withdraw Public Key (Exodus Wallet – found through bitaddress.org): 038F14B6B61EF0AE7EF8317E757807CA8322257C96D54635979C1FBBB899621AF2**

**Withdraw Address (Exodus Wallet):** bc1qrk768lztvrjduama2ruuut9eweamtz5ru4vmhl


# Market Activity

The market activity page helps in analysing the statistics of any trading pair. The statistics include the value of current price, change (in percentage), volume for any trading pair.

The trading pair will be between the following assets,

* BTC
* HBD
* HIVE
* PPY

The market page navigation can be done in two ways,

1. **From the Dashboard**

Click on the **Market Tab** in the Dashboard page and select any Trading pair to navigate to the Market page.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FE6Hq1HhBkMaU9gOAvizh%2FDashboard-marketpage-copy.JPG?alt=media&amp;token=4a4419c3-0578-43dc-9f48-c6834f348587" alt=""><figcaption><p>Fig-1: Dashboard selection</p></figcaption></figure>

&#x20; 2\. **From the Menu option**

On the home page, click on the three dots present in the right pane. All the options available will be listed and select Market from the available options to navigate to the Market tab.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FMIcVtn41Vh92lcKsLXEL%2FMarket-other-option.jpg?alt=media&amp;token=3bf5572b-58a2-4268-8cee-e1f88efecdf9" alt=""><figcaption><p>Fig-2: Menu option-Market page</p></figcaption></figure>

### 1. Market page Overview

The market page consists of the following sections,

* Trading pair selection
* Buy and Sell asset
* My Open orders
* My Open History

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FTWeEPqkrTRGzfgXFaLXK%2FMarketpage-overview.JPG?alt=media&amp;token=a35584ee-8892-4e8b-adee-08e7bfee7616" alt=""><figcaption><p>Fig-3: Market page </p></figcaption></figure>

### 1. Trading pair selection

To select any trading pair, click on the drop-down button available on the left pane of the market page. The drop-down option opens a tab to select the desired asset for trading.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FY9iztxFFUYSi0d9bmBhP%2FMarket-page.JPG?alt=media&amp;token=4b41e69a-736a-4cab-b2b9-9cfeeb1f3fe8" alt=""><figcaption><p>Fig-4: Trading pair selection</p></figcaption></figure>

The select pair tab will allow the user to choose any assets like BTC, HBD, HIVE, and PPY. The pairing can be done among these assets.&#x20;

In the recent pair option, the existing selection will be displayed. The user can choose the trading pair from this button too.

Finally, click on confirm to choose the trading pair or choose to cancel to go back to the market page.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F5dePJaw51BFtSXTCCtoS%2FMarketpage-tradingpair-selection.JPG?alt=media&amp;token=e1616976-49b7-4eef-86ff-9d8b1e2d505c" alt=""><figcaption><p>Fig-5: Select pair</p></figcaption></figure>

For any trading pair, the details about the pair will be listed like current price, change and volume. There are two options to analyse the selected trading pair namely,

* Order Book
* Trade history and My History

#### Order Book

This option provides details about the total, sell, and buy orders based on user selection from the options available.

It also has a drop-down list to choose the threshold value.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F6yzddcC3B1PBeDfds4g7%2FMP-order-book.JPG?alt=media&amp;token=61773afc-958c-4b44-bd82-0d88ff2c058e" alt=""><figcaption><p>Fig-6: Asset summary</p></figcaption></figure>

#### History

The history option helps the user to analyse the previous activities under the selected trading pair. It shows the details about the buy and selling details of asset with price and time.

Red color represents the sell orders while green color is for buy orders.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FWzisElLUHOh5rgrYS6mn%2FMP-Trade-history.jpg?alt=media&amp;token=02fb0f59-35b3-4628-a7a3-3b08e79b5d98" alt=""><figcaption><p>Fig-7: Trade history</p></figcaption></figure>

### 2. Buy and Sell Asset

This section on the Market page helps to Buy/sell the asset of the selected Trading pair. The assets will change according to the pair selection. In this example, the selected trading pair is BTC/PPY.

Input the value for the Price and quantity of an asset to calculate the Total value. Based on the input, the fees, market fees, and balance will be updated. Click on the Buy/Sell button to place the order.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FUK78k8FIjYaj8l2aXe4O%2FMP-Buy-asset-option.jpg?alt=media&amp;token=645e99f2-e10b-44f9-93f6-2c07f4f96b74" alt=""><figcaption><p>Fig-8: Buy  Asset</p></figcaption></figure>

The user has to click on the "sell" tab to sell the asset pair. The below diagram explains the options available to select when selling the asset.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FDroTz1lpXcFn6Cj7pIwc%2FMP-sell-option.JPG?alt=media&amp;token=b6e51dc0-3f89-457a-8dea-1230efb22843" alt=""><figcaption><p>Fig-9: Sell asset</p></figcaption></figure>

### 3. My Open Orders

The open orders tab displays the current order details for the selected trading pair. The details include price, asset value (in this case, BTC and PPY), expiration, and action.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FhI8I2FI0vYGbOKd00Zuw%2FMP-my-open-orders.jpg?alt=media&amp;token=abb3ed95-8351-4767-85d7-438f7e45f02e" alt=""><figcaption><p>Fig-10: My open order</p></figcaption></figure>

### 4. My Order History

In this section, the order history of the selected trading pair will be displayed. The values such as asset (In this example BTC and PPY), price and date of purchase are listed.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FiMs3ju2UWXrxAaS2iPkf%2FMP-my-order-history.JPG?alt=media&amp;token=b444e3b6-4978-477b-9e2b-5caafcac3f15" alt=""><figcaption><p>Fig-11: My open history</p></figcaption></figure>

## 5. Asset

The asset option on the market page has two options "Deposit" and "Withdraw"  which on the click navigates to the wallet page for receiving and sending assets respectively.&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F283PLHzoKLsr46zG7Pwz%2FMP-Assets-option.jpg?alt=media&amp;token=ed6bda41-e9f3-4bbe-b516-50962721a8c7" alt=""><figcaption><p>Fig-12: Assets tab to navigate to wallet page </p></figcaption></figure>


# Peerplays Blocks

The  Peerplays blockchain section helps the user to understand the transactions happening in the blocks. This page has the details of blockchain, assets, witnesses, committees, sons, and fees associated with that account.

To navigate to this page, click on the Blocks from the list of options available in the Menu on the right pane.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FHe5NweTlYapnZlnlOELx%2FBlocks-option.jpg?alt=media&amp;token=d873cfda-0c8a-45ec-a773-392c649e5b3d" alt=""><figcaption><p>Fig-1: Block option in Menu</p></figcaption></figure>

## Blocks Page - Overview

The block page consists of details about the blocks associated with the account. The tabs under this page are Blockchain, Assets, Witnesses, Committees, Sons, and Fees.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FOudaouWQ0bTWowXZC2Ax%2F1.JPG?alt=media&amp;token=ca65af37-9d0a-4cb1-8e99-1dd7063c61c0" alt=""><figcaption><p>Fig-2: Blockpage Overview</p></figcaption></figure>

## 1. Blockchain

This tab contains information about the block based on the recent activity. The information consists of current block, last irreversible block, confirmation time, supply.

The most recent block activity will be featured on the top of page and it will be updated based on each block activity.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FO6IQeGTlvuEg7PwGLlN7%2FShowing%20witness%20info.JPG?alt=media&amp;token=bca474c0-248f-421f-843b-ab91fe5de59a" alt=""><figcaption><p>Fig-3: List of blocks</p></figcaption></figure>

Click on a specfic Block ID to learn about the block in detail.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FwTGFCcuNXhlQHqiQ8B4f%2F2.JPG?alt=media&amp;token=7f4c8c79-162b-483c-8fcd-e642daf3a934" alt=""><figcaption><p>Fig-4: Block in detail</p></figcaption></figure>

## 2. Asset

The number of assets associated with the account will be listed in numbers. The search bar provides an option to search assets along with the option to download the details in PDF/CSV file format for future reference.

The filter options available to sort the assets are ID, Max supply, and Precision in ascending/descending order. Also, the assets can be sorted based on certain categories using symbol, name, and issuer options.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FVHtdOq7f8a9ypyRJKiIF%2F3-asset.JPG?alt=media&amp;token=21903123-72d9-4f59-a962-56a55d3ab566" alt=""><figcaption><p>Fig-5: Asset selection</p></figcaption></figure>

## 3. Witnesses

The witnesses associated with the account will be listed in blocks. The number of active and current witnesses along with earnings will be listed.

The search bar helps in finding the witness at ease. There is an option to download the list in PDF/CSV format for future reference.

The filter function helps to sort the data based on rank, total votes, last block, and missed block counts.

Click on the name to learn about the witness activity in detail.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FLQFkXwwrPjxlNmgus6Ea%2F4-witnessess.JPG?alt=media&amp;token=62b73627-2fd9-4cba-985c-b4203ac87f5e" alt=""><figcaption><p>Fig-6: List of Witness</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fm5pC8B1Xse6EyBp6lZPZ%2FWitness-activity.JPG?alt=media&amp;token=a87652c9-f3ca-409e-a40e-19c19ecded00" alt=""><figcaption><p>Fig-7: Asset in detail</p></figcaption></figure>

## 4. Committees

The number of active committees for the account will be displayed in blocks. The search bar helps in finding the member at ease. There is an option to download the list in PDF/CSV format for future reference.&#x20;

The filters will be based on rank, and total votes and can be sorted in ascending/descending order. Click on the name to learn the activity of each committee in detail.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FUYoPzdZ2AGF08OCVIf2T%2F5-committee.JPG?alt=media&amp;token=75a023fe-3361-4d42-a0a8-abb6ef978bbf" alt=""><figcaption><p>Fig-8: List t of active Committee </p></figcaption></figure>

The activities of any specific committee member can be monitored/viewed by clicking on the committee name.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FmeoNbP3NEJwCxH1Fd44U%2Fcommitte-activity.JPG?alt=media&amp;token=ae6a2bf5-390b-4265-bb7b-e8de5ebadfd7" alt=""><figcaption><p>Fig-9: Committee activity</p></figcaption></figure>

## 5. SONs

The number of active Sons will be displayed in blocks along with the budget and next vote update time.

The search bar helps in finding the account at ease. There is an option to download the list in PDF/CSV format for future reference.

Based on Rank and total votes the list can be filtered. Click on the particular name to learn their activity in detail.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FRKhQEBOgmzYHVk96ZKf7%2F6-Sons.JPG?alt=media&amp;token=38b6e045-b2bc-4738-944f-040d33cd3aa6" alt=""><figcaption><p>Fig-10: SONs detail</p></figcaption></figure>

## 6. Fees

The standard fees associated with each transaction will be listed along with their operation type like transfer, update, withdraw, etc.,

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FpjgaszvC0LYXFNKGlLGD%2F7-Fees.JPG?alt=media&amp;token=aa7c7514-fbbc-4e0a-9777-7dfdb4b54d0c" alt=""><figcaption><p>Fig-11: Fees details</p></figcaption></figure>

## 7. Accounts

This tab provides the list of accounts associated with the chain. Clicking on the account id/account name will direct to detailed activities of that particular account.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FynqogC3KbUdqgBXr4rTY%2FAccounts-1.JPG?alt=media&amp;token=ee4b8e6d-6dee-445c-88fd-35b6995af117" alt=""><figcaption><p>Fig-12 List of accounts</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fmz0SEvsv1vL7RbY3vte1%2FAccounts-activity.JPG?alt=media&amp;token=649e1b4d-f254-4b6a-9ded-9be0c867f77d" alt=""><figcaption><p>Fig-13: Activities of the account</p></figcaption></figure>


# Settings

The settings page helps the user to manage the activities of the accounts like language selection, lock account, notification settings, key management, and membership.

There are three sections in the settings page,

1. General
2. Key Management
3. Membership

## 1. General

The general section consists of option to select language, enable notification and set lock wallet time.

* **Select language** option has a drop-down menu to choose language among English and Russia.
* **Show notification** option has Yes/No selection to enable/disable notification based on user's choice.\
  By selecting **Yes,** the check boxes to enable notification for each activities will be visible.\
  By selecting **No,** the check boxes will be grayed out.
* **Lock wallet** option has the drop-down list with time in minutes. This helps the user to choose a desired time to lock the account.
* The URL to copy the faucet link will be provide at the bottom of the page.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F4jVfI5EgRiksNzJqJyc7%2Fsettings-3.JPG?alt=media&amp;token=17d78709-b229-45a2-8959-dcead20c30f5" alt=""><figcaption></figcaption></figure>

## &#x20;2. Key Management

This tab helps the user to generate keys for owner, active and memo account. The public account key will be listed at the bottom of the page.

a. The user has to enter the Master password in the tab provided.&#x20;

b. Select the keys that has to be generated by clicking the required name such as Owner, Active and Memo

c. Click the button ***Let's go*** to generate the keys.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FgBpboI2ikKi1SDbT0vDw%2F2.JPG?alt=media&amp;token=30a2083f-61d1-46c8-bf2d-196f31bbab03" alt=""><figcaption><p>Fig-2: Key management settings</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FU3xlXaPOvz5g4XjcUiLk%2F2-a.JPG?alt=media&amp;token=7289ea97-b3ee-4e1b-8dfa-4fab1ec19226" alt=""><figcaption><p>Fig-3: Key generation</p></figcaption></figure>

## 3. Membership

This tab provide the details about the existing information about the account. The details include Fee allocation, Fee statistics, Pending Fees, Vesting Fees.

This page allow the user to Buy Lifetime Subscription in a single click.

* [ ] Click on the **Buy Lifetime Subscription** button, next it shows a screen to enter password to confirm the login.
* [ ] After successful login, confirm the transaction to upgrade your account.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FHRftZfpZ8ZC3NagsAfGX%2F3.JPG?alt=media&amp;token=465900b2-f17c-407a-9e32-7e51e61633c0" alt=""><figcaption><p>Fig-4: Membership details</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FLAxsz9xWxQjZP8C6A9HP%2Fsubscription.JPG?alt=media&amp;token=df5483cf-ca5e-4db9-87ea-05572c8da9a5" alt=""><figcaption><p>Fig-5: Lifetime membership confirmation</p></figcaption></figure>


# Wallet

The wallet option allows the user to view the asset available in that account. It also has the option to send and receive assets from other accounts.

The Wallet has three sections,

1. Asset
2. Send
3. Receive

## 1. Asset

This section displays the list of assets available in the account. A search option is available to find any desired asset. The list of assets can be downloaded in the form of a PDF/CSV file.

The list of assets can be filtered based on symbol, name, available tokens, and orders.

Each asset has two buttons namely, send/receive to perform the transaction in a single click.&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FIjBziaUOnMHNpxj6UilB%2Fwallet-page.JPG?alt=media&amp;token=84c40504-7e0f-42f3-8a15-8f63045a726a" alt=""><figcaption><p>Fig-1: Asset details</p></figcaption></figure>

## 2. Send

The send section has the option to send available assets from one wallet to another account.&#x20;

1. Fill in the form with the correct input based on your transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FU2N47u5QGzWLOqCbifEk%2Fwallet-send.JPG?alt=media&amp;token=75d4ddde-32d8-4e58-a076-e72c79ee2ae5" alt=""><figcaption><p>Fig-2: Sending asset to account</p></figcaption></figure>

2\. Click on the **Send** button to initiate the transfer. Next, it prompts you to enter the password for validation.

3\. Click on **Confirm** to complete the transaction. The asset will be successfully transferred to another account.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FihTc8CkmBr5tQYg3UuQf%2Fsend-asset-confirm.JPG?alt=media&amp;token=9adfaa21-e958-4a32-883e-ff3a06a86169" alt=""><figcaption><p>Fig-3: Transaction confirmation</p></figcaption></figure>

## 3. Receive

To receive an asset from another account to your account, the wallet receives option can be used. Select the desired option under the **Receive** Assets drop-down list.

Based on the asset selection the hint to perform the transfer will be provided. Follow that to complete the transaction.

### List of assets

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FpcNRzdRvfgrdKzNq3IeG%2FWallet-receive.jpg?alt=media&amp;token=46815dfd-dfc7-453e-b131-4ee133c04a46" alt=""><figcaption><p>Fig-4: List of asset to receive</p></figcaption></figure>

### &#x20;After asset selection

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FLIRDVaP5tWtWyfEctWJC%2Fwallet-receive-info.JPG?alt=media&amp;token=53925f22-b79b-4313-abdb-da044fe5f0dd" alt=""><figcaption><p>Fig-5: Asset selection to receive</p></figcaption></figure>


# Profile

The profile page displays the information about the orders, activities and notification of the account.

## 1. Orders

The order tab displays the collection of all details about the Open order and Order history happened from the beginning of account creation.

It also provide the option to download the PDF/CSV file in a single click.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FrglFzw75pVdZvTinFQdq%2Fprofile-1.JPG?alt=media&amp;token=0c9e9fbe-07e5-4b8f-bb0c-e49945e98574" alt=""><figcaption><p>Fig-1: Order details</p></figcaption></figure>

## 2. Activities

This tab provide the list of activities happening in the account. Based on the time of activity, there is filter option to sort in either ascending/descending order.&#x20;

With the Type filter, based on activities like create an account, fill order, cancel order, etc., it can be sorted.

Each activities has its own information about the activity, ID and Fee involved in it.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FvqlEhLBioVOO9IMjzK85%2Fprofile-2-activities.JPG?alt=media&amp;token=691f328f-1fa9-4d5b-b00f-54ff2a2236b7" alt=""><figcaption><p>Fig-2: Account Activities</p></figcaption></figure>

## 3. Notification

This tab provides the list of notifications occurred in the account. Based on the time of notification, there is filter option to sort in either ascending/descending order.&#x20;

With the Type filter, based on notification like create account, fill order, cancel order, etc., it can be sorted.

Each notification has its own information about the activity, ID and Fee involved in it.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fx1mA9TxNlJua1bS6Bqvq%2Fnotofication.JPG?alt=media&amp;token=0cc2bb82-ff7d-434c-aa17-419c0117820a" alt=""><figcaption><p>Fig-3: Account notifications</p></figcaption></figure>


# GPOS - Voting

1\. GPOS

The GPOS page allows the user to perform operations like power up, power down, and voting. The Gamified Proof of Stake (GPOS) is for blockchain governance by voting for the various nodes in the network. Users need a simple and intuitive way to compare the candidates they can vote on. The page consists of 5 different tabs,  &#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FvHIcT88IQoBu5wtgI6O1%2FGPOS.JPG?alt=media&amp;token=9ede6bad-0ee9-48aa-9654-2c090d307d62" alt=""><figcaption><p>Fig-1: GPOS Page</p></figcaption></figure>

## A. Power Up

Click on the **Power Up** button in the GPOS tab. This mainly allows the user to participate in voting. The notice to explain the user participation is listed on this page.

### How to Vest?

* The opening and available balance is shown in the text boxes.
* Click on '+' to increase the deposit value
* The new balance will be updated based on the deposit.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fj2UCtMxrm7twyxB3ruDs%2FVest-1.JPG?alt=media&amp;token=43dac444-0347-413b-841a-0a150a7af0c7" alt=""><figcaption><p>Fig-2: Power up page</p></figcaption></figure>

* Click on **Vest** to begin the transaction and it prompts to enter the password for validation.
* Next, Click on confirm to complete the transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F4xWVuVCjDXs72Tkv2i0y%2FVest-1-powerup-password.JPG?alt=media&amp;token=c2753752-b3c1-4de5-b2ab-bb0e1b97f51e" alt=""><figcaption><p>Fig-3: Active Key </p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FrCPkbnv7SImamPBNOILw%2FVest-1-powerup-confirm.JPG?alt=media&amp;token=d10c22f8-6298-4baf-b34b-cbd88f2c7d8e" alt=""><figcaption><p>Fig-4: Transaction confirmation</p></figcaption></figure>

* Click on Done, after successful transaction. The amount will be vested into the desired account.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fb8Gxz7lWDWcih901ROuG%2FVest-1-powerup-success.JPG?alt=media&amp;token=f3df8e0e-99fe-416d-af26-2b0ba0ef8003" alt=""><figcaption><p>Fig-5: Successful Confirmation</p></figcaption></figure>

## B. Power Down

When the user has a need to withdraw the asset from power up, then Power down will be the option.&#x20;

Click on Power down option from the GPOS tab, that switch to power down tab in the next page

The notice about the withdraw of balance and it's impact will be listed.

Next, the opening balance, available balance will be listed in text boxes.

The user has to increase the withdraw value to withdraw any desired amount.

The new balance will be updated based on withdraw value.

Click on withdraw button to initiate the transaction. It prompts to enter the password to validate the account.

Next, Click on confirm to complete the transaction.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2ForsZvOegQVV6kYa733XD%2Fpower-down.JPG?alt=media&amp;token=fcde7e58-0760-45dc-a3eb-5a754c5c600b" alt=""><figcaption><p>Fig-6: Power down</p></figcaption></figure>

## C. Vote

Clicking on Vote will direct to the main page of GPOS. The tabs such as Witnesses, Sons, and committees has the list of name which has the option to Vote.

The **Action** section in the last column helps the user to vote desired account.

User has to click on the Thumps up icon symbol under the Action column of the desired account.

The icon will be grayed out to denote that voting has been done.

At the bottom of the page, Confirm button will be enabled and click on the button.

It prompts to enter the password to validate the account.

Next, click on confirm to complete the voting process.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FTOHuLhsZ49CbHls7WtXs%2Fwitness-vote.JPG?alt=media&amp;token=fcd8fb88-0fa2-45ee-89e0-a5f3324af3bb" alt=""><figcaption><p>Fig-7: Voting</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FyTYt4ZSOI9w4XcVafjpW%2Fvoting-confirm.JPG?alt=media&amp;token=b8e92fa3-61cb-449c-9ab0-dcfe4d6c4139" alt=""><figcaption><p>Fig-8: Voting Confirmation</p></figcaption></figure>

## 2. Witnesses

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FMO0mcAYtOhc47bnxe7ek%2Fwitness.JPG?alt=media&amp;token=00b68663-07ce-4019-98e4-d1890e8fa536" alt=""><figcaption><p>Fig-9: Witnesses list</p></figcaption></figure>

## 3. Sons

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FC2tEFM1p2E4XOaLhtei0%2FSons-voting-UI-change.JPG?alt=media&amp;token=28ed2484-853d-41e2-85ab-a2311310f26d" alt=""><figcaption><p>Fig-10: Sons account list</p></figcaption></figure>

The sidechains available for the account will be listed by clicking on the '+' symbol. The list of sidechains are Bitcoin, Ethereum, and Hive.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FdHXxQOiZFtqYeH7CwH1N%2FSONs-sidechain-list.JPG?alt=media&amp;token=9a1b1cc1-410d-4a26-adca-fb7f41833f46" alt=""><figcaption><p>Fig-11: List of sidechains</p></figcaption></figure>

## 4. Committees

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F0TkKisRL4whWYP2LhPw6%2Fcommittee.JPG?alt=media&amp;token=55848fdc-e4d8-49aa-9e62-70106e7405a1" alt=""><figcaption><p>Fig-12: List of committee members</p></figcaption></figure>

## 5. Proxy

The proxy option helps to add other account with the existing account to perform the function of that account in this existing one.

Enter a valid account name in the search box which enable Add button.

Click on ADD to add the account.

Click on Publish Changes button to apply the changes and to add the account.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FbhN0m8DxLenAWvljZVDc%2Fproxy.JPG?alt=media&amp;token=6a00457c-14ff-4e70-b478-ab5079ab38b6" alt=""><figcaption><p>Fig-13: Proxy account addition</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2Fdt5aVifvU3Nwu5eTu3yR%2Fproxy-confirm.JPG?alt=media&amp;token=a114b3bf-78e4-4595-bdf2-99bd972a6736" alt=""><figcaption><p>Fig-14: Confirmation</p></figcaption></figure>

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FdIwNhOiW4rcPbhSRVSZC%2Fproxy-success.JPG?alt=media&amp;token=4f73ff16-d86f-4c5f-a715-ea3d6302f67e" alt=""><figcaption><p>Fig-15: Proxy publishing Successful</p></figcaption></figure>


# Logout

To logout of the account, the user has two option.

1. The user can click on the account name in the header tab and choose logout option.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F20Wq3t2cm7nUleqnVhVE%2Flogout-1.jpg?alt=media&amp;token=d3236384-d04f-4368-b6fa-a5df14198014" alt=""><figcaption><p>Fig-1: Logout option1</p></figcaption></figure>

&#x20;2\. The user can click the menu option and logout will be at the bottom of the list.&#x20;

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FaVBLCjxl5iBfkVOtmwqc%2Flogout-2.jpg?alt=media&amp;token=bdd0ede4-bca7-4f84-8235-2b9dc6d23ccb" alt=""><figcaption><p>Fig-2: Logout option2</p></figcaption></figure>


# What is a Peerplays Witness?

{% hint style="info" %}
For installation instructions, refer <https://infra.peerplays.tech/witnesses/installation-guides>
{% endhint %}

### **So What is a Peerplays Witness?**

The short answer is, Witnesses run the Peerplays blockchain. The long answer is … well read on.

Chances are, even if you know very little about blockchain technology, you’ll have heard of Bitcoin and Bitcoin mining. And that’s important because as we talk about Witnesses we’ll draw a big distinction between the technology behind Bitcoin and that of the Peerplays blockchain.

### **The Bitcoin Way**

Bitcoin based blockchains use a consensus mechanism called Proof of Work (POW).&#x20;

At its simplest this means that if you want to create new blocks in the Bitcoin blockchain, colloquially become a ‘miner’, then you need to ‘work’. The harder you work the greater your chance of being paid.

The work involves solving a computational challenging puzzle. We don’t need to know what this puzzle is, but suffice to say the processing power required to profitable solve it is huge. You don’t need anybody’s permission to become a miner, and it’s quite possible to start mining on a home computer.

But realistically, the greater the computing power at your disposal the greater your chance of successfully solving the puzzle, and get paid for creating a new block. This system is anything but fair, one computer could be up against mining pools running literally thousands of computers. It’s easy to imagine the cost of such hardware, not to mention consuming enough power to run a small town!

### **The Peerplays Way**

So enter a consensus mechanism called Delegated Proof of Stake (DPOS).

Think of Delegated Proof of Stake as technological democracy; the opportunity for any PPY token holder to vote on who creates new blocks in the Peerplays blockchain; we call these block producers Witnesses, and they keep the blockchain alive.

Witnesses also have the authority to approve, or reject, any changes to the blockchain software. Their actions have an overarching impact on all PPY token holders.

Unlike Bitcoin miners, Peerplays Witnesses have to be voted in, and once elected they need to continue to accumulate positive votes as token holders don’t just have the power to vote Witnesses in, they have the power to vote them out;  remove bad actors.

To earn the right to be a Witness every prospect must accumulate votes by demonstrating why they would be a good Witness. It’s not enough for a prospective Witness to say they have a high spec computer in their basement and are tech savvy. A Witness should demonstrate qualities such as being active in the Peerplays community, blockchain competency, and past experience.

Peerplays has a unique enhancement to Delegated Proof of Stake called Gamified Proof of Stake (GPOS). In the context of Witness voting this is important as it incentivizes PPY token holders to vote. More information about GPOS can be found here:

{% content-ref url="/pages/-Lv6G74oQhGWbI9PXS\_T" %}
[Gamified Proof of Stake (GPOS)](/technology/gamified-proof-of-stake-gpos)
{% endcontent-ref %}

Vote strength is determined by how many PPY tokens somebody holds. This means that people who have more tokens will influence the network more than people who have very few tokens. Vote power is determined by ‘stake’.

As the community grows, it gets harder and harder to remain a paid Witness due to increased competition.

### **Voting for Witnesses**

With the introduction of GPOS it’s now more important than ever that PPY token holder’s vote. Without voting regularly any token holder’s rewards could be effected. Votes don’t have to be cast for Witnesses, they could be for advisors or proxies, but Witness voting is the most common; Witnesses generally have a higher profile and are more active in the community.

If we had to give only one reason for voting for Witnesses, then that’s simple … without them there would not be a working Peerplays blockchain. As mentioned earlier, the Witnesses are constantly signing blocks and ensuring transactions happen.

Choosing the right Witness to vote for doesn’t need to be difficult. Witnesses maintain their own blogs, contribute to public messaging channels and through the Peerplays Wallet it’s easy to see who are the most reliable block producers.

### **Witnesses and BookiePro**

BookiePro is a decentralized sports betting exchange, the first of its kind in the world and has been built for the Peerplays blockchain.

For the Peerplays witnesses this represents a unique opportunity to play a very important role in ensuring that BookiePro is provably fair. Operations in the blockchain have to be approved and this approval requires consensus from 50% + 1 of the Witnesses.&#x20;

What this means for BookiePro is that everything from the creation of a game to the final result, and settling the bet, has to be approved by more than one Witness.

For the BookiePro users this means a truly fair and decentralized application; no house and no single authority.

### **Bitcoin Miners v Peerplays Witnesses**

Let’s put the Peerplays Witnesses head-to-head against the Bitcoin miners.

| **Bitcoin Miners**                                                                                                                          | **Peerplays Witnesses**                                                                                                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| No selection process, anybody can be a miner.                                                                                               | Every Witness has to be voted in by the PPY token holders.                                                                                                                                       |
| Successful miner’s require a huge amount of computer processing power.                                                                      | Witnesses require computer processing power that is readily available and affordable.                                                                                                            |
| The block producing process is heavily biased towards mining pools.                                                                         | Every Witness has the same opportunity to create blocks.                                                                                                                                         |
| Block producing isn’t truly decentralized as over time the mining pools will control almost all the block production.                       | Truly decentralized because of the equal weight given to each witness for block production.                                                                                                      |
| Miner’s create one new block approximately every 10 minutes.                                                                                | Witnesses create one new block approximately every three seconds.                                                                                                                                |
| Miners are very well paid for each block they produce. But the probability of producing a block makes it cost prohibitive for many of them. | Witnesses receive much lower payment for each block, but all witnesses can create blocks equally, have a guaranteed income and the potential to create 1200 blocks or more an hour between them. |

### **Would you like to be a Witness?**

Your curiosity got you this far, but have you thought about taking the next step and becoming a Witness yourself?

Well if you have, there’s lots more resources available to you; we recommend starting here:

{% content-ref url="/pages/-Lsw4R0zjaoMtNcGKa3h" %}
[Becoming a Peerplays Witness](/witnesses/becoming-a-witness)
{% endcontent-ref %}


# Becoming a Peerplays Witness

{% hint style="info" %}
Note: You can find the installation instructions here <https://infra.peerplays.tech/witnesses/installation-guides>
{% endhint %}

Congratulations! You’ve taken the first step towards becoming a Peerplays Witness.

### **Can Anyone be a Peerplays Witness?**

Yes, anybody can become a Peerplays Witness and it can be rewarding professionally, personally and financially.

In this document we'll go through the first steps to becoming a Witness: your duties, node and server requirements, getting voted in and becoming a Bookie oracle.

### **The Duties of a Peerplays Witness**

The primary duty of Peerplays Witnesses is to bundle transactions into blocks and sign them with their signing key. Witnesses keep the blockchain alive by producing one block every three seconds. For example, if there are 20 Witnesses, each would produce one block every minute.

Other duties include:

* Operate a full node with enough bandwidth to support current network activities.&#x20;
* Operate a test version of the blockchain that functions as a public testing environment.
* Optionally operate an API seed node to support end user applications.
* Integrate, or reject, any changes to the blockchain software that are published.&#x20;
* Keep a block producing node running 24/7 every day of the year!

And one unique duty of a Peerplays Witness :

#### BookiePro & Bookie Oracle System (BOS)

BookiePro is the world’s first decentralized sports betting exchange application.&#x20;

For the application to function Peerplays Witnesses must also act as decentralized oracles, which means that the Witnesses are required to populate the Peerplays blockchain with real-world sporting data. For example, league and competition data, event data, betting market data for different sports, along with the final scores of each game. It requires consensus from a majority of Witnesses for any of this event data to be approved.&#x20;

This process is automated, but sometimes incident data from different sources doesn’t match and if no consensus can be made then it’s the duty of the Witnesses to manually intervene and make proposals to fix the data. Witnesses do this using the Manual Intervention Tool (MINT).

Smart contracts then use this data to grade and settle bets placed by users on BookiePro.

For more information on the Bookie Oracle System, and how to install it, go to:

{% embed url="<https://bos-auto.readthedocs.io/en/latest/>" %}

### Being a Peerplays Witness is a Paid Job

Blocks are produced every three seconds by Witnesses who take turns signing and validating the blockchain in variable rounds.

As a Peerplays Witnesses you are paid for this duty by the blockchain itself which releases new PPY tokens from the reserve pool, then issues them to the signing Witness after each block is validated.&#x20;

With 20 blocks being signed every minute this means 28,800 blocks a day, split evenly between the number of active Witnesses.&#x20;

As Peerplays Witness pay is dependant on the value of the PPY it can vary a lot. Not only is being a Peerplays Witness rewarding, but as the commitment and reliability of Witnesses has a direct impact on the value of the PPY, as a Peerplays Witness you'll play a role in setting your own 'salary'.

### How to Get Votes

As only active (block producing) Witnesses get paid it's very important to be voted in; to do this you must sell yourself to the PPY token holders. Every PPY token holder can vote for a Witness, multiple times if they want to, and only as a result of the number of votes cast will a Witness be promoted to an active, block producing, Witness. The votes are weighted according to the token holdings of each PPY token holder at the time of voting.

The Peerplays core wallet makes it easy for PPY token holders to vote for Witnesses. Anyone who holds PPY can do this by adding the name of the Witness to the voting tab. The wallet then sends the information about their votes directly to the Peerplays blockchain.

To sell yourself to the Witness voting community you'll need a web site and blog with information about how you intend to perform your duties as a Witness, and other ways in which you'll bring value to Peerplays. The best way to do this is by creating your own web page, publish the URL in as many places as possible, and make it simple to find.

A good place to start would be by checking out the web pages for existing witnesses, you can find that information here:

{% embed url="<https://market.peerplays.com/blockchain/witnesses>" %}

Be very active on social media, especially target Peerplays and Peerplays Witness channels on Telegram and Discord. Qualities that voters are going to be looking for include, experience, knowledge, commitment, responsibility and community participation.

Some useful links:

Peerplays official Rocket Chat and Telegram channels for Witnesses:

{% embed url="<https://chat.peerplays.live/channel/witness-info>" %}

{% embed url="<https://t.me/PeerplaysWitness>" %}

### **Getting started**

We've already talked about the personal qualities a Witness needs to have, and the duties they're expected to perform, now we need to talk about nodes and hardware requirements.

#### **Nodes**

All nodes keep updating an internal database by applying the transactions as they arrive in incoming blocks. The difference between the node types lies in the amount of history they keep track of, and in the functionality they provide.

A **Witness node,** as the name implies, is a node run by a Witness. Each Witness node validates all blocks and transactions it receives. The nodes of elected Witnesses take turns in bundling new transactions into blocks and broadcasting them to the network.

**API nodes** (nodes with an open RPC port) provide network services to client applications. They usually have account transaction histories accessible through API calls, but can vary in the amount of available history.&#x20;

**Full nodes** are API nodes with a complete transaction history of all accounts.

**Seed nodes** are nodes that accept incoming P2P connections. They are the first nodes contacted by a freshly started node; the entry point into the network. Once a node has entered the network it will receive additional node addresses from its peers, so all nodes can connect to each other. A seed node can also be an API node. Seed nodes are not mandatory, but highly recommended.

**BOS nodes** are required to operate the Bookie Oracle System and ensure the accuracy and decentralization of the data fed into the BookiePro application. The BOS node must be run on a separate server to the Witness node.

Every Witness is required to run nodes on both Public Mainnet and Public Testnet environments.

So the minimum node requirements are a Witness node and BOS node for both Testnet and Mainnet. If you also run a Seed Node and API Node then the number of required servers could be as many as eight.

#### **System Requirements**

Unlike mining Bitcoin, or other POW based blockchains, the processing power at your disposal has no influence on how many blocks you'll produce, and consequently how much you'll be paid as a Witness.

However, there are requirements in terms of what hardware and software you should be running.

{% hint style="danger" %}
Important: The following table shows the minimum requirements for each server.&#x20;
{% endhint %}

| CPU     | Memory | Storage   | Bandwidth | OS           |
| ------- | ------ | --------- | --------- | ------------ |
| 8 Cores | 8GB    | 300GB SSD | 1Gbps     | Ubuntu 18.04 |

These requirements are as of the time of writing, so consider deploying a server with specs slightly higher than the ones listed above in order to "future proof" your server in case the minimum requirements grow in the future.

Once you've procured your servers then it's time to set them up.

You're now ready to take the next step, setting up your own Witness node.

{% embed url="<https://infra.peerplays.com/witnesses/installation-guides>" %}


# RNG Technical Summary

## Introduction <a href="#randomnumbergenerationonpeerplays-howitsdone-howisrnggenerated" id="randomnumbergenerationonpeerplays-howitsdone-howisrnggenerated"></a>

The Peerplays blockchain RNG was initially added to the blockchain to provide draw features for the Easy5050 decentralized application (DApp).&#x20;

The first release of the RNG was localized to the Easy5050 DApp and wasn't exposing the number generated via an API, or a similar mechanism, such that other DApps or users could consume them.&#x20;

For the second release of the RNG the functionality was extended to become a general RNG, with a public API, for supporting games such as Slots, Poker, Roulette, Raffle, Bingo, Keno, etc.

## How the Random Numbers are Generated <a href="#randomnumbergenerationonpeerplays-howitsdone-howisrnggenerated" id="randomnumbergenerationonpeerplays-howitsdone-howisrnggenerated"></a>

Random numbers are generated from secret hashes taken from the previous and current block, which are then combined into a single data stream and encoded using the  `ripemd160` algorithm, and finally fed into a random number generator as a seed.

{% hint style="info" %}
For more information on the `ripemd160` algorithm see:

<https://en.wikipedia.org/wiki/RIPEMD>
{% endhint %}

### **Block-Hash Randomness**

In this approach, the hash of blocks or transactions is used as the source of randomness. As the hash is deterministic, everyone will get the same result. A block, once added to the blockchain, is likely to stay there forever, therefore everyone can verify the correctness of the generated numbers.

Consider an example of a lottery service that adopts this method. The players first buy a ticket by placing their number before a specific time, say 7PM everyday. After 8PM, the buying ticket phase is closed, the protocol proceeds to the next phase which is to determine the winning numbers for a ticket. This ticket is calculated based on the hash of the first block accessible for everyone on the blockchain after 8PM.&#x20;

As we can see, at 7PM, no one can predict the hash of block at 8PM which makes the service seemingly a sound one. However, this hash is subject to manipulation by the block-signers of the blockchain. When the reward of the lottery is small, the block-signers have little motivation to tamper with the block, but as soon as this amount is larger than the block reward plus the transaction fees, there is a chance that witnesses will start influencing the block-hash to generate their desired numbers.&#x20;

So on it's own a block-hash level of randomness is not enough. This is why the Peerplays RNG extends the block-hash mechanism by using the hash as a seed for randomization along with the `repemd160` algorithm and Secure Hash Algorithm (SHA).

### Distributed Ledger Technology (DLT)

Peerplays, and other blockchains, are one type of a distributed ledger. Distributed ledgers use independent computers (referred to as nodes) to record, share and synchronize transactions in their respective electronic ledgers (instead of keeping data centralized as in a traditional ledger).&#x20;

The immutability of DLT is critical for the RNG because it ensures that once a random number is generated it is authentic and can't be changed.

### Witness Randomness

Peerplays is based on the Delegated Proof of Stake (DPOS) consensus mechanism, which means that the block signers (Witnesses) are all elected by the token holders. This is important from an RNG perspective because it requires loyalty, commitment and honesty to get voted in as a Witness. Since a component of the randomness is based on the block hash, knowing that the block signers are a trusted, elected, group greatly mitigates the risk of block tampering.

Peerplays further extends the block-signing robustness and randomness because:

1. Not all Witnesses are block-signing (active) Witnesses. There is a second level of consensus that has to happen before a Witness is promoted to an active Witness.
2. Not all active Witnesses are signing blocks at any given time. The blockchain randomly selects which Witnesses are signing at ten minute intervals.

Because of the role of the Witnesses, Peerplays has two levels of randomness. First the Witnesses themselves are randomly selected, and secondly the randomness of the number generation itself.&#x20;

## Testing

For testing the RNG, the “Dieharder” random number generator testing suite was used.

Dieharder is intended to test generators, not files of possibly random numbers as the latter is based on the mistaken view of what it means to be random. Perfect random number generators produce "unlikely" sequences of random numbers -- at exactly the right average rate. Testing an RNG is therefore quite subtle.

Dieharder is a tool designed to push a weak generator to unambiguous failure.

{% hint style="info" %}
For more information on Dieharder see:

<https://webhome.phy.duke.edu/~rgb/General/dieharder.php>
{% endhint %}

### Install prerequisites for running RNG tests

```
sudo apt install dieharder
```

### To run RNG test suite, use the following command: <a href="#randomnumbergenerationonpeerplays-howitsdone-torunrngtestsuite-usethefollowingcommand" id="randomnumbergenerationonpeerplays-howitsdone-torunrngtestsuite-usethefollowingcommand"></a>

```
$ ./tests/random_test 
```

## Gaming Laboratories International (GLI)

GLI are an internationally recognized institute offering the the most experienced and robust RNG testing methodologies in the world. This includes software-based (pseudo-algorithmic) RNG’s, hardware RNG’s, and hybrid combinations of both.

The Peerplays RNG has been submitted to GLI for approval \[TBD: or has 'been approved']

GLI generally performs the testing of applications and games, such as Keno, as opposed to an API. The game testing will automatically include the backend API as well. On successful completion of all tests each application will be certified by GLI.

For each new game, different testing will be required. An example would be the Easy5050 DApp that can be tested and with all subsequent releases, tested again.

However, as the core Peerplays RNG is a blockchain (back-end) implementation and not an application it can only be approved by GLI rather than certified.

## API

The RNG has a very simple API for generating random numbers,  requiring just a single API call to `get_random_bits(bound)` ; supplying an upper bound.

```cpp
get_random_bits(uint64_t bound) 
```

For more information on the API see:

{% content-ref url="/pages/-M-jgEbQrKBh0thEAYRM" %}
[RNG API](/random-number-generator-rng/api)
{% endcontent-ref %}


# RNG API

Get a random number

```cpp
Function uint64_t database::get_random_bits(uint64_t bound) 
```

{% tabs %}
{% tab title="Parameters" %}
**`bound`**`:` The upper limit for the random number.
{% endtab %}

{% tab title="Returns" %}
A random number within the `bound` range.
{% endtab %}
{% endtabs %}

### TypeDefs

```cpp
peerplays/libraries/chain/include/graphene/chain/protocol/types.hpp
typedef fc::ripemd160 secret_hash_type;


peerplays/libraries/fc/include/fc/crypto/hash_ctr_rng.hpp
template<class HashClass, int SeedLength>

class hash_ctr_rng
{...}
```

### Declaration

```cpp
peerplays/libraries/chain/include/graphene/chain/database.hpp 

fc::hash_ctr_rng<secret_hash_type, 20> _random_number_generator;
```

### Examples

#### Initialization in constructor

```cpp
peerplays/libraries/chain/db_management.cpp

_random_number_generator(fc::ripemd160().data())
```

#### Updating seed on a new block

```cpp
peerplays/libraries/chain/db_update.cpp

modify( _dgp, [&]( dynamic_global_property_object& dgp ){
      secret_hash_type::encoder enc;       
      fc::raw::pack( enc, dgp.random );       
      fc::raw::pack( enc, b.previous_secret );        
      dgp.random = enc.result();
      _random_number_generator = fc::hash_ctr_rng<secret_hash_type, 20>(dgp.random.data());
```

#### Getting a new random number

```cpp
peerplays/libraries/chain/db_update.cpp

uint64_t database::get_random_bits( uint64_t bound )
{
   return _random_number_generator(bound);
}

peerplays/libraries/fc/include/fc/crypto/hash_ctr_rng.hpp

      uint64_t operator()( uint64_t bound )
      {
         if( bound <= 1 )
            return 0;
         uint8_t bitcount = boost::multiprecision::detail::find_msb( bound ) + 1;
         // probability of loop exiting is >= 1/2, so probability of
         // running N times is bounded above by (1/2)^N
         while( true )
         {
            uint64_t result = get_bits( bitcount );
            if( result < bound )
               return result;
         }
      }
```


# Peerplays Core API

{% content-ref url="/pages/-Ly6hpLXJnCnIup09zPi" %}
[Popular API Calls](/api/peerplays-core-api/popular-api-calls)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvMucrfblLF0qP9\_TK" %}
[Account History API](/api/peerplays-core-api/account-history-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvN3dTNcYlFmZtBDwf" %}
[Asset API](/api/peerplays-core-api/asset-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvN04DLLqd3iLr65Fi" %}
[Block API](/api/peerplays-core-api/block-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvNBP9EC8\_uEEY4HC4" %}
[Crypto API](/api/peerplays-core-api/crypto-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvMoT433sxUtdPDVXx" %}
[Database API](/api/peerplays-core-api/database-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvVuWknmOtKM1sWY56" %}
[Network Broadcast API](/api/peerplays-core-api/network-broadcast-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvW1OQd85D2-ptGdcA" %}
[Network Nodes API](/api/peerplays-core-api/network-nodes-api)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvN6hvoZTBVGcNJHJQ" %}
[Orders API](/api/peerplays-core-api/orders-api)
{% endcontent-ref %}


# Popular API Calls

## Overview

Some of the most interesting API calls for exchanges and gateways are listed in this document.&#x20;

We will now take a look at some sample outputs for some of the API calls.

## API Calls

### list\_account\_balances

List the balances of an account. Each account can have multiple balances, one for each type of asset owned by that account. The returned list will only contain assets for which the account has a nonzero balance.

```cpp
vector<asset> graphene::wallet::wallet_api::list_account_balances(
    const string &id)
```

{% tabs %}
{% tab title="Parameters" %}

* **`id`**: the name or id of the account whose balances you want
  {% endtab %}

{% tab title="Return" %}
A list of the given account’s balances.
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.list_account_balances("dan")
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
[
    {
        "asset_id": "1.3.0",
        "amount": "331104701530"
    },
    {
        "asset_id": "1.3.511",
        "amount": 3844848635
    },
    {
        "asset_id": "1.3.427",
        "amount": 8638
    },
    {
        "asset_id": "1.3.536",
        "amount": 31957981
    }
]
```

{% endtab %}
{% endtabs %}

### transfer

Transfer an amount from one account to another.

```cpp
signed_transaction graphene::wallet::wallet_api::transfer(
    string from, 
    string to, 
    string amount, 
    string asset_symbol, 
    string memo, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the name or id of the account sending the funds
* **`to`**: the name or id of the account receiving the funds
* **`amount`**: the amount to send (in nominal units to send half of a BTS, specify 0.5)
* **`asset_symbol`**: the symbol or id of the asset to send
* **`memo`**: a memo to attach to the transaction. The memo will be encrypted in the transaction and readable for the receiver. There is no length limit other than the limit imposed by maximum transaction size, but transaction increase with transaction size
* **`broadcast`**: true to broadcast the transaction on the network

The final parameter *True* states that the signed transaction will be broadcast. If this parameter is *False* the transaction will be signed but not broadcast, hence not executed.
{% endtab %}

{% tab title="Return" %}
The signed transaction transferring funds.
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.transfer("fromaccount","toaccount","10", "USD", "$10 gift", True);
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
{
  "ref_block_num": 18,
  "ref_block_prefix": 2320098938,
  "expiration": "2015-10-13T13:56:15",
  "operations": [[
      0,{
        "fee": {
          "amount": 2089843,
          "asset_id": "1.3.0"
        },
        "from": "1.2.17",
        "to": "1.2.7",
        "amount": {
          "amount": 10000000,
          "asset_id": "1.3.0"
        },
        "memo": {
          "from": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
          "to": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
          "nonce": "16430576185191232340",
          "message": "74d0e455e2e5587b7dc85380102c3291"
        },
        "extensions": []
      }
    ]
  ],
  "extensions": [],
  "signatures": [
    "1f147aed197a2925038e4821da54bd7818472ebe25257ac9a7ea66429494e7242d0dc13c55c6840614e6da6a5bf65ae609a436d13a3174fd12f073550f51c8e565"
  ]
}
```

{% endtab %}
{% endtabs %}

### transfer2

This method works just like transfer, except it always broadcasts and returns the transaction ID (hash) along with the signed transaction.

```cpp
pair<transaction_id_type, signed_transaction> graphene::wallet::wallet_api::transfer2(
    string from, 
    string to, 
    string amount, 
    string asset_symbol, 
    string memo)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the name or id of the account sending the funds
* **`to`**: the name or id of the account receiving the funds
* **`amount`**: the amount to send
* **`asset_symbol`**: the symbol or id of the asset to send
* **`memo`**: a memo to attach to the transaction. The memo will be encrypted in the transaction and readable for the receiver. There is no length limit other than the limit imposed by maximum transaction size, but transaction increase with transaction size
  {% endtab %}

{% tab title="Return" %}
The transaction ID (hash) along with the signed transaction transferring funds
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.transfer2("fromaccount","toaccount","10", "USD", "$10 gift");
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
 [b546a75a891b5c51de6d1aafd40d10e91a717bb3,{
   "ref_block_num": 18,
   "ref_block_prefix": 2320098938,
   "expiration": "2015-10-13T13:56:15",
   "operations": [[
       0,{
         "fee": {
           "amount": 2089843,
           "asset_id": "1.3.0"
         },
         "from": "1.2.17",
         "to": "1.2.7",
         "amount": {
           "amount": 10000000,
           "asset_id": "1.3.0"
         },
         "memo": {
           "from": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
           "to": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
           "nonce": "16430576185191232340",
           "message": "74d0e455e2e5587b7dc85380102c3291"
         },
         "extensions": []
       }
     ]
   ],
   "extensions": [],
   "signatures": [
     "1f147aed197a2925038e4821da54bd7818472ebe25257ac9a7ea66429494e7242d0dc13c55c6840614e6da6a5bf65ae609a436d13a3174fd12f073550f51c8e565"
   ]
 }
]
```

{% endtab %}
{% endtabs %}

### get\_account\_history

Returns the most recent operations on the named account.

This returns a list of operation history objects, which describe activity on the account.

```cpp
vector<operation_detail> graphene::wallet::wallet_api::get_account_history(
    string name, 
    int limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`name`**: the name or id of the account
* **`limit`**: the number of entries to return (starting from the most recent)
  {% endtab %}

{% tab title="Return" %}
A list of `operation_history_objects.`
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.get_account_history("dan", 1)
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
[
     {
         "description": "fill_order_operation dan fee: 0 CORE",
         "op": {
             "block_num": 28672,
             "op": [
                 4,
                 {
                     "pays": {
                         "asset_id": "1.3.536",
                         "amount": 20000
                     },
                     "fee": {
                         "asset_id": "1.3.0",
                         "amount": 0
                     },
                     "order_id": "1.7.1459",
                     "account_id": "1.2.21532",
                     "receives": {
                         "asset_id": "1.3.0",
                         "amount": 50000000
                     }
                 }
             ],
             "id": "1.11.213277",
             "trx_in_block": 0,
             "virtual_op": 47888,
             "op_in_trx": 0,
             "result": [
                 0,
                 {}
             ]
         },
         "memo": ""
     }
 ]
```

{% endtab %}
{% endtabs %}

### get\_object

Returns the blockchain object corresponding to the given id.

This generic function can be used to retrieve any object from the blockchain that is assigned an ID. Certain types of objects have specialized convenience functions to return their objects e.g., assets have [`get_asset()`](/api/peerplays-core-api/asset-api), accounts have [`get_account()`](https://dev.bitshares.works/en/master/api/wallet_api.html#classgraphene_1_1wallet_1_1wallet__api_1ae4133a2fe8f63695385c20d327a88ff9), but this function will work for any object.

```cpp
variant graphene::wallet::wallet_api::get_object(
    object_id_type id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`id`**: the id of the object to return
  {% endtab %}

{% tab title="Return" %}
The requested object.
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.get_object("1.11.213277")
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
{
    "trx_in_block": 0,
    "id": "1.11.213277",
    "block_num": 28672,
    "op": [
        4,
        {
            "fee": {
                "asset_id": "1.3.0",
                "amount": 0
            },
            "receives": {
                "asset_id": "1.3.0",
                "amount": 50000000
            },
            "pays": {
                "asset_id": "1.3.536",
                "amount": 20000
            },
            "account_id": "1.2.21532",
            "order_id": "1.7.1459"
        }
    ],
    "result": [
        0,
        {}
    ],
    "op_in_trx": 0,
    "virtual_op": 47888
}
```

{% endtab %}
{% endtabs %}

### get\_asset

Returns information about the given asset.

```cpp
extended_asset_object graphene::wallet::wallet_api::get_asset(
    string asset_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`asset_name_or_id`**: the symbol or id of the asset in question
  {% endtab %}

{% tab title="Return" %}
**T**he information about the asset stored in the block chain.
{% endtab %}

{% tab title="Script" %}

```javascript
import json
from grapheneapi import GrapheneAPI
client = GrapheneAPI("localhost", 8092, "", "")
res = client.get_asset("USD")
print(json.dumps(res,indent=4))
```

{% endtab %}

{% tab title="Result" %}

```javascript
{
    "symbol": "USD",
    "issuer": "1.2.1",
    "options": {
        "description": "1 United States dollar",
        "whitelist_authorities": [],
        "flags": 0,
        "extensions": [],
        "core_exchange_rate": {
            "quote": {
                "asset_id": "1.3.536",
                "amount": 11
            },
            "base": {
                "asset_id": "1.3.0",
                "amount": 22428
            }
        },
        "whitelist_markets": [],
        "max_supply": "1000000000000000",
        "blacklist_markets": [],
        "issuer_permissions": 79,
        "market_fee_percent": 0,
        "max_market_fee": "1000000000000000",
        "blacklist_authorities": []
    },
    "dynamic_asset_data_id": "2.3.536",
    "bitasset_data_id": "2.4.32",
    "id": "1.3.536",
    "precision": 4
}
```

{% endtab %}
{% endtabs %}


# Account History API

The history API is available from the full node via websockets.

## Account History

### get\_account\_history

Get operations relevant to the specified account.

```cpp
vector<operation_history_object> graphene::app::history_api::get_account_history(
    const std::string account_id_or_name, 
    operation_history_id_type stop = operation_history_id_type(), 
    unsigned limit = 100, 
    operation_history_id_type start = operation_history_id_type())const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_id_or_name`**: The account ID or name whose history should be queried
* **`stop`**: ID of the earliest operation to retrieve
* **`limit`**: Maximum number of operations to retrieve (must not exceed 100)
* **`start`**: ID of the most recent operation to retrieve
  {% endtab %}

{% tab title="Return" %}
A list of operations performed by account, ordered from most recent to oldest.
{% endtab %}
{% endtabs %}

### get\_account\_history\_operations

Get only asked operations relevant to the specified account.

```cpp
vector<operation_history_object> graphene::app::history_api::get_account_history_operations(
    const std::string account_id_or_name, 
    int operation_type, 
    operation_history_id_type start = operation_history_id_type(), 
    operation_history_id_type stop = operation_history_id_type(), 
    unsigned limit = 100)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_id_or_name`**: The account ID or name whose history should be queried
* **`operation_type`**: The type of the operation we want to get operations in the account ( 0 = transfer , 1 = limit order create, …)
* **`stop`**: ID of the earliest operation to retrieve
* **`limit`**: Maximum number of operations to retrieve (must not exceed 100)
* **`start`**: ID of the most recent operation to retrieve
  {% endtab %}

{% tab title="Return" %}
A list of operations performed by account, ordered from most recent to oldest.
{% endtab %}
{% endtabs %}

### get\_relative\_account\_history

Get operations relevant to the specified account referenced by an event numbering specific to the account. The current number of operations for the account can be found in the account statistics (or use 0 for start).

```cpp
vector<operation_history_object> graphene::app::history_api::get_relative_account_history(
    const std::string account_id_or_name, 
    uint64_t stop = 0, 
    unsigned limit = 100, 
    uint64_t start = 0)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_id_or_name`**: The account ID or name whose history should be queried
* **`stop`**: Sequence number of earliest operation. 0 is default and will query ‘limit’ number of operations.
* **`limit`**: Maximum number of operations to retrieve (must not exceed 100)
* **`start`**: Sequence number of the most recent operation to retrieve. 0 is default, which will start querying from the most recent operation.
  {% endtab %}

{% tab title="Return" %}
A list of operations performed by account, ordered from most recent to oldest.
{% endtab %}
{% endtabs %}

## Market History

### get\_fill\_order\_history

Get details of order executions occurred most recently in a trading pair.

```cpp
vector<order_history_object> graphene::app::history_api::get_fill_order_history(
    std::string a, 
    std::string b, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: Asset symbol or ID in a trading pair
* **`b`**: The other asset symbol or ID in the trading pair
* **`limit`**: Maximum records to return
  {% endtab %}

{% tab title="Return" %}
a list of order\_history objects, in most recent first order
{% endtab %}
{% endtabs %}

### get\_market\_history

Get OHLCV data of a trading pair in a time range.

```cpp
vector<bucket_object> graphene::app::history_api::get_market_history(
    std::string a, 
    std::string b, 
    uint32_t bucket_seconds, 
    fc::time_point_sec start, 
    fc::time_point_sec end)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: Asset symbol or ID in a trading pair
* **`b`**: The other asset symbol or ID in the trading pair
* **`bucket_seconds`**: Length of each time bucket in seconds.&#x20;

{% hint style="warning" %}
**Note**: It needs to be within result of  [get\_market\_history\_buckets()](/api/peerplays-core-api/account-history-api#get_market_history_buckets), otherwise no data will be returned
{% endhint %}

* **`start`**: The start of a time range, E.G. “2018-01-01T00:00:00”
* **`end`**: The end of the time range
  {% endtab %}

{% tab title="Return" %}
A list of OHLCV data, in least recent first order.&#x20;

If there are more than 200 records in the specified time range, the first 200 records will be returned.
{% endtab %}
{% endtabs %}

### get\_market\_history\_buckets

Get OHLCV time bucket lengths supported (configured) by this API server.

```cpp
flat_set<uint32_t> graphene::app::history_api::get_market_history_buckets()const
```

{% tabs %}
{% tab title="Return" %}
A list of time bucket lengths in seconds.&#x20;

For example, if the result contains a number “300” it means this API server supports OHLCV data aggregated in 5-minute buckets.
{% endtab %}
{% endtabs %}


# Asset API

## Asset

### get\_asset\_holders

Get asset holders for a specific asset.

```cpp
vector<account_asset_balance> graphene::app::asset_api::get_asset_holders(
    std::string asset, 
    uint32_t start, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`asset`**: The specific asset id or symbol
* **`start`**: The start index
* **`limit`**: Maximum limit must not exceed 100
  {% endtab %}

{% tab title="Return" %}
A list of asset holders for the specified asset.
{% endtab %}
{% endtabs %}

### get\_all\_asset\_holders

Get all asset holders.

```cpp
vector<asset_holders> graphene::app::asset_api::get_all_asset_holders()const
```

{% tabs %}
{% tab title="Return" %}
A list of all asset holders.
{% endtab %}
{% endtabs %}


# Block API

## Block

### get\_blocks

Get signed blocks.

```cpp
vector<optional<signed_block>> graphene::app::block_api::get_blocks(
    uint32_t block_num_from, 
    uint32_t block_num_to)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`block_num_from`**: The lowest block number
* **`block_num_to`**: The highest block number
  {% endtab %}

{% tab title="Return" %}
A list of signed blocks from `block_num_from` to `block_num_to`
{% endtab %}
{% endtabs %}


# Crypto API

The crypto API is available from the full node via websockets.

## Blinding and Un-Blinding

### blind

Get signed blocks.

Generates a Pedersen Commitment: \*commit = blind \* G + value \* G2. The commitment is 33 bytes, the blinding factor is 32 bytes.&#x20;

{% hint style="info" %}
**Tip**: For more information about Pedersen Commitment see: [Commitment Scheme](https://en.wikipedia.org/wiki/Commitment_scheme)
{% endhint %}

```cpp
commitment_type graphene::app::crypto_api::blind(
    const fc::ecc::blind_factor_type &blind, 
    uint64_t value)
```

{% tabs %}
{% tab title="Parameters" %}

* **`blind`**: Sha-256 blind factor type
* **`value`**: Positive 64-bit integer value
  {% endtab %}

{% tab title="Return" %}
A 33-byte Pedersen Commitment: *commit = blind* G + value \* G2
{% endtab %}
{% endtabs %}

### blind\_sum

Get SHA-256 blind factor type.

```cpp
blind_factor_type graphene::app::crypto_api::blind_sum(
    const std::vector<blind_factor_type> &blinds_in, 
    uint32_t non_neg)
```

{% tabs %}
{% tab title="Parameters" %}

* **`blinds_in`**: List of SHA-256 blind factor types
* **`non_neg`**: 32-bit integer value
  {% endtab %}

{% tab title="Return" %}
A blind factor type.
{% endtab %}
{% endtabs %}

## Range Proofs

### range\_get\_info

Gets “range proof” information.&#x20;

The cli\_wallet includes functionality for sending blind transfers in which the values of the input and output amounts are “blinded.”&#x20;

{% hint style="warning" %}
**Note**: In the case where a transaction produces two or more outputs, (e.g. an amount to the intended recipient plus “charge” back to the sender), a “range proof” must be supplied to prove that none of the outputs commit to a negative value.
{% endhint %}

```cpp
range_proof_info graphene::app::crypto_api::range_get_info(
    const std::vector<char> &proof)
```

{% tabs %}
{% tab title="Parameters" %}
**`proof`**: List of proof’s characters
{% endtab %}

{% tab title="Return" %}
A range proof info structure with exponent, mantissa, min and max values.
{% endtab %}
{% endtabs %}

### range\_proof\_sign

Proves with respect to min\_value the range for Pedersen Commitment which has the provided blinding factor and value.

```cpp
std::vector<char> graphene::app::crypto_api::range_proof_sign(
    uint64_t min_value, 
    const commitment_type &commit, 
    const blind_factor_type &commit_blind, 
    const blind_factor_type &nonce, 
    int8_t base10_exp, 
    uint8_t min_bits, 
    uint64_t actual_value
```

{% tabs %}
{% tab title="Parameters" %}

* **`min_value`**: Positive 64-bit integer value
* **`commit`**: 33-byte pedersen commitment
* **`commit_blind`**: Sha-256 blind factor type for the correct digits
* **`nonce`**: Sha-256 blind factor type for our non-forged signatures
* **`base10_exp`**: Exponents base 10 in range \[-1 ; 18] inclusively
* **`min_bits`**: 8-bit positive integer, must be in range \[0 ; 64] inclusively
* **`actual_value`**: 64-bit positive integer, must be greater or equal min\_value
  {% endtab %}

{% tab title="Return" %}
A list of characters as proof in proof.
{% endtab %}
{% endtabs %}

## Verification

### verify\_sum

Verifies that `commits` + `neg_commits` + `excess` == 0.

```cpp
bool graphene::app::crypto_api::verify_sum(
    const std::vector<commitment_type> &commits_in, 
    const std::vector<commitment_type> &neg_commits_in, 
    int64_t excess)
```

{% tabs %}
{% tab title="Parameters" %}

* **`commits_in`**: List of 33-byte Pedersen Commitments
* **`neg_commits_in`**: List of 33-byte Pedersen Commitments
* **`excess`**: Sum of two list of 33-byte Pedersen Commitments where sums the first set and subtracts the second
  {% endtab %}

{% tab title="Return" %}
(Boolean) True in event of `commits` + `neg_commits` + `excess` == 0, otherwise false
{% endtab %}
{% endtabs %}

### verify\_range

Verifies range proof for 33-byte Pedersen Commitment.

```cpp
verify_range_result graphene::app::crypto_api::verify_range(
    const fc::ecc::commitment_type &commit, 
    const std::vector<char> &proof)
```

{% tabs %}
{% tab title="Parameters" %}

* **`commit`**: 33-byte pedersen commitment
* **`proof`**: List of characters
  {% endtab %}

{% tab title="Return" %}
A structure with success, min and max values
{% endtab %}
{% endtabs %}

### verify\_range\_proof\_rewind

Verifies range proof rewind for 33-byte Pedersen Commitment.

```cpp
verify_range_proof_rewind_result graphene::app::crypto_api::verify_range_proof_rewind(
    const blind_factor_type &nonce, 
    const fc::ecc::commitment_type &commit, 
    const std::vector<char> &proof)
```

{% tabs %}
{% tab title="Parameters" %}

* **`nonce`**: Sha-256 blind refactor type
* **`commit`**: 33-byte pedersen commitment
* **`proof`**: List of characters
  {% endtab %}

{% tab title="Return" %}
A structure with success, min, max, value\_out, blind\_out and message\_out values.
{% endtab %}
{% endtabs %}


# Database API

The database API is available from the full node via web-sockets.

## Objects

### get\_objects

Get the objects corresponding to the provided IDs.

If any of the provided IDs does not map to an object, a null variant is returned in its position.

```cpp
fc::variants graphene::app::database_api::get_objects(
    const vector<object_id_type> &ids, 
    optional<bool> subscribe = optional<bool>())const
```

{% tabs %}
{% tab title="Parameters" %}

* **`ids`**: IDs of the objects to retrieve
* **`subscribe`**: *true* to subscribe to the queried objects; *false* to not subscribe; *null* to subscribe or not subscribe according to current auto-subscription setting (see [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c))
  {% endtab %}

{% tab title="Return" %}
The objects retrieved, in the order they are mentioned in ids.
{% endtab %}
{% endtabs %}

## Subscriptions

### set\_subscribe\_callback

Register a callback handle which then can be used to subscribe to object database changes.

{% hint style="warning" %}
**Note**: auto-subscription is enabled by default and can be disabled with [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c)&#x20;
{% endhint %}

```cpp
void graphene::app::database_api::set_subscribe_callback(
    std::function<void(const variant&)> cb, 
    bool notify_remove_create, )
```

{% tabs %}
{% tab title="Parameters" %}

* **`cb`**: The callback handle to register
* **`notify_remove_create`**: Whether subscribe to universal object creation and removal events. If this is set to true, the API server will notify all newly created objects and ID of all newly removed objects to the client, no matter whether client subscribed to the objects. By default, API servers don’t allow subscribing to universal events, which can be changed on server startup.
  {% endtab %}
  {% endtabs %}

### set\_pending\_transaction\_callback

Register a callback handle which will get notified when a transaction is pushed to database.

{% hint style="warning" %}
**Note**: A transaction can be pushed to the database and be popped from the database several times while processing, before and after,, included in a block. Every time a push is done, the client will be notified.
{% endhint %}

```cpp
void graphene::app::database_api::set_pending_transaction_callback(
    std::function<void(const variant &signed_transaction_object)> cb)
```

{% tabs %}
{% tab title="Parameters" %}

* **`cb`**: The callback handle to register
  {% endtab %}
  {% endtabs %}

### set\_block\_applied\_callback

Register a callback handle which will get notified when a block is pushed to database.

```cpp
void graphene::app::database_api::set_block_applied_callback(
    std::function<void(const variant &block_id)> cb)
```

{% tabs %}
{% tab title="Parameters" %}

* **`cb`**: The callback handle to register
  {% endtab %}
  {% endtabs %}

### cancel\_all\_subscriptions

Stop receiving any notifications.

This unsubscribes from all subscribed markets and objects.

```cpp
void graphene::app::database_api::cancel_all_subscriptions()
```

## Blocks and transactions

### get\_block\_header

Retrieve a block header.

```cpp
optional<block_header> graphene::app::database_api::get_block_header(
    uint32_t block_num)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`block_num`**: Height of the block whose header should be returned
  {% endtab %}

{% tab title="Return" %}

* The header of the referenced block, or null if no matching block was foun
  {% endtab %}
  {% endtabs %}

### get\_block

Retrieve a full, signed block.

```cpp
optional<signed_block> graphene::app::database_api::get_block(
    uint32_t block_num)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`block_num`**: Height of the block to be returned
  {% endtab %}

{% tab title="Return" %}
The referenced block, or null if no matching block was found.
{% endtab %}
{% endtabs %}

### get\_transaction

Fetch an individual transaction.

```cpp
processed_transaction graphene::app::database_api::get_transaction(
    uint32_t block_num, uint32_t trx_in_block)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`block_num`**: height of the block to fetch
* **`trx_in_block`**: the index (sequence number) of the transaction in the block, starts from 0
  {% endtab %}

{% tab title="Return" %}
The transaction at the given position.
{% endtab %}
{% endtabs %}

### get\_recent\_transaction\_by\_id

```cpp
optional<signed_transaction> graphene::app::database_api::get_recent_transaction_by_id(
    const transaction_id_type &txid)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`txid`**: hash of the transaction
  {% endtab %}

{% tab title="Return" %}
The corresponding transaction if found, or null if not found.
{% endtab %}
{% endtabs %}

If the transaction has not expired, this method will return the transaction for the given ID or it will return NULL if it is not known. Just because it is not known does not mean it wasn’t included in the blockchain.

## Globals

### get\_chain\_properties

Retrieve the [graphene::chain::chain\_property\_object](https://dev.bitshares.works/en/master/api/namespaces/chain.html#classgraphene_1_1chain_1_1chain__property__object) associated with the chain.

```cpp
chain_property_object graphene::app::database_api::get_chain_properties()const
```

### get\_global\_properties

Retrieve the current [graphene::chain::global\_property\_object](https://dev.bitshares.works/en/master/api/namespaces/chain.html#classgraphene_1_1chain_1_1global__property__object).

```cpp
global_property_object graphene::app::database_api::get_global_properties()const
```

### get\_config

Retrieve compile-time constants.

```cpp
fc::variant_object graphene::app::database_api::get_config()const
```

### get\_chain\_id

Get the chain ID.

```cpp
chain_id_type graphene::app::database_api::get_chain_id()cons
```

### get\_dynamic\_global\_properties

Retrieve the current [graphene::chain::dynamic\_global\_property\_object](https://dev.bitshares.works/en/master/api/namespaces/chain.html#classgraphene_1_1chain_1_1dynamic__global__property__object).

```cpp
dynamic_global_property_object graphene::app::database_api::get_dynamic_global_properties()const
```

## Keys

### get\_key\_references

Get all accounts that refer to the specified public keys in their owner authority, active authorities or memo key.

```cpp
vector<flat_set<account_id_type>> graphene::app::database_api::get_key_references(
    vector<public_key_type> keys)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`keys`**: a list of public keys to query
  {% endtab %}

{% tab title="Return" %}
ID of all accounts that refer to the specified keys.
{% endtab %}
{% endtabs %}

## Accounts

### get\_accounts

Get a list of accounts by names or IDs.

This function has semantics identical to[get\_objects](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a1f20e51d290fc3ac2409c49c058585b3)

```cpp
vector<optional<account_object>> graphene::app::database_api::get_accounts(
    const vector<std::string> &account_names_or_ids, 
    optional<bool> subscribe = optional<bool>())const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_names_or_ids`**: names or IDs of the accounts to retrieve
* **`subscribe`**: *true* to subscribe to the queried account objects; *false* to not subscribe; *null* to subscribe or not subscribe according to current auto-subscription setting (see [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c))
  {% endtab %}

{% tab title="Return" %}
The accounts corresponding to the provided names or IDs.
{% endtab %}
{% endtabs %}

### get\_full\_accounts

Fetch all objects relevant to the specified accounts and optionally subscribe to updates.

This function fetches all relevant objects for the given accounts, and subscribes to updates to the given accounts. If any of the strings in`names_or_ids` cannot be tied to an account, that input will be ignored. All other accounts will be retrieved and subscribed.

```cpp
std::map<string, full_account> graphene::app::database_api::get_full_accounts(
    const vector<string> &names_or_ids, 
    optional<bool> subscribe = optional<bool>())
```

{% tabs %}
{% tab title="Parameters" %}

* **`names_or_ids`**: Each item must be the name or ID of an account to retrieve
* **`subscribe`**: *true* to subscribe to the queried full account objects; *false* to not subscribe; *null* to subscribe or not subscribe according to current auto-subscription setting (see [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c))
  {% endtab %}

{% tab title="Return" %}
Map of string from `names_or_ids` to the corresponding account.
{% endtab %}
{% endtabs %}

### get\_account\_by\_name

Get info of an account by name.

```cpp
optional<account_object> graphene::app::database_api::get_account_by_name(
    string name)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`name`**: Name of the account to retrieve
  {% endtab %}

{% tab title="Return" %}
The account holding the provided name.
{% endtab %}
{% endtabs %}

### get\_account\_references

Get all accounts that refer to the specified account in their owner or active authorities.

```cpp
vector<account_id_type> graphene::app::database_api::get_account_references(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: Account name or ID to query
  {% endtab %}

{% tab title="Return" %}
All accounts that refer to the specified account in their owner or active authorities
{% endtab %}
{% endtabs %}

### lookup\_account\_names

Get a list of accounts by name.

This function has semantics identical to [get\_objects](/api/peerplays-core-api/database-api#get_objects), but doesn’t subscribe

```cpp
vector<optional<account_object>> graphene::app::database_api::lookup_account_names(
    const vector<string> &account_names)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_names`**: Names of the accounts to retrieve
  {% endtab %}

{% tab title="Return" %}
The accounts holding the provided names.
{% endtab %}
{% endtabs %}

### lookup\_accounts

Get names and IDs for registered accounts.

{% hint style="warning" %}
**Note**: In addition to the common auto-subscription rules, this API will subscribe to the returned account only if `limit` is 1.
{% endhint %}

```cpp
map<string, account_id_type> graphene::app::database_api::lookup_accounts(
    const string &lower_bound_name, 
    uint32_t limit, 
    optional<bool> subscribe = optional<bool>())const
```

{% tabs %}
{% tab title="Parameters" %}

* **`lower_bound_name`**: Lower bound of the first name to return
* **`limit`**: Maximum number of results to return must not exceed 1000
* **`subscribe`**: *true* to subscribe to the queried account objects; *false* to not subscribe; *null* to subscribe or not subscribe according to current auto-subscription setting (see [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c)).
  {% endtab %}

{% tab title="Return" %}
Map of account names to corresponding IDs.
{% endtab %}
{% endtabs %}

### get\_account\_count

Get the total number of accounts registered with the blockchain.

```cpp
uint64_t graphene::app::database_api::get_account_count()const
```

## Balances

### get\_account\_balances

Get an account’s balances in various assets.

```cpp
vector<asset> graphene::app::database_api::get_account_balances(
    const std::string &account_name_or_id, 
    const flat_set<asset_id_type> &assets)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: name or ID of the account to get balances for.
* **`assets`**: IDs of the assets to get balances of; if empty, get all assets account has a balance in.
  {% endtab %}

{% tab title="Return" %}
Balances of the account.
{% endtab %}
{% endtabs %}

### get\_named\_account\_balances

Semantically equivalent to [get\_account\_balances](/api/peerplays-core-api/database-api#get_account_balances).

```cpp
vector<asset> graphene::app::database_api::get_named_account_balances(
    const std::string &name, 
    const flat_set<asset_id_type> &assets)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: name or ID of the account to get balances for.
* **`assets`**: IDs of the assets to get balances of; if empty, get all assets account has a balance in.
  {% endtab %}

{% tab title="Return" %}
Balances of the account.
{% endtab %}
{% endtabs %}

### get\_balance\_objects

```cpp
vector<balance_object> graphene::app::database_api::get_balance_objects(
    const vector<address> &addrs)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`addrs`**: a list of addresses
  {% endtab %}

{% tab title="Return" %}
All unclaimed balance objects for the addresses.
{% endtab %}
{% endtabs %}

### get\_vested\_balances

Calculate how much assets in the given balance objects are able to be claimed at current head block time.

```cpp
vector<asset> graphene::app::database_api::get_vested_balances(
    const vector<balance_id_type> &objs)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`objs`**: a list of balance object IDs
  {% endtab %}

{% tab title="Return" %}
A list indicating how much asset in each balance object is available to be claimed.
{% endtab %}
{% endtabs %}

### get\_vesting\_balances

Return all vesting balance objects owned by an account.

```cpp
vector<vesting_balance_object> graphene::app::database_api::get_vesting_balances(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: name or ID of an account
  {% endtab %}

{% tab title="Return" %}
All vesting balance objects owned by the account.
{% endtab %}
{% endtabs %}

## Assets

### get\_assets

Get a list of assets by symbol names or IDs.

Semantically equivalent to [get\_objects](/api/peerplays-core-api/database-api#get_objects).

```cpp
vector<optional<extended_asset_object>> graphene::app::database_api::get_assets(
    const vector<std::string> &asset_symbols_or_ids, 
    optional<bool> subscribe = optional<bool>())const
```

{% tabs %}
{% tab title="Parameters" %}

* **`asset_symbols_or_ids`**: symbol names or IDs of the assets to retrieve
* **`subscribe`**: *true* to subscribe to the queried asset objects; *false* to not subscribe; *null* to subscribe or not subscribe according to current auto-subscription setting (see [set\_auto\_subscription](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a7ef2faf3e3e402ea9572067554c2dd2c))
  {% endtab %}

{% tab title="Return" %}
The assets corresponding to the provided symbol names or IDs.
{% endtab %}
{% endtabs %}

### list\_assets

Get assets alphabetically by symbol name.

```cpp
vector<extended_asset_object> graphene::app::database_api::list_assets(
    const string &lower_bound_symbol, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`lower_bound_symbol`**: Lower bound of symbol names to retrieve
* **`limit`**: Maximum number of assets to fetch (must not exceed 101)
  {% endtab %}

{% tab title="Return" %}
The assets found.
{% endtab %}
{% endtabs %}

### lookup\_asset\_symbols

Get a list of assets by symbol names or IDs.

Semantically equivalent to [get\_objects](/api/peerplays-core-api/database-api#get_objects), but doesn’t subscribe.

```cpp
vector<optional<extended_asset_object>> graphene::app::database_api::lookup_asset_symbols(
    const vector<string> &symbols_or_ids)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`symbols_or_ids`**: symbol names or IDs of the assets to retrieve
  {% endtab %}

{% tab title="Return" %}
The assets corresponding to the provided symbols or IDs
{% endtab %}
{% endtabs %}

## Markets / Feeds

### get\_order\_book

Returns the order book for the market base

```cpp
order_book graphene::app::database_api::get_order_book(
    const string &base, 
    const string &quote, 
    unsigned limit = 50)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`base`**: symbol name or ID of the base asset
* **`quote`**: symbol name or ID of the quote asset
* **`limit`**: depth of the order book to retrieve, for bids and asks each, capped at 50
  {% endtab %}

{% tab title="Return" %}
Order book of the market.
{% endtab %}
{% endtabs %}

### get\_limit\_orders

Get limit orders in a given market.

```cpp
vector<limit_order_object> graphene::app::database_api::get_limit_orders(
    std::string a, 
    std::string b, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: symbol or ID of asset being sold
* **`b`**: symbol or ID of asset being purchased
* **`limit`**: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The limit orders, ordered from least price to greatest.
{% endtab %}
{% endtabs %}

### get\_call\_orders

Get call orders (aka margin positions) for a given asset.

```cpp
vector<call_order_object> graphene::app::database_api::get_call_orders(
    const std::string &a, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* `a`: symbol name or ID of the debt asset
* `limit`: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The call orders, ordered from earliest to be called to latest
{% endtab %}
{% endtabs %}

### get\_settle\_orders

Get forced settlement orders in a given asset.

```cpp
vector<force_settlement_object> graphene::app::database_api::get_settle_orders(
    const std::string &a, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: Symbol or ID of asset being settled
* **`limit`**: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The settle orders, ordered from earliest settlement date to latest.
{% endtab %}
{% endtabs %}

### get\_margin\_positions

Get all open margin positions of a given account.

Similar to [get\_call\_orders\_by\_account](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a78eb082a3a0cfb33ccd00adeb8cfac1d), but without pagination.

```cpp
vector<call_order_object> graphene::app::database_api::get_margin_positions(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* `account_name_or_id`: name or ID of an account
  {% endtab %}

{% tab title="Return" %}
All open margin positions of the account.
{% endtab %}
{% endtabs %}

### subscribe\_to\_market

Request notification when the active orders in the market between two assets changes.

Callback will be passed a variant containing a vector\<pair\<operation, operation\_result>>.&#x20;

The vector will contain, in order, the operations which changed the market, and their results

```cpp
void graphene::app::database_api::subscribe_to_market(std::function<void(
    const variant&)> callback, 
    const std::string &a, 
    const std::string &b, )
```

{% tabs %}
{% tab title="Parameters" %}

* **`callback`**: Callback method which is called when the market changes
* **`a`**: symbol name or ID of the first asset
* **`b`**: symbol name or ID of the second asset
  {% endtab %}
  {% endtabs %}

### unsubscribe\_from\_market

Unsubscribe from updates to a given market.

```cpp
void graphene::app::database_api::unsubscribe_from_market(
    const std::string &a, 
    const std::string &b)
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: symbol name or ID of the first asset
* **`b`**: symbol name or ID of the second asset
  {% endtab %}
  {% endtabs %}

### get\_ticker

Returns the ticker for the market assetA:assetB.

```cpp
market_ticker graphene::app::database_api::get_ticker(
    const string &base, 
    const string &quote)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`base`**: symbol name or ID of the base asset
* **`quote`**: symbol name or ID of the quote asset
  {% endtab %}

{% tab title="Return" %}
The market ticker for the past 24 hours.
{% endtab %}
{% endtabs %}

### get\_24\_volume

Returns the 24 hour volume for the market assetA:assetB.

```cpp
market_volume graphene::app::database_api::get_24_volume(
    const string &base, 
    const string &quote)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`base`**: symbol name or ID of the base asset
* **`quote`**: symbol name or ID of the quote asset
  {% endtab %}

{% tab title="Return" %}
The market volume over the past 24 hours.
{% endtab %}
{% endtabs %}

### get\_trade\_history

Returns recent trades for the market base:quote, ordered by time, most recent first.&#x20;

{% hint style="warning" %}
**Note**: Currently, timezone offsets are not supported. The time must be UTC.
{% endhint %}

The range is \[stop, start). In case  there are more than 100 trades occurring in the same second, this API only returns the first 100 records; use [get\_trade\_history\_by\_sequence](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a19c22f540701825c9292e4a790a4b0d3) to query for the rest.

```cpp
vector<market_trade> graphene::app::database_api::get_trade_history(
    const string &base, 
    const string &quote, 
    fc::time_point_sec start, 
    fc::time_point_sec stop, 
    unsigned limit = 100)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`base`**: symbol or ID of the base asset
* **`quote`**: symbol or ID of the quote asset
* **`start`**: Start time as a UNIX timestamp, the latest trade to retrieve
* **`stop`**: Stop time as a UNIX timestamp, the earliest trade to retrieve
* **`limit`**: Number of transactions to retrieve, capped at 100.
  {% endtab %}

{% tab title="Return" %}
Recent transactions in the market
{% endtab %}
{% endtabs %}

## Witnesses

### get\_witnesses

Get a list of witnesses by ID.

Semantically equivalent to [get\_objects](/api/peerplays-core-api/database-api#get_objects), but doesn’t subscribe.

```cpp
vector<optional<witness_object>> graphene::app::database_api::get_witnesses(
    const vector<witness_id_type> &witness_ids)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`witness_ids`**: IDs of the witnesses to retrieve
  {% endtab %}

{% tab title="Return" %}
The witnesses corresponding to the provided IDs.
{% endtab %}
{% endtabs %}

### get\_witness\_by\_account

Get the witness owned by a given account.

```cpp
fc::optional<witness_object> graphene::app::database_api::get_witness_by_account(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: The name or ID of the account whose witness should be retrieved
  {% endtab %}

{% tab title="Return" %}
The witness object, or null if the account does not have a witness.
{% endtab %}
{% endtabs %}

### **lookup\_witness\_accounts**

Get names and IDs for registered witnesses.

```cpp
map<string, witness_id_type> graphene::app::database_api::lookup_witness_accounts(
    const string &lower_bound_name, uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`lower_bound_name`**: Lower bound of the first name to return
* **`limit`**: Maximum number of results to return must not exceed 1000
  {% endtab %}

{% tab title="Return" %}
Map of witness names to corresponding ID&#x73;**.**
{% endtab %}
{% endtabs %}

### get\_witness\_count

Get the total number of witnesses registered with the blockchain.

```cpp
uint64_t graphene::app::database_api::get_witness_count()const
```

## Committee members

### get\_committee\_members

Get a list of committee\_members by ID.

Semantically equivalent to [get\_objects](/api/peerplays-core-api/database-api#get_objects), but doesn’t subscribe.

```cpp
vector<optional<committee_member_object>> graphene::app::database_api::get_committee_members(
    const vector<committee_member_id_type> &committee_member_ids)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`committee_member_ids`**: IDs of the committee\_members to retrieve
  {% endtab %}

{% tab title="Return" %}
The committee\_members corresponding to the provided IDs.
{% endtab %}
{% endtabs %}

### **get\_committee\_member\_by\_account**

Get the committee\_member owned by a given account.

```cpp
fc::optional<committee_member_object> graphene::app::database_api::get_committee_member_by_account(
    const string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* `account_name_or_id`: The name or ID of the account whose committee\_member should be retrieved
  {% endtab %}

{% tab title="Return" %}
The committee\_member object, or null if the account does not have a committee\_membe&#x72;**.**
{% endtab %}
{% endtabs %}

### lookup\_committee\_member\_accounts

Get names and IDs for registered committee\_members.

```cpp
map<string, committee_member_id_type> graphene::app::database_api::lookup_committee_member_accounts(
    const string &lower_bound_name, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`lower_bound_name`**: Lower bound of the first name to return
* **`limit`**: Maximum number of results to return must not exceed 1000
  {% endtab %}

{% tab title="Return" %}
Map of committee\_member names to corresponding IDs
{% endtab %}
{% endtabs %}

## Workers

### get\_workers\_by\_account

Get the workers owned by a given account.

```cpp
vector<optional<worker_object>> graphene::app::database_api::get_workers_by_account(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: The name or ID of the account whose worker should be retrieved
  {% endtab %}

{% tab title="Return" %}
A list of worker objects owned by the account.
{% endtab %}
{% endtabs %}

## Votes

### lookup\_vote\_ids

Given a set of votes, returns the objects they are voting for.

This will be a mixture of `committee_member_objects`, `witness_objects`, and `worker_objects`

```cpp
vector<variant> graphene::app::database_api::lookup_vote_ids(
    const vector<vote_id_type> &votes)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`votes`**: a list of vote IDs
  {% endtab %}

{% tab title="Return" %}
The referenced objects

The results will be in the same order as the votes. Null will be returned for any vote IDs that are not found.
{% endtab %}
{% endtabs %}

## Authority / Validation

### get\_transaction\_hex

Get a hexdump of the serialized binary form of a transaction.

```cpp
std::string graphene::app::database_api::get_transaction_hex(
    const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* `trx`: a transaction to get hexdump from
  {% endtab %}

{% tab title="Return" %}
The hexdump of the transaction.
{% endtab %}
{% endtabs %}

### **get\_required\_signatures**

This API will take a partially signed transaction and a set of public keys that the owner has the ability to sign for and return the minimal subset of public keys that should add signatures to the transaction.

```cpp
set<public_key_type> graphene::app::database_api::get_required_signatures(
    const signed_transaction &trx, 
    const flat_set<public_key_type> &available_keys)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: the transaction to be signed
* **`available_keys`**: a set of public keys
  {% endtab %}

{% tab title="Return" %}
A subset of `available_keys` that could sign for the given transaction.
{% endtab %}
{% endtabs %}

### get\_potential\_signatures

This method will return the set of all public keys that could possibly sign for a given transaction. This call can be used by wallets to filter their set of public keys to just the relevant subset prior to calling [get\_required\_signatures](https://dev.bitshares.works/en/master/api/namespaces/app.html#classgraphene_1_1app_1_1database__api_1a9ae2eb6a83c27a7b4eec2b00ee8ba371) to get the minimum subset.

```cpp
set<public_key_type> graphene::app::database_api::get_potential_signatures(
    const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: the transaction to be signed
  {% endtab %}

{% tab title="Return" %}
A set of public keys that could possibly sign for the given transaction.
{% endtab %}
{% endtabs %}

### **get\_potential\_address\_signatures**

This method will return the set of all addresses that could possibly sign for a given transaction.

```cpp
set<address> graphene::app::database_api::get_potential_address_signatures(
    const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: the transaction to be signed
  {% endtab %}

{% tab title="Return" %}
A set of addresses that could possibly sign for the given transaction.
{% endtab %}
{% endtabs %}

### **verify\_authority**

Check whether a transaction has all of the required signatures

```cpp
bool graphene::app::database_api::verify_authority(
    const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: a transaction to be verified
  {% endtab %}

{% tab title="Return" %}
true if the `trx` has all of the required signatures, otherwise throws an exceptio&#x6E;**.**
{% endtab %}
{% endtabs %}

### **verify\_account\_authority**

Verify that the public keys have enough authority to approve an operation for this account.

```cpp
bool graphene::app::database_api::verify_account_authority(
    const string &account_name_or_id, 
    const flat_set<public_key_type> &signers)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: name or ID of an account to check
* **`signers`**: the public keys
  {% endtab %}

{% tab title="Return" %}
*true* if the passed in keys have enough authority to approve an operation for this accoun&#x74;**.**
{% endtab %}
{% endtabs %}

### validate\_transaction

Validates a transaction against the current state without broadcasting it on the network.

```cpp
processed_transaction graphene::app::database_api::validate_transaction(
const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: a transaction to be validated
  {% endtab %}

{% tab title="Return" %}
A processed\_transaction object if the transaction passes the validation, otherwise an exception will be thrown.
{% endtab %}
{% endtabs %}

### **get\_required\_fees**

For each operation calculate the required fee in the specified asset type.

```cpp
vector<fc::variant> graphene::app::database_api::get_required_fees(
    const vector<operation> &ops, 
    const std::string &asset_symbol_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`ops`**: a list of operations to be query for required fees
* **`asset_symbol_or_id`**: symbol name or ID of an asset that to be used to pay the fees
  {% endtab %}

{% tab title="Return" %}
A list of objects which indicates required fees of each operation
{% endtab %}
{% endtabs %}

## Proposed Transactions

### get\_proposed\_transactions

Gets a set of proposed transactions (proposals) that the specified account can add approval to or remove approval from.

```cpp
vector<proposal_object> graphene::app::database_api::get_proposed_transactions(
    const std::string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: The name or ID of an account
  {% endtab %}

{% tab title="Return" %}
A  set of proposed transactions that the specified account can act on.
{% endtab %}
{% endtabs %}

## **Blinded balances**

### get\_blinded\_balances

Gets the set of blinded balance objects by commitment ID.

```cpp
vector<blinded_balance_object> graphene::app::database_api::get_blinded_balances(
    const flat_set<commitment_type> &commitments)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`commitments`**: a set of commitments to query for
  {% endtab %}

{% tab title="Return" %}
The set of blinded balance objects by commitment ID.
{% endtab %}
{% endtabs %}


# Network Broadcast API

The network broadcast API is available from the full node via web-sockets.

## Transactions

### broadcast\_transaction

Broadcast a transaction to the network.

The transaction will be checked for validity in the local database prior to broadcasting. If it fails to apply locally, an error will be thrown and the transaction will not be broadcast

```cpp
void graphene::app::network_broadcast_api::broadcast_transaction(
    const precomputable_transaction &trx)
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: The transaction to broadcast
  {% endtab %}
  {% endtabs %}

### broadcast\_transaction\_with\_callback

This version of broadcast transaction registers a callback method that will be called when the transaction is included into a block. The callback method includes the transaction id, block number, and transaction number in the block.

```cpp
void graphene::app::network_broadcast_api::broadcast_transaction_with_callback(
    confirmation_callback cb, 
    const precomputable_transaction &trx)
```

{% tabs %}
{% tab title="Parameters" %}

* **`cb`**: the callback method
* **`trx`**: the transaction
  {% endtab %}
  {% endtabs %}

## Block

### broadcast\_block

Broadcast a signed block to the network.

```cpp
void graphene::app::network_broadcast_api::broadcast_block(
    const signed_block &block)
```

{% tabs %}
{% tab title="Parameters" %}

* **`block`**: The signed block to broadcast.
  {% endtab %}
  {% endtabs %}


# Network Nodes API

The network node API is available from the full node via web-sockets.

## Obtain Network Information

### get\_info

Return general network information, such as p2p port.

```cpp
fc::variant_object graphene::app::network_node_api:get_info()const
```

### get\_connected\_peers

Get status of all current connections to peers.

```cpp
std::vector<net::peer_status> graphene::app::network_node_api::get_connected_peers()const
```

### get\_potential\_peers

Return list of potential peers.

```cpp
std::vector<net::potential_peer_record> graphene::app::network_node_api::get_potential_peers()const
```

### get\_advanced\_node\_parameters

Get advanced node parameters, such as desired and max number of connections.

```cpp
fc::variant_object graphene::app::network_node_api::get_advanced_node_parameters()const
```

## Change Network Settings

### add\_node

Connect to a new peer

```cpp
void graphene::app::network_node_api::add_node(
    const fc::ip::endpoint &ep)
```

{% tabs %}
{% tab title="Parameters" %}

* **`ep`**: The IP/Port of the peer to connect to
  {% endtab %}
  {% endtabs %}

### **set\_advanced\_node\_parameters**

Set advanced node parameters, such as desired and max number of connections.

```cpp
void graphene::app::network_node_api::set_advanced_node_parameters(
    const fc::variant_object &params)
```

{% tabs %}
{% tab title="Parameters" %}

* **`params`**: a JSON object containing the name/value pairs for the parameters to set
  {% endtab %}
  {% endtabs %}


# Orders API

## Orders

### get\_grouped\_limit\_orders

Get grouped limit orders in given market.

```cpp
vector<limit_order_group> graphene::app::orders_api::get_grouped_limit_orders(
    std::string base_asset, 
    std::string quote_asset, 
    uint16_t group, 
    optional<price> start, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`base_asset`**: ID or symbol of asset being sold
* **`quote_asset`**: ID or symbol of asset being purchased
* **`group`**: Maximum price diff within each order group, have to be one of configured values
* **`start`**: Optional price to indicate the first order group to retrieve
* **`limit`**: Maximum number of order groups to retrieve (must not exceed 101)
  {% endtab %}

{% tab title="Return" %}
The grouped limit orders, ordered from best offered price to the worst.
{% endtab %}
{% endtabs %}


# Wallet API

The wallet (`cli_wallet`) requires a running full node to connect to because it does not offer P2P or blockchain capabilities directly.

If you have not set up your wallet yet, you can find more information here: [CLI Wallet Setup](https://infra.peerplays.com/the-basics/using-the-cli-wallet).

{% content-ref url="/pages/-LxvXEAQ6aozq6oDVoMC" %}
[Account Calls](/api/peerplays-wallet-api/account-calls)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvXJrYSm8VWWrrcbD0" %}
[Asset Calls](/api/peerplays-wallet-api/asset-calls)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvXTmHgNP4Fm6TKQfd" %}
[Blockchain Inspection](/api/peerplays-wallet-api/blockchain-inspection)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvWzbty\_KlMMmpeUOR" %}
[General Calls](/api/peerplays-wallet-api/general-calls)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvXML2lYPVKOWybghn" %}
[Governance](/api/peerplays-wallet-api/governance)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvXRLLF9vF7e7YH2df" %}
[Privacy Mode](/api/peerplays-wallet-api/privacy-mode)
{% endcontent-ref %}

{% content-ref url="/pages/-LxvXGtPbKlAjaSP\_DoX" %}
[Trading Calls](/api/peerplays-wallet-api/trading-calls)
{% endcontent-ref %}

<br>


# Account Calls

## Account Calls

### list\_my\_accounts

Lists all accounts controlled by this wallet. This returns a list of the full account objects for all accounts whose private keys we possess

```cpp
vector<account_object> graphene::wallet::wallet_api::list_my_accounts()
```

{% tabs %}
{% tab title="Return" %}
A list of account objects
{% endtab %}
{% endtabs %}

### list\_accounts

Lists all accounts registered in the blockchain. This returns a list of all account names and their account ids, sorted by account name.

Use the `lowerbound` and limit parameters to page through the list. To retrieve all accounts, start by setting `lowerbound` to the empty string `""`, and then each iteration, pass the last account name returned as the `lowerbound` for the next `list_accounts()` call.

```cpp
map<string, account_id_type> graphene::wallet::wallet_api::list_accounts(
    const string &lowerbound, 
    uint32_t limit)
```

{% tabs %}
{% tab title="Parameters" %}

* **`lowerbound`**: the name of the first account to return. If the named account does not exist, the list will start at the account that comes after `lowerbound`
* **`limit`**: the maximum number of accounts to return (max: 1000)
  {% endtab %}

{% tab title="Return" %}
A list of accounts mapping account names to account ids.
{% endtab %}
{% endtabs %}

### list\_account\_balances

List the balances of an account. Each account can have multiple balances, one for each type of asset owned by that account. The returned list will only contain assets for which the account has a non-zero balance.

```cpp
vector<asset> graphene::wallet::wallet_api::list_account_balances(
    const string &id)
```

{% tabs %}
{% tab title="Parameters" %}

* **`id`**: the name or id of the account whose balances you want
  {% endtab %}

{% tab title="Return" %}
A list of the given account’s balances
{% endtab %}
{% endtabs %}

### **register\_account**

Registers a third party’s account on the blockchain.

This function is used to register an account for which you do not own the private keys. When acting as a registrar, an end user will generate their own private keys and send you the public keys. The registrar will use this function to register the account on behalf of the end user.

**See also** [create\_account\_with\_brain\_key()](https://dev.bitshares.works/en/master/api/wallet_api.html?highlight=set_voting_proxy#classgraphene_1_1wallet_1_1wallet__api_1ac27928f7ca6db74e0ec4aee3ff0c545e)

```cpp
signed_transaction graphene::wallet::wallet_api::register_account(
    string name, 
    public_key_type owner, 
    public_key_type active, 
    string registrar_account, 
    string referrer_account, 
    uint32_t referrer_percent, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`name`**: the name of the account, must be unique on the blockchain. Shorter names are more expensive to register; the rules are still in flux, but in general names of more than 8 characters with at least one digit will be cheap.
* **`owner`**: the owner key for the new account
* **`active`**: the active key for the new account
* **`registrar_account`**: the account which will pay the fee to register the user
* **`referrer_account`**: the account who is acting as a referrer, and may receive a portion of the user’s transaction fees. This can be the same as the registrar\_account if there is no referrer.
* **`referrer_percent`**: the percentage (0 - 100) of the new user’s transaction fees not claimed by the blockchain that will be distributed to the referrer; the rest will be sent to the registrar. Will be multiplied by GRAPHENE\_1\_PERCENT when constructing the transaction.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction registering the account
{% endtab %}
{% endtabs %}

### upgrade\_account

Upgrades an account to prime status. This makes the account holder a ‘lifetime member’.

```cpp
signed_transaction graphene::wallet::wallet_api::upgrade_account(
    string name, 
    bool broadcast)
```

{% tabs %}
{% tab title="Parameters" %}

* **`name`**: the name or id of the account to upgrade
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction upgrading the account
{% endtab %}
{% endtabs %}

### create\_account\_with\_brain\_key

Creates a new account and registers it on the blockchain.

**See also** [suggest\_brain\_key()](https://dev.bitshares.works/en/master/api/wallet_api.html?highlight=set_voting_proxy#classgraphene_1_1wallet_1_1wallet__api_1ab936e7a26d41b35cbfaf44d369d60e1d),  [register\_account()](https://dev.bitshares.works/en/master/api/wallet_api.html?highlight=set_voting_proxy#classgraphene_1_1wallet_1_1wallet__api_1aba1c5e3025f44273fb19e264c2b3ec2f)

```cpp
signed_transaction graphene::wallet::wallet_api::create_account_with_brain_key(
    string brain_key, 
    string account_name, 
    string registrar_account, 
    string referrer_account, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`brain_key`**: the brain key used for generating the account’s private keys
* **`account_name`**: the name of the account, must be unique on the blockchain. Shorter names are more expensive to register; the rules are still in flux, but in general names of more than 8 characters with at least one digit will be cheap.
* **`registrar_account`**: the account which will pay the fee to register the user
* **`referrer_account`**: the account who is acting as a referrer, and may receive a portion of the user’s transaction fees. This can be the same as the registrar\_account if there is no referrer.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction registering the account
{% endtab %}
{% endtabs %}

### transfer

Transfer an amount from one account to another.

```cpp
signed_transaction graphene::wallet::wallet_api::transfer(
    string from, 
    string to, 
    string amount, 
    string asset_symbol, 
    string memo, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the name or id of the account sending the funds
* **`to`**: the name or id of the account receiving the funds
* **`amount`**: the amount to send (in nominal units to send half of a BTS, specify 0.5)
* **`asset_symbol`**: the symbol or id of the asset to send
* **`memo`**: a memo to attach to the transaction. The memo will be encrypted in the transaction and readable for the receiver. There is no length limit other than the limit imposed by maximum transaction size, but transaction increase with transaction size
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction transferring funds
{% endtab %}
{% endtabs %}

### transfer2

This method works just like transfer, except it always broadcasts and returns the transaction ID (hash) along with the signed transaction.

```cpp
pair<transaction_id_type, signed_transaction> graphene::wallet::wallet_api::transfer2(
    string from, 
    string to, 
    string amount, 
    string asset_symbol, 
    string memo)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the name or id of the account sending the funds
* **`to`**: the name or id of the account receiving the funds
* **`amount`**: the amount to send (in nominal units to send half of a BTS, specify 0.5)
* **`asset_symbol`**: the symbol or id of the asset to send
* **`memo`**: a memo to attach to the transaction. The memo will be encrypted in the transaction and readable for the receiver. There is no length limit other than the limit imposed by maximum transaction size, but transaction increase with transaction size
  {% endtab %}

{% tab title="Return" %}
The transaction ID (hash) along with the signed transaction transferring funds
{% endtab %}
{% endtabs %}

### whitelist\_account

Whitelist and blacklist accounts, primarily for transacting in whitelisted assets.

Accounts can freely specify opinions about other accounts, in the form of either whitelisting or blacklisting them. This information is used in chain validation only to determine whether an account is authorized to transact in an asset type which enforces a whitelist, but third parties can use this information for other uses as well, as long as it does not conflict with the use of whitelisted assets.

An asset which enforces a whitelist specifies a list of accounts to maintain its whitelist, and a list of accounts to maintain its blacklist. In order for a given account A to hold and transact in a whitelisted asset S, A must be whitelisted by at least one of S’s whitelist\_authorities and blacklisted by none of S’s blacklist\_authorities. If A receives a balance of S, and is later removed from the whitelist(s) which allowed it to hold S, or added to any blacklist S specifies as authoritative, A’s balance of S will be frozen until A’s authorization is reinstated.

```cpp
signed_transaction graphene::wallet::wallet_api::whitelist_account(
    string authorizing_account, 
    string account_to_list, 
    account_whitelist_operation::account_listing new_listing_status, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`authorizing_account`**: the account who is doing the whitelisting
* **`account_to_list`**: the account being whitelisted
* **`new_listing_status`**: the new whitelisting status
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction changing the whitelisting status
{% endtab %}
{% endtabs %}

### get\_vesting\_balances

Get information about a vesting balance object or vesting balance objects owned by an account.

```cpp
vector<vesting_balance_object_with_info> graphene::wallet::wallet_api::get_vesting_balances(
    string account_name)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name`**: An account name, account ID, or vesting balance object ID.
  {% endtab %}

{% tab title="Return" %}
A list of vesting balance objects with additional info
{% endtab %}
{% endtabs %}

### withdraw\_vesting

Withdraw a vesting balance.

```cpp
signed_transaction graphene::wallet::wallet_api::withdraw_vesting(
    string witness_name, 
    string amount, 
    string asset_symbol, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`witness_name`**: The account name of the witness, also accepts account ID or vesting balance ID type.
* **`amount`**: The amount to withdraw.
* **`asset_symbol`**: The symbol of the asset to withdraw.
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed transaction
{% endtab %}
{% endtabs %}

### get\_account

Returns information about the given account.

```cpp
account_object graphene::wallet::wallet_api::get_account(
    string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: the name or ID of the account to provide information about
  {% endtab %}

{% tab title="Return" %}
The public account data stored in the blockchain
{% endtab %}
{% endtabs %}

### **get\_account\_id**

Lookup the id of a named account.

```cpp
account_id_type graphene::wallet::wallet_api::get_account_id(
    string account_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: the name or ID of the account to look up
  {% endtab %}

{% tab title="Return" %}
The id of the named account
{% endtab %}
{% endtabs %}

### get\_account\_history

Returns the most recent operations on the named account.

This returns a list of operation history objects, which describe activity on the account.

```cpp
vector<operation_detail> graphene::wallet::wallet_api::get_account_history(
    string name, 
    int limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`name`**: the name or id of the account
* **`limit`**: the number of entries to return (starting from the most recent)
  {% endtab %}

{% tab title="Return" %}
A list of `operation_history_objects`
{% endtab %}
{% endtabs %}

### approve\_proposal

Approve or disapprove a proposal.

```cpp
signed_transaction graphene::wallet::wallet_api::approve_proposal(
    const string &fee_paying_account, 
    const string &proposal_id, 
    const approval_delta &delta, 
    bool broadcast)
```

{% tabs %}
{% tab title="Parameters" %}

* **`fee_paying_account`**: The account paying the fee for the op.
* **`proposal_id`**: The proposal to modify.
* **`delta`**: Members contain approvals to create or remove. In JSON you can leave empty members undefined.
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed version of the transaction
{% endtab %}
{% endtabs %}


# Asset Calls

## Asset Calls

### list\_assets

Lists all assets registered on the blockchain.

To list all assets, pass the empty string `""` for the `lowerbound` to start at the beginning of the list, and iterate as necessary.

```cpp
vector<extended_asset_object> graphene::wallet::wallet_api::list_assets(
    const string &lowerbound, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`lowerbound`**: the symbol of the first asset to include in the list.
* **`limit`**: the maximum number of assets to return (max: 100)
  {% endtab %}

{% tab title="Return" %}
The list of asset objects, ordered by symbol.
{% endtab %}
{% endtabs %}

### create\_asset

Creates a new user-issued or market-issued asset.

Many options can be changed later using [`update_asset()`](/api/peerplays-wallet-api/asset-calls#update_asset)

{% hint style="warning" %}
**Note**: Right now this function is difficult to use because you must provide raw JSON data structures for the options objects, and those include prices and asset ids.
{% endhint %}

```cpp
signed_transaction graphene::wallet::wallet_api::create_asset(
    string issuer, 
    string symbol, 
    uint8_t precision, 
    asset_options common, 
    fc::optional<bitasset_options> bitasset_opts, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`issuer`**: the name or id of the account who will pay the fee and become the issuer of the new asset. This can be updated later
* **`symbol`**: the ticker symbol of the new asset
* `precision`: the number of digits of precision to the right of the decimal point, must be less than or equal to 12
* **`common`**: asset options required for all new assets. Note that core\_exchange\_rate technically needs to store the asset ID of this new asset. Since this ID is not known at the time this operation is created, create this price as though the new asset has instance ID 1, and the chain will overwrite it with the new asset’s ID.
* **`bitasset_opts`**: options specific to BitAssets. This may be null unless the `market_issued` flag is set in common.flags
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction creating a new asset.
{% endtab %}
{% endtabs %}

### update\_asset

Update the core options on an asset. There are a number of options which all assets in the network use. These options are enumerated in the `asset_object::asset_options` struct.&#x20;

This command is used to update these options for an existing asset.

```cpp
signed_transaction graphene::wallet::wallet_api::update_asset(
    string symbol, 
    optional<string> new_issuer, 
    asset_options new_options, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`symbol`**: the name or id of the asset to update
* **`new_issuer`**: if changing the asset’s issuer, the name or id of the new issuer. null if you wish to remain the issuer of the asset
* **`new_options`**: the new asset\_options object, which will entirely replace the existing options.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction updating the asset
{% endtab %}
{% endtabs %}

### update\_bitasset

Update the options specific to a BitAsset.

BitAssets have some options which are not relevant to other asset types. This operation is used to update those options an an existing BitAsset.

**See** [update\_asset()](/api/peerplays-wallet-api/asset-calls#update_asset)

```cpp
signed_transaction graphene::wallet::wallet_api::update_bitasset(
    string symbol, 
    bitasset_options new_options, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`symbol`**: the name or id of the asset to update, which must be a market-issued asset
* **`new_options`**: the new `bitasset_options` object, which will entirely replace the existing options.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction updating the Bitasset
{% endtab %}
{% endtabs %}

### update\_asset\_feed\_producers

Update the set of feed-producing accounts for a BitAsset.

BitAssets have price feeds selected by taking the median values of recommendations from a set of feed producers. This command is used to specify which accounts may produce feeds for a given BitAsset.

```cpp
signed_transaction graphene::wallet::wallet_api::update_asset_feed_producers(
    string symbol, 
    flat_set<string> new_feed_producers, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`symbol`**: the name or id of the asset to update
* **`new_feed_producers`**: a list of account names or ids which are authorized to produce feeds for the asset. this list will completely replace the existing list
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction updating the BitAsset’s feed producers
{% endtab %}
{% endtabs %}

### publish\_asset\_feed

Publishes a price feed for the named asset.

Price feed providers use this command to publish their price feeds for market-issued assets. A price feed is used to tune the market for a particular market-issued asset. For each value in the feed, the median across all committee\_member feeds for that asset is calculated and the market for the asset is configured with the median of that value.

The feed object in this command contains three prices:&#x20;

* A call price limit
* A short price limit,
* A settlement price

The call limit price is structured as (collateral asset) / (debt asset) and the short limit price is structured as (asset for sale) / (collateral asset).&#x20;

{% hint style="warning" %}
**Note**:  The asset IDs are opposite to each other, so if we’re publishing a feed for USD, the call limit price will be CORE/USD and the short limit price will be USD/CORE.&#x20;
{% endhint %}

The settlement price may be flipped either direction, as long as it is a ratio between the market-issued asset and its collateral.

```cpp
signed_transaction graphene::wallet::wallet_api::publish_asset_feed(
    string publishing_account, 
    string symbol, 
    price_feed feed, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`publishing_account`**: the account publishing the price feed
* **`symbol`**: the name or id of the asset whose feed we’re publishing
* **`feed`**: the price\_feed object containing the three prices making up the feed
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction updating the price feed for the given asset.
{% endtab %}
{% endtabs %}

### issue\_asset

Issue new shares of an asset.

```cpp
signed_transaction graphene::wallet::wallet_api::issue_asset(
    string to_account, 
    string amount, 
    string symbol, 
    string memo, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`to_account`**: the name or id of the account to receive the new shares
* **`amount`**: the amount to issue, in nominal units
* **`symbol`**: the ticker symbol of the asset to issue
* **`memo`**: a memo to include in the transaction, readable by the recipient
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction issuing the new shares
{% endtab %}
{% endtabs %}

### get\_asset

Returns information about the given asset.

```cpp
extended_asset_object graphene::wallet::wallet_api::get_asset(
    string asset_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`asset_name_or_id`**: the symbol or id of the asset in question
  {% endtab %}

{% tab title="Return" %}
The information about the asset stored in the block chain.
{% endtab %}
{% endtabs %}

### **get\_bitasset\_data**

Returns the BitAsset-specific data for a given asset. Market-issued assets’s behaviour are determined both by their “BitAsset Data” and their basic asset data, as returned by [`get_asset()`](/api/peerplays-wallet-api/asset-calls#get_asset)

```cpp
asset_bitasset_data_object graphene::wallet::wallet_api::get_bitasset_data(
    string asset_name_or_id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`asset_name_or_id`**: the symbol or id of the BitAsset in question
  {% endtab %}

{% tab title="Return" %}
The BitAsset-specific data for this asset
{% endtab %}
{% endtabs %}

### **fund\_asset\_fee\_pool**

Pay into the fee pool for the given asset.

User-issued assets can optionally have a pool of the core asset which is automatically used to pay transaction fees for any transaction using that asset (using the asset’s core exchange rate).

This command allows anyone to deposit the core asset into this fee pool.

```cpp
signed_transaction graphene::wallet::wallet_api::fund_asset_fee_pool(
    string from, 
    string symbol, 
    string amount, 
    bool broadcast = false)

```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the name or id of the account sending the core asset
* **`symbol`**: the name or id of the asset whose fee pool you wish to fund
* **`amount`**: the amount of the core asset to deposit
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
**T**he signed transaction funding the fee pool.
{% endtab %}
{% endtabs %}

### reserve\_asset

Burns an amount of given asset.

This command burns an amount of given asset to reduce the amount in circulation.

{% hint style="warning" %}
**Note: Y**ou can't burn market-issued assets.
{% endhint %}

```cpp
signed_transaction graphene::
wallet
::
wallet_api
::reserve_asset(string from, string amount, string symbol, bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from`**: the account containing the asset you wish to burn
* **`amount`**: the amount to burn, in nominal units
* **`symbol`**: the name or id of the asset to burn
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction burning the asset
{% endtab %}
{% endtabs %}

### global\_settle\_asset

Forces a global settling of the given asset (black swan or prediction markets).

In order to use this operation, `asset_to_settle` must have the `global_settle` flag set

When this operation is executed all open margin positions are called at the settle price. A pool will be formed containing the collateral got from the margin positions. Users owning an amount of the asset may use [`settle_asset()`](https://dev.bitshares.works/en/master/api/wallet_api.html?highlight=set_voting_proxy#classgraphene_1_1wallet_1_1wallet__api_1a95a3baa4b0c83c1fce14827acbbddd62) to claim collateral instantly at the settle price from the pool.&#x20;

If this asset is used as backing for other BitAssets, those BitAssets will not be affected.

{% hint style="warning" %}
**Note: T**his operation is used only by the asset issuer.
{% endhint %}

```cpp
signed_transaction graphene::
wallet
::
wallet_api
::global_settle_asset(string symbol, price settle_price, bool broadcast = false)

```

{% tabs %}
{% tab title="Parameters" %}

* **`symbol`**: the name or id of the asset to globally settle
* **`settle_price`**: the price at which to settle
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction settling the named asset
{% endtab %}
{% endtabs %}


# Blockchain Inspection

## Blockchain Inspection

### get\_block

Returns info about a specified block.

```cpp
optional<signed_block_with_info> graphene::wallet::wallet_api::get_block(
    uint32_t num)
```

{% tabs %}
{% tab title="Parameters" %}

* **`num`**: height of the block to retrieve
  {% endtab %}

{% tab title="Return" %}
Info about the block, or null if not found.
{% endtab %}
{% endtabs %}

### **get\_account\_count**

Returns the number of accounts registered on the blockchai&#x6E;**.**

```cpp
uint64_t graphene::wallet::wallet_api::get_account_count()const
```

{% tabs %}
{% tab title="Return" %}
The number of registered accounts
{% endtab %}
{% endtabs %}

### get\_global\_properties

Returns the block chain’s slowly-changing settings.&#x20;

This object contains all of the properties of the blockchain that are fixed or that change only once per maintenance interval (daily) such as the current list of witnesses, committee\_members, block interval, etc.

**See** [`get_dynamic_global_properties()`](/api/peerplays-wallet-api/blockchain-inspection#get_dynamic_global_properties) for frequently changing properties.

```cpp
global_property_object graphene::wallet::wallet_api::get_global_properties()const
```

{% tabs %}
{% tab title="Return" %}
The global properties.
{% endtab %}
{% endtabs %}

### get\_dynamic\_global\_properties

Returns the block chain’s rapidly-changing properties. The returned object contains information that changes every block interval such as the head block number, the next witness, etc.**See**

[`get_global_properties()`](/api/peerplays-wallet-api/blockchain-inspection#get_global_properties) for less-frequently changing properties

```cpp
dynamic_global_property_object graphene::wallet::wallet_api::get_dynamic_global_properties()const
```

{% tabs %}
{% tab title="Return" %}
The dynamic global properties.
{% endtab %}
{% endtabs %}

### get\_object

Returns the blockchain object corresponding to the given id.

This generic function can be used to retrieve any object from the blockchain that is assigned an ID. Certain types of objects have specialized convenience functions to return their objects e.g., assets have [`get_asset()`](/api/peerplays-wallet-api/asset-calls#get_asset), accounts have [`get_account()`](/api/peerplays-wallet-api/account-calls#get_account), but this function will work for any object.

```cpp
variant graphene::wallet::wallet_api::get_object(
    object_id_type id)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`id`**: the id of the object to return.
  {% endtab %}

{% tab title="Return" %}
The requested object.
{% endtab %}
{% endtabs %}


# General Calls

## General Calls

### help

Returns a list of all commands supported by the wallet API.

This lists each command, along with its arguments and return types. For more detailed help on a single command, use [`gethelp()`](/api/peerplays-wallet-api/general-calls#gethelp)

```cpp
string graphene::wallet::wallet_api::help()const
```

{% tabs %}
{% tab title="Return" %}
A multi-line string suitable for displaying on a terminal.
{% endtab %}
{% endtabs %}

### gethelp

Returns detailed help on a single API command.

```cpp
string graphene::wallet::wallet_api::gethelp(
    const string &method)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`method`**: the name of the API command you want help with
  {% endtab %}

{% tab title="Return" %}
A multi-line string suitable for displaying on a terminal.
{% endtab %}
{% endtabs %}

### info

Returns info about head block, chain\_id, maintenance, participation, current active witnesses and committee members.

```cpp
variant graphene::wallet::wallet_api::info()
```

{% tabs %}
{% tab title="Return" %}
Runtime info about the blockchain
{% endtab %}
{% endtabs %}

### about

Returns info such as client version, git version of graphene/fc, version of boost, openssl etc.

```cpp
variant_object graphene::
wallet
::
wallet_api
::about()const
```

{% tabs %}
{% tab title="Return" %}
Compile time info and client and dependencies versions.
{% endtab %}
{% endtabs %}

#### network\_add\_nodes

```cpp
void graphene::wallet::wallet_api::network_add_nodes(
    const vector<string> &nodes)
```

{% tabs %}
{% tab title="Parameters" %}
**`nodes`**: Nodes to be added.<br>
{% endtab %}
{% endtabs %}

### network\_get\_connected\_peers

```cpp
vector<variant> graphene::wallet::wallet_api::network_get_connected_peers()
```

{% tabs %}
{% tab title="Return" %}
List of connected peers.
{% endtab %}
{% endtabs %}


# Governance

## Governance

### create\_committee\_member

Creates a committee\_member object owned by the given account.

An account can have at most one committee\_member object.

```cpp
signed_transaction graphene::wallet::wallet_api::create_committee_member(
    string owner_account, 
    string url, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`owner_account`**: the name or id of the account which is creating the committee\_member
* **`url`**: a URL to include in the committee\_member record in the blockchain. Clients may display this when showing a list of committee\_members. May be blank.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction registering a committee\_member
{% endtab %}
{% endtabs %}

### get\_witness

Returns information about the given witness.

```cpp
witness_object graphene::wallet::wallet_api::get_witness(
    string owner_account)
```

{% tabs %}
{% tab title="Parameters" %}

* **`owner_account`**: the name or id of the witness account owner, or the id of the witness
  {% endtab %}

{% tab title="Return" %}
The information about the witness stored in the block chain.
{% endtab %}
{% endtabs %}

### **get\_committee\_member**

Returns information about the given committee\_member.

```cpp
committee_member_object graphene::wallet::wallet_api::get_committee_member(
    string owner_account)
```

{% tabs %}
{% tab title="Parameters" %}

* **`owner_account`**: the name or id of the committee\_member account owner, or the id of the committee\_member.
  {% endtab %}

{% tab title="Return" %}
**T**he information about the committee\_member stored in the block chain
{% endtab %}
{% endtabs %}

### list\_witnesses

Lists all Witnesses registered in the blockchain. This returns a list of all account names that own Witnesses, and the associated witness id, sorted by name. This lists Witnesses whether they are currently voted in or not.

Use the `lowerbound` and limit parameters to page through the list. To retrieve all Witness's, start by setting `lowerbound` to the empty string `""`, and then each iteration, pass the last witness name returned as the `lowerbound` for the next `list_witnesss()` call.

```cpp
map<string, witness_id_type> graphene::wallet::wallet_api::list_witnesses(
    const string &lowerbound, 
    uint32_t limit)
```

{% tabs %}
{% tab title="Parameters" %}

* `lowerbound`: the name of the first Witness to return. If the named Witness does not exist, the list will start at the witness that comes after `lowerbound`
* `limit`: the maximum number of Witness's to return (max: 1000)
  {% endtab %}

{% tab title="Return" %}
A list of Witness's mapping witness names to witness ids
{% endtab %}
{% endtabs %}

### list\_committee\_members

Lists all committee\_members registered in the blockchain. This returns a list of all account names that own committee\_members, and the associated committee\_member id, sorted by name. This lists committee\_members whether they are currently voted in or not.

Use the `lowerbound` and limit parameters to page through the list. To retrieve all committee\_members, start by setting `lowerbound` to the empty string `""`, and then each iteration, pass the last committee\_member name returned as the `lowerbound` for the next `list_committee_members()` call.

```cpp
map<string, committee_member_id_type> graphene::wallet::wallet_api::list_committee_members(
    const string &lowerbound, 
    uint32_t limit)
```

{% tabs %}
{% tab title="Parameters" %}

* **`lowerbound`**: the name of the first committee\_member to return. If the named committee\_member does not exist, the list will start at the committee\_member that comes after `lowerbound`
* **`limit`**: the maximum number of committee\_members to return (max: 1000)
  {% endtab %}

{% tab title="Return" %}
A list of committee\_members mapping committee\_member names to committee\_member ids
{% endtab %}
{% endtabs %}

### create\_witness

Creates a witness object owned by the given account.

An account can have at most one witness object.

```cpp
signed_transaction graphene::wallet::wallet_api::create_witness(
    string owner_account, 
    string url, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`owner_account`**: the name or id of the account which is creating the witness
* **`url`**: a URL to include in the witness record in the blockchain. Clients may display this when showing a list of witnesses. May be blank.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction registering a witness
{% endtab %}
{% endtabs %}

### update\_witness

Update a witness object owned by the given account.

```cpp
signed_transaction graphene::wallet::wallet_api::update_witness(
    string witness_name, 
    string url, 
    string block_signing_key, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`witness_name`**: The name of the witness’s owner account. Also accepts the ID of the owner account or the ID of the witness.
* **`url`**: Same as for create\_witness. The empty string makes it remain the same.
* **`block_signing_key`**: The new block signing public key. The empty string makes it remain the same.
* **`broadcast`**: true if you wish to broadcast the transaction.
  {% endtab %}

{% tab title="Return" %}
The signed transaction
{% endtab %}
{% endtabs %}

### create\_worker

Create a worker object.

```cpp
signed_transaction graphene::wallet::wallet_api::create_worker(
    string owner_account, 
    time_point_sec work_begin_date, 
    time_point_sec work_end_date, 
    share_type daily_pay, 
    string name, string url, 
    variant worker_settings, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`owner_account`**: The account which owns the worker and will be paid
* **`work_begin_date`**: When the work begins
* **`work_end_date`**: When the work ends
* **`daily_pay`**: Amount of pay per day (NOT per maint interval)
* **`name`**: Any text
* **`url`**: Any text
* **`worker_settings`**: {“type” : “burn”|”refund”|”vesting”, “pay\_vesting\_period\_days” : x}
* **`broadcast`**: true if you wish to broadcast the transaction.
  {% endtab %}

{% tab title="Return" %}
The signed transaction
{% endtab %}
{% endtabs %}

### update\_worker\_votes

Update your votes for workers.

```cpp
signed_transaction graphene::wallet::wallet_api::update_worker_votes(
    string account, 
    worker_vote_delta delta,
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account`**: The account which will pay the fee and update votes.
* **`delta`**: {“vote\_for” : \[…], “vote\_against” : \[…], “vote\_abstain” : \[…]}
* **`broadcast`**: true if you wish to broadcast the transaction.
  {% endtab %}

{% tab title="Return" %}
The signed transaction
{% endtab %}
{% endtabs %}

### vote\_for\_committee\_member

Vote for a given committee\_member.

An account can publish a list of all committee\_members they approve of. This command allows you to add or remove committee\_members from this list. Each account’s vote is weighted according to the number of shares of the core asset owned by that account at the time the votes are tallied.

{% hint style="warning" %}
**Note:** You can't vote against a committee\_member, you can only vote for the committee\_member or not vote for the committee\_member.
{% endhint %}

```cpp
signed_transaction graphene::wallet::wallet_api::vote_for_committee_member(
    string voting_account, 
    string committee_member, 
    bool approve, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`voting_account`**: the name or id of the account who is voting with their shares
* **`committee_member`**: the name or id of the committee\_member’ owner account
* **`approve`**: true if you wish to vote in favour of that committee\_member, false to remove your vote in favour of that committee\_member
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed transaction changing your vote for the given committee\_member.
{% endtab %}
{% endtabs %}

### vote\_for\_witness

Vote for a given witness.

An account can publish a list of all witnesses they approve of. This command allows you to add or remove witnesses from this list. Each account’s vote is weighted according to the number of shares of the core asset owned by that account at the time the votes are tallied.

{% hint style="warning" %}
Note: You can't vote against a witness, you can only vote for the witness or not vote for the witness.
{% endhint %}

```cpp
signed_transaction graphene::wallet::wallet_api::vote_for_witness(
    string voting_account, 
    string witness, 
    bool approve, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`voting_account`**: the name or id of the account who is voting with their shares
* **`witness`**: the name or id of the witness’ owner account
* **`approve`**: true if you wish to vote in favour of that witness, false to remove your vote in favour of that witness
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed transaction changing your vote for the given witness
{% endtab %}
{% endtabs %}

### set\_voting\_proxy

Set the voting proxy for an account.

If a user does not wish to take an active part in voting, they can choose to allow another account to vote their stake.

Setting a vote proxy does not remove your previous votes from the blockchain, they remain there but are ignored. If you later null out your vote proxy, your previous votes will take effect again.

This setting can be changed at any time.

```cpp
signed_transaction graphene::wallet::wallet_api::set_voting_proxy(
    string account_to_modify, 
    optional<string> voting_account, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_to_modify`**: the name or id of the account to update
* **`voting_account`**: the name or id of an account authorized to vote account\_to\_modify’s shares, or null to vote your own shares
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed transaction changing your vote proxy settings
{% endtab %}
{% endtabs %}

### set\_desired\_witness\_and\_committee\_member\_count

Set your vote for the number of witnesses and committee\_members in the system.

Each account can voice their opinion on how many committee\_members and how many witnesses there should be in the active committee\_member/active witness list. These are independent of each other. You must vote your approval of at least as many committee\_members or witnesses as you claim there should be (you can’t say that there should be 20 committee\_members but only vote for 10).

There are maximum values for each set in the blockchain parameters (currently defaulting to 1001).

This setting can be changed at any time. If your account has a voting proxy set, your preferences will be ignored.

```cpp
signed_transaction graphene::wallet::wallet_api::set_desired_witness_and_committee_member_count(
    string account_to_modify, 
    uint16_t desired_number_of_witnesses, 
    uint16_t desired_number_of_committee_members, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_to_modify`**: the name or id of the account to update
* **`desired_number_of_witnesses`**: desired number of active witnesses
* **`desired_number_of_committee_members`**: desired number of active committee members
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Result" %}
The signed transaction changing your vote proxy settings
{% endtab %}
{% endtabs %}

### propose\_parameter\_change

Creates a transaction to propose a parameter change.

Multiple parameters can be specified if an atomic change is desired.

```cpp
signed_transaction graphene::wallet::wallet_api::propose_parameter_change(
    const string &proposing_account, 
    fc::time_point_sec expiration_time, 
    const variant_object &changed_values, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`proposing_account`**: The account paying the fee to propose the tx
* **`expiration_time`**: Timestamp specifying when the proposal will either take effect or expire.
* **`changed_values`**: The values to change; all other chain parameters are filled in with default values
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed version of the transaction
{% endtab %}
{% endtabs %}

### propose\_fee\_change

Propose a fee change.

```cpp
signed_transaction graphene::wallet::wallet_api::propose_fee_change(
    const string &proposing_account, 
    fc::time_point_sec expiration_time, 
    const variant_object &changed_values, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`proposing_account`**: The account paying the fee to propose the tx
* **`expiration_time`**: Timestamp specifying when the proposal will either take effect or expire.
* **`changed_values`**: Map of operation type to new fee. Operations may be specified by name or ID. The “scale” key changes the scale. All other operations will maintain current values.
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed version of the transaction
{% endtab %}
{% endtabs %}


# Privacy Mode

## Privacy Mode

### set\_key\_label

These methods are used for stealth transfers This method can be used to set a label for a public key

{% hint style="warning" %}
**Note**: No two keys can have the same label.
{% endhint %}

```cpp
bool graphene::wallet::wallet_api::set_key_label(
    public_key_type key, 
    string label)
```

{% tabs %}
{% tab title="Parameters" %}

* **`key`**: a public key
* **`label`**: a user-defined string as label
  {% endtab %}

{% tab title="Return" %}
*True* if the label was set, otherwise *false*
{% endtab %}
{% endtabs %}

### get\_key\_label

Get label of a public key.

```cpp
string graphene::wallet::wallet_api::get_key_label(
    public_key_type key)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`key`**: a public key
  {% endtab %}

{% tab title="Return" %}
The label if already set by [`set_key_label()`](/api/peerplays-wallet-api/privacy-mode#set_key_label), or an empty string if not set
{% endtab %}
{% endtabs %}

### get\_public\_key

Get the public key associated with a given label

```cpp
public_key_type graphene::wallet::wallet_api::get_public_key(
    string label)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`label`**: a label
  {% endtab %}

{% tab title="Return" %}
The public key associated with the given label.
{% endtab %}
{% endtabs %}

### get\_blind\_accounts

Get all blind accounts.

```cpp
map<string, public_key_type> graphene::
wallet
::
wallet_api
::get_blind_accounts()const
```

{% tabs %}
{% tab title="Return" %}
All blind accounts
{% endtab %}
{% endtabs %}

### get\_my\_blind\_accounts

Get all blind accounts for which this wallet has the private key.

```cpp
map<string, public_key_type> graphene::wallet::wallet_api::get_my_blind_accounts()const
```

{% tabs %}
{% tab title="Return" %}
All blind accounts for which this wallet has the private key.
{% endtab %}
{% endtabs %}

### get\_blind\_balances

Return the total balances of all blinded commitments that can be claimed by the given account key or label.

```cpp
vector<asset> graphene::wallet::wallet_api::get_blind_balances(
    string key_or_label)
```

{% tabs %}
{% tab title="Parameters" %}

* **`key_or_label`**: a public key in Base58 format or a label
  {% endtab %}

{% tab title="Return" %}
The total balances of all blinded commitments that can be claimed by the given account key or label
{% endtab %}
{% endtabs %}

### **create\_blind\_account**

Generates a new blind account for the given brain key and assigns it the given label

```cpp
public_key_type graphene::
wallet
::
wallet_api
::create_blind_account(string label, string brain_key)
```

{% tabs %}
{% tab title="Parameters" %}

* **`label`**: a label
* **`brain_key`**: the brain key to be used to generate a new blind account
  {% endtab %}

{% tab title="Return" %}
The public key of the new account
{% endtab %}
{% endtabs %}

### transfer\_to\_blind

Transfers a public balance from `from_account_id_or_name` to one or more blinded balances using a stealth transfer.

```cpp
blind_confirmationgraphene::wallet::wallet_api::transfer_to_blind(
    string from_account_id_or_name, 
    string asset_symbol, 
    vector<pair<string, string>> to_amounts, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from_account_id_or_name`**: ID or name of an account to transfer from
* **`asset_symbol`**: symbol or ID of the asset to be transferred
* **`to_amounts`**: map from key or label to amount
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
A blind confirmation
{% endtab %}
{% endtabs %}

### transfer\_from\_blind

Transfers funds from a set of blinded balances to a public account balance.

```cpp
blind_confirmationgraphene::wallet::wallet_api::transfer_from_blind(
    string from_blind_account_key_or_label, 
    string to_account_id_or_name, 
    string amount, 
    string asset_symbol, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from_blind_account_key_or_label`**: a public key in Base58 format or a label to transfer from
* **`to_account_id_or_name`**: ID or name of an account to transfer to
* **`amount`**: the amount to be transferred
* **`asset_symbol`**: symbol or ID of the asset to be transferred
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
A blind confirmation.
{% endtab %}
{% endtabs %}

### blind\_transfer

Transfer from one set of blinded balances to another.

```cpp
blind_confirmationgraphene::wallet::wallet_api::blind_transfer(
    string from_key_or_label, 
    string to_key_or_label, 
    string amount, 
    string symbol, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`from_key_or_label`**: a public key in Base58 format or a label to transfer from
* **`to_key_or_label`**: a public key in Base58 format or a label to transfer to
* **`amount`**: the amount to be transferred
* **`symbol`**: symbol or ID of the asset to be transferred
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
A blind confirmation
{% endtab %}
{% endtabs %}

### blind\_history

Get all blind receipts to/form a particular account.

```cpp
vector<blind_receipt> graphene::wallet::wallet_api::blind_history(
    string key_or_account)
```

{% tabs %}
{% tab title="Parameters" %}

* **`key_or_account`**: a public key in Base58 format or an account
  {% endtab %}

{% tab title="Return" %}
All blind receipts to/form the account.
{% endtab %}
{% endtabs %}

### **receive\_blind\_transfer**

Given a confirmation receipt, this method will parse it for a blinded balance and confirm that it exists in the blockchain. If it exists then it will report the amount received and who sent it.

```cpp
blind_receipt graphene::
wallet
::
wallet_api
::receive_blind_transfer(string confirmation_receipt, string opt_from, string opt_memo)
```

{% tabs %}
{% tab title="Parameters" %}

* **`confirmation_receipt`**: a base58 encoded stealth confirmation
* **`opt_from`**: if not empty and the sender is a unknown public key, then the unknown public key will be given the label `opt_from`
* **`opt_memo`**: a self-defined label for this transfer to be saved in local wallet file
  {% endtab %}

{% tab title="Return" %}
A blind receipt.
{% endtab %}
{% endtabs %}


# Trading Calls

## Trading Calls

### sell\_asset

Place a limit order attempting to sell one asset for another.

Buying and selling are the same operation on Graphene; if you want to buy BTS with USD, you should sell USD for BTS.

The blockchain will attempt to sell the `symbol_to_sell` for as much `symbol_to_receive` as possible, as long as the price is at least `min_to_receive` / `amount_to_sell`.

In addition to the transaction fees, market fees will apply as specified by the issuer of both the selling asset and the receiving asset as a percentage of the amount exchanged.

If either the selling asset or the receiving asset is whitelist restricted, the order will only be created if the seller is on the whitelist of the restricted asset type.

Market orders are matched in the order they are included in the block chain.

```cpp
signed_transaction graphene::wallet::wallet_api::sell_asset(
    string seller_account, 
    string amount_to_sell, 
    string symbol_to_sell, 
    string min_to_receive, 
    string symbol_to_receive, 
    uint32_t timeout_sec = 0, 
    bool fill_or_kill = false, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`seller_account`**: the account providing the asset being sold, and which will receive the proceeds of the sale.
* **`amount_to_sell`**: the amount of the asset being sold to sell (in nominal units)
* **`symbol_to_sell`**: the name or id of the asset to sell
* **`min_to_receive`**: the minimum amount you are willing to receive in return for selling the entire amount\_to\_sell
* **`symbol_to_receive`**: the name or id of the asset you wish to receive
* **`timeout_sec`**: if the order does not fill immediately, this is the length of time the order will remain on the order books before it is cancelled and the un-spent funds are returned to the seller’s account
* **`fill_or_kill`**: if true, the order will only be included in the blockchain if it is filled immediately; if false, an open order will be left on the books to fill any amount that cannot be filled immediately.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction selling the funds.
{% endtab %}
{% endtabs %}

### borrow\_asset

Borrow an asset or update the debt/collateral ratio for the loan.

This is the first step in shorting an asset.&#x20;

Call [`sell_asset()`](/api/peerplays-wallet-api/trading-calls#sell_asset) to complete the short.

```cpp
signed_transaction graphene::
wallet
::
wallet_api
::borrow_asset(string borrower_name, string amount_to_borrow, string asset_symbol, string amount_of_collateral, bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`borrower_name`**: the name or id of the account associated with the transaction.
* **`amount_to_borrow`**: the amount of the asset being borrowed. Make this value negative to pay back debt.
* **`asset_symbol`**: the symbol or id of the asset being borrowed.
* **`amount_of_collateral`**: the amount of the backing asset to add to your collateral position. Make this negative to claim back some of your collateral. The backing asset is defined in the **`bitasset_options`** for the asset being borrowed.
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction borrowing the asset
{% endtab %}
{% endtabs %}

### cancel\_order

Cancel an existing order.

```cpp
signed_transaction graphene::wallet::wallet_api::cancel_order(
    object_id_type order_id, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`order_id`**: the id of order to be cancelled
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction canceling the order
{% endtab %}
{% endtabs %}

### settle\_asset

Schedules a market-issued asset for automatic settlement.

Holders of market-issued assets may request a forced settlement for some amount of their asset. This means that the specified sum will be locked by the chain and held for the settlement period, after which time the chain will choose a margin position holder and buy the settled asset using the margin’s collateral.

The price of this sale will be based on the feed price for the market-issued asset being settled. The exact settlement price will be the feed price at the time of settlement with an offset in favour of the margin position, where the offset is a blockchain parameter set in the global\_property\_object.

```cpp
signed_transaction graphene::wallet::wallet_api::settle_asset(
    string account_to_settle, 
    string amount_to_settle, 
    string symbol, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_to_settle`**: the name or id of the account owning the asset
* **`amount_to_settle`**: the amount of the named asset to schedule for settlement
* **`symbol`**: the name or id of the asset to settle
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}

{% tab title="Return" %}
The signed transaction settling the named asset.
{% endtab %}
{% endtabs %}

### get\_market\_history

Get OHLCV data of a trading pair in a time range.

```cpp
vector<bucket_object> graphene::wallet::wallet_api::get_market_history(
    string symbol, 
    string symbol2, 
    uint32_t bucket, 
    fc::time_point_sec start, 
    fc::time_point_sec end)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`symbol`**: name or ID of the base asset
* **`symbol2`**: name or ID of the quote asset
* **`bucket`**: length of each time bucket in seconds.
* **`start`**: the start of a time range, E.G. “2018-01-01T00:00:00”
* **`end`**: the end of the time range
  {% endtab %}

{% tab title="Return" %}
A list of OHLCV data, in “least recent first” order.
{% endtab %}
{% endtabs %}

### get\_limit\_orders

Get limit orders in a given market.

```cpp
vector<limit_order_object> graphene::wallet::wallet_api::get_limit_orders(
    string a, 
    string b, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: symbol or ID of asset being sold
* **`b`**: symbol or ID of asset being purchased
* **`limit`**: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The limit orders, ordered from least price to greatest.
{% endtab %}
{% endtabs %}

### get\_call\_orders

Get call orders (aka margin positions) for a given asset.

```cpp
vector<call_order_object> graphene::wallet::wallet_api::get_call_orders(
    string a, 
    uint32_t limit)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: symbol name or ID of the debt asset
* **`limit`**: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The call orders, ordered from earliest to be called to latest
{% endtab %}
{% endtabs %}

### get\_settle\_orders

Get forced settlement orders in a given asset.

```cpp
vector<force_settlement_object> graphene::wallet::wallet_api::get_settle_orders(
    string a, 
    uint32_t limit)const

```

{% tabs %}
{% tab title="Parameters" %}

* **`a`**: Symbol or ID of asset being settled
* **`limit`**: Maximum number of orders to retrieve
  {% endtab %}

{% tab title="Return" %}
The settle orders, ordered from earliest settlement date to latest
{% endtab %}
{% endtabs %}


# Transaction Builder

## Transaction Builder

### begin\_builder\_transaction

Create a new transaction builder.

```cpp
transaction_handle_typegraphene::wallet::wallet_api::begin_builder_transaction()
```

{% tabs %}
{% tab title="Return" %}
Handle of the new transaction builder.
{% endtab %}
{% endtabs %}

### add\_operation\_to\_builder\_transaction

Append a new operation to a transaction builder.

```cpp
void graphene::wallet::wallet_api::add_operation_to_builder_transaction(
    transaction_handle_typetransaction_handle, 
    const operation &op)
```

{% tabs %}
{% tab title="Parameters" %}

* **`transaction_handle`**: handle of the transaction builder
* **`op`**: the operation in JSON format
  {% endtab %}
  {% endtabs %}

### replace\_operation\_in\_builder\_transaction

Replace an operation in a transaction builder with a new operation.

```cpp
void graphene::wallet::wallet_api::replace_operation_in_builder_transaction(
    transaction_handle_typehandle, 
    unsigned operation_index, 
    const operation &new_op)
```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
* **`operation_index`**: the index of the old operation in the builder to be replaced
* **`new_op`**: the new operation in JSON format
  {% endtab %}
  {% endtabs %}

### set\_fees\_on\_builder\_transaction

Calculate and update fees for the operations in a transaction builder.

```cpp
asset graphene::wallet::wallet_api::set_fees_on_builder_transaction(
    transaction_handle_typehandle, 
    string fee_asset = GRAPHENE_SYMBOL)
```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
* **`fee_asset`**: name or ID of an asset that to be used to pay fees
  {% endtab %}

{% tab title="Return" %}
Total fees.
{% endtab %}
{% endtabs %}

### preview\_builder\_transaction

Show content of a transaction builder.

```cpp
transaction graphene::wallet::wallet_api::preview_builder_transaction(
    transaction_handle_typehandle)
```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
  {% endtab %}

{% tab title="Return" %}
A transaction.
{% endtab %}
{% endtabs %}

### **sign\_builder\_transaction**

Sign the transaction in a transaction builder and optionally broadcast to the network.

```cpp
signed_transaction graphene::wallet::wallet_api::sign_builder_transaction(
    transaction_handle_typetransaction_handle, 
    bool broadcast = true)
```

{% tabs %}
{% tab title="Parameters" %}

* **`transaction_handle`**: handle of the transaction builder
* **`broadcast`**: whether to broadcast the signed transaction to the network
  {% endtab %}

{% tab title="Return" %}
A signed transaction.
{% endtab %}
{% endtabs %}

### propose\_builder\_transaction

Create a proposal containing the operations in a transaction builder (create a new proposal\_create operation, then replace the transaction builder with the new operation), then sign the transaction and optionally broadcast to the network.

{% hint style="warning" %}
**Note**: this command is not effective because you're unable to specify a proposer. It will be deprecated in a future release. Use [`propose_builder_transaction2()`](/api/peerplays-wallet-api/transaction-builder#propose_builder_transaction2) instead.
{% endhint %}

```cpp
signed_transaction graphene::wallet::wallet_api::propose_builder_transaction(
    transaction_handle_typehandle, 
    time_point_sec expiration = time_point::now() + fc::minutes(1), 
    uint32_t review_period_seconds = 0, 
    bool broadcast = true)

```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
* **`expiration`**: when the proposal will expire
* **`review_period_seconds`**: review period of the proposal in seconds
* **`broadcast`**: whether to broadcast the signed transaction to the network
  {% endtab %}

{% tab title="Return" %}
A signed transaction.
{% endtab %}
{% endtabs %}

### propose\_builder\_transaction2

Create a proposal containing the operations in a transaction builder (create a new proposal\_create operation, then replace the transaction builder with the new operation), then sign the transaction and optionally broadcast to the network.

```cpp
signed_transaction graphene::wallet::wallet_api::propose_builder_transaction2(
    transaction_handle_typehandle, 
    string account_name_or_id, 
    time_point_sec expiration = time_point::now() + fc::minutes(1), 
    uint32_t review_period_seconds = 0, 
    bool broadcast = true)
```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
* **`account_name_or_id`**: name or ID of the account who would pay fees for creating the proposal
* **`expiration`**: when the proposal will expire
* **`review_period_seconds`**: review period of the proposal in seconds
* **`broadcast`**: whether to broadcast the signed transaction to the network
  {% endtab %}

{% tab title="Return" %}
A signed transaction.
{% endtab %}
{% endtabs %}

### remove\_builder\_transaction

Destroy a transaction builder.

```cpp
void graphene::wallet::wallet_api::remove_builder_transaction(
    transaction_handle_typehandle)
```

{% tabs %}
{% tab title="Parameters" %}

* **`handle`**: handle of the transaction builder
  {% endtab %}
  {% endtabs %}

### serialize\_transaction

Converts a signed\_transaction in JSON form to its binary representation.

```cpp
string graphene::wallet::wallet_api::serialize_transaction(
    signed_transaction tx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`tx`**: the transaction to serialize
  {% endtab %}

{% tab title="Return" %}
The binary form of the transaction. It will not be hex encoded, this returns a raw string that may have null characters embedded in it
{% endtab %}
{% endtabs %}

### **sign\_transaction**

Signs a transaction.

Given a fully-formed transaction that is only lacking signatures, this signs the transaction with the necessary keys and optionally broadcasts the transactio&#x6E;**.**

```cpp
signed_transaction graphene::wallet::wallet_api::sign_transaction(
    signed_transaction tx, 
    bool broadcast = false)
```

{% tabs %}
{% tab title="Parameters" %}

* **`tx`**: the unsigned transaction
* **`broadcast`**: true if you wish to broadcast the transaction
  {% endtab %}

{% tab title="Return" %}
The signed version of the transaction
{% endtab %}
{% endtabs %}

### get\_prototype\_operation

Returns an uninitialized object representing a given blockchain operation.

This returns a default-initialized object of the given type; it can be used during early development of the wallet when we don’t yet have custom commands for creating all of the operations the blockchain supports.

Any operation the blockchain supports can be created using the transaction builder’s [`add_operation_to_builder_transaction()`](/api/peerplays-wallet-api/transaction-builder#add_operation_to_builder_transaction) , but to do that from the CLI you need to know what the JSON form of the operation looks like. This will give you a template you can fill in. It’s better than nothing.

```cpp
operation graphene::wallet::wallet_api::get_prototype_operation(
    string operation_type)
```

{% tabs %}
{% tab title="Parameters" %}

* **`operation_type`**: the type of operation to return, must be one of the operations defined in `graphene/protocol/operations.hpp` (e.g., “global\_parameters\_update\_operation”)
  {% endtab %}

{% tab title="Return" %}
A default-constructed operation of the given type.
{% endtab %}
{% endtabs %}


# Wallet Calls

## Wallet Calls

### is\_new

Checks whether the wallet has just been created and has not yet had a password set.

Calling `set_password` will transition the wallet to the locked state.

```cpp
bool graphene::wallet::wallet_api::is_new()const
```

{% tabs %}
{% tab title="Return" %}
*True* if the wallet is new.
{% endtab %}
{% endtabs %}

### is\_locked

Checks whether the wallet is locked (is unable to use its private keys).

This state can be changed by calling [`lock()`](/api/peerplays-wallet-api/wallet-calls#lock) or [`unlock()`](/api/peerplays-wallet-api/wallet-calls#unlock)

```cpp
bool graphene::wallet::wallet_api::is_locked()const
```

{% tabs %}
{% tab title="Return" %}
*True* if the wallet is locked
{% endtab %}
{% endtabs %}

### lock

Locks the wallet immediately.

```cpp
void graphene::wallet::wallet_api::lock()
```

### unlock

Unlocks the wallet.

The wallet remain unlocked until the `lock` is called or the program exits.

When used in command line, if typed “unlock” without a password followed, the user will be prompted to input a password without echo.

```cpp
void graphene::wallet::wallet_api::unlock(
    string password)
```

{% tabs %}
{% tab title="Parameters" %}

* **`password`**: the password previously set with [`set_password()`](https://dev.bitshares.works/en/master/api/wallet_api.html?highlight=set_voting_proxy#classgraphene_1_1wallet_1_1wallet__api_1a2a5d174ec4fde8633b8e962fabc00804)
  {% endtab %}
  {% endtabs %}

### **set\_password**

Sets a new password on the wallet.

The wallet must be either ‘new’ or ‘unlocked’ to execute this command.

When used in command line, if typed “set\_password” without a password followed, the user will be prompted to input a password without echo.

```cpp
void graphene::wallet::wallet_api::set_password(
    string password)
```

{% tabs %}
{% tab title="Parameters" %}

* **`password`**: a new password
  {% endtab %}
  {% endtabs %}

### **dump\_private\_keys**

Dumps all private keys owned by the wallet.

The keys are printed in WIF format. You can import these keys into another wallet using [`import_key()`](/api/peerplays-wallet-api/wallet-calls#import_key)

```cpp
map<public_key_type, string> graphene::wallet::wallet_api::dump_private_keys()
```

{% tabs %}
{% tab title="Return" %}
A map containing the private keys, indexed by their public key
{% endtab %}
{% endtabs %}

### import\_key

Imports the private key for an existing account.

The private key must match either an owner key or an active key for the named account.

See also [`dump_private_keys()`](/api/peerplays-wallet-api/wallet-calls#dump_private_keys)

```cpp
bool graphene::wallet::wallet_api::import_key(
    string account_name_or_id, 
    string wif_key)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: the account owning the key
* **`wif_key`**: the private key in WIF format
  {% endtab %}

{% tab title="Return" %}
*true* if the key was imported
{% endtab %}
{% endtabs %}

### import\_accounts

Imports accounts from a Peerplays 0.x wallet file. Current wallet file must be unlocked to perform the import.

```cpp
map<string, bool> graphene::wallet::wallet_api::import_accounts(
    string filename, 
    string password)
```

{% tabs %}
{% tab title="Parameters" %}

* **`filename`**: the Peerplays 0.x wallet file to import
* **`password`**: the password to encrypt the Peerplays 0.x wallet file
  {% endtab %}

{% tab title="Return" %}
A map containing the accounts found and whether imported.
{% endtab %}
{% endtabs %}

### import\_account\_keys

Imports from a Peerplays 0.x wallet file, find keys that were bound to a given account name on the Peerplays 0.x chain, rebind them to an account name on the 2.0 chain. Current wallet file must be unlocked to perform the import.

```cpp
bool graphene::wallet::wallet_api::import_account_keys(
    string filename, 
    string password, 
    string src_account_name, 
    string dest_account_name)
```

{% tabs %}
{% tab title="First Tab" %}

* **`filename`**: the Peerplays 0.x wallet file to import
* **`password`**: the password to encrypt the Peerplays 0.x wallet file
* **`src_account_name`**: name of the account on Peerplays 0.x chain
* **`dest_account_name`**: name of the account on Peerplays 2.0 chain, can be same or different to `src_account_name`
  {% endtab %}

{% tab title="Return" %}
Whether the import has succeeded
{% endtab %}
{% endtabs %}

### import\_balance

This call will construct transaction(s) that will claim all balances controlled by wif\_keys and deposit them into the given account.

```cpp
vector<signed_transaction> graphene::wallet::wallet_api::import_balance(
    string account_name_or_id, 
    const vector<string> &wif_keys, 
    bool broadcast)
```

{% tabs %}
{% tab title="Parameters" %}

* **`account_name_or_id`**: name or ID of an account that to claim balances to
* **`wif_keys`**: private WIF keys of balance objects to claim balances from
* **`broadcast`**: true to broadcast the transaction on the network
  {% endtab %}
  {% endtabs %}

### suggest\_brain\_key

Suggests a safe brain key to use for creating your account. [`create_account_with_brain_key()`](/api/peerplays-wallet-api/account-calls#create_account_with_brain_key) requires you to specify a ‘brain key’, a long passphrase that provides enough entropy to generate cryptographic keys.&#x20;

This function will suggest a suitably random string that should be easy to write down (and, with effort, memorize).

```cpp
brain_key_info graphene::wallet::wallet_api::suggest_brain_key()const
```

{% tabs %}
{% tab title="Return" %}
A suggested brain\_key
{% endtab %}
{% endtabs %}

### get\_transaction\_id

This method is used to convert a JSON transaction to its transacting ID.

```cpp
transaction_id_type graphene::wallet::wallet_api::get_transaction_id(
    const signed_transaction &trx)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`trx`**: a JSON transaction
  {% endtab %}

{% tab title="Return" %}
The ID (hash) of the transaction.
{% endtab %}
{% endtabs %}

### **get\_private\_key**

Get the WIF private key corresponding to a public key. The private key must already be in the wallet.

```cpp
string graphene::wallet::wallet_api::get_private_key(
    public_key_type pubkey)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`pubkey`**: a public key in Base58 format
  {% endtab %}

{% tab title="Return" %}
**T**he WIF private key
{% endtab %}
{% endtabs %}

### **load\_wallet\_file**

Loads a specified Graphene wallet.

The current wallet is closed before the new wallet is loaded.

{% hint style="danger" %}
**Important:** This does not change the filename that will be used for future wallet writes, so this may cause you to overwrite your original wallet unless you also call `set_wallet_filename()`
{% endhint %}

```cpp
bool graphene::wallet::wallet_api::load_wallet_file(
    string wallet_filename = "")
```

{% tabs %}
{% tab title="Parameters" %}

* **`wallet_filename`**: the filename of the wallet JSON file to load. If `wallet_filename` is empty, it reloads the existing wallet file.
  {% endtab %}

{% tab title="Return" %}
*True* if the specified wallet is loaded.
{% endtab %}
{% endtabs %}

### normalize\_brain\_key

Transforms a brain key to reduce the chance of errors when re-entering the key from memory.

This takes a user-supplied brain key and normalizes it into the form used for generating private keys. In particular, this upper-cases all ASCII characters and collapses multiple spaces into one.

```cpp
string graphene::wallet::wallet_api::normalize_brain_key(
    string s)const
```

{% tabs %}
{% tab title="Parameters" %}

* **`s`**: the brain key as supplied by the user
  {% endtab %}

{% tab title="Return" %}
The brain key in its normalized form.
{% endtab %}
{% endtabs %}

### **save\_wallet\_file**

Saves the current wallet to the given filename.

{% hint style="danger" %}
**Important:** This does not change the wallet filename that will be used for future writes, so think of this function as ‘Save a Copy As…’ instead of ‘Save As…’. Use `set_wallet_filename()` to make the filename persist.
{% endhint %}

```cpp
void graphene::wallet::wallet_api::save_wallet_file(
    string wallet_filename = "")
```

{% tabs %}
{% tab title="Parameters" %}

* **`wallet_filename`**: the filename of the new wallet JSON file to create or overwrite. If `wallet_filename` is empty, save to the current filename.
  {% endtab %}
  {% endtabs %}


# Bookie API

{% content-ref url="/pages/-Lz-cHnNlvBZAcvC-rjg" %}
[General](/api/bookie-api/general)
{% endcontent-ref %}

{% content-ref url="/pages/-Lz-cLdKL77JQc78Ywwp" %}
[Tournaments](/api/bookie-api/tournaments)
{% endcontent-ref %}

{% content-ref url="/pages/-Lz-cR6Pqp8TivB-d8xO" %}
[Listeners](/api/bookie-api/listeners)
{% endcontent-ref %}


# General

This page documents the BookiePro data abstraction layer with the Peerplays blockchain.&#x20;

BookiePro communicates with the blockchain using web-socket API calls.

### list\_sports

Get a list of available sports.

```javascript
Apis.instance().db_api().exec( "list_sports", [] )
```

{% tabs %}
{% tab title="Return" %}
A list of all the available sports.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getSportsList = function getSportsList() {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().db_api().exec('list_sports', []).then(function (sportsList) {
        if (sportsList) {
          resolve(sportsList);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### list\_event\_groups

Get a list of all event groups for a sport, for example, all soccer leagues in soccer.

```javascript
Apis.instance().db_api().exec( "list_event_groups", [sportId] )
```

{% tabs %}
{% tab title="Parameters" %}
`sportId`: The id of the sport that the event groups are to be listed for.
{% endtab %}

{% tab title="Return" %}
A list of all event groups for the selected sport.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getEventGroupsList = function getEventGroupsList(sportId) {
    var _this17 = this;

    var eventGroupsList = this.event_groups_list_by_sport_id.get(sportId);

    if (eventGroupsList === undefined) {
      this.event_groups_list_by_sport_id = this.event_groups_list_by_sport_id.set(sportId, _immutable2.default.Set());

      _ws.Apis.instance().db_api().exec('list_event_groups', [sportId]).then(function (eventGroups) {
        var set = new Set();

        for (var i = 0, len = eventGroups.length; i < len; ++i) {
          set.add(eventGroups[i]);
        }

        _this17.event_groups_list_by_sport_id = _this17.event_groups_list_by_sport_id.set(sportId, _immutable2.default.Set(set));
        _this17.notifySubscribers();
      }, function () {
        _this17.event_groups_list_by_sport_id = _this17.event_groups_list_by_sport_id.delete(sportId);
      });
    }

    return this.event_groups_list_by_sport_id.get(sportId);
  };
```

{% endtab %}
{% endtabs %}

### list\_betting\_market\_groups

Get a list of all betting market groups for an event, for example, Moneyline and OVER/UNDER for soccer)

```javascript
Apis.instance().db_api().exec( "list_betting_market_groups", [eventId] )
```

{% tabs %}
{% tab title="Parameters" %}
`eventId`: The id of the event that the betting market groups are to be listed for.
{% endtab %}

{% tab title="Return" %}
A list of all the betting market groups for the event.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getBettingMarketGroupsList = function getBettingMarketGroupsList(eventId) {
    var _this18 = this;

    var bettingMarketGroupsList = this.betting_market_groups_list_by_sport_id.get(eventId);

    if (bettingMarketGroupsList === undefined) {
      this.betting_market_groups_list_by_sport_id = this.betting_market_groups_list_by_sport_id.set(eventId, _immutable2.default.Set());

      _ws.Apis.instance().db_api().exec('list_betting_market_groups', [eventId]).then(function (bettingMarketGroups) {
        var set = new Set();

        for (var i = 0, len = bettingMarketGroups.length; i < len; ++i) {
          set.add(bettingMarketGroups[i]);
        }

        _this18.betting_market_groups_list_by_sport_id = _this18.betting_market_groups_list_by_sport_id.set( // eslint-disable-line
        eventId, _immutable2.default.Set(set));
        _this18.notifySubscribers();
      }, function () {
        _this18.betting_market_groups_list_by_sport_id = _this18.betting_market_groups_list_by_sport_id.delete( // eslint-disable-line
        eventId);
      });
    }

    return this.betting_market_groups_list_by_sport_id.get(eventId);
  };
```

{% endtab %}
{% endtabs %}

### list\_betting\_markets

Get a list of all betting markets for a betting market group (BMG).

```javascript
Apis.instance().db_api().exec( "list_betting_markets", [bettingMarketGroupId] )
```

{% tabs %}
{% tab title="Parameters" %}
`bettingMarketGroupId:` The id of the betting market group that the betting markets are to be listed for.
{% endtab %}

{% tab title="Return" %}
A list of all the betting markets for the betting market group.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getBettingMarketsList = function getBettingMarketsList(bettingMarketGroupId) {
    var _this19 = this;

    var bettingMarketsList = this.betting_markets_list_by_sport_id.get(bettingMarketGroupId);

    if (bettingMarketsList === undefined) {
      this.betting_markets_list_by_sport_id = this.betting_markets_list_by_sport_id.set(bettingMarketGroupId, _immutable2.default.Set());

      _ws.Apis.instance().db_api().exec('list_betting_markets', [bettingMarketGroupId]).then(function (bettingMarkets) {
        var set = new Set();

        for (var i = 0, len = bettingMarkets.length; i < len; ++i) {
          set.add(bettingMarkets[i]);
        }

        _this19.betting_markets_list_by_sport_id = _this19.betting_markets_list_by_sport_id.set(bettingMarketGroupId, _immutable2.default.Set(set));
        _this19.notifySubscribers();
      }, function () {
        _this19.betting_markets_list_by_sport_id = _this19.betting_markets_list_by_sport_id.delete(bettingMarketGroupId);
      });
    }

    return this.betting_markets_list_by_sport_id.get(bettingMarketGroupId);
  };
```

{% endtab %}
{% endtabs %}

### get\_global\_betting\_statistics

Get global betting statistics

```javascript
Apis.instance().db_api().exec( "get_global_betting_statistics", [] )
```

{% tabs %}
{% tab title="Return" %}
A list of all the global betting statistics.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getGlobalBettingStatistics = function getGlobalBettingStatistics() {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().db_api().exec('get_global_betting_statistics', []).then(function (getGlobalBettingStatistics) {
        if (getGlobalBettingStatistics) {
          resolve(getGlobalBettingStatistics);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_binned\_order\_book

Get the binned order book for a betting market.

```javascript
Apis.instance().bookie_api().exec( "get_binned_order_book", [ betting_market_id, precision ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `betting_market_id:` The id of the betting market for the order book.
* `precision:` Precision
  {% endtab %}

{% tab title="Return" %}
A list of binned orders for the betting market.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getBinnedOrderBook = function getBinnedOrderBook(betting_market_id, precision) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().bookie_api().exec('get_binned_order_book', [betting_market_id, precision]).then(function (order_book_object) {
        if (order_book_object) {
          resolve(order_book_object);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_total\_matched\_bet\_amount\_for\_betting\_market\_group

Get the total matched bets for a betting market group (BMG).

```javascript
Apis.instance().bookie_api().exec( "get_total_matched_bet_amount_for_betting_market_group", [ group_id ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `group_id`: The betting market group id.
  {% endtab %}

{% tab title="Return" %}
Total of all the matched bet amounts for the selected betting market group.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getTotalMatchedBetAmountForBettingMarketGroup = function getTotalMatchedBetAmountForBettingMarketGroup(group_id) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().bookie_api().exec('get_total_matched_bet_amount_for_betting_market_group', [group_id]).then(function (total_matched_bet_amount) {
        if (total_matched_bet_amount) {
          resolve(total_matched_bet_amount);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### **get\_events\_containing\_sub\_string**

Used to search for events.

```javascript
Apis.instance().bookie_api().exec( "get_events_containing_sub_string", [ sub_string, language ])
```

{% tabs %}
{% tab title="Parameters" %}

* `sub_string:` The (sub) string of text to search for
* `language`: Language id.
  {% endtab %}

{% tab title="Return" %}
List of events that contain the `sub-string`
{% endtab %}

{% tab title="Code" %}

```javascript
function getEventsContainingSubString(sub_string, language) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().bookie_api().exec('get_events_containing_sub_string', [sub_string, language]).then(
        function (events_containing_sub_string) {
        if (events_containing_sub_string) {
          resolve(events_containing_sub_string);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_unmatched\_bets\_for\_bettor

Get unmatched bets for a bettor.

```javascript
Apis.instance().bookie_api().exec( "get_matched_bets_for_bettor", [ bettor_id ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `bettor_id`: The id of the bettor.
  {% endtab %}

{% tab title="Return" %}
List of all matched bets for a bettor.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getUnmatchedBetsForBettor = function getUnmatchedBetsForBettor(betting_market_id_type, account_id_type) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().db_api().exec('get_unmatched_bets_for_bettor', [betting_market_id_type, account_id_type]).then(function (unmatched_bets_for_bettor) {
        if (unmatched_bets_for_bettor) {
          resolve(unmatched_bets_for_bettor);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### list\_events\_in\_group

Get a list of events in any event group.

```javascript
Apis.instance().db_api().exec( "list_events_in_group", [ event_group_id ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `event_group_id`: The id of the event group.
  {% endtab %}

{% tab title="Return" %}
A list of all the events in the event group.
{% endtab %}

{% tab title="Code" %}

```javascript
 ChainStore.listEventsInGroup = function listEventsInGroup(event_group_id) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().db_api().exec('list_events_in_group', [event_group_id]).then(function (events_in_group) {
        if (events_in_group) {
          resolve(events_in_group);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_all\_unmatched\_bets\_for\_bettor

Get all unmatched bets of a bettor according to account type.

```javascript
Apis.instance().db_api().exec( "get_all_unmatched_bets_for_bettor", [ account_id_type ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `account_type_id`: The id of the bettor account type/
  {% endtab %}

{% tab title="Return" %}
All unmatched bets by bettor account type.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getAllUnmatchedBetsForBettor = function getAllUnmatchedBetsForBettor(account_id_type) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().db_api().exec('get_all_unmatched_bets_for_bettor', [account_id_type]).then(function (all_unmatched_bets_for_bettor) {
        if (all_unmatched_bets_for_bettor) {
          resolve(all_unmatched_bets_for_bettor);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_matched\_bets\_for\_bettor

Get the matched bets for a bettor.

```javascript
Apis.instance().bookie_api().exec( "get_matched_bets_for_bettor", [ bettor_id ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `bettor_id`: The id of the bettor.
  {% endtab %}

{% tab title="Return" %}
All matched bets for the bettor.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getMatchedBetsForBettor = function getMatchedBetsForBettor(bettor_id) {
    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().bookie_api().exec('get_matched_bets_for_bettor', [bettor_id]).then(function (matched_bets_for_bettor) {
        if (matched_bets_for_bettor) {
          resolve(matched_bets_for_bettor);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}

### get\_all\_matched\_bets\_for\_bettor

Get all matched bets for a bettor within a range.

```javascript
Apis.instance().bookie_api().exec( "get_all_matched_bets_for_bettor", [ bettor_id, start, limit ] )
```

{% tabs %}
{% tab title="Parameters" %}

* `bettor_id`: The id of the bettor
* `start`: The start date
* `limit`: Number of bets to be returned
  {% endtab %}

{% tab title="Return" %}
All matched bets for the better within the range `start` to `limit.`
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.getAllMatchedBetsForBettor = function getAllMatchedBetsForBettor(bettor_id, start) {
    var limit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1000;

    return new Promise(function (resolve, reject) {
      _ws.Apis.instance().bookie_api().exec('get_all_matched_bets_for_bettor', [bettor_id, start, limit]).then(function (all_matched_bets_for_bettor) {
        if (all_matched_bets_for_bettor) {
          resolve(all_matched_bets_for_bettor);
        } else {
          resolve(null);
        }
      }, reject);
    });
  };
```

{% endtab %}
{% endtabs %}


# Tournaments

### get\_tournaments\_in\_state

Get a list of tournament ids for upcoming tournaments

```javascript
Apis.instance().db_api().exec('get_tournaments_in_state', [stateString, accountId])
```

{% tabs %}
{% tab title="Parameters" %}

* `stateString`: The tournament state
* `accountId`:Account Id
  {% endtab %}

{% tab title="Return" %}
All tournaments for the selected state.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getTournamentIdsInState = function getTournamentIdsInState(accountId, stateString) {
    var _this7 = this;

    var tournamentIdsForThisAccountAndState = void 0;
    var tournamentIdsForThisAccount = this.tournament_ids_by_state.get(accountId);

    if (tournamentIdsForThisAccount === undefined) {
      tournamentIdsForThisAccountAndState = new _immutable2.default.Set();
      tournamentIdsForThisAccount = new _immutable2.default.Map().set(stateString, tournamentIdsForThisAccountAndState);
      this.tournament_ids_by_state = this.tournament_ids_by_state.set(accountId, tournamentIdsForThisAccount);
    } else {
      tournamentIdsForThisAccountAndState = tournamentIdsForThisAccount.get(stateString);

      if (tournamentIdsForThisAccountAndState !== undefined) {
        return tournamentIdsForThisAccountAndState;
      }

      tournamentIdsForThisAccountAndState = new _immutable2.default.Set();
      tournamentIdsForThisAccount = tournamentIdsForThisAccount.set(stateString, tournamentIdsForThisAccountAndState);
      this.tournament_ids_by_state = this.tournament_ids_by_state.set(accountId, tournamentIdsForThisAccount);
    }

    _ws.Apis.instance().db_api().exec('get_tournaments_in_state', [stateString, 100]).then(function (tournaments) {
      var originalTournamentIdsInState = _this7.tournament_ids_by_state.getIn([accountId, stateString]);
      // call updateObject on each tournament, which will classify it
      tournaments.forEach(function (tournament) {
        /**
         * Fix bug: we cant update tournament_ids_by_state if objects_by_id has a tournament
         */
        if (!originalTournamentIdsInState.get(tournament.id)) {
          _this7.clearObjectCache(tournament.id);
        }

        _this7._updateObject(tournament);
      });

      var tournament_id = _this7.tournament_ids_by_state.getIn([accountId, stateString]);

      if (tournament_id !== originalTournamentIdsInState) {
        _this7.notifySubscribers();
      }
    });
    return tournamentIdsForThisAccountAndState;
  };
```

{% endtab %}
{% endtabs %}

### get\_registered\_tournaments

Get a list of registered tournaments by account id.

```javascript
Apis.instance().db_api().exec('get_registered_tournaments', [accountId, 100])
```

{% tabs %}
{% tab title="Parameters" %}

* `accountId`: Account Id.
  {% endtab %}

{% tab title="Return" %}
All registered tournaments for an account.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getRegisteredTournamentIds = function getRegisteredTournamentIds(accountId) {
    var _this8 = this;

    var tournamentIds = this.registered_tournament_ids_by_player.get(accountId);

    if (tournamentIds !== undefined) {
      return tournamentIds;
    }

    tournamentIds = new _immutable2.default.Set();
    this.registered_tournament_ids_by_player = this.registered_tournament_ids_by_player.set(accountId, tournamentIds);

    _ws.Apis.instance().db_api().exec('get_registered_tournaments', [accountId, 100]).then(function (registered_tournaments) {
      var originalTournamentIds = _this8.registered_tournament_ids_by_player.get(accountId);
      var newTournamentIds = new _immutable2.default.Set(registered_tournaments);

      if (!originalTournamentIds.equals(newTournamentIds)) {
        _this8.registered_tournament_ids_by_player = _this8.registered_tournament_ids_by_player.set(accountId, newTournamentIds);
        _this8.notifySubscribers();
      }
    });

    return tournamentIds;
  };

```

{% endtab %}
{% endtabs %}

### get\_tournaments

Get all tournaments between `last_tournament_id` and `start_tournament_id`.

```javascript
 _ws.Apis.instance().db_api().exec('get_tournaments', [last_tournament_id, limit, start_tournament_id])
```

{% tabs %}
{% tab title="Parameters" %}

* `last_tournament_id`: The last tournament id
* `limit`: The limit of tournaments to return.
* `start_tournament_id`: The starting tournament id.
  {% endtab %}

{% tab title="Return" %}
A list of all tournaments between `last_tournament_id` and `start_tournament_id`.
{% endtab %}

{% tab title="Code" %}

```javascript
ChainStore.prototype.getTournaments = function getTournaments(last_tournament_id) {
    var _this20 = this;

    var limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
    var start_tournament_id = arguments[2];

    return _ws.Apis.instance().db_api().exec('get_tournaments', [last_tournament_id, limit, start_tournament_id]).then(function (tournaments) {
      var list = _immutable2.default.List();

      _this20.setLastTournamentId(null);

      if (tournaments && tournaments.length) {
        list = list.withMutations(function (l) {
          tournaments.forEach(function (tournament) {
            if (!_this20.objects_by_id.has(tournament.id)) {
              _this20._updateObject(tournament);
            }

            l.unshift(_this20.objects_by_id.get(tournament.id));
          });
        });
      }

      return list;
    });
  };
```

{% endtab %}
{% endtabs %}


# Listeners

### **subscribe\_to\_market**

Subscribe a listener to a betting market.

```javascript
Apis.instance().db_api().exec( "subscribe_to_market", [updateListener, "1.3.0", "1.3.19"])
```

{% tabs %}
{% tab title="Parameters" %}

* `updateListener`: An object of type updateListener.
* `1.3.0:` Start version.
* `1.3.19:` End version.
  {% endtab %}
  {% endtabs %}

### **unsubscribe\_from\_market**

Unsubscribe a listener from a betting market.

```javascript
Apis.instance().db_api().exec( "unsubscribe_from_market", [updateListener, "1.3.0", "1.3.19"])
```

{% tabs %}
{% tab title="Parameters" %}

* `updateListener`: An object of type updateListener.
* `1.3.0:` Start version.
* `1.3.19:` End version.
  {% endtab %}
  {% endtabs %}


# Python Peerplays

Introduction

Its the Python library for communicating with the Peerplays blockchain.

The code is maintained at <https://gitlab.com/PBSA/PeerplaysIO/tools-libs/python-peerplays>

### Ids

`1.2.x : accounts`

`1.3.x : assets`

#### Notes

```
def transfer(self, to, amount, asset, memo="", account=None, **kwargs):
```

`p.rpc.get_account_balances("jemshid", [])`

`p.rpc.get_global_properties`

`private-key = ["TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"]`


# Installation

The python-peerplays library has following dependencies. Make sure that the above dependencies are installed, if not install with:

```
sudo apt-get install python3-dev build-essential libssl-dev\
 libffi-dev libxml2-dev libxslt1-dev zlib1g-dev
```

Now install python-peerplays as follows:

```
 pip install peerplays
```

Ipython is a rich interactive python command shell. It's recommended for trying out python-peerplays library. It can be installed with

`pip install ipython`&#x20;

In case Python 2.7 is the default Python for your machine, repalce

pip with pip3

python with python3

ipython with ipython3

Ipython shell can be started with the command

`ipython`

{% hint style="info" %}
To work with the latest development version of python-peerplays

`git clone git@gitlab.com:PBSA/PeerplaysIO/tools-libs/python-peerplays.git`

`cd python-peerplays`

`git checkout develop`

{% endhint %}

## `To Do`

1. How to install system level from git for develop branch


# Creating the wallet

All these experiments and examples are expected to be tried out in ipython command shell. Start the command shell with `ipython`

Node is the chain with which you wish to interact.

```
node = "wss://elizabeth.peerplays.download/api"
```

`password = "password"`

`from peerplays import PeerPlays`

```
p = PeerPlays(node)
```

To create a new wallet

`p.newWallet(password)`

Unlock the wallet

`p.unlock(password)`

Add private key / keys

`p.wallet.addPrivateKey("5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3")`

## Additional Methods

`p.wallet.unlocked() #returns True if wallet is unlocked. Wallet needs to be unlocked to perform operations on the blockchain.`

`p.wallet.getAccounts() #Lists all the accounts associated with the private key.`


# Creating an Account

vThere are two ways to create  an account.

1. Python-Peerplays way: If you already have an account, that can be used to create another account.
2. Faucet Way

### Python-Peerplays Way

You need a funded account to create additional accounts. The funded account should be upgraded to create new accounts. To upgrade an account

```
p.upgrade_account(account="account_name")
```

Once the account is upgraded

`p.create_account(account_name="new_account_name", registrar="the_upgraded_account", owner_key='TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV', active_key='TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV', memo_key='TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV')`

### Faucet Method

`url =` [`https://elizabeth-faucet.peerplays.download/api/v1/accounts`](https://elizabeth-faucet.peerplays.download/api/v1/accounts)

```
params = {'account': {
    'name': 'new_account_name',
    'owner_key': 'TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV',
    'active_key': 'TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV',
    'memo_key': 'TEST6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV',
    'refcode': '',
    'referrer': ''}}
    
```

`requests.post(url, json=params)`

## Additional Methods

```
p.transfer(to, amount, asset, memo="", account=None)
```


# NFT

Non Fungible Tokens

### Operations

#### Create NFT Meta

```
p.nft_metadata_create(
    owner_account_id_or_name,        # owner of nft meta
    name,                            # nft meta name
    symbol,                          # nft symbol
    base_uri,                        # nft uri
    is_transferable=True,
    is_sellable=True,
    )
```

For example

```
p.nft_metadata_create("1.2.7", self.nameMetadata, self.nameMetadata, self.nameMetadata, revenue_partner="1.2.8", revenue_split=300, is_sellable=False, is_transferable=False)
```

#### Update NFT Meta

```
p.nft_metadata_update(
    owner_account_id_or_name,
    nft_metadata_id,
    name,
    symbol,
    base_uri,
    is_transferable=True,
    is_sellable=True,
    )
```

For example

```
p.nft_metadata_update("1.2.7", "1.30.11", self.nameMetadata + "m", self.nameMetadata + "m", self.nameMetadata + "m", "1.2.9", 400, True, True)
```

#### Mint NFT

```
p.nft_mint(
    metadata_owner_account_id_or_name,
    metadata_id, 
    owner_account_id_or_name,
    approved_account_id_or_name,
    approved_operators,                     # list of operators
    token_uri,
    )
```

For example&#x20;

```
p.nft_mint("1.2.7", "1.30.11", "1.2.7", "1.2.7", "1.2.7", self.nameNft)
```

#### Transfer NFT

```
p.nft_safe_transfer_from(
    operator_,                # operator account name or id
    from_,
    to_,
    token_id,
    data,                     # notes as string
    )
```

For example

```
p.nft_safe_transfer_from("1.2.7", "1.2.7", "1.2.9", "1.31.5", "whatever")
```

#### Approve Control over NFT

```
def nft_approve(
    operator_,
    approved,         # approved account id or name
    token_id,
    )
```

For example&#x20;

```
p.nft_approve("1.2.9", "1.2.8", "1.31.5")
```

#### Approve for all the tokens owned

```
def nft_set_approval_for_all(
    owner,
    operator_,
    approved,
    )
```

For example

```
p.nft_set_approval_for_all("1.2.7", "1.2.10", True)
```

#### Info calls

`p.rpc.nft_get_balance(owner)`&#x20;

`p.rpc.nft_owner_of(token_id)`

`p.rpc.nft_get_approved(token_id)`

`p.rpc.nft_is_approved_for_all(owner, operator)`

`p.rpc.nft_get_name(nft_metadata_id)`

`p.rpc.nft_get_symbol(nft_metadata_id)`

`p.rpc.nft_get_token_uri(token_id)`

`p.rpc.nft_get_total_supply(nft_metadata_id)`

`p.rpc.nft_token_by_index(nft_metadata_id, token_idx)`

`p.rpc.nft_token_of_owner_by_index(nft_metadata_id, owner, token_idx)`

`p.rpc.nft_get_all_tokens()`

`p.rpc.nft_get_tokens_by_owner(owner)`

#### Additional Info

For examples, refer to  `tests/test_nft.py` &#x20;


# Market Place

### Operations

#### Create Offer

```
p.create_offer(
    item_ids,                  # list of items
    issuer_id_or_name,
    minimum_price,             # asset type
    maximum_price,             # asset type
    buying_item,               # bool
    offer_expiration_date,     # "2020-09-18T11:05:39"
    memo=None,                 # optional
    )
```

For example

```
p.create_offer(["1.31.5"], "1.2.9", {"amount":5,"asset_id":"1.3.0"}, {"amount":15,"asset_id":"1.3.0"}, False, "2030-09-18T11:05:39", "") 
```

#### Bid

```
p.create_bid(
    bidder_account_id_or_name,
    bid_price,                     # asset
    offer_id,                      # offer_id type, 1.29.x
    )
```

For example

```
p.create_bid("1.2.10", {"amount":8,"asset_id":"1.3.0"}, offer["id"]) 
```

#### Cancel Offer

```
p.cancel_offer(
    issuer_account_id_or_name,
    offer_id,                     # offer_id type, 1.29.x
    )
```

For example

```
p.cancel_offer("1.2.9", offer["id"]) 
```

####

#### Calls for info

```
p.rpc.list_offers(lower_id, limit)   # limt is number of entries requested as integer
p.rpc.list_sell_offers(lower_id, limit)
p.rpc.list_buy_offers(lower_id, limit)
p.rpc.list_offer_history(lower_id, limit)
p.rpc.get_offers_by_issuer(lower_id, issuer_account_id, limit)
p.rpc.get_offers_by_item(lower_id, nft_id_type_item, limit)
p.rpc.get_offer_history_by_issuer(lower_id, issuer_account_id, limit)
p.rpc.get_offer_history_by_item(lower_id, item, limit)
p.rpc.get_offer_history_by_bidder(lower_id, bidder_account_id, limit)
```

#### Additional Info

For examples, refer to  `tests/test_market_place.py` &#x20;


# HRP / RBAC

### Operations

#### Create Custom Permission

```
p.custom_permission_create(
    permission_name,
    owner_account=None,
    weight_threshold=[],
    account_auths=[],
    key_auths=[],
    address_auths=[],
    )
```

For example&#x20;

```
    p.custom_permission_create(
        testperm1,
        owner_account="1.2.7",
        weight_threshold=1,
        account_auths=[["1.2.8", 1]])
```

#### Custom Permission Update

```
p.custom_permission_update(
    permission_id,
    owner_account=None,
    weight_threshold=[],
    account_auths=[],
    key_auths=[],
    address_auths=[],
    )
```

For example

```
            p.custom_permission_update(
                    permission_id,
                    weight_threshold=1,
                    account_auths=[["1.2.9", 2]],
                    owner_account="1.2.7"
            )
```

#### Custom Permission Delete

```
p.custom_permission_delete(
    permission_id,
    owner_account=None,
    )
```

For example

```
            p.custom_permission_delete(
                    permission_id,
                    owner_account="1.2.7"
            )
```

#### Custom Account Authority Create

```
p.custom_account_authority_create(
    permission_id,
    operation_type,
    valid_from,
    valid_to,
    owner_account=None,
    )
```

For example

```
p.custom_account_authority_create(
                    permission_id,
                    0,
                    "2020-07-27T00:00:00",
                    "2030-07-27T00:00:00",
                    owner_account="1.2.7") 
```

#### Custom Account Authority Update

```
p.custom_account_authority_update(
    auth_id,
    new_valid_from,
    new_valid_to,
    owner_account=None,
    )
```

For example

```
p.custom_account_authority_update(
            authority_id,
            "2020-07-27T00:00:00",
            "2040-07-27T00:00:00",
            owner_account="1.2.7")
```

#### Custom Account Authority Delete

```
p.custom_account_authority_delete(
    auth_id,
    owner_account=None,
    )
```

For example

```
    p.custom_account_authority_delete(
            authority_id,
            owner_account="1.2.7")
```

### RPC Info calls

```
get_custom_permissions(account)
get_custom_permission_by_name(account, permission_name)
get_custom_account_authorities(account)
get_custom_account_authorities_by_permission_id(permission_id)
get_custom_account_authorities_by_permission_name(account, permission_name)
get_active_custom_account_authorities_by_operation(account, int operation_type)
```


# Connecting Elasticsearch to a blockchain node

### Editing the configuration for Elasticsearch <a href="#id-3.-editing-the-configuration-for-elasticsearch" id="id-3.-editing-the-configuration-for-elasticsearch"></a>

Inside ./witness\_node\_data\_dir/config.ini edit the following:

Uncomment `plugins =` and add the `elasticsearch` and `es_object` plugins.

```
# Space-separated list of plugins to activate 
plugins = elasticsearch es_objects
```

Uncomment `elasticsearch-node-url =` and add the Endpoint URL for your Elasticsearch instance.

Make sure to keep the trailing slash at the end of the URL.

```
# Elastic Search database node url(http://localhost:9200/) 
elasticsearch-node-url = <ES-ENDPOINT>
```

Uncomment `es-objects-elasticsearch-url =` and add the Endpoint URL for your Elasticsearch instance.

Make sure to keep the trailing slash at the end of the URL.

```
# Elasticsearch node url(http://localhost:9200/) 
es-objects-elasticsearch-url = <ES-ENDPOINT>
```

### Start the witness node <a href="#id-4.-start-the-witness-node" id="id-4.-start-the-witness-node"></a>

Start the witness node to being pushing indexes to Elasticsearch. The beginning few logs should show the Elasticsearch plugins started:

```
572387ms th_a elasticsearch_plugin.cpp:516 plugin_startup ] elasticsearch ACCOUNT HISTORY: plugin_startup() begin
572387ms th_a application.cpp:1235 startup_plugins ] Plugin elasticsearch started
572395ms th_a es_objects.cpp:405 plugin_startup ] elasticsearch OBJECTS: plugin_startup() begin
572395ms th_a application.cpp:1235 startup_plugins ] Plugin es_objects started ...

575659ms th_a es_objects.cpp:82 genesis
```

## Basic Checks <a href="#basic-checks" id="basic-checks"></a>

You can check the indexes created after the witness start with the next call:

```
$ curl -X GET '<ES-ENDPOINT>/_cat/indices'
yellow open ppobjects-asset   vnF2F0BMSKKNxQfu013OCQ 1 1  2 0 12.4kb 12.4kb
yellow open ppobjects-balance 3psSvHIeRC-fKHyqP2Legg 1 1  1 0  5.9kb  5.9kb
yellow open ppobjects-account zQ7uv01ESEeqCED3WHmmxg 1 1 21 0 42.4kb 42.4kb
```

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MS-Gisdh7ZOfu3a1hrL%2F-MS-Ktd81IkyvsFkST9A%2Fimage.png?alt=media\&token=d4852574-8050-441b-a857-58fefd604be3)

You can also get index search data with:

```
curl -X GET '<ES-ENDPOINT>/peerplays-*/data/_search?pretty=true' -H 'Content-Type: application/json' 
```


# GitLab Ticket Templates

Templates for the different types of tickets in GitLab.

## 1. Overview

The following templates help document tickets (issues) in GitLab. They are a starting point and reference for anyone unfamiliar with the ticketing process. There are two main templates given here; one for reporting bugs, and one for the implementation of a User Story (new feature).

{% hint style="info" %}
**Required** fields listed below may not be required (strictly speaking) in GitLab when submitting a new ticket. The information in these fields are required for our team to handle bug fixes and new features with speed and efficiency. A few extra minutes of your time now can save the team hours or days in the long run.
{% endhint %}

## 2. Bug Tickets

A **bug** is a defect in something that already exists. When found, bugs need to be documented in tickets to be tracked like any other work item. Bugs are unique in that they can be difficult to reproduce, have obscure root causes, and may not present themselves in all contexts. This is why providing detailed tickets is key to solving these issues.

Key Elements of a Bug ticket:

1. **Title** (Required): Short title that clearly states the Bug.
2. **Type** (Required): `Issue` (for general work) or `Incident` (For investigating IT service disruptions or outages).
3. **Description** (Required): Detailed enough so that QA does not need to ask questions in order to test the ticket. This should include the following sections:
   1. Description: Describe the bug.
   2. Preconditions: If necessary in order to run the Scenario steps properly.
   3. Affected Version(s): If known, list the build(s) where the issue has been observed.
   4. Scenario: The steps to reproduce the issue. Should be clear, direct, and have enough details to be reproducible.
   5. Current Bugged Behavior: The observed issue as it actually happens.
   6. Expected Correct Behavior: The requirements that describe a successful outcome. Simply, what *should* happen.
   7. Attempted Fixes: What has already been done to try to solve the issue, and the results of the attempts.
   8. Possible Fixes: If possible, link to the line of code that might be responsible for the problem. Or list other insights into the problem.
   9. Attachments: This is the visual proof (screenshots, logs, video, etc.) of the existing issue. Any other useful information should be attached as well.
   10. Quick Actions: If necessary, use quick actions to relate issues to this ticket. (`/relate #issue1 #issue2`) See [Quick Actions](https://docs.gitlab.com/ee/user/project/quick_actions.html#issues-merge-requests-and-epics) for more info.
4. **Assignees**: If known, adding the appropriate individual(s) here will save time.
5. **Weight**: Estimate of the effort needed to solve the issue. See [Time Tracking > Weight](https://community.peerplays.tech/gitlab/time-tracking#weight) for more info.
6. **Epic**: If known, select the best related epic.
7. **Due Date**: Can be left blank. It's useful if the issue is blocking something with a deadline.
8. **Milestone**: If known, select the best related milestone.
9. **Labels** (Required): The following *three label types* must be provided, but others can be added if necessary. See [Labels > Scoped Labels](https://community.peerplays.tech/gitlab/labels#scoped-labels) for more info.
   1. Priority: (low, medium, high, or critical) see the chart in [Appendix A](/gitlab/gitlab-ticket-templates#appendix-a-determining-ticket-priority) for help deciding the priority level.
   2. Type: bug (in the case of this template!)
   3. State: pending (for new tickets)

## 3. User Story / Implementation of a New Feature

A **user story** is a simple way to describe features that need to be implemented (and does not yet exist). The template below is built to help fully describe the task(s) that needs to be completed to satisfy the requirements of a user story. In this case, a user story may be an improvement, a previously missed requirement or functional spec, or even a brand new feature.

Key Elements of a User Story:

1. **Title** (Required): Short title that clearly states the User Story.
2. **Type** (Required): `Issue` (for general work) or `Incident` (For investigating IT service disruptions or outages).
3. **Description** (Required): A clear explanation of the required story's content so that QA does not need to ask questions in order to test and close the story ticket. Additional notes are welcome. This should include the following sections:
   1. Description: Describe the user story.
   2. Affected Version(s): If necessary, list the build(s) where the issue applies.
   3. Acceptance Criteria: The clear definition of the final solution. What does the goal look like?
   4. Attachments: If helpful, provide screenshots, logs, video, diagrams, documents, etc. pertaining to the issue. Any other useful information should be attached as well.
   5. Quick Actions: If necessary, use quick actions to relate issues to this ticket or provide a time estimate. (`/relate #issue1 #issue2`) See [Quick Actions](https://docs.gitlab.com/ee/user/project/quick_actions.html#issues-merge-requests-and-epics) for more info.
4. **Assignees**: If known, adding the appropriate individual(s) here will save time.
5. **Weight**: Estimate of the effort needed to solve the issue. See [Time Tracking > Weight](https://community.peerplays.tech/gitlab/time-tracking#weight) for more info.
6. **Epic**: If known, select the best related epic.
7. **Due Date**: Can be left blank. It's useful if the issue is blocking something with a deadline.
8. **Milestone**: If known, select the best related milestone.
9. **Labels** (Required): The following *three label types* must be provided, but others can be added if necessary. See [Labels > Scoped Labels](https://community.peerplays.tech/gitlab/labels#scoped-labels) for more info.
   1. Priority: (low, medium, high, or critical) see the chart in [Appendix A](/gitlab/gitlab-ticket-templates#appendix-a-determining-ticket-priority) for help deciding the priority level.
   2. Type: feature (in the case of this template!)
   3. State: pending (for new tickets)

## Appendix A - Determining Ticket Priority

The priority of a ticket depends on a mix of aspects. Applying a priority is subjective. But we can help classify the priority by thinking in terms of impact and urgency:

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MifrKEuD3yzEHyP7May%2F-MifrnYZnRrzFSlBX4Uu%2Fticket-priority-matrix.png?alt=media\&token=9d0b3d6a-bbf9-4a07-b819-f770278d26d7)

{% file src="/files/-Mifs3TM7ltu1ykJwMpl" %}
Ticket Priority Matrix (Draw\.io XML)
{% endfile %}

## Appendix B - Copy / Paste Description Templates

### Bugs

Here is a template that you can quickly copy and paste into the Description field in the new GitLab bug ticket. This one has information to help guide you when entering information into the ticket.

```
## Description

(Required) Describe the bug here.

## Preconditions

(If necessary) In order to run the Scenario steps properly, list any preconditions.

- Precondition A
- Precondition B

## Affected Version(s)

(If known) List the build(s) where the issue has been observed.

- Build A
- Build B

## Scenario

(Required) The steps to reproduce the issue. Should be clear, direct, and have enough details to be reproducible.

1. Step 1...
2. Step 2...
3. Step 3...

## Current Bugged Behavior

(Required) The observed issue as it actually happens.

## Expected Correct Behavior

(Required) The requirements that describe a successful outcome. Simply, what should happen.

## Attempted Fixes

(Required, even if nothing) What has already been done to try to solve the issue, and the results of the attempts.

## Possible Fixes

(If possible) Link to the line of code that might be responsible for the problem. Or list other insights into the problem.

**Note**: Don't forget to attach any relevant files, and to use quick actions to link related issues or add time estimates. Then delete this note!

```

Or just the section headers if you prefer...

```
## Description



## Preconditions



## Affected Version(s)



## Scenario



## Current Bugged Behavior



## Expected Correct Behavior



## Attempted Fixes



## Possible Fixes



```

### User Stories

Here is a template that you can quickly copy and paste into the Description field in the new GitLab user story ticket. This one has information to help guide you when entering information into the ticket.

```
## Description

(Required) Describe the user story.

## Affected Version(s)

(If necessary) List the build(s) where the issue applies.

- Build A
- Build B

## Acceptance Criteria

(Required) The clear definition of the final solution. What does the goal look like?

**Note**: Don't forget to attach any relevant files, and to use quick actions to link related issues or add time estimates. Then delete this note!

```

Or just the section headers if you prefer...

```
## Description



## Affected Version(s)



## Acceptance Criteria



```


# Labels

<https://gitlab.com/groups/PBSA/-/labels>

## Scoped Labels

The scoped labels (ending with ::) are mutually exclusive. Only one of these labels can be assigned at a time to an issue.

### Priority::

* low&#x20;
* medium priority
* high priority
* critical priority

### State::

* pending&#x20;
* accepted
* in progress
* in review
* in testing
* completed
* on hold
* blocked
* revision needed

### Type::

* bug
* feature
* documentation
* question
* maintenance&#x20;

## Other Labels

* duplicate
* discussion
* security

## Issue Lifecycle

All issues should have a `state` and `type` scoped label attached to them. The following is a proposed lifecycle an issue should have:

1. Pending - Issues that are newly created and haven't been reviewed.
2. Accepted - Issues that are newly created and have been accepted after review.
3. In Progress - Issues that are currently being worked on.
4. In Review - Issues that require a proposed solution to be reviewed.
5. In Testing - Issues that require a proposed solution to be tested.&#x20;
6. Completed - Issues that are closed with a working solution.

This will cover a standard lifecycle of an issue. There are other `state` labels for issues that are not being worked on:

* On Hold - Issues that were at least accepted, that should not be worked on at the moment.
* Blocked - Issues that cannot be worked on due to other factors linked to it.
* Revision Needed - Issues that need to be revised before being accepted.

## Glossary

| Label                       | Description                                                                           |
| --------------------------- | ------------------------------------------------------------------------------------- |
| <p></p><p>priority::low</p> | (optional) Issues that are marked as low priority.                                    |
| priority::medium            | (optional) Issues that are marked as medium priority.                                 |
| priority::high              | (optional) Issues that are marked as high priority.                                   |
| priority::critical          | (optional) Issues that are marked as critical priority. Should be taken care of ASAP. |
| state::pending              | Issues that are newly created and haven't been reviewed.                              |
| state::accepted             | Issues that are newly created and have been accepted after review.                    |
| state::in progress          | Issues that are currently being worked on.                                            |
| state::in review            | Issues that require a proposed solution to be reviewed.                               |
| state::in testing           | Issues whose proposed solution is being tested.                                       |
| state::completed            | Issues that are closed with a working solution.                                       |
| state::on hold              | Issues that were at least accepted, that should not be worked on at the moment.       |
| state::blocked              | Issues that cannot be worked on due to other factors linked to it.                    |
| state::revision needed      | Issues that need to be revised before being accepted.                                 |
| type::bug                   | Issues that are an unexpected, or incorrect result in the project.                    |
| type::feature               | Issues that bring new functionality to the project.                                   |
| type::documentation         | Issues that relate to the documentation of the project.                               |
| type::question              | Issues that are questions related to the project.                                     |
| type::maintenance           | Issues that require maintenance on the project.                                       |
| duplicate                   | (optional) Issues that are duplicates of existing issues in the same project.         |
| discussion                  | (optional) Issues that discuss specific project changes.                              |
| security                    | (optional) Issues that relate to the security of the project.                         |


# Time Tracking

How to use GitLab quick actions for estimates, time spent and weights on issues.

<https://docs.gitlab.com/ee/user/project/quick_actions.html>

Quick actions are text-based shortcuts for common actions that are usually done by selecting buttons or dropdowns in the GitLab user interface. You can enter these commands in the descriptions or comments of issues, epics, merge requests, and commits.

Be sure to enter each quick action on a separate line to allow GitLab to properly detect and execute the commands.

## Selecting an Issue

1. Navigate to the project of choice in GitLab.
2. Click on the `issues` menu option

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-_Q-pVSGlK8nVMSzQ%2F-MW-ikaw0EZBzpVdOgbg%2Fimage.png?alt=media\&token=6809e1e5-63df-4e4f-ba88-3ceafe650c10)

3\. Select the issue of choice.

## Time Tracking

Lead developers who will assign issues should make sure to provide a time estimate and weight to them. They should also ensure these issues are attached to the appropriate milestones and epics.&#x20;

The purpose of this is to collect metrics and be able to provide a better timeline for project delivery.

### Estimates

To estimate an issue in GitLab, quick actions can be utilized. Inside the comment section of an issue type the following command: `/estimate <1w 3d 2h 14m>`.&#x20;

![Providing an 8 hour estimate to an issue](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-_Q-pVSGlK8nVMSzQ%2F-MW-lifxVhYJY7mFogqK%2Fimage.png?alt=media\&token=077adbd2-ed3b-49a8-ba93-fd9559fa1aa8)

Once an estimation is provided, the issue will update to reflect the submitted comment.

![Issue updated based on time estimate](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-spI7UK1dMRNxMR8q%2F-MW-stPbV9asyDNIy-DT%2Fimage.png?alt=media\&token=72d7eff3-765a-4e1f-aa69-550c7ecc8298)

### Spent Time

To track the time spent on an issue in GitLab, quick actions can be utilized. Inside the comment section of an issue type the following command: `/spend <time(1h30m|-1h30m)> <date(YYYY-MM-DD)>` to add or subtract spent time.

![Providing a 2 hour time spend](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-_Q-pVSGlK8nVMSzQ%2F-MW-nHy-bHirV_3xtcmt%2Fimage.png?alt=media\&token=39957104-7096-463b-8dde-fa9f3b174075)

Once the spent time is provided, the issue will update to reflect the submitted comment.

![Issue updated based on time spent](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-spI7UK1dMRNxMR8q%2F-MW-t859S152W7Ug_YoN%2Fimage.png?alt=media\&token=9cc4ad83-914f-4801-b667-d7bf19669d51)

### Weight

When you have a lot of issues, it can be hard to get an overview. By adding weight to each issue, you can get a better idea of how much time, value or complexity a given issue has or costs.

Weight points can be associated for the following task sizes:

* Extra Small (8h or less) - 1
* Small (9h - 16h)  - 2
* Medium (17h - 24h) - 3
* Large (25h - 40h ) - 5
* Extra Large (greater than 40h) - 8<br>

To add weight to an issue in GitLab, quick actions can be utilized. Inside the comment section of an issue type the following command:  `/weight 0, 1, 2...`.

![Providing 8 points to weight](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-spI7UK1dMRNxMR8q%2F-MW-ua1f4n6RPuP7lcas%2Fimage.png?alt=media\&token=edba8263-a51f-471f-9e03-4689f5742655)

Once the weight is provided, the issue will update to reflect the submitted comment.

![](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-spI7UK1dMRNxMR8q%2F-MW-uyWrf0BRI3T7Etxt%2Fimage.png?alt=media\&token=bfa69504-834a-4b71-9e3f-83d3a12a00e8)

### Milestones

Utilizing time tracking on issues and attaching them to milestones also updates the time tracking of that milestone for all issues attached.&#x20;

![Milestone with attached issues that have time tracking](https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LssGFn6gx89DxPYsP95%2F-MW-spI7UK1dMRNxMR8q%2F-MW-vxe-G4xzZYii3D_w%2Fimage.png?alt=media\&token=ca294d94-0a6c-4818-b78e-05d9fe679b99)


# Peerplays Disaster Recovery Plan

The objective of this disaster recovery (DR) plan is to ensure that anyone can respond to a disaster or other emergency that affects the Peerplays Blockchain and minimize the effect on the operation of the blockchain. This document should be stored in a safe, accessible location off site.

## 1. Goals

The major goals of the disaster recovery plan:

* To minimize interruptions to normal operations.
* To limit the extent of disruption and damage.
* To minimize the economic impact of the interruption.
* To establish alternative means of operation in advance.
* To provide for smooth and rapid restoration of service.

## 2. Personnel

Node operators, Witnesses in particular, hold the power to keep the blockchain up and running. Given the decentralized nature of blockchain technology, active and standby node operators may not be known or reachable for communication. It is advisable to keep an up-to-date list of node operators and information on how to reach them to coordinate DR activities. The level of community participation of any particular node operator should be kept in mind while voting for active node operators. More communicative node operators help to ensure the chain can continue to run in the event of disaster.

For this DR plan, it is advisable to create and maintain a register of node operators. This register should be maintained and regularly updated with node operators, a reliable means of communicating with each of them, and running seed node addresses.

PBSA employees and contractors should be registered with their screen name, PBSA issued email, and communication channel handles as a communications roster. This roster should be publicly available and used for DR related communications and notifications.

## 3. Application Profiles

### 3.1. Peerplays Mainnet

#### Source Code

The Peerplays chain and all its plugins is stored in GitLab and GitHub. Build artifacts are also stored in GitLab.

#### Witness Nodes

The witness\_node program is distributed across many private (node operator) servers. Each node operator is responsible for maintaining their own copy of the Peerplays source code and builds. This is most often done on GitHub though individuals may store local copies and follow their own procedures.

The Peerplays database is synchronized among all running (active and inactive) witness nodes. This decentralized and distributed approach makes the database integrity and security extremely robust. Even if the mainnet has an outage, the database remains intact and duplicated across potentially dozens of individual servers globally.

### 3.2. Documentation

Documentation is stored on GitHub and GitBook. This includes all public documentation for community docs, developer docs, and infrastructure docs. Both GitHub and GitBook are third-party SaaS solutions. Other private or internal documentation for PBSA is stored in Confluence workspaces and Google Drive. These are also third-party SaaS solutions. For the purposes of this DR plan, it is assumed that these providers have sufficient recovery capabilities on their own and that recovery of our documentation is covered under their DR plans and protocols.

Documentation that is currently being worked on is sometimes stored on personal computers or workstations. In these cases, it is recommended to store or back-up such documents on a cloud solution such as Google Drive, GitBook, GitHub, etc.

#### GitBook.com Resources

* <https://docs.gitbook.com/resources/faq#where-and-how-is-my-data-stored>
* Gitbook Support is available in the gitbook app. Once logged in, go to Spaces > "?" menu (lower left) > Contact Support

### 3.3. Source Code

Peerplays source code is stored and hosted on GitLab.com (a SaaS solution). The source code is then mirrored to GitHub.com (another SaaS solution). Since both GitLab and GitHub are third-party providers, for the purposes of this DR plan, it is assumed that these providers have sufficient recovery capabilities on their own and that recovery of our source code is covered under their DR plans and protocols.

#### GitLab.com Resources

* <https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/>
* <https://about.gitlab.com/handbook/engineering/infrastructure/faq/>
* <https://status.gitlab.com/>
* <https://about.gitlab.com/support/#contact-support>

#### GitHub.com Resources

* <https://docs.github.com/en/repositories/archiving-a-github-repository/backing-up-a-repository>
* <https://www.githubstatus.com/>
* <https://support.github.com/request>

### 3.4. Peerplays.tech

#### Source Code

The website Peerplays.tech has its source code stored in GitHub. The website is static and requires no database or dynamic data. No data backup is required.

#### Hosting

Peerplays.tech is hosted on a PBSA VM. The following software is used to serve the website:

* **Nginx**: The server software.
* **Certbot**: Manages the SSL certificates.
* **Node.js**: Node.js serves the website through Nginx.
* **NPM**: is used to install required packages.
* **Next.js**: used to build the website from its source code.

### 3.6. Communication Channels

The following is a list of all the communication channels, where they are hosted, and what they are primarily used for.

| Communication Channel |   Hosting   | Uses                                                            |
| --------------------- | :---------: | --------------------------------------------------------------- |
| Email                 | Third-Party | Daily internal communications                                   |
| Telegram              | Third-Party | Community discussions, Group discussions (witnesses)            |
| Rocket Chat           |   On-Prem   | Internal and Community discussions, Group discussions, Meetings |
| Jitsi                 |   On-Prem   | Meetings                                                        |
| Twitter               | Third-Party | Social Media                                                    |
| Facebook              | Third-Party | Social Media                                                    |
| Instagram             | Third-Party | Social Media                                                    |

#### Telegram Resources

* <https://telegram.org/faq>
* <https://telegram.org/faq#telegram-support>

## 4. Hardware Profiles

### 4.1. Witness Nodes

Each witness has their own hardware required to run the witness\_node software, whether on prem or remote. For the purposes of this DR plan, we will assume that each witness has acquired the hardware to run backup servers in addition to their main production server. In general the hardware requirements for a production witness node are as follows:

* CPU = 4 Cores
* RAM = 16GB
* Storage = 100GB
* Bandwidth = 1Gbps
* Operating System = Ubuntu 18.04

**Note**: Building Peerplays on the machine from source code will require higher levels of RAM. It is recommended to download GitLab Artifacts for witness node installation.

### 4.2. Super-Node

A super-node is used to bootstrap the network if an outage occurs. The super-node needs to be able to handle block production for all active nodes and handle a limited number of transactions. Here is the minimum hardware requirements for a super-node:

* CPU = 32 Cores
* RAM = 50GB
* Storage = 400GB
* Bandwidth = 1Gbps
* Operating System = Ubuntu 18.04

### 4.3. Node Hardware Considerations

Server hardware may be on-prem or hosted by a cloud provider. Using a cloud-based virtual machine, like with Amazon EC2 or Google Cloud Platform, can be faster to provision in a DR scenario. Since super-nodes are only used temporarily to handle unexpected outages, going cloud-based is preferred and will be used in the protocols of this DR plan. DR scenarios that impact site operations might also make the use of on-prem hardware impractical or impossible.

## 5. Backup Procedures

All source code stored in GitLab is backed up by being mirrored to GitHub. Additionally, Peerplays is forked by witnesses on GitHub. The Peerplays database is synchronized and distributed among all node operators in the network. Witnesses maintain backup servers as per PBSA recommended guidelines in the witness node operator documentation.

## 6. Disaster Recovery Procedures

### 6.1. Mainnet Outage Recovery Using a Super-Node

If a scenario occurs which halts the chain, such as low node operator network participation, temporary witnesses must be used until the network regains stability. In cases like this, the Super-Node solution has been proven to work. Here are the steps required to recover the network:

1. A suitable (not corrupted or unintentionally forked) copy of the Peerplays database should be collected.
2. Provision a Super-Node (SN) server using a cloud provider VM.
   1. The SN should be firewalled such that no incoming nodes can sync with the SN.
   2. The database copy should be loaded to the SN.
   3. The latest Peerplays chain code should be installed on the SN.
   4. The SN should be configured with as many witness nodes as required to recover the network. (Init accounts and/or collaborating witness accounts)
   5. The SN should be replayed using the database.
   6. The SN should be producing blocks for most or all witnesses at this point.
3. Seed nodes should be created on the SN machine and synced with the block producing SN node.
4. The `cli_wallet` program on the SN can be used to update witness votes by collaborating voters. It can also allow witnesses to generate new signing keys.
5. Witnesses should be allowed through the firewall to begin syncing their independent nodes with the seed nodes.
   1. Restarted witness nodes should configure their nodes to use only seed nodes from the SN.
   2. They should also be configured with new signing keys so as not to interfere with block signing once synced.
   3. Block checkpoints should be established and configured.
   4. Witnesses can also use the backed up database from the SN to run replays.
6. Once the witnesses are synced, they can resume block production by swapping their signing keys with `update_witness`.

### 6.2. Communication Channel Recovery Using Telegram

If the on-prem servers go down, the Rocket Chat and Jitsi communication channels will be temporarily unavailable until the servers can come online again. Since our Telegram communication channel is hosted by a third-party and is also publicly available, communications during the outage should happen in Telegram. Email should not be effected by such an outage and can also be used for communication. Initially, all personnel should be notified of a communications channel outage via email and Telegram.

The Telegram channel used for this backup communication is available here: <https://t.me/Peerplays>

On-Prem servers can then be restored using their initial hardware and software specifications. When the on-prem communication channels have been restored, all personnel should be notified via email and Telegram.

## 7. Procedure for Truncating the Block Index

The blockchain database is located in the `witness_node_data_dir` folder in the following path: `./witness_node_data_dir/blockchain/database/block_num_to_block`

There should be two files here, `blocks` which contains the block data, and `index` which is the index used by the witness node program. To set the database back to a specific block number, a `truncate` operation must be done on the index file.

{% hint style="danger" %}
You cannot undo a `truncate` on a file. It's best to **always make a backup** of the file and to put the backup in a safe place **before performing a `truncate`**. Otherwise you could potentially corrupt your only copy of the database.
{% endhint %}

For each block in the database, the index file will contain the index information for the block which requires 32 bytes worth of space. First we'll find the current size of the index file and then divide that number by 32 to see how many blocks are currently stored in the database. Here are the steps (with an example, to illustrate):

1. Use the `ls -l` command in the folder with the database files to find the size (in bytes) of the `index` file.
2. Take the size of the `index` and divide by 32. The result is the number of currently indexed blocks.
3. Decide which block you should set the index back to (keeping in mind that each block represents about 3 seconds worth of time if you need to calculate the block number at a certain point in time.)
4. Take the new block number that you determined in step 3 and multiply that by 32. This will give you the new size that the `index` file must be. You're now ready to truncate.
5. Use the `truncate` command on the `index` file specifying the new file size that you calculated in step 4. The `truncate` command will return `0` if successful.

An Example:

```bash
cd ./witness_node_data_dir/blockchain/database/block_num_to_block

# Step 1
ls -l

drwxr-xr-x 2 bunker bunker       4096 Sep 13 04:01 ./
drwxr-xr-x 3 bunker bunker       4096 Sep 13 04:01 ../
-rw-r--r-- 1 bunker bunker 6982339677 Sep 13 10:54 blocks
-rw-r--r-- 1 bunker bunker 1386818464 Sep 13 10:54 index

# Step 2
# 1386818464 / 32 = 43,338,077 (last block # indexed)

# Step 3
# we should go back 10,000 blocks, so 43,338,077 - 10,000 = 43,328,077

# Step 4
# 43,328,077 * 32 = 1386498464

# Step 5
truncate --size=1386498464 ./index
```

## 8. Testing the Disaster Recovery Plan

A local testnet can be set up for testing using the standard procedure for [standing up a local testnet](https://infra.peerplays.tech/advanced-topics/private-testnets/private-testnets-manual-install). Once the testnet is running, it's possible to run various DR scenarios in a safe and controlled manner.

### 8.1 Testing Network Recovery Procedures

Testing a mainnet outage can be achieved by setting up a local testnet with two sets of witnesses and some voting accounts. To cause a chain halt:

1. The local testnet contains the entire network.
2. Vote for misconfigured witness accounts until they become active and eventually halt the chain.
3. Another testnet can be configured at this point to act as the Super-Node in this test.
4. The database can be recovered from the first testnet, processed to be suitable for a restart, and used in the second testnet.
5. The protocol in section 6.1. above can be used at this point to test the outage recovery scenario.

## 9. Example Config.ini File

Here is an example `config.ini` file which demonstrates the use of checkpoints:

```
# Endpoint for P2P node to listen on
p2p-endpoint = 0.0.0.0:9777

# P2P nodes to connect to on startup (may specify multiple times)
seed-node = 96.46.48.98:19777
seed-node = 96.46.48.98:29777
seed-node = 96.46.48.98:39777
seed-node = 96.46.48.98:49777
seed-node = 96.46.48.98:59777

# JSON array of P2P nodes to connect to on startup
seed-nodes = []

# Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.
#"2021-09-09T21:59:33"
checkpoint = ["43328076","0295224c22b145b43c6ed6d4d56390b7fddb4758"]
#"2021-09-14T20:41:27"
checkpoint = ["43328077","0295224df70e863823bc29bb171e8380cd0d5f14"]
#"2021-09-14T20:41:45"
checkpoint = ["43328078","0295224e77097787cb53a4a573ac253f27912df9"]
#"2021-09-14T20:41:54"
checkpoint = ["43328079","0295224f0cbce57e982f68420a99de051f930636"]
#"2021-09-15T01:23:03"
checkpoint = ["43333079","029535d7245f2185541980db609f83afcafba04c"]
#"2021-09-15T05:55:06"
checkpoint = ["43338079","0295495fbf60a36d3070c25df0a82ed2e37155c5"]
#"2021-09-15T10:28:15"
checkpoint = ["43343079","02955ce706c015b9fcba279e0d7d45954461f586"]
#"2021-09-15T14:59:30"
checkpoint = ["43348079","0295706f11aa31f3f99579b232e184ec3a920cd3"]
#"2021-09-15T19:32:24"
checkpoint = ["43353079","029583f7af8a0784a391cdba382016b4c01f4bce"]
#"2021-09-16T00:03:42"
checkpoint = ["43358079","0295977f1764106629878a0d6e032d22f4ebaed3"]
#"2021-09-16T02:56:24"
checkpoint = ["43361260","0295a3ece12430f3f29def8c1fe16eaca07c9e9c"]

# Endpoint for websocket RPC to listen on
rpc-endpoint = 0.0.0.0:8090

# Endpoint for TLS websocket RPC to listen on
# rpc-tls-endpoint =

# The TLS certificate file for this server
# server-pem =

# Password for this certificate
# server-pem-password =

# File to read Genesis State from
# genesis-json =

# Block signing key to use for init witnesses, overrides genesis file
# dbg-init-key =

# JSON file specifying API permissions
# api-access =

# Whether to enable tracking of votes of standby witnesses and committee members. Set it to true to provide accurate data to API clients, set to false for slightly better performance.
# enable-standby-votes-tracking =

# Space-separated list of plugins to activate
plugins = witness account_history market_history accounts_list affiliate_stats bookie peerplays_sidechain


# ==============================================================================
# witness plugin options
# ==============================================================================

# Enable block production, even if the chain is stale.
enable-stale-production = false

# Percent of witnesses (0-99) that must be participating in order to produce blocks
required-participation = false

# ID of witness controlled by this node (e.g. "1.6.5", quotes are required, may specify multiple times)
witness-id = "1.6.###"

# IDs of multiple witnesses controlled by this node (e.g. ["1.6.5", "1.6.6"], quotes are required)
# witness-ids =

# Tuple of [PublicKey, WIF private key] (may specify multiple times)
private-key = ["PPY...","5K..."]


# ==============================================================================
# peerplays_sidechain plugin options
# ==============================================================================

# ID of SON controlled by this node (e.g. "1.33.5", quotes are required)
# son-id =

# IDs of multiple SONs controlled by this node (e.g. ["1.33.5", "1.33.6"], quotes are required)
# son-ids =

# Tuple of [PublicKey, WIF private key] (may specify multiple times)
peerplays-private-key = ["PPY...","5K..."]

# IP address of Bitcoin node
bitcoin-node-ip = 127.0.0.1

# ZMQ port of Bitcoin node
bitcoin-node-zmq-port = 11111

# RPC port of Bitcoin node
bitcoin-node-rpc-port = 8332

# Bitcoin RPC user
bitcoin-node-rpc-user = 1

# Bitcoin RPC password
bitcoin-node-rpc-password = 1

# Bitcoin wallet
bitcoin-wallet = son-wallet

# Bitcoin wallet password
# bitcoin-wallet-password =

# Tuple of [Bitcoin public key, Bitcoin private key] (may specify multiple times)
bitcoin-private-key = ["02...","..."]

# Sidechain retry throttling threshold
sidechain-retry-threshold = 150
```


# Sept 2021 Mainnet Outage - Postmortem Report

## 1. Background

The Peerplays Mainnet (Alice) network experienced a chain halt on 10-September-2021 at 10:27am GMT. A chain halt is an error condition of the network where no new blocks are produced and therefore no transactions or operations can occur. The halt is the effect of witness node software running (or not running) on multiple node servers and not being able to form chain consensus. When consensus breaks down, a halt or chain fork will occur.

## 2. Incident Timeline

The timeline represented here will start prior to the halt and end at the incident resolution. The time of incident resolution is defined as when a public announcement was made declaring that mainnet was back online and provided connection details to witnesses not directly involved in the incident resolution.

The entire incident happened between 09-September-2021 10:00pm GMT and 16-September-2021 5:06pm GMT. The total incident duration was 6 days, 19 hours, and 6 minutes.

### 2.1. Key Events

1. 09-September-2021 10:00pm GMT - The GPOS sub-period elapsed. Stale votes were removed for Witnesses. A new set of Witnesses became active. The Last Irreversible Block (LIB) stopped incrementing at block #43328077.
2. 10-September-2021 10:27am GMT - Blocks continued to be created until 10,000 blocks past the LIB, block #43338077. Blocks could no longer be created and the chain halted.
3. 10-September-2021 11:21am GMT - Jbahai and others noticed that Mainnet was having issues. Sofie found that the chain had halted.
4. 10-September-2021 02:10pm GMT - Surgeon proposes a "super-node" approach.
5. 10-September-2021 08:01pm GMT - Robert.Hedler finishes setting up the super-node. Witness keys are gathered and put in the super-node config.
6. 12-September-2021 08:21pm GMT - Witnesses begin to sync with the super-node.
7. 12-September-2021 09:51pm GMT - Sofie and other Witnesses run into sync issues with the super-node.
8. 13-September-2021 02:24am GMT - Hiltos connects to the super-node cli wallet and votes in active Witnesses.
9. 13-September-2021 12:18pm GMT - Surgeon, Hiltos, sieRRa19xx, Robert.Hedler, Jemshid, and Bobinson begin to collaborate in a Rocket Chat direct message channel.
10. 13-September-2021 01:38pm GMT - Surgeon discovers rouge nodes are connecting to the network which are causing the syncing issues. A clean database up to the chain halt (block #43338077) is made publicly available.
11. 15-September-2021 01:24pm GMT - A Firewall is configured to protect the super-node from rouge p2p nodes.
12. 15-September-2021 06:46pm GMT - Hiltos takes over block production for the hiltos-witness account from the super-node.
13. 15-September-2021 10:41pm GMT - Robert.Hedler takes over block production for the robert-hedler account from the super-node.
14. 16-September-2021 01:03pm GMT - The Firewall is removed from the super-node.
15. 16-September-2021 05:06pm GMT - A public announcement was made in the witness-info channel in Rocket Chat that Mainnet was back online. Seed nodes and checkpoints were provided to configure the witness node program.

### 2.2. Key Actions Taken by Responders

Discussions, both public and private, happened throughout the incident on Rocket Chat channels and Telegram channels.

**Surgeon**: Offered the super-node approach to solve the incident.

**sieRRa19xx**: Collaborated with Surgeon and Hiltos to solve the incident.

**Hiltos**: Collaborated with Surgeon and sieRRa19xx, and voted active Witnesses into place.

**Bobinson**: Coordinated with Witnesses in Rocket Chat and Telegram. Helped troubleshoot syncing issues.

**Robert.Hedler**: Set up the super-node machine / environment. Collaborated to set up the super-node firewall.

**Jemshid**: Collaborated with Witnesses to continue block production.

**Sofie**: Identified the incident and collaborated on the solution.

**Jbahai**: Alerted the team to the issue and relayed info with witnesses.

**Hbelakon**: Monitored the issue and helped to coordinate work tasks to give the issue top priority.

## 3. Superficial & Root Causes

### 3.1. (Root) Low Number of Engaged Community Members (Low GPOS Voting Turnout)

One main factor of this incident was that only one community member voted within the six months leading up to the incident. Because of the diminishing nature of GPOS voting, after six months of not voting, the vote power provided by a voter is completely removed. This means the one voter within the six months was the only vote power left. This drastically shifted the active witnesses to include many non-producing (and otherwise inactive) witness accounts.

A larger number of engaged community members, and therefore a larger GPOS voting turnout, would have prevented this incident. Recent votes will continue to maintain the full strength of their voting power. This would keep a sudden shift of active witnesses from occurring.

**Recommendations**:

* Change the consensus algorithm to the new Proof-of-Pulse model.
* Develop awareness in the community through outreach.
* Introduce notification features in upcoming dapps (Peerplays DEX).

### 3.2. (Superficial) Information About Witnesses is Hard to Find

The ability for community members to vote with confidence depends on the quality and availability of information about the node operators. Key Performance Indicators (KPIs) are not standardized or tracked for node operators (except for total missed blocks). It's also difficult to gage the level of dedication or engagement node operators have.

Additionally it's currently not possible to tell the state of an inactive node. Some inactive witnesses may be ready to take on block production and others may have shut down their servers. Community members may accidentally vote in a witness that no longer exists.

**Recommendations**:

* Identify and track a set of KPIs for node operators and make the information public and easily accessible.
* Provide greater visibility into the status of nodes.

### 3.3. (Root) Low Number of Engaged Witnesses

Similar to the issue of disengaged community members, witnesses must also remain engaged and alert to upcoming events. Inactive witnesses that are on standby should be ready to take over as an active node. If previously inactive nodes get voted in, the nodes must be ready to produce blocks. If all listed witnesses were ready for block production the outage would not have occurred.

**Recommendations**:

* Node operators should be able to set their nodes to maintenance mode or similar function, like SON nodes.

### 3.4. (Superficial) Lack of System Fail-safes

The chain has no fallback system. This is a tricky topic because the intention is to remain decentralized and a fallback would most likely be under the control of one organization. But the risk of not having a fallback system may just outweigh the need for total decentralization. A fallback could be as simple as making all the "init" accounts the active witnesses until voting resumes. This could keep the chain moving along to prevent the financial losses people could experience during an outage.

No disaster recovery protocol existed at the time of the outage. This hindered the recovery of the network.

**Recommendations**:

* Investigate feasible fallback mechanisms to include into the chain.
* Develop a disaster recovery protocol to bring the chain back online as quickly and safely as possible.

## 4. Impacts

The known impacts of the mainnet outage are as follows:

* The Peerplays mainnet network was down for 6 days, 19 hours, and 6 minutes. No transactions could occur during this time.
* Community members could not transfer tokens or coins, vote for node operators, use any Peerplays dApp, or access their wallets.
* Exchanges that are integrated with Peerplays could not access their Peerplays wallets, deposit, or withdraw funds.
* External third-party programs and websites using the Peerplays API could not access chain data.
* Witnesses were not producing blocks and so were not given block production pay during the outage.

Although the impacts were far reaching in scope, the damage was minimal because of the low utilization of the network as evidenced by the low level of transactions over the preceding months. Bringing the mainnet back online restored functionality and has mitigated the impacts listed above.

## 5. Incident Resolution

The Peerplays mainnet was back online 16-September-2021 05:06pm GMT.

The solution, step-by-step:

1. Create a super-node, a single node running all the witnesses, using a snapshot of the database from the last irreversible block (LIB).
2. Firewall it off from the internet.
3. Create several seed nodes on the same machine which sync from the super-node.
4. Allow the super-node and new seeds time to create blocks well beyond the LIB.
5. Allow engaged witnesses through the firewall to sync their nodes with the seed nodes. (witnesses use the database snapshot.)
6. Witnesses begin to take over their block production from the super-node, becoming new seed nodes as well.
7. When all active witnesses resume their block production, the super-node can be shut down.

## 6. Lessons Learned

Ultimately, the higher the risk that a mainnet outage would cause also means the system will be more resistant to such issues. A high level of network utilization means a more engaged community. Bringing more value to the network by providing dApps and on-boarding more third-party solutions will do more for protecting the network than trying to fool-proof the system in its early stages.

The most good that can be done for preventing further incidents such as this will be in planning for system recovery. Until the network is highly utilized, having protocols in place to shorten the downtime would be the best use of our time.

## 7. Action Items

1. The need for a disaster recovery (DR) plan has been identified due to this incident. The DR plan must include ways of mitigating the specific risks causing the September mainnet outage and a protocol for recovering the network should an outage happen again. The DR plan should include similar plans for systems other than the Peerplays mainnet.
2. The need for a disaster communications (DC) plan has also been identified due to this incident. The DC plan should cover communications protocols during and after outage events.
3. A simple network monitoring tool should be developed to warn about potential adverse events and to give a simple health check when required.


# Peerplays Developer

This page helps in learning about the developer workflow.

## Introduction

This document focus on providing the concepts, workflow, basic process for a newly onboarded developer. The detailed description of each categories are summarized in a single page to provide easy navigation and access to the desired topic.&#x20;

## [Development workflow](https://devs.peerplays.com/development-workflow-docs/development-workflow)

The workflow guides the developer to learn the process followed by the team. The workflow mainly focus on ticket creation and progress involved in the life cycle of any issue. The various stages of a ticket under the labels can be categorized as accepted, in-progress, in-review, blocked, on-hold, testing, completed. As the work progress, the labels has to be modified based on ticket completion. Click the heading to learn in detail about the development workflow.

## Basic requirements

As a newbie, there are certain concepts that are significant in starting as a developer in Peerplays. To begin with, there are three major notion that to be grasped to build any project under Peerplays. The list of three concepts are,

1. Setup a Local Testnet
2. Deploy a project with docker
3. Clone and build a project

## 1. Setup a Local Testnet

### What is a Testnet?

A test blockchain used by developer to experiment with new ideas without disturbing or breaking the main software.

The local testnet is a private testnet used for troubleshooting network issue, experimenting new ideas, or developing new dApp on a chain with complete access and control over the testnet. The testnet can be customized based on the user's requirement to perform any desired operation. To begin as part of development team, build a private testnet is the first phase to learn, experiment and explore the various features of Peerplays.

### [Steps to Install Testnet](https://infra.peerplays.com/advanced-topics/private-testnets/private-testnets-manual-install)

Click the above link to learn the detailed instructions involved in installing a private testnet. The glimpse of steps are highlighted in the below section. &#x20;

1. Check for the hardware requirements and install required software.
2. Install library for common development tasks. In Peerplays, Boost is used as a comprehensive C++ library to begin with any task.
3. Install Peerplays&#x20;
4. Generate a Genesis config file and edit the file with necessary changes to complete the testnet setup
5. Run the witness\_node
6. Run the cli\_wallet
7. Setup a second node

## 2. Deploy a project with Docker

To set-up a SON and witness node a pre-configured Docker container is necessary.&#x20;

### A. SONs - Sidechain Operator Nodes

**Sidechain Operator Nodes** - SONs facilitate the transfer of off-chain assets (like Bitcoin, Hive, or Ethereum tokens) between the Peerplays chain and the asset's native chain. These nodes often run the Peerplays node software and node software of other chains.

New to SONs ?? Click [here](https://community.peerplays.com/technology/sidechain-operator-nodes-sons/new-to-sons) to learn in detail.

### SONs - Docker Installation

This details are provided based on the assumption that, your system is running with Ubuntu 18.04 and above.

### [Installation steps](https://infra.peerplays.com/sidechain-operator-nodes-sons/installation-guides/docker-install)

Click above link to learn each installation steps in detail. The steps involved in docker installation is outlined below.

1. Update `config.ini` with SON Account Info
2. Using the CLI wallet
3. Starting the environment
4. Installing the `peerplays:son` image
5. The Bitcoin node
6. Installing Docker
7. Preparing the Environment

## B. Witness Node - Docker Installation

A witness node runs on the Peerplays blockchain. In a Peerplays way, enter a consensus mechanism called Delegated Proof of Stake (DPOS).

Think of Delegated Proof of Stake as technological democracy; the opportunity for any PPY token holder to vote on who creates new blocks in the Peerplays blockchain; we call these block producers Witnesses, and they keep the blockchain alive.

Witnesses also have the authority to approve, or reject, any changes to the blockchain software. Their actions have an overarching impact on all PPY token holders.

New to witness?? Click [here](https://community.peerplays.com/witnesses/what-is-a-peerplays-witness) to learn in detail.

### [Installation steps](https://infra.peerplays.com/witnesses/installation-guides/docker-install)

Click above link to learn the witness node docker installation in details. The outline of installation steps are listed below.

1. &#x20;Start the Container and Vote for Yourself
2. Update `config.ini` with Witness Account Info
3. Create a Peerplays Account
4. Update the `config.ini` File
5. Starting the Container
6. Installing the Peerplays image
7. Installing Docker
8. Preparing the Environment

## 3. Clone and build a project

Cloning and forking are the two mechanism that can be opted to use the files without interrupting the main repository by making a copy of the file.

### A. Project Forking workflow

When the user has no write access for any repository, then create a fork to make a personal copy of the required repository and all of its branches in a desired namespace.&#x20;

The user can make changes in their own fork and submit the changes through a merge request to reflect them in repository.

### Steps to create fork for an existing project in GitLab

1\.  Select **Fork** on the right of project's name.

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F0a0VVstbF6aEjCHiyGGa%2Fforking_workflow_fork_button_v13_10.png?alt=media&amp;token=a88fb511-b3fa-4b30-b98f-ae20fbcddf45" alt=""><figcaption></figcaption></figure>

2\. For **Project URL**, select [namespace](https://docs.gitlab.com/ee/user/namespace/index.html) for the fork created

3\. Add a **Project slug**. This value becomes part of the URL to the fork. It must be unique in the namespace.

4\. Select the **Visibility level** for the fork. For more information about visibility levels, read [Project and group visibility](https://docs.gitlab.com/ee/user/public_access.html).

6\. Select **Fork project**.

GitLab creates the fork and redirects to the new fork's page.

The other forking activities are,

1. [Repository mirroring](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#repository-mirroring)
2. [Merging upstream](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#merging-upstream)
3. [Removing a fork relationship](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#removing-a-fork-relationship)

### B. How to clone git project with Visual Studio Code ?

Cloning a project is making a copy of the files in the repository to work on the code locally and later update the changes into the original repository.&#x20;

1. Open Visual Studio Code, Go to **Top Menu -> Files -> Open Folder.**
2. Select the folder you would like to download the cloned project.
3. Go to **Top Menu -> View -> Integrated Terminal.**

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2F7la1QHvACJV4Cp2uJFSm%2F1.jpg?alt=media&amp;token=44f592cb-7c27-4bb3-a278-653506a06ac8" alt=""><figcaption></figcaption></figure>

4\. Execute **'git clone'** command with the repository path to clone in the integrated terminal.

```
git clone <url>
```

5\. If credentials are required to login, then the integrated terminal will prompt for Username and Password.

6\. The complete output will be similar to the below example,

```
C:\Projects\TestProject>git clone https://bitbucket.org/velingeorgiev/rouge
Cloning into 'rouge'...
github --credentials get: github: command not found
Username for 'https://bitbucket.org': velin.georgiev@somemail.com
Password for 'https://velin.georgiev@somemail.com@bitbucket.org':
github --credentials store: github: command not found
github --credentials store: github: command not found
remote: Counting objects: 1082, done.
remote: Compressing objects: 100% (1000/1000), done.
Receiving objects: 100% (1082/1082), 3.98 MiB | 301.00 KiB/s, done.cts:  87% (942/1082), 3.88 MiB | 299.00 KiB/s

Resolving deltas: 100% (587/587), done.

C:\Projects\TestProject>
```

7\. The cloned files will be available in the local folder

<figure><img src="https://1740771217-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LssGFn6gx89DxPYsP95%2Fuploads%2FvbNuM9j5NuV2ySeZ7M2S%2F2.jpg?alt=media&amp;token=5159f9ac-fb7b-415e-8a86-5d970a6c632f" alt=""><figcaption></figcaption></figure>

Click below link to learn about working with GitHub in VS code\
<https://code.visualstudio.com/docs/sourcecontrol/github>

## Development FAQs

The basic questions such as&#x20;

1. How to generate bitcoin address?
2. How to get Test BTC?
3. How to generate public key for a bitcoin address?

and so on.,

Click the below link to find the answers,

<https://devs.peerplays.com/supporting-and-reference-docs/peerplays-development-faqs>

## Related Documents

* <https://docs.docker.com/engine/install/>
* <https://docs.docker.com/engine/install/linux-postinstall/>
* <https://infra.peerplays.com/witnesses/installation-guides/manual-install>


# Introduction

The Risk register document helps the user to have an understanding about the risk that has occurred/ might occur in Peerplays. The document focus on the top 3 risks that are voted by the SMEs, categorized as High risk and also provides the possible solutions to solve the risk.

The document has the section which features the Responder Team which is vital to inform about the issue and to find the solution to solve the issue.

The inputs are gathered from the SMEs and categorized as mentioned below,

1. Bunker Issue
2. Core-Block Issue
3. Credential Security


# Bunker Issue

The entire Peerplays network works in a Bunker. There are several things that might bring down the network. This document covers the possible risks along with the plan to solve any such occurrences. Though there are several possible risks, only 4 risks are filtered based on the audience (SME's) choice.

The list of Risks discussed are

1. DDOS
2. Hypervisor Compromised
3. Power and backup Failure
4. Crypto Restriction


# DDOS Attack

Distributed Denial-of-Service (DDOS)

## Description

DDOS attack will deny the User to connect with any online services, sites, and application. This is a cyber attack and it's unpredictable. If a user come across any such circumstances, the below ideas, response plan can be helpful.&#x20;

## Mitigation Ideas

The following ideas are listed based on the inputs from SMEs

1. Having Load balancers in place.
2. A method to detect DDOS attack while they originate.
3. Using services like **CloudFlare** to secure the internet connectivity.
4. Limit the number of connections (Reasonable counts).
5. Direct communication with ISP NOCs.
6. Keeping the Backups servers Off-premises .
7. Find a good counter-measure software to stop/fight against the attack.

## Response Plan

1. If attack has happened, the servers can be flipped to backups.
2. Communicate with marketing team depending on the services attacked.

## Responder Team

In order to find the solution / to know in details about the risk that has happened, responder team is one to be communicated first.&#x20;

### First Responder Team

Devops Team\
**Point of contact:** Haxhi&#x20;

### Second Responder Team

Development Team


# Hypervisor Compromised

## Description

If the attacker has the control over the hypervisor, then the full access to VMs will be under threat. In order to overcome this situation, the following plans and ideas can be helpful. The document outcome is the ideas discussed among the SMEs.

## Mitigation Ideas

1. Limit the access to admin
2. PEN Testing the accounts to evaluate the security. Example: Brute force test on password.
3. Having Backups of Hypervisor and nodes for Fallback/re-deployment
4. Performing Audits periodically&#x20;

## Response Plan

1. Updated backups that can be written over the compromised systems.
2. A Kill-switch to stop the process.

## Responder Team

In order to find the solution/ to know in details about the risk that has happened, responder team is one to be communicated first.&#x20;

### First Responder Team

**Point of Contact:** Rily and/or Robert

### Second Responder Team

**Point of Contact:** Kyle and Haxhi


# Power and Backup Failure

## Description

Power is the key factor to run any server. There are situation where the power and backup can fail to switch back which halt the servers to come up. It can be any disaster, natural calamities, accidents, etc., In order to overcome this situation, the following ideas and plans were proposed by the SMEs. This can help the user to understand the possibilities and person to help in retrieve the situation to normal.

## Mitigation Ideas

1. Providing a backup to backups.
2. Plan Tier-3 availability.
3. Generators for critical operations with auto-on features over power failure.
4. Key actors need to have clear communication among themselves
5. The mirrored servers can be Off-premises
6. Maintenance Team with 24/7 availability

## Response Plan

1. Re-deploy the services such as AWS, Linode, etc., whenever in need
2. Pre-written redeploy plans for critical services
3. Start the Generator

## Responder Team

In order to find the solution/ to know in details about the risk that has happened, responder team is one to be communicated first.&#x20;

### First Responder Team

**Point of Contact:** Jonathan / Maintenance Team

### Second Responder Team

**Point of Contact:** Kyle and Riley respectively


# Crypto Restriction

## Description

There are possibilities that Government can restrict/ban crypto in the country or in any particular province. If that is the situation, the following plans helps in overcoming the problem. Also, provide the responder team who can clarify the status of that condition and possible solutions.&#x20;

## Mitigation Ideas

1. Always having a proactive design to avoid the regulatory compliance&#x20;
2. A separate role to monitor the regulatory trends
3. Having a duplicate setup in another country
4. Lobby the Govt to have a Crypto friendly policy
5. Stay away from promoting ideas that could cause regulation issue
6. Have a legal counsel
7. Anonymous users as witnesses

## Response Plan

1. Create Server space to Offload several services in other countries with Jurisdictional ability.

## Responder Team

In order to find the solution/ to know in details about the risk that has happened, responder team is one to be communicated first.&#x20;

### First Responder Team

**Point of contact:** Jonathan / Leadership Team

### Second Responder Team

**Point of contact:** Team B


# Core-Block Issue

The list of risk discussed in this document are,

1. Too expensive servers for witnesses/SONS
2. Witness node not reachable
3. Witnesses get DDOS'd
4. Bad actor infiltrate witness/SONs


# Expensive Servers

## Description

The network run the servers which can become expensive for the user based on the demands, usage and availability. In this case, to maintain the users the following plans and ideas can be useful. Also, the point of contact to understand the issue is listed in this section.

## Mitigation Ideas

1. Increase liquidity to bring value to the token.
2. Run a node with less demand, Find a way for it.
3. To avoid compilation, provide the binaries of witness\_node and cli\_wallet.
4. Create best practices to build cost effective nodes
5. Have Periodic sync-up with other witnesses to learn about the ways remain economical.
6. Static-linking of libbitcoin
7. Publish minimum requirements to witnesses to maintain the standard spec across the platform.
8. Provide the Personal Package Archives (PPA) on ubuntu.&#x20;

## Response Plan

1. Increase witness / SON pay

## Responder Team

In order to find the solution/ to know in details about the risk that has happened, responder team is one to be communicated first.&#x20;

### First Responder Team

**Point of Contact:** DOCS Team

### Second Responder Team

**Point of Contact:** Dev Team (For Static Link / PPA)




---

[Next Page](/llms-full.txt/1)

