Hive Developer logo

Hive Developer Portal - Services

hive.blog

Hive.blog endpoints

Hive.blog offers a few endpoints for getting common data. User profile and post JSON data is very convenient and simple by appending .json to your request.

Getting a particular user profile JSON:

https://hive.blog/@curie.json

User object

{
  "user": {
    "id": 81544,
    "name": "curie",
    "owner": {
      "weight_threshold": 1,
      "account_auths": [
        
      ],
      "key_auths": [
        [
          "STM69WGR1yhUdKrnzwQLDPnXrW9kaAERwHze8Uvtw2ecgRqCEjWxT",
          1
        ]
      ]
    },
    "active": {
      "weight_threshold": 1,
      "account_auths": [
        
      ],
      "key_auths": [
        [
          "STM5GAbbS84ViMEouJL3LKcM8VZzPejn68AfPaYaLZZDdmy98kwU5",
          1
        ]
      ]
    },
    "posting": {
      "weight_threshold": 1,
      "account_auths": [
        [
          "buildteam",
          1
        ],
        [
          "busy.app",
          1
        ],
        [
          "dpoll.xyz",
          1
        ],
        [
          "peakd.app",
          1
        ],
        [
          "steemauto",
          1
        ],
        [
          "steempeak.app",
          1
        ]
      ],
      "key_auths": [
        [
          "STM5cmuKw6EPkZWeVNXcZorKtattZTX5wSopcRb4xNe6VhRKjETgv",
          1
        ]
      ]
    },
    "memo_key": "STM7ZBi61xYz1b9STE1PHcAraPXJbvafzge3AcPjcfeq4XkKtM2At",
    "json_metadata": {
      "profile": {
        "profile_image": "https://i.imgur.com/Mjewc66.jpg",
        "name": "Curie",
        "about": "Discovering exceptional content. ",
        "location": "Worldwide",
        "website": "http://curiesteem.com",
        "trail": "true",
        "trail_threshold": "20"
      }
    },
    "posting_json_metadata": "{\"profile\":{\"profile_image\":\"https://i.imgur.com/Mjewc66.jpg\",\"name\":\"Curie\",\"about\":\"Discovering exceptional content. \",\"location\":\"Worldwide\",\"website\":\"http://curiesteem.com\",\"trail\":\"true\",\"trail_threshold\":\"20\"}}",
    "proxy": "",
    "last_owner_update": "1970-01-01T00:00:00",
    "last_account_update": "2020-03-28T05:21:09",
    "created": "2016-09-02T10:44:24",
    "mined": false,
    "recovery_account": "anonsteem",
    "last_account_recovery": "1970-01-01T00:00:00",
    "reset_account": "null",
    "comment_count": 0,
    "lifetime_vote_count": 0,
    "post_count": 14278,
    "can_vote": true,
    "voting_manabar": {
      "current_mana": "751713587852076",
      "last_update_time": 1616631966
    },
    "downvote_manabar": {
      "current_mana": "234963797035828",
      "last_update_time": 1616631966
    },
    "voting_power": 7998,
    "balance": "1049.412 HIVE",
    "savings_balance": "0.000 HIVE",
    "hbd_balance": "10.497 HBD",
    "hbd_seconds": "17953549833",
    "hbd_seconds_last_update": "2021-03-24T21:28:54",
    "hbd_last_interest_payment": "2021-03-04T15:28:54",
    "savings_hbd_balance": "0.000 HBD",
    "savings_hbd_seconds": "0",
    "savings_hbd_seconds_last_update": "1970-01-01T00:00:00",
    "savings_hbd_last_interest_payment": "1970-01-01T00:00:00",
    "savings_withdraw_requests": 0,
    "reward_hbd_balance": "0.000 HBD",
    "reward_hive_balance": "0.000 HIVE",
    "reward_vesting_balance": "71075.814385 VESTS",
    "reward_vesting_hive": "37.503 HIVE",
    "vesting_shares": "120306952.831903 VESTS",
    "delegated_vesting_shares": "19516.482729 VESTS",
    "received_vesting_shares": "824816954.196218 VESTS",
    "vesting_withdraw_rate": "5249202.402079 VESTS",
    "post_voting_power": "945104390.545392 VESTS",
    "next_vesting_withdrawal": "2021-03-28T11:44:57",
    "withdrawn": "57741226422869",
    "to_withdraw": "68239631227024",
    "withdraw_routes": 0,
    "pending_transfers": 0,
    "curation_rewards": 240534093,
    "posting_rewards": 177681311,
    "proxied_vsf_votes": [
      "14780750819354",
      0,
      0,
      0
    ],
    "witnesses_voted_for": 30,
    "last_post": "2021-03-24T22:49:27",
    "last_root_post": "2021-03-07T20:51:00",
    "last_vote_time": "2021-03-25T00:26:06",
    "post_bandwidth": 10000,
    "pending_claimed_accounts": 0,
    "delayed_votes": [
      
    ],
    "vesting_balance": "0.000 HIVE",
    "reputation": "550647465022459",
    "transfer_history": [
      
    ],
    "market_history": [
      
    ],
    "post_history": [
      
    ],
    "vote_history": [
      
    ],
    "other_history": [
      
    ],
    "witness_votes": [
      "abit",
      "actifit",
      "aggroed",
      "anyx",
      "arcange",
      "ausbitbank",
      "blocktrades",
      "cervantes",
      "curie",
      "drakos",
      "emrebeyler",
      "followbtcnews",
      "good-karma",
      "gtg",
      "jesta",
      "liondani",
      "lukestokes.mhth",
      "netuoso",
      "ocd-witness",
      "pharesim",
      "riverhead",
      "roelandp",
      "someguy123",
      "steempeak",
      "steempress",
      "stoodkev",
      "thecryptodrive",
      "themarkymark",
      "therealwolf",
      "yabapmatt"
    ],
    "tags_usage": [
      
    ],
    "guest_bloggers": [
      
    ]
  },
  "status": "200"
}

Getting a particular post JSON:

https://hive.blog/curation/@curie/the-daily-curie-12-13-feb-2017.json

Post object

{
  "post": {
    "id": 1965592,
    "author": "curie",
    "permlink": "the-daily-curie-12-13-feb-2017",
    "category": "curation",
    "parent_author": "",
    "parent_permlink": "curation",
    "title": "The Daily Curie (12-13 Feb 2017)",
    "body": "...",
    "json_metadata": {
      "tags": ["curation", "curie"],
      "users": [
        "nextgencrypto",
        "berniesanders",
        "val",
        "silversteem",
        "clayop",
        "hendrikdegrote",
        "proskynneo",
        "kushed",
        "curie"
      ],
      "image": [],
      "links": [],
      "app": "steemit/0.1",
      "format": "markdown"
    },
    "last_update": "2017-02-13T18:00:51",
    "created": "2017-02-13T18:00:51",
    "active": "2017-02-14T16:19:24",
    "last_payout": "2017-03-16T19:08:27",
    "depth": 0,
    "children": 9,
    "net_rshares": 0,
    "abs_rshares": 0,
    "vote_rshares": 0,
    "children_abs_rshares": 0,
    "cashout_time": "1969-12-31T23:59:59",
    "max_cashout_time": "1969-12-31T23:59:59",
    "total_vote_weight": 0,
    "reward_weight": 10000,
    "total_payout_value": "23.678 HBD",
    "curator_payout_value": "1.196 HBD",
    "author_rewards": 167726,
    "net_votes": 465,
    "root_author": "curie",
    "root_permlink": "the-daily-curie-12-13-feb-2017",
    "max_accepted_payout": "1000000.000 HBD",
    "percent_hbd": 0,
    "allow_replies": true,
    "allow_votes": true,
    "allow_curation_rewards": true,
    "beneficiaries": [],
    "url": "/curation/@curie/the-daily-curie-12-13-feb-2017",
    "root_title": "The Daily Curie (12-13 Feb 2017)",
    "pending_payout_value": "0.000 HBD",
    "total_pending_payout_value": "0.000 HBD",
    "active_votes": [],
    "replies": [],
    "author_reputation": "545477526857484",
    "promoted": "0.000 HBD",
    "body_length": 0,
    "reblogged_by": []
  },
  "status": "200"
}

Hivesigner

What is Hivesigner?

The goal of Hivesigner is to provide a safe way of connecting to the blockchain via 3rd party apps without compromising the security of your private keys and passwords. It’s a simple identity layer built on top of the blockchain allowing users safe access and developers the freedom of not having to handle the authentication system, i.e. managing users’ private keys and encryption. This means that devs won’t have to open-source their projects in order to gain user trust. When connecting to apps in this manner, neither Hivesigner nor the authorized app store the private keys as the posting key is encrypted on your cookie.

How Hivesigner is implemented

Hivesigner works by granting an access token to the requesting app once the application has been approved. A full tutorial on how to set up an application, request authorization and grant access can be found here.

Hive Authorisation and OAuth 2

The OAuth protocol allows third party apps to grant limited access to an HTTP service, either on behalf of a resource owner or by allowing the app to obtain access on its own behalf. The authorization is provided without the private key or password of the user being shared with the third party. Simplified, the process includes the following steps:

  1. The user is presented with an authorization link that requests a token from the API
  2. The user has to log in to the service to verify their identity whereupon they will be prompted to authorize the application
  3. The user is redirected to the application redirect URI along with the access token

Once the application has an access token, it may use the token to access the user’s account via the API, limited to the scope of access, until the token expires or is revoked. A full breakdown of OAuth2 and how it applies to Hive and Hivesigner can be found here.

Useful Links

For additional material you can refer to the original Hive blog post by @good-karma

Jussi

A reverse proxy that forwards json-rpc requests.

Jussi is a custom-built caching layer for use with hived.

The purpose of this document is to help developers and node operators set up their own jussi node within a docker container.

Intro

Jussi is a reverse proxy that is situation between the API client and the hived server. It allows node operators to route an API call to nodes that are optimized for the particular call, as if they are all hosted from the same place.

Sections

Installation

To run jussi locally:
git clone https://gitlab.syncad.com/hive/jussi.git
cd jussi
docker build -t="$USER/jussi:$(git rev-parse --abbrev-ref HEAD)" .
docker run -itp 9000:8080 "$USER/jussi:$(git rev-parse --abbrev-ref HEAD)"

Kitematic Example jussi in a docker container as seen from Kitematic for macOS.

Try out your local configuration:
curl -s --data '{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":[8675309], "id":1}' http://localhost:9000

See: Running Condenser, Jussi and a new service locally + adding feature flags to Condenser


Adding Upstreams

The default DEV_config.json is:

{
   "limits":{"blacklist_accounts":["badguy"]},
   "upstreams":[
      {
         "name":"hived",
         "translate_to_appbase":false,
         "urls":[["hived", "http://api.hive.blog"]],
         "ttls":[
            ["hived", 3],
            ["hived.login_api", -1],
            ["hived.network_broadcast_api", -1],
            ["hived.follow_api", 10],
            ["hived.market_history_api", 1],
            ["hived.database_api", 3],
            ["hived.database_api.get_block", -2],
            ["hived.database_api.get_block_header", -2],
            ["hived.database_api.get_content", 1],
            ["hived.database_api.get_state", 1],
            ["hived.database_api.get_state.params=['/trending']", 30],
            ["hived.database_api.get_state.params=['trending']", 30],
            ["hived.database_api.get_state.params=['/hot']", 30],
            ["hived.database_api.get_state.params=['/welcome']", 30],
            ["hived.database_api.get_state.params=['/promoted']", 30],
            ["hived.database_api.get_state.params=['/created']", 10],
            ["hived.database_api.get_dynamic_global_properties", 1]
         ],
         "timeouts":[
            ["hived", 5],
            ["hived.network_broadcast_api", 0]
         ],
         "retries": [
            ["hived", 3],
            ["hived.network_broadcast_api", 0]
         ]
      },
      {
         "name":"appbase",
         "urls":[["appbase", "https://api.hive.blog"]],
         "ttls":[
            ["appbase", -2],
            ["appbase.block_api", -2],
            ["appbase.database_api", 1]
         ],
         "timeouts":[
            ["appbase", 3],
            ["appbase.chain_api.push_block", 0],
            ["appbase.chain_api.push_transaction", 0],
            ["appbase.network_broadcast_api", 0],
            ["appbase.condenser_api.broadcast_block", 0],
            ["appbase.condenser_api.broadcast_transaction", 0],
            ["appbase.condenser_api.broadcast_transaction_synchronous", 0]
         ]
      }
   ]
}

Upstreams can be added to the upstreams array:

{
  "name": "foo",
  "urls": [["foo", "https://foo.host.name"]],
  "ttls": [["foo", 3]],
  "timeouts": [["foo", 5]]
}

Once the above upstream is added to the local config and docker has been built, the following curl will work:

curl -s --data '{"jsonrpc":"2.0", "method":"foo.bar", "params":["baz"], "id":1}' http://localhost:9000

Note: if you set translate_to_appbase as true, jussi will do the translation for you and that specific endpoint will work with libraries that don’t yet support appbase.

Benefits of jussi

Time To Live

Jussi can be configured with various TTL (Time To Live) schemes. A TTL is an integer value in seconds. Integers equal to or less than 0 have special meaning. A reasonable set of defaults would be:

Upstream API Method Parameters TTL (seconds)
hived login_api all all -1
hived network_broadcast_api all all -1
hived follow_api all all 10
hived market_history_api all all 1
hived database_api all all 3
hived database_api get_block all -2
hived database_api get_block_header all -2
hived database_api get_content all 1
hived database_api get_state all 1
hived database_api get_state '/trending' 30
hived database_api get_state 'trending' 30
hived database_api get_state '/hot' 30
hived database_api get_state '/welcome' 30
hived database_api get_state '/promoted' 30
hived database_api get_state '/created' 10
hived database_api get_dynamic_global_properties all 1
hivemind all all all 3

In this case, requests for login_api and network_broadcast_api have a TTL of -1, which means requests with those namespaces are not cached, whereas follow_api request have a TTL of 10 seconds.

Some methods and parameters have their own TTL that overrides the general default, like database_api.get_block, which overrides database_api.*.

Time to Live Special Meaning

If you have a local copy of jussi (see: Installation), you can change these defaults by modifying DEV_config.json.

Multiple Routes

Each urls key can have multiple endpoints for each namespace. For example:

{
  "urls":[
    ["appbase", "http://anyx.io"]
  ]
}

… can also be expressed as:

{
  "urls":[
    ["appbase","http://anyx.io"],
    ["appbase.condenser_api.get_account_history","http://anyx.io"],
    ["appbase.condenser_api.get_ops_in_block","http://anyx.io"]
  ]
}

In these examples, the methods get_account_history and get_ops_in_block route to a dedicated API endpoint, while the rest of the appbase namespace routes to a common endpoint.

Retry

Adding a retries element defines the number of retry attempts, where 0 (or absent) means no retry. The maximum number of retries is 3.

Note that retrying broadcast methods is not recommended, which is why the example explicitly sets hived.network_broadcast_api to 0.

json-rpc batch

Normally, a request is made with a JSON Object ({}). But jussi also supports batch requests, which is constructed with a JSON Array of Objects ([{}]).

For example, this would be a typical, non-batched JSON Object request that asks for a single block:

curl -s --data '{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":[1], "id":1}' https://api.hive.blog
{
   "id":1,
   "jsonrpc":"2.0",
   "result":{
      "previous":"0000000000000000000000000000000000000000",
      "timestamp":"2016-03-24T16:05:00",
      "witness":"initminer",
      "transaction_merkle_root":"0000000000000000000000000000000000000000",
      "extensions":[

      ],
      "witness_signature":"204f8ad56a8f5cf722a02b035a61b500aa59b9519b2c33c77a80c0a714680a5a5a7a340d909d19996613c5e4ae92146b9add8a7a663eef37d837ef881477313043",
      "transactions":[

      ],
      "block_id":"0000000109833ce528d5bbfb3f6225b39ee10086",
      "signing_key":"STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX",
      "transaction_ids":[

      ]
   }
}

To request more than one block using the batch construct, wrap each call in a JSON Array, that asks for two blocks in one request:

curl -s --data '[{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":[1], "id":1},{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":[2], "id":2}]' https://api.hive.blog
[
   {
      "id":1,
      "jsonrpc":"2.0",
      "result":{
         "previous":"0000000000000000000000000000000000000000",
         "timestamp":"2016-03-24T16:05:00",
         "witness":"initminer",
         "transaction_merkle_root":"0000000000000000000000000000000000000000",
         "extensions":[

         ],
         "witness_signature":"204f8ad56a8f5cf722a02b035a61b500aa59b9519b2c33c77a80c0a714680a5a5a7a340d909d19996613c5e4ae92146b9add8a7a663eef37d837ef881477313043",
         "transactions":[

         ],
         "block_id":"0000000109833ce528d5bbfb3f6225b39ee10086",
         "signing_key":"STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX",
         "transaction_ids":[

         ]
      }
   },
   {
      "id":2,
      "jsonrpc":"2.0",
      "result":{
         "previous":"0000000109833ce528d5bbfb3f6225b39ee10086",
         "timestamp":"2016-03-24T16:05:36",
         "witness":"initminer",
         "transaction_merkle_root":"0000000000000000000000000000000000000000",
         "extensions":[

         ],
         "witness_signature":"1f3e85ab301a600f391f11e859240f090a9404f8ebf0bf98df58eb17f455156e2d16e1dcfc621acb3a7acbedc86b6d2560fdd87ce5709e80fa333a2bbb92966df3",
         "transactions":[

         ],
         "block_id":"00000002ed04e3c3def0238f693931ee7eebbdf1",
         "signing_key":"STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX",
         "transaction_ids":[

         ]
      }
   }
]

Error responses are returned in the JSON Array response as well. Notice the "WRONG" parameter in the second element. The first block is returned as expected, the second one generates an error.

curl -s --data '[{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":[1], "id":1},{"jsonrpc":"2.0", "method":"condenser_api.get_block", "params":["WRONG"], "id":2}]' https://api.hive.blog
[
   {
      "jsonrpc":"2.0",
      "result":{
         "previous":"0000000000000000000000000000000000000000",
         "timestamp":"2016-03-24T16:05:00",
         "witness":"initminer",
         "transaction_merkle_root":"0000000000000000000000000000000000000000",
         "extensions":[

         ],
         "witness_signature":"204f8ad56a8f5cf722a02b035a61b500aa59b9519b2c33c77a80c0a714680a5a5a7a340d909d19996613c5e4ae92146b9add8a7a663eef37d837ef881477313043",
         "transactions":[

         ],
         "block_id":"0000000109833ce528d5bbfb3f6225b39ee10086",
         "signing_key":"STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX",
         "transaction_ids":[

         ]
      },
      "id":1
   },
   {
      "jsonrpc":"2.0",
      "error":{
         "code":-32000,
         "message":"Parse Error:Couldn't parse uint64_t",
         "data":{
            "code":4,
            "name":"parse_error_exception",
            "message":"Parse Error",
            "stack":[
               {
                  "context":{
                     "level":"error",
                     "file":"string.cpp",
                     "line":113,
                     "method":"to_uint64",
                     "hostname":"",
                     "timestamp":"2018-05-21T18:02:41"
                  },
                  "format":"Couldn't parse uint64_t",
                  "data":{

                  }
               },
               {
                  "context":{
                     "level":"warn",
                     "file":"string.cpp",
                     "line":116,
                     "method":"to_uint64",
                     "hostname":"",
                     "timestamp":"2018-05-21T18:02:41"
                  },
                  "format":"",
                  "data":{
                     "i":"WRONG"
                  }
               },
               {
                  "context":{
                     "level":"warn",
                     "file":"variant.cpp",
                     "line":405,
                     "method":"as_uint64",
                     "hostname":"",
                     "timestamp":"2018-05-21T18:02:41"
                  },
                  "format":"",
                  "data":{
                     "*this":"WRONG"
                  }
               }
            ]
         }
      },
      "id":2
   }
]

Also see: block_api.get_block_range

Footnotes


Latin

jussi

noun

declension: 2nd declension
gender: neuter

Definitions:
  1. order, command, decree, ordinance, law

ImageHoster

Definition

Imagehoster is a Hive-powered image hosting and proxying service. Any image uploaded to, or proxied through, your Imagehoster has a copy stored within it. This means that the image continues to be available even if 3rd party sites go down or change their URLs. For as long as your instance of imagehoster is running the image will be available, anytime you need it.

The purpose of this tool is to provide a way to host and proxy images used by condenser to help maintain the privacy of the authors and general users accessing the images.

Using ImageHoster will help limit access to IP addresses of the general user. It will also strip image metadata related to the author’s geographical location. It also helps to verify that the original author uploaded the image they intended.

The ability to upload images on hive.blog was originally added in January, 2017. Please note that this tool does not store any image data on the blockchain.

Detaied information on Imagehoster can be found in its repository

The API

Below are examples of how to process images with the API

  1. Upload an image
  2. Fetch an uploaded image
  3. Proxy and resize an image
  4. Get user avatar image
  5. Signing uploads
  6. How to run

1. Upload an image

POST /<username>/<signature>

This returns a JSON object container the URL to the uploaded image, ex:

{
    "url": "https://images.example.com/DQmZi174Xz96UrRVBMNRHb6A2FfU3z1HRPwPPQCgSMgdiUT/test.jpg"
}

For this to succeed it requires a signature from a Hive account in good standing.

2. Fetch an uploaded image

GET /<image_hash>/<filename>

This downloads a previously uploaded image.

<filename> is optional but can be provided to help users and applications understand the content type (Content-Type header will still always reflect actual image type)

3. Proxy and resize an image

GET /<width>x<hight>/<image_url>

This downloads and serves the provided image_url. Something to note is that a copy will be taken of the image and will be served on subsequent requests, so even if the upstream is removed or changes, you will still get the original from the proxy endpoint.

<width> and <height> can be set to 0 to preserve the image’s dimensions, if they are >0 the image will be aspect resized (down-sample only) to fit.

4. Get user avatar image

GET /u/<username>/avatar/<size>

This presents the avatar for username. If no avatar is set, a default image will be served. This default is set in the service config.

The sizes are:

The avatars follow the same sizing rules as proxied images, so you not guaranteed to get a square image, just an image fitting inside of the size square

5. Signing uploads

Uploads also require a signature made by a Hive account’s posting authority. The account has to also be above a certain (service configurable) reputation threshold.

Creating a signature for node.js and with dhive:

const dhive = require('dhive')
const crypto = require('crypto')
const fs = require('fs')

const [wif, file] = process.argv.slice(2)

if (!wif || !file) {
    process.stderr.write(`Usage: ./sign.js <posting_wif> <file>\n`)
    process.exit(1)
}

const data = fs.readFileSync(file)
const key = dhive.PrivateKey.fromString(wif)
const imageHash = crypto.createHash('sha256')
    .update('ImageSigningChallenge')
    .update(data)
    .digest()

process.stdout.write(key.sign(imageHash).toString() + '\n')

6. How to run

This imagehoster demo must be run through linux due to a dependency on the make commandline. You will also require node.js and yarn to run

This will pull in all dependencies and spin up a hot-reloading development server. From there the HTTP methods can be used to alter the image loaded from the <./test> module.

Default configuration variables are in <./config/defailt.toml> and can be overridden by environment variables as definded in <./config/custom-enfironment-variables.toml>

The load order for the config files are: env vars > config/$NODE_ENV.toml > config/default.toml

DHF

Intro

The DHF (Decentralized Hive Fund) is an account on the Hive blockchain (currently @hive.fund) that receives 10% of the annual new supply. These funds are dedicated to Hive platform improvements.

Every day a portion of the HBD fund managed by the DHF is distributed to various proposals, depending on a) how much the proposal is asking for and b) how much approval the proposal has.

The DHF was a concept proposed by @blocktrades to allow Hive users to publicly propose work they are willing to do in exchange for pay. Hive users can then vote on these proposals in almost the same way they vote for witnesses. It uses stake-weighted votes, but voters can vote for as many proposals as they want.

The Decentralized Hive Fund (DHF) is a proposal-based DPoS financing alternative. The DHF places the consensus behind direct financing of development and other ecosystem-positive projects into the hands of the stakeholders. The distribution of the DHF is decentralized by design. Support for a proposal is calculated based on the total stake in support of that proposal. When a user opts to support a number of proposals, their stake influences the proposals equally. Support for a proposal may be granted or removed but the mechanism cannot be used to negate the sum of supporting stake with a negative vote. This prevents one single large stakeholder from doubling the impact of their stake and influencing the remuneration of numerous proposals, creating a level playing field.

Proposal funding is released when the total value of that supporting stake surpasses the stake behind a benchmark proposal. The benchmark proposal itself may vertically traverse the rankings as per the amount of its supporting stake. The payments are distributed on a hourly schedule over a set period of time as specified upon launch of each proposal. Proposals that surpass the benchmark proposal and unlock funding will receive the funding as remaining in the total ask of the proposal minus the time that had passed prior to funding. The total amount is only released where the proposal unlocks the funds prior to its scheduled duration.

Tools

API

To access the proposal system by JSON-RPC request, see: database_api.list_proposals. Proposal creation by broadcast operation, see: create_proposal.