Blockchain

Home

The ADS Blockchain

The ADS Blockchain is a fork of the Enterprise Service Chain (ESC), a blockchain software technology capable of facilitating high volumes of simple transactions which, similarly to other cryptocurrencies, allows sending tokens between user accounts. ESC derives its name from the concept of the Enterprise Service Bus, where a cryptocurrency is used as the communication protocol.

The main features of the ADS Blockchain can be summarized as follows:

  • Delegated Proof of Stake as block consensus mechanism to reduce network maintenance costs
  • Small account and transaction identifiers, reduced transaction set and parallel processing of transactions to facilitate high transaction volumes (>100kHz one-one transactions, >1MHz one-many transactions)
  • Nodes are heavily penalized for double spends so most transactions can be trusted almost instantly
  • Small set of VIP nodes responsible for network integrity to facilitate incorporation of slow nodes with reduced transaction processing capabilities
  • Hash of all accounts is part of the block and enables instant synchronization with the block chain
  • Hierarchical organization of accounts and nodes facilitates KYC, AML , eID supply and governance
  • Dividend payments to account holders and node managers to support the growth of the economy of the ESC system

Details

A white paper provides a more detailed description of the concept of the Enterprise Service Chain which is foundation of the ADS Blockchain.

Installation

The software is developed for Linux platform. There is no intent to support other platforms. The software was tested on Debian and Ubuntu.

Although compilation from source is available, we suggest to use binaries from Adshares PPA.

sudo add-apt-repository ppa:adshares/releases -y
sudo apt-get update -y
sudo apt-get install ads ads-tools

Compilation

To compile the software You need boost and ssl libraries. Check the Makefile if anything else is missing.

sudo apt-get update -y
sudo apt-get install -y openssl libboost-all-dev libssl-dev cmake

Start with cloning the git directory.

git clone https://github.com/adshares/ads.git

Before compiling ADS You could check if the ed25519 cryptography software is working correctly and what compile option gives You better speed for Your CPU.

cd ads/external/ed25519
make -f Makefile.sse2
./mytest
make clean
make
./mytest

In our case compiling for sse2 reduces the speed of batch signature verifications by over 30% (it is not the case on AWS). The results of the 2 runs are shown below. The line stating with "BATC" reports number of signature verifications per second. Compiling against the regular Makefile (make) generates a code that can perform over 30k signature verifications per second.

START
HASH: 1295553.388/s [79.074MiB/s]
PKEY: 29027.926/s
SIGN: 28596.429/s [1.745MiB/s]
OPEN: 8721.537/s [0.532MiB/s]
BATC: 18608.159/s [1.136MiB/s]

START
HASH: 836288.155/s [51.043MiB/s]
PKEY: 48491.258/s
SIGN: 47754.419/s [2.915MiB/s]
OPEN: 14017.216/s [0.856MiB/s]
BATC: 30312.243/s [1.850MiB/s]

Keep the compiled object files in the directory and compile ADS.

cd ../..
mkdir build
cd build
cmake -DCMAKE_PROJECT_CONFIG=ads ../src/
make -j `nproc` ads adsd install

The default build is for production. If You want to compile DEBUG version, add -DCMAKE_BUILD_TYPE=DEBUG option to cmake command.

cmake -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_PROJECT_CONFIG=ads ../src/

When compiling, the compiler will detect if You have a recent kernel that supports the "FALLOC_FL_COLLAPSE_RANGE" option for fallocate(). This option is used to remove old (first) pages from log files and works only on ext4 file systems. If You don't have a recent kernel or run the software on a different file system, then user log files will not be purged (will grow forever). We will consider adding support for this case in the future.

Check if ads and adsd are installed properly.

ads -v
adsd -v

Both commands should return version.

Setting up a local test net

Create a directory for Your first node and the first user, and create link to key generator for convenience.

mkdir /tmp/node1
mkdir /tmp/user0
ln -s `pwd`/external/ed25519/key /tmp/user0/key

To start the first node enter

cd /tmp/node1
echo 'svid=1' > options.cfg
echo 'offi=9091' >> options.cfg
echo 'port=8091' >> options.cfg
adsd --init 1 -w .

The program will detect that it is in an empty directory and will create an initial setup with a single node and an administrator account for the node. You can stop a node by [Ctrl-C]. You can continue with the same block-chain by running the code again with the '--init 1' switch.

adsd --init 1 -w .

The first node will start with the default node secret key stored in key/key.txt . The secret key to the admin account is the same. Secret keys can be created by running the key executable with a selected brain-key-string (ed25519/key "brain-key-string"). Both keys can be changed later. In production the node key and the admin key should differ for security reasons. To add more nodes and users open a new terminal and connect to the running node as admin (user with account number 0). We have created a directory for the user previously. Let's go there.

cd /tmp/user0

Let's create the file containing the connection setting for the user.

echo 'port=9091' > settings.cfg
echo 'host=127.0.0.1' >> settings.cfg
echo 'address=0001-00000000-XXXX' >> settings.cfg
echo 'secret=14B183205CA661F589AD83809952A692DFA48F5D490B10FD120DA7BF10F2F4A0' >> settings.cfg
chmod go-r settings.cfg

This is the account address of our user 0001-00000000-XXXX. Last 4 characters should be hex characters defining the checksum. They are optional and string 'XXXX' can be provided instead. Let's try to connect to the node and get the current status of our user.

echo '{"run":"get_me"}' | ads -w . 2>err.txt

This command should list the current status of the user. We should get something like this:

{
    "current_block_time": "1534837760",
    "previous_block_time": "1534837248",
    "tx": {
        "data": "100100000000000100000000007AC47B5B",
        "signature": "CEC32B3484794BDBA19252C67C13F24600AEB0DF951E668BFB6DC5BAF7A9EAA2CA81C46F7DEA15BB4712EC06B6A190316628D46BB284EEDBAF7A09C13CDA780B",
        "time": "1534837882"
    },
    "account": {
        "address": "0001-00000000-9B6F",
        "node": "1",
        "id": "0",
        "msid": "1",
        "time": "1534837248",
        "date": "2018-08-21 09:40:48",
        "status": "0",
        "paired_node": "0",
        "paired_id": "0",
        "local_change": "1534837248",
        "remote_change": "1534837248",
        "balance": "38758205.99999999000",
        "public_key": "7D21F4EE7DE72EEDDC2EBFFEC5E7F33F140A975A629EE312075BB04610A9CFFF",
        "hash": "7FBDB0D6A217E5808B33363D13FC0B8E119EDAC625EA278197961B7DA429F5A5"
    },
    "network_account": {
        "address": "0001-00000000-9B6F",
        "node": "1",
        "id": "0",
        "msid": "1",
        "time": "1534837248",
        "date": "2018-08-21 09:40:48",
        "status": "0",
        "paired_node": "0",
        "paired_id": "0",
        "local_change": "1534837248",
        "remote_change": "1534837248",
        "balance": "38758205.99999999000",
        "public_key": "7D21F4EE7DE72EEDDC2EBFFEC5E7F33F140A975A629EE312075BB04610A9CFFF",
        "hash": "7FBDB0D6A217E5808B33363D13FC0B8E119EDAC625EA278197961B7DA429F5A5",
        "checksum": "true"
    }
}

No standard output means the connection failed. You can try to examine the err.txt file for some clues. Correct standard output show the correct account number for the admin of the first node, which is "0001-00000000-9B6F" (the checksum is 9B6F). Now let's change our secret key and create a new account with a new key. First let's generate 2 keys.

./key "user-0-0"
SK: FF767FC8FAF9CFA8D2C3BD193663E8B8CAC85005AD56E085FAB179B52BD88DD6
PK: D69BCCF69C2D0F6CED025A05FA7F3BA687D1603AC1C8D9752209AC2BBF2C4D17
SG: 7A1CA8AF3246222C2E06D2ADE525A693FD81A2683B8A8788C32B7763DF6037A5DF3105B92FEF398AF1CDE0B92F18FE68DEF301E4BF7DB0ABC0AEA6BE24969006
./key "user-0-1"
SK: 5BF11F5D0130EC994F04B6C5321566A853B7393C33F12E162A6D765ADCCCB45C
PK: C9965A1417F52B22514559B7608E4E2C1238FCA3602382C535D42D1759A2F196
SG: ED8479C0EDA3BB02B5B355E05F66F8161811F5AD9AE9473AA91E2DA32457EAB850BC6A04D6D4D5DDFAB4B192D2516D266A38CEA4251B16ABA1DF1B91558A4A05

The secret keys are printed in the lines starting with "SK:". The line starting with "SG:" contains the signature of an empty phrase signed with the secret key. This signature is uses as checksum when creating a new account. Let's change the key for the admin account now:

(echo '{"run":"get_me"}';echo '{"run":"change_account_key","public_key":"D69BCCF69C2D0F6CED025A05FA7F3BA687D1603AC1C8D9752209AC2BBF2C4D17","confirm":"7A1CA8AF3246222C2E06D2ADE525A693FD81A2683B8A8788C32B7763DF6037A5DF3105B92FEF398AF1CDE0B92F18FE68DEF301E4BF7DB0ABC0AEA6BE24969006"}') | ads -w.

In response should be PKEY changed result. After this the admin needs a new secret key to connect to its account, so let's fix the settings.cfg file.

echo 'port=9091' > settings.cfg
echo 'host=127.0.0.1' >> settings.cfg
echo 'address=0001-00000000-9B6F' >> settings.cfg
echo 'secret= FF767FC8FAF9CFA8D2C3BD193663E8B8CAC85005AD56E085FAB179B52BD88DD6' >> settings.cfg

And confirm that we can connect again with the new key.

echo '{"run":"get_me"}' | ads -w . 2>err.txt

The output should indicate that our transaction id was incremented and is now equal 2 ("msid": "2",). Let's now create the second user.

(echo '{"run":"get_me"}'; echo '{"run":"create_account"}') | ads -w .

The new user is managed by our node so the creation process will be fast and the node will report the new account number for the local user in the paired_id field ("paired_id": "1"). Let's read the status of the new user account.

echo '{"run":"get_account","address":"0001-00000001-XXXX"}' | ads -w .

We should see that the correct new account address is "0001-00000001-8B4E". The balance of the new user is too small to make any transactions so let's send him some funds.

(echo '{"run":"get_me"}'; echo '{"run":"send_one","address":"0001-00000001-8B4E","amount":0.1,"message":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"}') | ads -w .

The new balance should be 0.10020000000

echo '{"run":"get_account","address":"0001-00000001-8B4E"}' | ads -w . 2>/dev/null | grep balance

Let's change the public key of the new user by connecting as the new user with the current coppied key. Do not forget to use the "--address 0001-00000001-8B4E" here, otherwise You will change Your own public key. In normal cases You don't know the corresponding secret key so You will loose Your account.

(echo '{"run":"get_me"}'; echo '{"run":"change_account_key","public_key":"C9965A1417F52B22514559B7608E4E2C1238FCA3602382C535D42D1759A2F196","confirm":"ED8479C0EDA3BB02B5B355E05F66F8161811F5AD9AE9473AA91E2DA32457EAB850BC6A04D6D4D5DDFAB4B192D2516D266A38CEA4251B16ABA1DF1B91558A4A05"}' ) | ads -w . --address 0001-00000001-8B4E

The output should indicate that the public key was changed. Let's connect as the new user after setting up the new environment.

mkdir ../user1
cd ../user1
echo 'port=9091' > settings.cfg
echo 'host=127.0.0.1' >> settings.cfg
echo 'address=0001-00000001-8B4E ' >> settings.cfg
echo 'secret= 5BF11F5D0130EC994F04B6C5321566A853B7393C33F12E162A6D765ADCCCB45C ' >> settings.cfg
chmod go-r settings.cfg
echo '{"run":"get_me"}' | ads -w .

The output should indicate that You have successfully connected to the node as user "0001-00000001-8B4E". You don't have enough funds to create a new node. User0 will help You.

cd ../user0
(echo '{"run":"get_me"}'; echo '{"run":"send_one","address":"0001-00000001-8B4E","amount":10000,"message":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"}') | ads -w .

Let's now try to create a new node. The new node will get the public key of the requesting user.

cd ../user1
(echo '{"run":"get_me"}'; echo '{"run":"create_node"}') | ads -w .

It will take at least 1 block time for the network to create a new node. You can examine the log of the first node. Before block creation the node should show now info about 3 nodes (the first one is the unused node number 0). You should see lines like these

NOD: 00000000 00000000 ffff0000 00000000 595E8D80 0 0000000000000000 0
NOD: eef4217d c08c88e1 8936fa16 0000003C 595EA5BB 6 3FFFC1DB71A5379A 2
NOD: 145a96c9 e186f4ad ffff0002 00000000 595EA5A0 0 0000000FFFF08000 1

When the new node is created You can send some funds to the new admin account (0002-00000000-XXXX) if You plan to perform any transaction. We will skip it because we will only try to connect a new node.

Let's create the directory and the files for the new node

mkdir ../node2
cd ../node2
echo 'svid=2' > options.cfg
echo 'offi=9092' >> options.cfg
echo 'port=8092' >> options.cfg
echo 'addr=127.0.0.1' >> options.cfg
echo 'peer=127.0.0.1:8091' >> options.cfg
mkdir key
chmod go-rx key/
echo '5BF11F5D0130EC994F04B6C5321566A853B7393C33F12E162A6D765ADCCCB45C' > key/key.txt
chmod go-r key/key.txt

The configuration file (options.cfg) indicates an initial peer address that we want to start syncing from. Now we should be able to connect the new node to the network.

adsd -f 1 -w .

The connection should be established shortly. You can stop the node again by [Ctrl-C]. The -f switch indicates that we want to start from the current status of the blockchain. After stopping the second node, we should start it again without the -f option to load the missing blocks.

adsd -w .

Connecting more nodes can be done iteratively . The nodes broadcast their IPs and ports on the network so there is no need to provide many peers in the options.cfg file.

ADS API

This document describes the format of the communication with the ADS wallet program (ads).

Methods

Methods are defined using the run input parameter.

name description
broadcast broadcast a message on the network
change_account_key change public key of my account
change_node_key change public key of a node
create_account create new user account
create_node create new node
decode_raw decode transaction
get_account get account info by address
get_blocks download and store block headers
get_broadcast download broadcast messages
get_log download and store transaction log
get_me get my account info
get_transaction get info about a single transaction
get_vipkeys get list of public keys of VIP nodes
get_signatures get signatures of a block
get_block get block header and list of nodes
get_accounts get account of a node
get_message_list get list of messages in a block
get_message get message in a block
log_account record account state in network
retrieve_funds retrieve funds from a remote node
send_again resend a transaction
send_one send payment to one destination
send_many send payment to many destinations
set_account_status set status bits of a user account
set_node_status set status bits of a node
unset_account_status unset status bits of a user account
unset_node_status unset status bits of a node

Command line parameters and config file options

Run ads -h to get the list of command line options and config file parameters.

> ads -h
Usage: ads [settings]
Generic options:
  -w [ --work-dir ] arg (=$HOME/.ads) working directory
  -v [ --version ]                    print version string
  -h [ --help ]                       produce help message

Configuration [command_line + config_file]:
  -P [ --port ] arg (=6511)      node port (for clients)
  -H [ --host ] arg (=127.0.0.1) node hostname or ip
  -A [ --address ] arg           address (don't use with --bank, --user)
  -b [ --bank ] arg              node id (don't use with --address)
  -u [ --user ] arg              user id (don't use with --address)
  -i [ --msid ] arg (=0)         last message id
  -n [ --nice ] arg (=1)         request pretty json
  -o [ --olog ] arg (=1)         record submitted transactions in log file
  -d [ --dry-run ] arg (=0)      dry run (do not submit to network)
  -x [ --hash ] arg              last hash [64chars in hex format / 32bytes]
  -s [ --secret ] [=arg(=-)]     passphrase or private key [64chars in hex 
                                 format / 32bytes]

The default config file is settings.cfg. You can store authentication data inside settings.cfg file or pass them as parameters.

Sample content of settings.cfg file:

port=6511
host=127.0.0.1
address=0001-00000000-XXXX
secret=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF

is equivalent to following parameters:

--port=6511 --host=127.0.0.1 --address=0001-00000000-XXXX --secret=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF

Config file should be placed in working directory, where cached data is stored as well. Default location is $HOME/.ads directory.

If --secret parameter is used, but has default value -, private key will be read from stdin.

Input values

Input should be provided in json format (other available input options are obsolete, incomplete and depreciated). The input for a single transaction should be in a single line (this can be overwritten by startup settings). Multiple input lines will be interpreted as independent method calls. The main input parameter (run) is the definition of the requested transaction method.

Example: "run" : "get_me"

Binary input data must be provided in hexadecimal format without leading '0x' and with even number of characters (hexadecimal digits).

Example: "public_key" : "2D1FC97FA56B785E0FDAE5752DE613BAD7FBBB5EBBB46DAEE5DBFA822F976B63"

Integer values (for example amount of coins) must be provided in decimal format. Time values must be provided in seconds since the beginning of current epoch. Special formats are used for account addresses, transaction, message and block ids.

Example:

  • address : "00FF-0AB01234-XXXX" (16 hexadecimal characters separate with 2 '-', 'XXXX' is allowed as last part of string).
  • txid : "00FF:000000AB:000C" (16 hexadecimal characters separated by 2 ':').
  • message_id : "000F:000000AB" (12 hexadecimal characters separated by ':').
  • block_id : "5B695BA0" (8 hexadecimal characters).

Return values

In case of success ads returns json formatted objects. In case of error json response has an error field.

Before submission of the transaction to the node some transaction input values are returned:

  • tx.data complete transaction byte stream (data) as hexadecimal string.
  • tx.account_hashin last account transaction hash used in this transaction as input for signing.
  • tx.account_hashout new account transaction hash after signing the new transaction.
  • tx.deduct calculated cost of the transaction (deduction from balance).
  • tx.fee calculated fee of the transaction (part of tx.deduct).
  • tx.account_msid current transaction number of the account.
  • tx.account_public_key current public key of the account.

Some of the above parameters are returned only for specific methods or n specific cases (for example the public key is returned only if there was never a transaction submitted from this account). Further processing of the transaction stops if the --dry-run switch is set and the transaction is not submitted to the node.

If the transaction was submitted to the node and is scheduled for broadcast on the network, the node returns a transaction identifier:

  • tx.id in format 'NNNN:MMMMMMMM:PPPP' (NNNN: node id, MMMMMMMM: node message number, PPPP: position).
  • tx.node_msid node message number [integer].
  • tx.node_mpos transaction position in message [integer].

If the transaction was successful the node returns the updated local user account object. If the transaction requested info about the account the local and the global user account object is returned.

Currently node id and account id are often returned as integer, while fixed length hexadecimal format is used as input. This will be changed in the future to have consistent fixed length hexadecimal representation also in the output.

User account object

The local account object is the state of the account as seen by the node after committing last transaction. The global account object is the state of the account as seen by the network, possible before submission of the transaction. Both objects are handled independently and can differ is the node processed a transaction but the message containing the transaction was not yet created, submitted or processed. Both objects can also differ if there is a transaction from the network (deposit) that was not yet processed and committed in the local database.

Local account object includes following fields:

  • account.address account id in the standard format "NNNN-UUUUUUUU-XXXX".
  • account.node node id as integer.
  • account.id user id of the account (number of account in node).
  • account.msid last transaction number (number of submitted transactions + 1).
  • account.time time of last transaction in second since epoch (integer).
  • account.date time as date string.
  • account.status 16 status bits as integer.
  • account.paired_node node of a linked account (account with same public key) as integer
  • account.paired_id user id of the linked account.
  • account.paired_address address of the cousin account, displayed only if there is a linked account. A linked account info is recorded in this account if a new account was created as result of a request from this account or if an account from a different node requested fund retrieval from this account.
  • account.local_change block time of an outgoing transaction request.
  • account.remote_change block time of an incoming transaction from a remote host.
  • account.balance account balance.
  • account.public_key public key of the account.
  • account.hash account hash after last outgoing transaction (private block-chain).

Global account objects returns the same parameters in the network_account container. In addition a checksum verification result is returned (checksum) that can be ignored.

Fees

Fees are expressed in clicks.

1 click = 1e-11 ADS = 0.00000000001 ADS (the main ADS network token)

Most transaction have a fixed fee. The minimum transaction fee is TXS_MIN_FEE. Broadcast transactions have a variable fee part proportional to the length of the broadcasted data string. Wire transfer transactions have a variable fee proportional to the transferred amount.

name amount description
TXS_MIN_FEE 10,000 minimum fee per transaction
TXS_DIV_FEE (600,000,000/year = 0.006 ADS/year) dividend fee collected every dividend block
TXS_KEY_FEE 10,000,000 change account key fee
TXS_BRO_FEE(x) TXS_MIN_FEE if length<=32 bytes, 1000 for each next byte broadcast message fee, x is message length in bytes
TXS_PUT_FEE(x) x * 0.05% local wires fee (weight), x is transferred amount
TXS_LNG_FEE(x) x * 0.05% additional remote wires fee (weight), x is transferred amount
TXS_MPT_FEE(x) x * 0.05% local multiple wires fee (weight), x is transferred amount
TXS_GET_FEE 1,000,000 retrieve funds from remote/dead bank request fee (each retrieve_funds function call)
TXS_GOK_FEE(x) x * 0.1% retrieve funds from remote/dead bank fee, x is retrieved amount, also TXS_LNG_FEE is charged by receiving node
TXS_USR_FEE 100,000,000 create user fee
TXS_RUS_FEE 100,000,000 additional create user fee for remote applications
TXS_SUS_FEE 10,000,000 set user status bits fee
TXS_SBS_FEE 10,000,000 set bank status bits fee
TXS_UUS_FEE 10,000,000 unset user status bits fee
TXS_UBS_FEE 10,000,000 unset bank status bits fee
TXS_SAV_FEE 10,000,000 record account status in chain fee
TXS_BNK_FEE 100,000,000,000,000 (=1000 ADS) create new bank fee
TXS_BKY_FEE 10,000,000,000 (=0.1 ADS) change bank key fee
BANK_USER_FEE(x) (60,000,000/year = 0.0006 ADS/year) * x bank user fee, charged every block, x is a number of users created in a bank
MESSAGE_FEE(x) x + 4,096 fee for each bank message sent to network, payed by bank operator, x is message length in bytes

Examples

Many examples start with the get_me method call. This call is needed for ads to load the latest account data (the account msid and hash) to correctly sign the next transaction. This call is not needed if the account msid and hash is provided as command line option or is set in the settings.cfg file.

Methods reference

broadcast

Broadcast a message on the network.

Parameters

  • message hexadecimal string (without leading '0x', with even number of character). Maximum size of message is 32000 bytes. It means that maximum length of message string is 64000, because every byte is encoded as two characters.
  • message_ascii ASCII string. Maximum size of message is 32000 bytes. It means that at maximum 32000 characters can be sent. This parameter can be used as alternative for message. Using both parameters will generate an error.

Fees

fee = TXS_BRO_FEE(message_size)

Fee depends on the length of the broadcasted string (message size in bytes).

Returns

On success returns the updated local user account object.

Errors

  • time of the transaction (set by the ads program) must not be bigger than node's current clock time + 1 second
  • parameter message and message_ascii cannot be used together in one request

Example

(echo '{"run":"get_me"}'; echo '{"run":"broadcast","message":"D69BCCF69C2D0F6CED025A05FA7F3BA687D1603AC1C8D9752209AC2BBF2C4D17"}') | ads

change_account_key

Change public key of my account. The transaction takes as argument the signature of an empty string signed with the new private key. The signature is used only as the checksum of the new private key. The signature is only verified by ads. The signature is not verified by adsd.

Parameters

  • public_key new public key as hexadecimal string
  • confirm signature (as hexadecimal string) of an empty string signed with the new private key

Fees

fee = TXS_KEY_FEE

Returns

On success returns JSON response with field result equal PKEY changed.

Errors

  • in case of signature error ads returns "ERROR, bad new KEY empty string signature".

Example

(echo '{"run":"get_me"}'; echo '{"run":"change_account_key","public_key":"2D1FC97FA56B785E0FDAE5752DE613BAD7FBBB5EBBB46DAEE5DBFA822F976B63","confirm":"D050CCFC88086A13BC6633BF8267523E2E51607EE01D60AF40A3A1AA12E6F078B6AD9231335D774AE37E7CCF48401B7D9D7D1D68FB3BBB22508685BB31368905"}') | ads

change_node_key

Change public key of the node I manage. After broadcast of this transaction to the network the node will look for a new matching private key in the key file of the node (key/key.txt). If the key is found, the node will continue signing future messages with the new key. If the key is not found the transaction is rejected. Node key changes are expensive and complicated procedures that modify core parameters of the network. It is advised to do this rarely. If the node parameter is provided, the transactions attempts to set a new key for a remote double-spend node. Only the master VIP node has the right to do this and only keys of double-spend nodes can be changed remotely.

Parameters

  • public_key new public key
  • node node id [optional]

Fees

fee = TXS_BKY_FEE

Returns

On success returns the updated local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"change_node_key","public_key":"2D1FC97FA56B785E0FDAE5752DE613BAD7FBBB5EBBB46DAEE5DBFA822F976B63"}') | ads
(echo '{"run":"get_me"}'; echo '{"run":"change_node_key","public_key":"2D1FC97FA56B785E0FDAE5752DE613BAD7FBBB5EBBB46DAEE5DBFA822F976B63","node":"16"}') | ads

create_account

Create new user account. If no node parameter is provided or node is 0 the node will assume I request a new local account managed by the same node. If the node parameter is not 0 and not equal to the local node id, the node will assume that I request the creation of an account by a remote node (remote account). Local account creation requests are cheaper and are processed immediately by the node (accepted or rejected). In case of success the node will modify the local account and modify the paired account id. Remote account creation requests are expensive and the success of the process depends on the response of the remote node. The result of the process will be stored in my log kept by my node. The logs need to be examined to extract the new account id created by the remote node. In both cases (local and remote) the new account will have the same public key as the original account. By default created account has the same key as user who requested operation. It can be changed with passing new public key and signature of empty string.

Parameters

  • node node id in decimal format [optional]
  • to set account key [optional] two parameters are needed:
    • public_key public key of account
    • confirm empty string signed with secret key

Fees

For local accounts:

fee = TXS_USR_FEE

For remote accounts the fee is larger:

fee = TXS_USR_FEE + TXS_RUS_FEE

In addition to the fees the "minimum account creation balance" (USER_MIN_MASS = 0.00020000000 ADS) is deducted from the sending account and credited to the new account. In case of failure the balance is returned to the sending account. In case of remote account creation requests the network will return the "minimum account creation balance" to the sending account if the remote node fails to accept the request within the same block period.

Returns

On success returns the updated local user account object. For local account creation the updated local user account object contains the paired account id, that can be used to obtain the id of the newly created account. For remote account creation future logs must be examined to check for the id of the created account.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"create_account"}') | ads
(echo '{"run":"get_me"}'; echo '{"run":"create_account","node":"16"}') | ads
(echo '{"run":"get_me"}'; echo '{"run":"create_account","public_key":"D69BCCF69C2D0F6CED025A05FA7F3BA687D1603AC1C8D9752209AC2BBF2C4D17", "confirm":"7A1CA8AF3246222C2E06D2ADE525A693FD81A2683B8A8788C32B7763DF6037A5DF3105B92FEF398AF1CDE0B92F18FE68DEF301E4BF7DB0ABC0AEA6BE24969006"}') | ads

create_node

Create new node. Node creation is a process that requires synchronized effort of the network. The process can fail if range of available ids is exhausted and there are no available zombie nodes. The new node id will be recorded in the logs of the sending account after the completion of the block.

Parameters

none

Fees

fee = TXS_BNK_FEE

In addition to the fees the "minimum bank account creation balance" (BANK_MIN_UMASS = 1 ADS) is deducted from the sending account and credited to the new account. In case of failure the balance is returned to the sending account.

Returns

On success returns the updated local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"create_node"}') | ads

decode_raw

Decodes transaction encoded as hexadecimal string.

All transactions are binary encoded before sending to network. This encoded string in hexadecimal format is returned to user in reponse field tx.data. Function decode_raw allows user to decode transaction back if needed.

Parameters

  • data transaction encoded as hexadecimal string. Length of string depends on transaction type,
  • signature signature of the transaction [optional].

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

On success returns decoded transaction in JSON format.

Errors

No errors specific to this method are returned.

Example

{"run":"decode_raw","data":"040100000000000D0000008F56605B01000100000000A0724E180900000000000000000000000000000000000000000000000000000000000000000000","signature":"59707836D82E184546D243F3F61D8DFA12F9A7DF45EC61CE04B33C15788660A08DE32D697A6AC06635D719EA393DCA10896A1F0BC96C4C63DA193D298A61E50A"}

get_account

Get account data by address.

Parameters

  • address account address in the standard format "NNNN-UUUUUUUU-XXXX" [optional]:
    • "NNNN" indicates the node id (4 hexadecimal characters).
    • "UUUUUUUU" is the id of the user account (8 hexadecimal characters).
    • "XXXX" is the account address checksum (4 hexadecimal characters). If the checksum is not known the string "XXXX" can be used.

If account address is not provided, data for current account is returned.

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

On success returns the local and the global user account object. The local version of the object represents the status of the object after committing all transactions submitted to the node. The global version of the object represents the status of the object after processing messages available on the network. Both objects may differ if local transactions submitted from the account are not yet processed by the network or if there are transactions generated by the network (for example remote account creation or dividend payments) that have not yet been fully processed by the local node (local office).

Errors

No errors specific to this method are returned by ads.

Example

echo '{"run":"get_account","address":"000F-0000000F-XXXX"}' | ads

get_blocks

Download, process and store a range of block headers in local archive. While downloading, the blocks signatures are validated. Changes in the VIP public keys are also validated and recorded. Block headers are stored in 'blk/'. VIP keys are stored in 'vip/'. Local block header ('blk/') repository contains only hashes of blocks validated by confirming the correctness of the signing signature sequence. The repository will grow approximately only by 32 bytes with every new block and, due to its small size, should fit on a mobile device.

Parameters

  • from first block time in seconds since epoch as hexadecimal string [optional]. If parameter is missing ads will request the download starting after the last locally stored block header. If local block header repository is empty 0 will be passed to the node and the node will set this parameter to the time of the first block it knows.
  • to block time of the last block to download, in seconds since epoch as hexadecimal string [optional]. If parameter is missing the node will send all blocks from the starting block until the last known block on the network. In a single request the node will only return a range of blocks for which the set of VIP keys did not change. A second request (transaction call) is needed to download the subsequent range of blocks.

In the most common use case no parameters are provided.

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

Nothing is returned except errors and debug messages. Local block and VIP keys repository is updated.

Errors

Most common error message is No new blocks to download. It means that all blocks were updated. It is advised to call get_block function until this error occurs.

ads will report many communication and validation errors specific for the method.

Communication errors include:

  • ERROR, failed to read VIP keys for first hash
  • ERROR, failed to read blocks since ...
  • ERROR, failed to check ... VIP keys for hash ...
  • ERROR, failed to confirm first header hash, fatal
  • ERROR, failed to get correct block ..., fatal
  • ERROR, failed to get signatures for header ...
  • ERROR, failed to check VIP keys for hash ...

Validation errors include:

  • ERROR opening vip/....vip, fatal
  • ERROR failed to match viphash for header ..., fatal
  • ERROR failed to match oldhash for header ..., fatal
  • ERROR failed to confirm nowhash for header ..., fatal
  • ERROR vipkey (...) not found ... [not fatal]
  • ERROR vipkey (...) failed ... [not fatal]

In case of error local block archive (block headers) will not be updated.

Example

echo '{"run":"get_blocks"}' | ads

get_broadcast

Display broadcast messages log from a block. If no block time is provided the last completed block is assumed. The node does not guaranty the completeness, consistency nor order of broadcast messages stored in the log. It is expected that different nodes have different order of broadcast messages in log files. It is possible that broadcast messages are duplicated or copies of them are in different log files on different nodes. The node guaranties that at least one copy of the broadcast message is in the log file of the block in which the broadcast message is included. Logs from older blocks are expected to remain unchanged on a node, unless the node will resync these blocks again.

ads keeps a local archive of broadcast message log files in the 'bro/' directory. ads will automatically request missing log files from the node. If the downloaded log file is from an uncompleted block the log file will not be saved in local archive.

Parameters

  • from block time in seconds since epoch as hexadecimal string [optional]. If block time is not provided (is equal zero) the node will return the log file from the last committed block. It is expected that this log file will not change in the future on this node, unless the node will resync the block again.

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

The method returns info about the log file:

  • log_file archive|new|pending
    • archive: reporting previously reported broadcast log
    • new: reporting new broadcast log
    • pending: reported broadcast log is not final
  • block_time time of the block in seconds since epoch
  • block_time_hex time of the block in seconds since epoch in hexadecimal format, compatible with filename format in 'bro/' archive directory

The method returns info about the broadcast transactions in the log file. The transactions are stored in the json blocktree array and contain:

  • block_time block time of the transaction in seconds (integer)
  • block_date block time of the transaction as date string
  • node node of the sender (integer)
  • account account id of the sender (integer)
  • address account address of the sender (address format)
  • account_msid message number of the sender (integer)
  • time time of the transaction in seconds (integer)
  • date time of the transaction ad date string
  • message broadcasted message in hexadecimal format
  • data transaction data string in hexadecimal format
  • signature transaction signature in hexadecimal format
  • input_hash transaction input hash used when signing in hexadecimal format
  • public_key public key of the sender when signing in hexadecimal format
  • verify failed|passed , result of the verification of the signature
  • node_msid node message number of the message
  • node_mpos position of the broadcast transaction in message
  • id id of the transaction (transaction id format)

If the supplied block time is in an unknown, future block the node will return an empty broadcast log file.

Errors

  • Broadcast not ready, try again later Broadcast messages are not ready. Need to wait and retry,
  • No broadcast file to send Block has not messages. Need to check next block.

Example

echo '{"run":"get_broadcast", "from":"5B9BC820")' | ads

get_log

Download and store transaction log. The log includes incoming and outgoing transactions. With every get_log method call ads will read the local log archive of the user to load the time of the latest downloaded log entry. ads will then request from the node log entries not earlier than the time loaded from the archive. Downloaded entries will be checked for duplicates and appended to the local archive. After download and store the method will print all entries starting from the time provided in the from parameter.

Using default settings the node will purge its the log file of the user frequently keeping at least a 4kB block of latest logs. However log entries that are younger than 0x800 blocks (MAX_LOG_AGE) will not be deleted.

Parameters

  • address address of an account which log will be read [optional]. Account must be in the same node as an account issuing the request
  • from earliest time of the log entry in seconds since epoch as decimal number [optional]. If time is not provided (is equal zero) the full log will be returned
  • type return only transaction of specified type eg. send_one, create_account [optional]. If type is not provided all transaction types will be returned
  • full allows to access log of deleted accounts. For 1 full log is returned, for 0 (default) only current user log is returned. This parameter is useful when one account was deleted and another user has received it. By default user can only see events from time of his account creation. When full option is set to 1, user can see events before his account creation, if there were any.

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

The transaction log will be returned in the json array log. Each transaction can have following fields:

  • time time, the log entry was created by the server, in seconds since epoch
  • date time as date string
  • type_no transaction type (method) as integer including status bits. Currently 2 bits are OR'ed to transaction number:
    • 0x4000 indicating log error (restart of the node with forced resync of older blocks),
    • 0x8000 indicating transaction originating from the network
  • confirmed placeholder, always equal 1, depreciated
  • type transaction type (method) as string (without status bits)

Depending on the type of transaction entry different additional parameters are provided. The list below is grouped by types.

The following transactions are incoming transactions initiated by the network:

node_started with error 0x4000:

  • account.error always equal 'logerror'
  • account.newtime server starting new sync from this time in the past (in seconds)
  • account.newdate server starting new sync from this time in the past (as date string)
  • account.badtime server failed at this time (in seconds)
  • account.baddate server failed at this time (as date string)
  • account.badblock server failed after this block time (in seconds)

node_started without error:

  • node_start_msid node message number when node started
  • node_start_block block time when node started (in seconds)
  • dividend added dividend Info about my account is returned at node start
  • account.balance balance
  • account.local_change time of last local (outgoing) transaction
  • account.remote_change time of last remote transaction
  • account.hash_prefix_8 first 8 bytes of account message hash
  • account.public_key_prefix_6 first 6 bytes of public key
  • account.status status bits as integer
  • account.msid last local (outgoing) transaction number
  • account.node node of the account as integer
  • account.id user id of the account
  • account.address address of the account

dividend record:

  • node_msid node message number
  • node_block dividend block time (in seconds)
  • dividend added dividend

bank_profit from a message

  • profit profit for the node
  • node node sending the message
  • node_msid node message number
  • profit_fee fees on local transactions (if my node's message)
  • profit_div fees on account maintenance (if my node's message)

bank_profit from network transactions and maintenance at block end

  • profit profit for the node
  • node_block block time of accounting (in seconds)
  • profit_div fees on account maintenance
  • profit_usr fees on remote user account creation
  • profit_get fees on retrieve_funds transactions
  • fee bank fee on number of accounts

account_created remote account creation request response

  • node node creating the account
  • node_block block time (in seconds) if successful
  • account user id of the new account
  • address of the new account
  • request failed|accepted|late
    • failed: node did not create the account
    • accepted: node created the account
    • late: node created the account in the next block after account creation request transaction
  • amount amount returned on failure (0 or (USER_MIN_MASS))
  • public_key public key of the new account (hexadecimal)

create_node create node request response

  • node_block block time (in seconds)
  • node id of the created node
  • request accepted|failed
    • accepted: node created
    • failed: node creation failed
  • amount amount returned on failure (0 or (BANK_MIN_TMASS))

The remaining transactions were initiated by users. The list of returned fields includes those listed below. For some transaction some fields are not available.

  • node node id of the sender or receiver (as integer)
  • account user id of the sender or receiver
  • address account address of the sender or receiver
  • node_block block time of the transaction
  • node_msid node message number of the transaction
  • account_msid transaction id of the sender
  • amount amount transferred
  • sender_fee fee paid
  • message message info as 32 byte hexadecimal string
  • sender_balance account balance of the sender
  • sender_amount total cost of the transaction
  • sender_fee fee of the transaction
  • sender_fee_total total fee of complete MPT transaction
  • sender_public_key_prefix_5 first 5 bytes of sender public key
  • sender_public_key_prefix_6 first 6 bytes of sender public key
  • sender_status status bits of the sending account
  • inout in|out
    • in: incoming transaction
    • out: outgoing transaction
  • id id of the transaction

Errors

  • ERROR reading log length failed to communicate with the node, fatal.
  • ERROR reading log failed to read the log after reading log length, fatal.
  • No new log entries is reported if no log entries with time not earlier than provided were downloaded from the node

Example

echo '{"run":"get_log","from":1491210824}' | ads

get_me

Returns the same as get_account with no account address. Returns info about my account.

get_transaction

Get info about a single transaction. The transaction info is loaded from local archive or downloaded from the node if missing. The transaction is verified by validating the hash path and comparing the result with the block hash stored in local archive. If the block hash is missing from the archive the transaction can not be validated and an error is returned. Update local block hash archive to resolve this problem (get_blocks); Only validated transactions are stored in local archive.

Parameters

  • txid in format 'NNNN:MMMMMMMM:PPPP' (NNNN: node id, MMMMMMMM: node message number, PPPP: position)

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

A transaction object is returned.

  • network_tx.id transaction id in format 'NNNN:MMMMMMMM:PPPP'
  • network_tx.block_id block id
  • network_tx.node_id node id
  • network_tx.node_msid node message number
  • network_tx.position position in message
  • network_tx.len length of the transaction data
  • network_tx.hash_path_len number of hashes in hash path (path to block hash)
  • network_tx.hextstring transaction data as hexadecimal string
  • network_tx.hashpath hash path to block hash
  • network_tx.type transaction type (method)
  • network_tx.abank sender node id
  • network_tx.auser sender user id
  • network_tx.amsid sender transaction number
  • network_tx.ttime time of the transaction
  • network_tx.bbank target node id
  • network_tx.buser target user id
  • network_tx.amount amount
  • network_tx.message transaction memo (32 byte message)
  • network_tx.signature transaction signature

For some transaction type the meaning of the reported fields (abank, auser, amsid, ttime, bbank, buser, amount, message) can differ.

Errors

  • ERROR, failed to read transaction path for txid ... communication error, fatal.
  • ERROR, got empty block for txid ... missing transaction data, fatal.
  • ERROR, got wrong transaction ... wrong transaction data, fatal.
  • ERROR, failed to load hash for block ... missing block info in local archive. The requested transaction can not be verified because it is included in a block that is not stored in local block archive. Local archive should be updated to fix this problem. See: get_blocks.
  • ERROR, failed to confirm first hash for txid ... wrong transaction data, incorrect (first) hash, fatal.
  • ERROR, failed to confirm nowhash for txid ... wrong transaction data, incorrect hash tree, fatal.
  • ERROR opening txs/... error opening transaction archive file. Transaction will not be archived.

Example

echo '{"run":"get_transaction","txid":"0001:00000002:0001"}' | ads

get_vipkyes

Get list of public keys of VIP nodes. These sets are usually downloaded during block download (get_blocks). Running this method will overwrite the data for the provided hash if it exists in the archive.

Parameters

  • viphash 32 bytes long hexadecimal string representing the hash of the VIP keys set.

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

  • viphash requested hash of VIP keys set
  • vipkeys keys of VIP servers, first key is the key of the master VIP server

Errors

  • ERROR, failed to read VIP keys for hash ... set not found by node, fatal
  • ERROR, failed to check VIP keys for hash ... incorrect data received, fatal
  • ERROR opening vip/..., fatal failed to store vip set in archive, fatal

Example

echo '{"run":"get_vipkeys","viphash":"D3FD529F6305F574BA22F3BDF761B4778094CB38958300ACDF21D35BE03BDC4F"}' | ads

get_signatures

Get list of signatures of a block.

Parameters

  • block block time as hexadecimal string [optional]. If not provided previous block time will be used (last closed block)

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

The function returns array of signatures.

  • signatures.node node id confirming the block
  • signatures.signature signature of the node
  • fork_signatures.node node id confirming a different block
  • fork_signatures.signature signature of the node

Errors

  • ERROR, bad block number ... node returned different block than requested

Example

echo '{"run":"get_signatures","block":"5B2B5B00"}' | ads

get_block

Get the block header and the list of nodes.

Parameters

  • block block time as hexadecimal string [optional]. If not provided previous block time will be used (last closed block)

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

  • block.id block time as hex
  • block.time block time as decimal
  • block.message_count number of messages
  • block.oldhash old block hash
  • block.minhash input block hash
  • block.msghash hash of messages
  • block.nodhash hash of nodes
  • block.viphash hash of vip public keys
  • block.nowhash block hash
  • block.vote_yes confirming signatures
  • block.vote_no forking signatures
  • block.vote_total total number of signatures
  • block.node_count number of nodes (includes technical node 0000)
  • block.dividend_balance dividend
  • block.dividend_pay is true if this is the first block in the dividend period

Array of nodes is returned as well.

  • block.nodes.id node id
  • block.nodes.public_key public key of the node
  • block.nodes.hash hash of accounts
  • block.nodes.message_hash hash of last message
  • block.nodes.msid number of last message
  • block.nodes.mtim time of last message
  • block.nodes.balance sum of account balances
  • block.nodes.status status
  • block.nodes.account_count number of accounts
  • block.nodes.port port number for blockchain messaging
  • block.nodes.ipv4 ip of the node

Errors

No errors specific to this method are returned by ads.

Example

echo '{"run":"get_block","block":"5B2B5B00"}' | ads

get_accounts

Print accounts of a node. Currently, the node will refuse to send accounts from a different block than the (default) previous one. In the future only accounts from blocks used for dividend calculations will be returned. In the future the hash of the accounts should be returned as well.

Parameters

  • node id of the node
  • block block time as hexadecimal string [optional]. If not provided previous block time will be used (last closed block)

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

  • accounts. list of accounts in the same format as reported by get_account

Errors

No errors specific to this method are returned by ads.

Example

echo '{"run":"get_accounts","block":"5B2B5B00","node":1}' | ads

get_message_list

Get list of messages in a block.

Parameters

  • block block time as hexadecimal string [optional]. If not provided previous block time will be used (last closed block)

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

  • msghash hash of messages in the block
  • messages list of message ids in the block in format NNNN:MMMMMMMM node:msid
  • msghash_calculated hash calculated by ads returned if different from msghash
  • confirmed confirmation of the correct hash calculation (yes|no)

Errors

  • error_bad_length node returned data in wrong format

Example

echo '{"run":"get_message_list","block":"5B2B5B00"}' | ads

get_message

Print message.

Parameters

  • message_id message id as returned by get_message_list
  • block block time as hexadecimal string [optional]. If not provided previous block time will be automatically calculated

Fees

This transaction is not sent to the network, so there is no network fee.

Returns

  • block_id block in which message was included
  • message_id message id assigned by network
  • node id of the node
  • node_msid message number assigned by node
  • time time of the message as integer
  • length length of the message in bytes
  • hash hash of the message
  • network_txs.id transaction id in format 'NNNN:MMMMMMMM:PPPP'
  • network_txs.type transaction type (method)
  • network_txs.abank sender node id
  • network_txs.auser sender user id
  • network_txs.amsid sender transaction number
  • network_txs.ttime time of the transaction
  • network_txs.bbank target node id
  • network_txs.buser target user id
  • network_txs.amount amount
  • network_txs.message transaction memo (32 byte message)
  • network_txs.signature transaction signature
  • network_txs.size size of the transaction in bytes

Errors

  • error_bad_length node returned data in wrong format
  • error_parse error parsing the message

Example

echo '{"run":"get_message","message_id":"0005:000017A6"}' | ads

log_account

Record account state in network. Account data from moment of executing transaction can be read like every other transaction by tx.id.

Parameters

This function takes no parameters.

Fees

fee = TXS_SAV_FEE

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}';echo '{"run":"log_account"}') | ads

retrieve_funds

Retrieve funds from a remote node. The public key of the account on the remote node must match the key of my account. This method must be called 2 times to retrieve funds. The remote account must be silent for 2048 blocks before executing the first transaction (initiation). Another 2048 blocks must pass after initiation to finally retrieve the funds with the second call. All funds from the remote account will be transferred. This method does not require the intervention of the remote node. This method is useful in case of node failure or dispute with the node.

Parameters

  • address account id in the standard format "NNNN-UUUUUUUU-XXXX".

Fees

fee = 2*TXS_GET_FEE + TXS_GOK_FEE(funds) + TXS_LNG_FEE(funds-TXS_GOK_FEE(funds))

Fixed part is charged for both calls (retrieve request and actual retrieve). Variable part is for second call (retrieve) and is proportional to retrieved funds.

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"retrieve_funds","address":"0002-00000001-XXXX"}') | ads

send_again

Send (resend) a raw transaction.

Parameters

  • data full transaction data as hexadecimal string.

Fees

The fees of the original transaction apply. The resubmission process implies that the original transaction was not received or accepted by the network so the total fees remain unchanged.

Returns

Returns the results as expected from the original transaction.

Example

(echo '{"run":"get_me"}'; echo '{"run":"send_again","data":"05010000000000010000004A3CC9580200020000000000204E0000000000000300000000003075000000000000521B9E6932FD4973EC8364662B898249635C777BB0AA801F7DA5E9423C920EAECC39AD7B519FF6C6D27E43B9B294C0504816CE20735F11E9D8A252CF8A686806"}') | ads

send_one

Send payment to one destination account. Payments to account managed by a different node are more expensive.

Parameters

  • address destination account id in the standard format "NNNN-UUUUUUUU-XXXX".
  • amount in ADS.
  • message a 32 bytes long message in hexadecimal format [optional].

Fees

Fee for (local) transaction within a node is:

fee = TXS_PUT_FEE(amount)

Fee for (remote) transaction to a different node is:

fee = TXS_PUT_FEE(amount) + TXS_LNG_FEE(amount)

Due to rounding the order of operations is important while calculating remote fee. Total fee is sum of rounded fees for local and remote node.

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"send_one","address":"0003-00000000-XXXX","amount":2.1,"message":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"}') | ads

send_many

Send payment to many destinations. Payments to account managed by a different node are more expensive. The transaction does not have a message field compared to send_one.

Parameters

  • wires json array with key value pairs. Keys are destination accounts in standard account address format and values are amounts to be wired in ADS. All destination must be unique.

Fees

Fee for each (local) wire within a node is:

local_fee = TXS_MPT_FEE(amount)

Fee for each (remote) wire to a different node is:

remote_fee = TXS_MPT_FEE(amount) + TXS_LNG_FEE(amount)

Returns

On success returns the local user account object.

Errors

Duplicated target when any destination appears in the wires array more than once.

Example

(echo '{"run":"get_me"}'; echo '{"run":"send_many","wires":{"0002-00000000-XXXX":20000.0,"0003-00000000-XXXX":0.003}}') | ads

set_account_status

Set status bits of a user account. Any user is authorized to change the second, the third and the fourth status bits of another account in the same node. The first status bit is reserved and indicates a deleted account. Other bits can be changed only by the owner of the destination account or the administrator of the node. Changes of user status bits on remote nodes are not allowed.

Parameters

  • address destination account id in the standard format "NNNN-UUUUUUUU-XXXX".
  • status bits to set as unsigned integer 16 bit.

Fees

fee = TXS_SUS_FEE

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"set_account_status","address":"0001-00000000-XXXX","status":"10"}') | ads

This transaction will set the 2nd and the 4th bit of the destination account status to 1.

set_node_status

Set status bits of a node. The node status bits can be changed by the administrator of the node or by the administrator of a VIP node. First 3 bits are reserved and can not be changed using this transaction:

  • 1st bit – node is deleted
  • 2nd bit – node belongs to the vip group
  • 3rd bit – node has most funds in network

The administrator of a node can change bits 4-16 of the status of the managed node. VIP node administrators can change bits 17-24 of any node. The last 8 bits of any node can be changed only if more than 50% of the VIP node administrators send the node status change transaction in one block. The 50% minimum is required for any of the last 8 bits.

Parameters

  • node node number as decimal number
  • status bits to set as unsigned integer 32 bit.

Fees

fee = TXS_SBS_FEE

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"set_node_status","node":"1","status":"8"}') | ads

This transaction will set the 4th bit of the destination node status to 1.

unset_account_status

Unset status bits of a user account. Any user is authorized to change the second, the third and the fourth status bits of another account in the same node. The first status bit is reserved and indicates a deleted account. Other bits can be changed only by the owner of the destination account or the administrator of the node. Changes of user status bits on remote nodes are not allowed.

Parameters

  • address destination account id in the standard format "NNNN-UUUUUUUU-XXXX".
  • status bits to unset as unsigned integer 16 bit.

Fees

fee = TXS_UUS_FEE

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"unset_account_status","address":"0001-00000000-XXXX","status":"10"}') | ads

This transaction will set the 2nd and the 4th bit of the destination account status to 0.

unset_node_status

Unset status bits of a node. The node status bits can be changed by the administrator of the node or by the administrator of a VIP node. First 3 bits are reserved and can not be changed using this transaction:

  • 1st bit – node is deleted
  • 2nd bit – node belongs to the vip group
  • 3rd bit – node has most funds in network

The administrator of a node can change bits 4-16 of the status of the managed node. VIP node administrators can change bits 17-24 of any node. The last 8 bits of any node can be changed only if more than 50% of the VIP node administrators send the node status change transaction in one block. The 50% minimum is required for any of the last 8 bits.

Parameters

  • node node number as decimal number
  • status bits to unset as unsigned integer 32 bit.

Fees

fee = TXS_UBS_FEE

Returns

On success returns the local user account object.

Errors

No errors specific to this method are returned by ads.

Example

(echo '{"run":"get_me"}'; echo '{"run":"unset_node_status","node":"1","status":"8"}') | ads

This transaction will set the 4th bit of the destination node status to 0.

How to convert ADST tokens

Please keep in mind that ADST stored on cryptocurrency exchanges must be also converted. Exchanges are not automatically converting ADST into ADS, that is why it is necessary to transfer ADST to a wallet first (e.g. MEW / MetaMask) and then follow the procedure.

Please, read the entire instruction before you start the conversion. If you have any doubts, you can refer to the simplified version of our instruction created by rus33 - one of our Reddit community members: http://adshar.es/EasyConversion


Please, remember that ADST -> ADS conversion ends on the 30th of June 2019. After this date, it will not be possible to convert ADST into ADS anymore.

The token swap will be done at a 1:1 ratio. This means that one ADST ERC-20 token will be exchanged for one ADS coin. There will be no cost for the swap except the Ethereum Gas cost for the transaction.

Please keep in mind that once the process is over, it will not be possible to convert your ADS coins back to ADST ERC-20 tokens. After the 30th of June 2019, the ADST ERC-20 token will not be usable and will not be supported by Adshares. Please make sure to swap your tokens before the deadline.

Also, keep in mind that, depending on the number of conversions, the later you will start the conversion process, the longer it may take, so we advise to start the procedure before the 20th of June, 2019.


Install and configure ADS Wallet

A detailed instruction covering ADS Wallet installation and configuration, as well as new account creation is available here.

Burn your tokens

Once your account is operational, you can move on to the conversion. We prepared a web tool that will help you prepare a proper transaction for Ethereum network. This tool will also validate the account address. Click the following link to launch the tool:

https://conversion.adshares.net/

How to use Adshares conversion tool

ADST-ADS conversion tool

First of all, you need to enter the amount of ADST you would like to burn. Please note that it has to be a whole number. Next, you need to type in your ADS account address and click the "Generate" button.

ADST-ADS conversion tool

In the next step, you need to send 0 ETH (zero ETH) to ADST contract address displayed by the tool. The transfer has to be sent from your personal wallet (e.g. MyEtherWallet, MetaMask), using data generated by the conversion tool. In case you are using MetaMask you can send the transaction using the plugin. You just need to click the button.

If you are not using MetaMask you must enter transaction data to your wallet manually — i.e. copy the contract address and paste it in the “To Address” section. Next, you must copy your transaction data and paste it in the message section.

Please make sure that you are NOT sending ADST instead of ETH and that you are NOT using a smart contract. Also, please note that in case you accidentally send an ADST transfer instead of the ETH one, the conversion will not be effective, as we will not get the account information necessary to transfer ADS.

We recommend setting the gas limit in your wallet to 100,000.

Enjoy brand new ADS coins

Every conversion is checked manually, so it usually takes up to 24-48 hours. You can check the status of the conversion here:

https://conversion.adshares.net/status

Once the conversion process is over your account balance will be increased by the equivalent of your burned tokens in ADS. In case the conversion takes longer do not hesitate to message us on Telegram.

How to validate account address

Address format

The standard format of an account address is NNNN-UUUUUUUU-XXXX:

  • NNNN indicates the node id (4 hexadecimal characters).
  • UUUUUUUU is the id of the user account (8 hexadecimal characters).
  • XXXX is the account address CRC-16/AUG-CCITT checksum (4 hexadecimal characters). If the checksum is not known the string "XXXX" can be used.

Examples:

  • 0001-00000000-9B6F
  • 0001-00000000-XXXX
  • 0015-00000002-3671
  • FFFF-FFFFFFFF-A6E1

CRC calculation

JavaScript

function calculateCrc(nodeId, accountId) {
  const d = `${nodeId}${accountId}`;
  let crc = 0x1D0F;
  for (let i = 0, len = d.length; i < len; i += 2) {
    let x = (crc >> 8) ^ parseInt(d.substr(i, 2), 16);
    x ^= x >> 4;
    crc = ((crc << 8) ^ ((x << 12)) ^ ((x << 5)) ^ (x)) & 0xFFFF;
  }
  return crc.toString(16).toUpperCase().padStart(4, '0');
}

PHP

function calculateCrc(string $nodeId, string $accountId): string
{
  $chars = hex2bin($nodeId . $accountId);
  $crc = 0x1D0F;
  for ($i = 0; $i < strlen($chars); $i++) {
    $x = ($crc >> 8) ^ ord($chars[$i]);
    $x ^= $x >> 4;
    $crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ ($x)) & 0xFFFF;
  }
  return sprintf('%04X', $crc);
}

Validation

JavaScript

function validateAddress(address) {
  const r = /^([0-9A-F]{4})-([0-9A-F]{8})-([0-9A-F]{4}|XXXX)$/;
  const m = r.exec((address || '').toUpperCase());
  if (!m) return false;
  return m[3] === 'XXXX' || m[3] === calculateCrc(m[1], m[2]);
}

PHP

function validateAddress(string $address): bool
{
  $r = '/^([0-9A-F]{4})-([0-9A-F]{8})-([0-9A-F]{4}|XXXX)$/';
  $m = [];
  if (!preg_match($r, strtoupper($address), $m)) {
    return false;
  }
  return $m[3] === 'XXXX' || $m[3] === calculateCrc($m[1], $m[2]);
}

How to generate transactions offline with JSON RPC

Abstract

The ADS blockchain allows users to prepare transactions and execute them later. The aim of this article is to show how to sign a transaction and execute it later without the secret key. This flow is widely used by exchanges, because secret key does not have to be transferred anywhere (even through safe channels).

This article also introduces ads-json-rpc, the JSON-RPC client for ADS.

Requirements

JSON-RPC client for ADS

The JSON-RPC client for ADS (ads-json-rpc) was created to simplify ads wallet program usage. It supports most of ADS-API methods and complies JSON-RPC specification version 2.0. The client can be used for creating transaction for ADS blockchain. The ads-json-rpc is part of ads-tool package. It's installation and usage is described in details on ads-tools project page.

Adshares made publicly available JSON-RPC clients for ADS Mainnet and Testnet.

Both clients have disabled transaction methods, but can send transactions to network using send_again method.

Installation

Binary version of ads-json-rpc can be installed from official Adshares PPA.

sudo add-apt-repository ppa:adshares/releases -y
sudo apt-get update
sudo apt-get install ads ads-tools

Setup

Run ads-json-rpc -h to get the list of command line options and config file parameters. To ensure operation working directory must contains settings.cfg file with address, host, port, and secret set. Below is sample content of settings.cfg file.

port=6511
host=127.0.0.1
address=0001-00000000-XXXX
secret=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF

Above file should be placed in working directory. The ads-json-rpc client utilizes two working directories:

  • first for read_only functions
  • second for transactions

By default working directories are the same as for ads client which is $HOME/.ads. They can be changed with --working-dir [-w] and --transactions-dir [-t] option.

It is important that publicly available clients should forbid to execute transaction functions, eg. send_one. Therefore --transactions-dir should be set to empty directory, or at least to directory where settings.cfg file is NOT present.

Usage

The ads-json-rpc supports JSON-RPC specification version 2.0. It means that each request must have body with request id, method, parameters, and supported JSON-RPC version. All requests must be HTTP POST and should have header Content-Type: application/json.

The client supports most of ADS-API methods. Method get_block cannot be requested directly. It is called by client in background while needed. All others method can be requested with parameters described in ADS-API documentation. Name of the method must be given as method instead of run parameter. Other parameters must be passed as fields of params object.

Below is example body of request executed with curl.

curl -X POST 127.0.0.1:6868 \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "get_account",
    "params": {
        "address": "0001-00000000-9B6F"
    }
}
EOF

It is equivalent to the following ads call.

echo '{"run":"get_account","address":"0001-00000000-9B6F"}' | ads

The dry-run option for ads client causes that transaction will not be sent to network. Functions which read network status are not affected by this options. The dry-run is turned off by default. It can be enabled in ads-json-rpc by adding special param "_dry-run": true.

Dry-run example

Below is example usage of dry-run. Function broadcast allows send message up to 32,000 bytes. Compare output with and without dry-run. Meaning of msid and hash option will be explained in next paragraph.

Dry-run is on. Parameter "_dry-run": true is added. Transaction will not be sent.

curl -X POST 127.0.0.1:6868 \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "broadcast",
    "params": {
        "message": "01020304050607080900",
        "_dry-run": true
    }
}
EOF
{
    "id": "1",
    "jsonrpc": "2.0",
    "result": {
        "current_block_time": "1547033088",
        "previous_block_time": "1547032576",
        "tx": {
            "account_hashin": "6967DE3325EEB7A3C0B2EC1DC88539E76A8185D4371F8C591417F04836860423",
            "account_hashout": "E3500202C37D7CE1D45AF789CEF69E481FE9544CEBEB5D82D9C481AD62ADBCC3",
            "account_msid": "12",
            "data": "030100050000000C00000074DA355C0A0001020304050607080900",
            "deduct": "0.00000010000",
            "fee": "0.00000010000",
            "signature": "DECA9D7E4D74AFB3F6D085FEDFEF57BE1259F750AC70D47ECA57ADE67F559FF658C1900E324E5373BF2AB851F2F037E4A01EE09FE24CDEF6E296BA235744630C",
            "time": "1547033204"
        }
    }
}

Dry-run is off. Parameter "_dry-run" is omitted. Transaction will be sent.

curl -X POST 127.0.0.1:6868 \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "broadcast",
    "params": {
        "message": "01020304050607080900"
    }
}
EOF
{
    "id": "1",
    "jsonrpc": "2.0",
    "result": {
        "account": {
            "address": "0001-00000005-CBCA",
            "balance": "1041.93194747647",
            "date": "2019-01-09 12:28:02",
            "hash": "43AB819727F407DE32DC0BD8174353DD0890ECF087F67EFD8A9445CEC64F5334",
            "id": "5",
            "local_change": "1547033088",
            "msid": "13",
            "node": "1",
            "paired_id": "0",
            "paired_node": "0",
            "public_key": "860BB97F2E355C094CEFB63A7A1245C3D3073E535087FBACEF573C6EC48E17A9",
            "remote_change": "1545309696",
            "status": "0",
            "time": "1547033282"
        },
        "current_block_time": "1547033088",
        "previous_block_time": "1547032576",
        "tx": {
            "account_hashin": "6967DE3325EEB7A3C0B2EC1DC88539E76A8185D4371F8C591417F04836860423",
            "account_hashout": "43AB819727F407DE32DC0BD8174353DD0890ECF087F67EFD8A9445CEC64F5334",
            "account_msid": "12",
            "data": "030100050000000C000000C2DA355C0A0001020304050607080900",
            "deduct": "0.00000010000",
            "fee": "0.00000010000",
            "id": "0001:000016FE:0001",
            "node_mpos": "1",
            "node_msid": "5886",
            "signature": "539F038651996E7045C8DD0011AAD528A4644A5C7AE445F66DE3E9D6AB9E4EAD7837A567699039E16CCD58CDF5AFB9C60ECDE517532B28DA44B3614500BF7405",
            "time": "1547033282"
        }
    }
}

When dry-run is not active transaction is sent to network. In this case response has additional fields. The most important elements are:

  • result.tx.id - id of transaction assigned by node, which means that node accepted transaction
  • result.account object - current state of account, which created transaction

Blockchain network account

ADS account will be treat as transaction issuer and will be charged for executing transaction.

Address

Address is needed to indicate transaction's sender. Every account has unique address assigned during creation.

Secret key, msid, hash

Secret key, msid, and hash are required to sign transaction. Secret key is private and should not be revealed to anyone. Msid is number of account's transactions. Hash is hash of last transaction. Both msid and hash are public. They are changing after each transaction. They can be read from:

Host and port of node

Node's host and port must be known to connect to the network and send transaction.

Transaction signing

Each transaction must be signed before executing. Usually sign and execute operations are done together, but this article describes different approach as mentioned in abstract.

Assume that money transfer of 12 ADS should be sent to account 0002-00000001-659C. Transfer can be written as send_one transaction. All transaction types are listed on ADS-API page.

Below is example ads client input.

{"run":"send_one", "amount":"12", "address":"0002-00000001-659C"}

Below is the same request for ads-json-rpc client.

{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "send_one",
    "params": {
        "address": "0002-00000001-659C",
        "amount": "12"
    }
}

Option "_dry-run": true should be used to get transaction signature without executing it. Also msid and hash should be provided.

Below is curl request.

curl -X POST 127.0.0.1:6868 \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "send_one",
    "params": {
        "address": "0002-00000001-659C",
        "amount": "12",
        "_dry-run": true,
        "hash": "EED4BB783ABA5A2943CCB59F4DBE48845651CF650BDBA06C74A8334F9AAB726F",
        "msid": 14
    }
}
EOF

Below is the response after formatting.

{
    "id": "1",
    "jsonrpc": "2.0",
    "result": {
        "current_block_time": "1547053568",
        "previous_block_time": "1547053056",
        "tx": {
            "account_hashin": "EED4BB783ABA5A2943CCB59F4DBE48845651CF650BDBA06C74A8334F9AAB726F",
            "account_hashout": "3D4DC529AC97D1AA76A5F4B4D4E8515A22E7AD84A025DC3D451575FD20D74E73",
            "account_msid": "14",
            "data": "040100050000000E0000001A2B365C02000100000000E09265170100000000000000000000000000000000000000000000000000000000000000000000",
            "deduct": "12.01200000000",
            "fee": "0.01200000000",
            "signature": "6A6E0166C7CE584FC4885E4EE9DF4FD731B93B0C927426B7469A53603A6DAFAF73EF2EC7405BAD745BC2925430DA6DC2988DE790B0C99ED438D0C6453CA1450A",
            "time": "1547053850"
        }
    }
}

To send transaction result.tx.data and result.tx.signature from above response are needed. The result.tx.data is transaction data encoded as hexadecimal string. Length of this string varies between transactions. If You want to prepare next transaction, increment msid and use result.tx.account_hashout as params.hash.

Transaction send

Send transaction without secret key using encoded transaction data and signature. To connect to node only node's host and port are needed. They are passed as special parameters _host and _port.

curl -X POST 127.0.0.1:6868 -H "Content-Type: application/json" -d @- << EOF
{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "send_again",
    "params": {
        "data": "040100050000000E0000001A2B365C02000100000000E09265170100000000000000000000000000000000000000000000000000000000000000000000",
        "signature": "6A6E0166C7CE584FC4885E4EE9DF4FD731B93B0C927426B7469A53603A6DAFAF73EF2EC7405BAD745BC2925430DA6DC2988DE790B0C99ED438D0C6453CA1450A",
        "_host": "t01.e11.click",
        "_port": 6511
    }
}
EOF

Below is the formatted response.

{
    "id": "1",
    "jsonrpc": "2.0",
    "result": {
        "account": {
            "address": "0001-00000005-CBCA",
            "balance": "1017.90794747647",
            "date": "2019-01-09 18:10:50",
            "hash": "3D4DC529AC97D1AA76A5F4B4D4E8515A22E7AD84A025DC3D451575FD20D74E73",
            "id": "5",
            "local_change": "1547054080",
            "msid": "15",
            "node": "1",
            "paired_id": "0",
            "paired_node": "0",
            "public_key": "860BB97F2E355C094CEFB63A7A1245C3D3073E535087FBACEF573C6EC48E17A9",
            "remote_change": "1545309696",
            "status": "0",
            "time": "1547053850"
        },
        "current_block_time": "1547054080",
        "previous_block_time": "1547053568",
        "tx": {
            "data": "040100050000000E0000001A2B365C02000100000000E09265170100000000000000000000000000000000000000000000000000000000000000000000",
            "deduct": "12.01200000000",
            "fee": "0.01200000000",
            "id": "0001:00001700:0001",
            "node_mpos": "1",
            "node_msid": "5888",
            "signature": "6A6E0166C7CE584FC4885E4EE9DF4FD731B93B0C927426B7469A53603A6DAFAF73EF2EC7405BAD745BC2925430DA6DC2988DE790B0C99ED438D0C6453CA1450A",
            "time": "1547053850"
        }
    }
}

Note that in result object tx.data and tx.signature are the same as given, account.msid and account.hash are the same as read from dry-run response. Transaction was accepted by node, because result.tx.id is present.

Generating transaction batches

Transaction can be created in batches. The most important thing to remember is not to change transaction order. Transactions for particular account must be executed in the same order as they were signed. It is result of fact that each transaction signature is generated using hash and incremented msid of previous transaction.

How to get ADS

Please remember that it is necessary to include a message when transferring ADS coins TO a cryptocurrency exchange. The message to be copy-pasted is always provided by the exchange – please see a relevant part of the deposit section on your trading platform. It is not necessary to include a message when transferring ADS coins to your ADS Wallet or your ADS account on the platform.


There are several ways of getting ADS coins.

Cryptocurrency exchanges

You can purchase ADS coins on a cryptocurrency exchange:

Name URL Markets
Graviex https://graviex.net BTC GIO LTC USDT

You can track ADS on many websites, e.g.:

Airdrops and bounty campaigns

We recommend following our Twitter profile @adsharesNet, where we are announcing airdrops and bounty campaigns in which you can earn ADS.

Earning ADS as a Publisher

If you own a website you can join Adshares network as a Publisher, place our ad unit on your site and earn ADS based on your site views.

How to generate transactions offline

Abstract

The ADS blockchain allows users to prepare transactions and execute them later. The aim of this article is to show how to sign a transaction and execute it later without the secret key. This flow is widely used by exchanges, because secret key does not have to be transferred anywhere (even through safe channels).

Requirements

Wallet program ads

Creating transaction requires the ADS wallet program ads. Below are excerpts from the ADS documentation. Installation and usage are described in details on ADS project page.

Installation

Binary version of ads can be installed from official Adshares PPA.

sudo add-apt-repository ppa:adshares/releases -y
sudo apt-get update
sudo apt-get install ads

Usage

Run ads -h to get the list of command line options and config file parameters. While all options can be written in command line, it is suggested to create settings.cfg file to store address, host, port, and secret. Below is sample content of settings.cfg file.

port=6511
host=127.0.0.1
address=0001-00000000-XXXX
secret=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF

Above file should be placed in ads working directory. By default working directory is $HOME/.ads, but it can be changed with --work-dir [-w] option.

ads support commands in JSON format. The simplest command get_me does not need any parameters. You can run ads and then type {"run":"get_me"}. Below is presented more convenient usage with stdout pipe.

echo '{"run":"get_me"}' | ads

Dry-run option --dry-run [-d] causes that transaction will not be sent to network. Dry-run is turned off by default (value equal 0). Value of 1 turns dry-run on. Please, note that functions which read network status are not affected by this options.

Dry-run example

Below is example usage of dry-run. Function broadcast allows send message up to 32,000 bytes. Compare output with and without dry-run. Meaning of msid and hash option will be explained in next paragraph.

Dry-run is on, command line parameter --dry-run=1 is added. Transaction will not be sent.

echo '{"run":"broadcast", "message":"01020304"}' | ads -w . --msid=1 --hash=0671C3CF5044009E66AC8BE5896A28F967578F86BB956A3B5804AA5A3A6735A7 --dry-run=1
{
    "current_block_time": "1537527584",
    "previous_block_time": "1537527552",
    "tx": {
        "data": "030100000000000100000031CFA45B040001020304",
        "signature": "673EF843E69158B53FF7483101C79B9E0EC4B01F6FD58E758F596E05E01728620FB992D4668C4A4DFF2E03F9C7D0CB5FE766A5170DE52FE20BE0492062A10E07",
        "time": "1537527601",
        "account_msid": "1",
        "account_hashin": "0671C3CF5044009E66AC8BE5896A28F967578F86BB956A3B5804AA5A3A6735A7",
        "account_hashout": "D978D6996671E88E9121433B113F36107C0C8BD0E9644035616CAA7EB0C928C3",
        "deduct": "0.00000010000",
        "fee": "0.00000010000"
    }
}

Dry-run is off, command line parameter --dry-run is omitted. Transaction will be sent.

echo '{"run":"broadcast", "message":"01020304"}' | ads -w . --msid=1 --hash=0671C3CF5044009E66AC8BE5896A28F967578F86BB956A3B5804AA5A3A6735A7
{
    "current_block_time": "1537527616",
    "previous_block_time": "1537527584",
    "tx": {
        "data": "030100000000000100000044CFA45B040001020304",
        "signature": "E55B82E15F7F5A37BA2F83BF9D987F00A87F6116754F52F9A64527C7EB2224E2B6DFC1A0FF8F2CF5BDBA37958ACEFFF9B82D855B2ECB2C785E8CEF08FDA33802",
        "time": "1537527620",
        "account_msid": "1",
        "account_hashin": "0671C3CF5044009E66AC8BE5896A28F967578F86BB956A3B5804AA5A3A6735A7",
        "account_hashout": "5D23B4EFD69D255A5F8463AC9ED47739DF3C4AE70FAD35BAEDCAF212442E53F0",
        "deduct": "0.00000010000",
        "fee": "0.00000010000",
        "node_msid": "4",
        "node_mpos": "1",
        "id": "0001:00000004:0001"
    },
    "account": {
        "address": "0001-00000000-9B6F",
        "node": "1",
        "id": "0",
        "msid": "2",
        "time": "1537527620",
        "date": "2018-09-21 13:00:20",
        "status": "0",
        "paired_node": "0",
        "paired_id": "0",
        "local_change": "1537527616",
        "remote_change": "1537527584",
        "balance": "8612934.66646612606",
        "public_key": "A9C0D972D8AAB73805EC4A28291E052E3B5FAFE0ADC9D724917054E5E2690363",
        "hash": "5D23B4EFD69D255A5F8463AC9ED47739DF3C4AE70FAD35BAEDCAF212442E53F0"
    }
}

When dry-run is not active transaction is sent to network. In this case response has additional fields. The most important elements are:

  • tx.id - id of transaction assigned by node, which means that node accepted transaction
  • account object - current state of account, which created transaction

Blockchain network account

ADS account will be treat as transaction issuer and will be charged for executing transaction.

Address

Address is needed to indicate transaction's sender. Every account has unique address assigned during creation.

Secret key, msid, hash

Secret key, msid, and hash are required to sign transaction. Secret key is private and should not be revealed to anyone. Msid is number of account's transactions. Hash is hash of last transaction. Both msid and hash are public. They are changing after each transaction. They can be read from:

IP address and port of node

Node's IP address and port must be known to connect to the network and send transaction.

Transaction signing

Each transaction must be signed before executing. Usually sign and execute operations are done together, but this article describes different approach as mentioned in abstract.

Assume that money transfer of 120 ADS should be sent to account 0002-00000001-659C. Transfer can be written as send_one transaction. All transaction types are listed on ADS-API page.

{"run":"send_one", "amount":"120", "address":"0002-00000001-659C"}

Option is-dry-run=1 should be used to get transaction signature without executing it. Also msid and hash should be provided. Following command assumes that secret key is stored in settings.cfg file inside working directory, so it does not need to be provided explicitly.

echo '{"run":"send_one", "amount":"120", "address":"0002-00000001-659C"}' | ads --dry-run=1 --msid=1 --hash=81900B3D4A4470946CE6A183BE20B4B8D620CF0E99C94EB06841713F008783E9

Below is the response.

{
    "current_block_time": "1537351648",
    "previous_block_time": "1537351616",
    "tx": {
        "data": "0401000100000001000000F71FA25B02000100000000C0BCF7E90A00000000000000000000000000000000000000000000000000000000000000000000",
        "signature": "1B0F7D6F0C10EF77B25827D27735FFB1D77D2372CC87D2AA385E376B6B780BC7B761DF9B58502807910BD20F5D117FD530E4760FC99B811AEA81F84BE733F50E",
        "time": "1537351671",
        "account_msid": "1",
        "account_hashin": "81900B3D4A4470946CE6A183BE20B4B8D620CF0E99C94EB06841713F008783E9",
        "account_hashout": "210CF7BE22C38E11E7828C52E58E21D20CDBC80F8BC3FE2D44BA74260568D835",
        "deduct": "120.12000000000",
        "fee": "0.12000000000"
    }
}

To send transaction tx.data and tx.signature are needed. The tx.data is transaction data encoded as hexadecimal string. Length of this string varies between transactions. If You want to prepare next transaction, increment msid and use tx.account_hashout as hash.

Transaction send

Send transaction without secret key using encoded transaction data and signature. To connect to node only node's IP address and port are needed. Command below does not declare them explicitly, because they are stored in settings.cfg file.

echo '{"run":"send_again", "data":"0401000100000001000000F71FA25B02000100000000C0BCF7E90A00000000000000000000000000000000000000000000000000000000000000000000", "signature":"1B0F7D6F0C10EF77B25827D27735FFB1D77D2372CC87D2AA385E376B6B780BC7B761DF9B58502807910BD20F5D117FD530E4760FC99B811AEA81F84BE733F50E"}' | ads

Below is the response.

{
    "current_block_time": "1537353728",
    "previous_block_time": "1537353696",
    "tx": {
        "data": "0401000100000001000000F71FA25B02000100000000C0BCF7E90A00000000000000000000000000000000000000000000000000000000000000000000",
        "signature": "1B0F7D6F0C10EF77B25827D27735FFB1D77D2372CC87D2AA385E376B6B780BC7B761DF9B58502807910BD20F5D117FD530E4760FC99B811AEA81F84BE733F50E",
        "time": "1537351671",
        "deduct": "120.12000000000",
        "fee": "0.12000000000",
        "node_msid": "174",
        "node_mpos": "1",
        "id": "0001:000000AE:0001"
    },
    "account": {
        "address": "0001-00000001-8B4E",
        "node": "1",
        "id": "1",
        "msid": "2",
        "time": "1537351671",
        "date": "2018-09-19 12:07:51",
        "status": "0",
        "paired_node": "0",
        "paired_id": "0",
        "local_change": "1537353728",
        "remote_change": "1537342208",
        "balance": "2153113.52866666666",
        "public_key": "6431A8580B014DA2420FF32842B0BA3CAB3B77F01D1150E5A0D34743F243B778",
        "hash": "210CF7BE22C38E11E7828C52E58E21D20CDBC80F8BC3FE2D44BA74260568D835"
    }
}

Please, note that tx.data and tx.signature are the same as given, account.msid and account.hash are the same as read from dry-run response.

Generating transaction batches

Transaction can be created in batches. The most important thing to remember is not to change transaction order. Transactions for particular account must be executed in the same order as they were signed. It is result of fact that each transaction signature is generated using hash and incremented msid of previous transaction.

How to generate ADS keys

Online tool

You can generate keys by using our online tool: https://conversion.adshares.net/key

Store the secret keys safely. Only the public key and signatures can be revealed. The seed phrase and the secret key must not be transferred to anyone.

Compilation of key program

Another way is to compile the source code of the key program.

The software is developed for the Linux platform. There is no intent to support other platforms. The software was tested on Debian and Ubuntu. To compile the software, You need boost and SSL libraries. Check the Makefile if anything else is missing.

sudo apt-get update
sudo apt-get install openssl libboost-all-dev libssl-dev git build-essential

Start with cloning the git directory.

git clone https://github.com/adshares/ads.git

Then proceed to compile key generation program

cd ads/external/ed25519
make

Key generation

After successful compilation, please run ./key program with your desired secret passphrase. Please use at least 16 random characters. Please use a good source of entropy to generate the passphrase.

./key "your secret passphrase"

You can also use random bytes generated by OpenSSL

./key `OpenSSL rand -hex 32`

The program will output your secret key (SK), public key (PK) and signature for the empty string (SG).

# Example
# Do not use those keys!
SK: EFD0380D9B29829AE9F30F41E85D6C09A97220E6CF76FE8C1B479A34A38D12EC
PK: 124793C618E3D25A96011F690EB00089144D89FB58FB96D7A3BFCEC78DFF5F8A
SG: C248A65080E7CED9081DDB3C849A17AEC102B3D044A3F38E530DD28A4AC9B3D5934B5ECA3306894BDCF0B3D8951F0FB339889CBC3D63EF3A54E6FA6EAD2C1A00

Please store your secret key (SK) securely and copy PK and SG.

Log rotation

ADS logs can grow in size fairly fast, so we recommend you set up logrotate.

Installation

You can check if logrotate is installed by asking:

logrotate --version

If not, you can install it from a system package. On Debian/Ubuntu:

sudo apt-get install logrotate

Configuration

You need to create a configuruation file.

nano /etc/logrotate.d/ads

File contents:

"/home/ads/.adsd/*.log" {
    daily
    weekly
    size 25M
    rotate 7
    missingok
    compress
    delaycompress
    copytruncate
}

That's it. After the filesize will be bigger than 25M you will see compressed log rotations.

How to join the Testnet

The Testnet

Testnet is Adshares' testing environment. It is a place where all applications will be deployed before the production phase. Adshares' intention is to run production-ready code in the Testnet and make it available to master node operators and exchanges who wish to try out Adshares’ solutions. Everyone is invited to take part. Testnet block explorer is available here:

https://operator.e11.click/blockexplorer

Testnet comparison with the production environment

Although applications in the Testnet are ready for production deployment, this environment cannot be used for commercial purposes. Stability (thus security) of the Testnet is lower. Adshares does not assure continuity of services. It is possible that the Testnet will be restarted and some data will be lost.

We strongly advise NOT TO USE the same credentials (secret keys) in the Testnet and in the production environment.

Test network structure

Currently, there are five ADS blockchain nodes. The next chapter describes how to join blockchain network. Standard ads client can be used to connect. It is important to use host from the Testnet.

In the table below are listed initial nodes.

Node Id Host Port
0001 t01.e11.click 6511
0002 t02.e11.click 6511
0003 t03.e11.click 6511
0004 t04.e11.click 6511
0005 t05.e11.click 6511

Creating an account

ADS Testnet account can be created automatically using browser Wallet.

After the installation you should switch to the Testnet, configure ADS Wallet and click "Get free account" button. Now you can copy your account address.

Get free test coins

You can get coins using Twitter. Simply, tweet a message containing #adsTestnet hashtag and your account address. Don’t forget to mention @adsharesNet.

Below is the sample tweet.

@adsharesNet fill up my account 0003-0000000B-6E87 in #adsTestNet

You should receive a response with success info within a few minutes. Your account will have 1024 ADS, which is sufficient to perform tests. Three accounts per user can be created at most.

How to use ADS Wallet

What is ADS wallet

ADS Wallet is a secure identity vault for Adshares, that was designed to store keys and provide cryptographic transaction signing. It can also be used to create or import accounts and send basic transactions. Our wallet provides integration with internal and external services connected to Adshares network. It is a convenient, free, open-source client-side tool.

There are two versions of the plugin - the first one works with Chrome and Opera browsers (install via Chrome Web Store), while the other one was designed for Mozilla Firefox (install via Firefox Add-ons).

Installing ADS Wallet web browser plugin is a recommended step to join Adshares network as an advertiser or a publisher.

Who can use ADS Wallet

ADS Wallet can be used by three types of users:

  • those who don't have an account and a key - i.e. new users
  • those who already have an account and a key that is not based on a seed phrase
  • those who already have a key based on a seed phrase

What is important, ADS Wallet also supports Testnet, so each user can try it prior to handling actual transactions or storing real keys. The plugin operated in Testnet mode uses Testnet accounts.

How to configure ADS Wallet

Let's start with the main panel. Depending on whether you already have a seed phrase, you can either create a new vault or recover the one you already have. Please note that you can use ADS Wallet both in mainnet and testnet mode.

I don’t have a seed phrase

In case you don’t have a seed phrase, you need to follow the procedure described below:

  • Hit the start button. The plugin will ask you to enter and confirm the password. After accepting the Terms of Use, the plugin will assign a seed phrase. As soon as you write down the seed phrase and store it in a safe place, you are good to go.

Configuration

  • Choose between setting a new free account (green button) and importing account that you already have (blue button).

Free account

  • If you choose "Get free account" a set of keys will be generated based on your seed phrase. All keys, which are cryptographically protected by the password, are stored locally on a device and are not archived or sent anywhere. It's important to keep that in mind, as the seed phrase is the only way of recovering the vault. If you want to view your keys you need to go into Main Menu -> Settings -> and click the orange icon next to the account address

Settings

  • If you choose "Import account" you will be asked to enter the account name and account address and hit "Import" key. In case you want to add another account to ADS Wallet, you need to go into Main Menu -> Settings -> hit the "Add account" button, provide account name & address and authenticate the operation with your password. Once your account is added, you can use the plugin to sign ADS Operator transactions.

I already have a seed phrase

In case you are one of the users who already have a seed phrase, you have to begin with clicking "Restore the vault from a seed" button. The next step requires entering your seed phrase and setting a password. Once you are done, you have to import your account. The procedure is the same for users who have a seed phrase as well as for the ones who don't.

Restore the vault


The plugin can serve up to 20 accounts. In order to switch to a different wallet you need to click the account name on the top of the plugin and select the one you want to use from a dropdown list.

Apart from transferring assets to other accounts, users can view their account balance in real time.

Dashboard

How to transfer assets

In order to transfer funds you just need to hit "Send Transaction" button in the main panel, provide the ID of the account you want to transfer your ADS to, enter the amount and write a message in hexadecimal format (0–9; A-F; up to 64 characters) or alternatively a regular text (up to 32 characters).

In the next step, you need to review transfer data. At this point, you can also tick "Advanced data" to view all information that will be sent to the blockchain. Once you accept the transaction, you'll get a transaction ID along with the fee information. The blockchain charges 0.1% fee in case of transactions between nodes and 0.05% in case of transactions within the same node.

Once you click the transaction ID, you are transferred to the Block Explorer, where you can check your account balance. It's visible after approx. 15 minutes, as soon as the blockchain scans it. It is also possible to access Block Explorer from the main panel after clicking the "Details" button.

If you want to know how to transfer your funds from the Adshares platform to your ADS Wallet, click here.

Importing private keys

ADS Wallet also offers private keys import. To import your private key, you need to access the menu from the main panel, then go into Settings. Next, you simply hit "Manage keys" and "Import new key". It's necessary to type in your key name and private key. The plugin can also check if the private key is correct. It's possible to verify it using your public key. You can view your keys once you click the yellow icon. The plugin can handle up to 20 imported private keys.

Importing private keys

Please keep in mind that it is not possible to recover private keys that were imported manually after uninstalling the plugin, as all private keys are stored only locally. In case of accounts with such keys (e.g. genesis block accounts), we recommend changing keys to seed-phrase-based keys. For security reasons we also advise not to use the master key and to use one key with one account only.

General remarks

ADS Wallet uses our own JSON-RPC to communicate with blockchain. It is publicly available on our GitHub along with the documentation.

For some users, it may be more convenient to use the plugin in a separate browser window. In order to switch to this mode you just need to click “Expand view” in the Main Menu.

The Chrome version of our plugin supports Google Chrome synchronization, which means it can be synchronized across many devices.

How to check incoming transactions

Abstract

This article aims to explain how an owner of a particular account could list and check incoming transactions.

Requirements

Blockchain network account

Every user of ADS blockchain needs an account to connect to the network. An account can be created by the node operator or Browser Wallet.

Address

The address is needed to indicate the transaction's sender. Every account has a unique address assigned during creation.

Secret key

The secret key is needed to sign the transaction. Secret key is private and should not be revealed to anyone.

IP address and port of node

Node's IP address and port must be known to connect to the network and send transaction.

Communication with the node

All the operations performed on the ADS blockchain are done using the ADS wallet program ads or JSON-RPC.

Collecting transactions' ids from account's log

To get the account's log user needs to call get_log function.

Function get_log takes one parameter: from. Parameter from is the earliest time of the log entry in seconds since epoch as a decimal number. If time is not provided (is equal zero) the full log will be returned.

Call with parameter from

{"run":"get_log","from":"1543247363"} #ads
{"jsonrpc":"2.0","id":"1","method":"get_log", "params":{"address":"0001-00000004-DBEB","from":1543247363}} #JSON-RPC

Below is a sample response. Account's events are in log array. Log array can be empty if there are no events in the selected period. Each event has time, date, type, and type_no fields. Different types of events have different structure.

{
    "current_block_time": "1543244800",
    "previous_block_time": "1543244288",
    "tx": {
        "data": "110200040000000100F05B",
        "signature": "029C4587D45DB0A5550E1155F6D4D3A159E2234C46290380FE28E80FCF5CF137467EC75928E9945102DA5F5916369F7ED16675F27D7363D0755090AB8CC8020A",
        "time": "1542455297",
        "account_msid": "0",
        "account_hashin": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
        "account_hashout": "9909BA21378298A96B132C73BBCD17757559350FE81ACAA5246C3B1614A9A345",
        "deduct": "0.00000000000",
        "fee": "0.00000000000"
    },
    "account": {
        "address": "0002-00000004-3539",
        "node": "2",
        "id": "4",
        "msid": "64",
        "time": "1543230001",
        "date": "2018-11-26 12:00:01",
        "status": "0",
        "paired_node": "0",
        "paired_id": "0",
        "local_change": "1543229952",
        "remote_change": "1542197760",
        "balance": "1042.79299389909",
        "public_key": "860BB97F2E355C094CEFB63A7A1245C3D3073E535087FBACEF573C6EC48E17A9",
        "hash": "5D4D150853A7BBF2713EE23BA3774B88493A7C95990C9E5E506197E45D76362E"
    },
    "log": [{
            "time": "1542291341",
            "date": "2018-11-15 15:15:41",
            "type_no": "32768",
            "confirmed": "yes",
            "type": "node_started",
            "node_start_msid": "3189",
            "node_start_block": "1542290432",
            "account": {
                "balance": "1043.99939870000",
                "local_change": "1542290432",
                "remote_change": "1542197760",
                "hash_prefix_8": "177D7A31BF3F915C",
                "public_key_prefix_6": "860BB97F2E35",
                "status": "0",
                "msid": "14",
                "node": "0",
                "id": "0",
                "address": "0000-00000000-313E"
            },
            "dividend": "0.00000000000"
        }, {
            "time": "1542455298",
            "date": "2018-11-17 12:48:18",
            "type_no": "32784",
            "confirmed": "yes",
            "type": "dividend",
            "node_msid": "3320",
            "block_id": "5BF00000",
            "dividend": "-0.00020000000"
        },
        {
            "time": "1543248387",
            "date": "2018-11-26 17:06:27",
            "type_no": "32772",
            "confirmed": "no",
            "type": "send_one",
            "node": "1",
            "account": "4",
            "address": "0001-00000004-DBEB",
            "node_msid": "3744",
            "node_mpos": "1",
            "account_msid": "11",
            "amount": "1.00000000000",
            "sender_fee": "0.00100000000",
            "message": "000000000000000000000000000000002A3DBD3F9B1A4E41AED0A3C0732BC729",
            "inout": "in",
            "id": "0001:00000EA0:0001"
        }
    ]
}

To make a list of incoming transactions, a log must be filtered. Incoming transactions have field type equal send_one and field inout equal in.

For those events which match the filter field, id should be stored to process later.

Only one incoming transaction is present in the log example above. Its id is 0001:00000EA0:0001.

See more:

Validation of transactions' ids

If transaction id is known, it should be checked in ADS blockchain. Transaction checking is divided into two parts:

  • collecting block headers (required only when using ads program)
  • comparing transaction id with collected headers

Collecting block header

Collecting the block header should be done before checking transaction ids.

Collecting header depends on calling get_blocks function as long as all header will be updated.

{"run":"get_blocks"}

All headers are updated when a value of updated_blocks is equal 0. Below is sample response after a successful update.

{
    "current_block_time": "1543249408",
    "previous_block_time": "1543248896",
    "tx": {
        "data": "130200040000006E1EFC5B001EFC5B00000000",
        "signature": "C1201AA1EC8D8FD1DA31FB3F1AF59D3DF0AB431FC82657D18DCBD436EECD2D0D636755F7FA0F50AB529EED8AD56BCA9236B402DD9A44D1D51327A9027B802A07",
        "time": "1543249518"
    },
    "updated_blocks": "0"
}

See more:

Checking transaction id

Comparing transaction id with collected headers needs to call get_transaction function. It takes one required parameter txid - transaction id.

{"run":"get_transaction","txid":"0001:00000EA0:0001"} #ads
{"jsonrpc":"2.0","id":"1","method":"get_transaction", "params":{"txid":"0001:00000EA0:0001"}} #JSON-RPC

Below is sample response

{
    "current_block_time": "1543249408",
    "previous_block_time": "1543248896",
    "tx": {
        "data": "140200040000006E1FFC5B0100A00E00000100",
        "signature": "F8A1244D8C0FD364715A439585787DAD7854614DA91B3D1451F68314F1DCB14309526A84ED4AE771A8C75C61969054355CFC8E63743F4AE76DD6117B4C978E0D",
        "time": "1543249774",
        "account_msid": "0",
        "account_hashin": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
        "account_hashout": "6B9F7E7D4EAD9292AE4273246CCA7E691DB595E01F66A0A6478C5841C8BC34F4",
        "deduct": "0.00000000000",
        "fee": "0.00000000000"
    },
    "network_tx": {
        "id": "0001:00000EA0:0001",
        "block_time": "1543247872",
        "block_id": "5BFC1800",
        "node": "1",
        "node_msid": "3744",
        "node_mpos": "1",
        "size": "125",
        "hashpath_size": "6",
        "data": "040100040000000B000000C118FC5B02000400000000E8764817000000000000000000000000000000000000002A3DBD3F9B1A4E41AED0A3C0732BC7291515D72AF2D0041D8F41727740F8B40A662BC1D7691A00E9B85FE8B15DC5A6C0B08AB898569F432531D89FC762B128962EABD895B3F1D41FB12851B15860E908",
        "hashpath": [
            "D35C5C427D59F0F461CAAE33D941CFF01A3A0F2BFB4A86E349408F45BB48AEBA",
            "807C957C867CA1FA190E1FCDD22A626685E9C554E2235B699142932DE96CE089",
            "BCF77DCB77AA3FB6328B35998DC5917F81F8EF96F82B5441B2FFDD0DBBFC8480",
            "3C90B8BCAE204C3479C45515D584D0F73061149A4427F2716F4E8026BCFA8536",
            "18340797415AF7E5F7B6A61815C210D7007635EA242800A805408BAFBFE76842",
            "F26A9BD1C882E83B865C6EFD82F789FD7548A6A40748BBF4C384B87DB86B8C7B"
        ]
    },
    "txn": {
        "type": "send_one",
        "node": "1",
        "user": "4",
        "msg_id": "11",
        "time": "1543248065",
        "target_node": "2",
        "target_user": "4",
        "sender_fee": "0.00100000000",
        "sender_address": "0001-00000004-DBEB",
        "target_address": "0002-00000004-3539",
        "amount": "1.00000000000",
        "message": "000000000000000000000000000000002A3DBD3F9B1A4E41AED0A3C0732BC729",
        "signature": "1515D72AF2D0041D8F41727740F8B40A662BC1D7691A00E9B85FE8B15DC5A6C0B08AB898569F432531D89FC762B128962EABD895B3F1D41FB12851B15860E908"
    }
}

Transaction details can be read from txn object. Especially:

  • sender address: txn.sender_address
  • transaction amount: txn.amount
  • transaction title (memo): txn.message

Warning! Field txn.time is insecure (it can be freely set by the user); use time of the message or the block instead.

See more:

QA tests

Moved to ads-tests

How to start ADS node

How to start ADS node

This manual will show how to start ADS node and change key of main (technical) account.

Node is the basic element of blockchain network. Every node can have multiple user accounts. At least one account is always present. It is main (technical) account, which number is 0. By default secret key of node and main account are the same, so it is suggested to change one of them.

Requirements

Node data

To setup the ADS node, you will need to provide a node identifier (4 hexadecimal characters) and a secret key which consist of 64 hexadecimal characters. Usually you will also need to specify an IP address.

If You participate in genesis, You can find Your node id on Genesis Block page. Just look for Your public key on nodes list and get node id bind with this key. On the same page You can check Your account address and it's balance. By default first account has the same key as node.

Tools

Install ADS binaries from official PPA.

sudo add-apt-repository ppa:adshares/releases -y
sudo apt-get update
sudo apt-get install ads ads-tools

Check if ads is installed.

ads --version

Above command should return working directory and ads version.

Open ports

The ADS node uses two TCP ports: 6510 and 6511 (by default). First is used to communicate with other nodes. Second is needed for clients' connections.

Open both ports.

sudo apt-get install -y ufw
sudo ufw allow 6510,6511/tcp

More information can be found on Ubuntu Uncomplicated Firewall documentation page.

Synchronize time

It is crucial to synchronize time between nodes. Time difference should not exceed one second. We advise to set synchronization with NTP servers. For more information check official Ubuntu documentation on Time Synchronization.

Setup the node

Configure the node. You will be asked for node's secret key (64 hexadecimal characters), id (4 hexadecimal characters), and host IP address.

ads-service configure

Start the node.

ads-service start

Check the node status.

ads-monitor status -v

If node works, you should see current time, block time (or time to genesis block) and node number.

Change account key

After genesis block all nodes can receive transaction requests. In general, if You want to execute transaction, You should know authentication data:

  • for account which will send transaction: address $ADDRESS and secret key $SECRET;
  • for node in which above account is: host name or IP address $HOST and port for clients connections $PORT (default is 6511);

Change of key also requires new credential data for account. For security reasons secret key is not send. Instead You need to provide public key $NEW_PUBLIC_KEY and signature of empty string $NEW_CONFIRM. To create this data please use key program described in How to generate ADS keys instruction.

When You collect all needed data, execute change_account_key command. Exchange all placeholders starting with "$" with real parameters.

(echo '{"run":"get_me"}';echo '{"run":"change_account_key", "public_key":"$NEW_PUBLIC_KEY", "confirm":"$NEW_CONFIRM"}') | ads --address=$ADDRESS --secret=$SECRET --host=$HOST --port=$PORT

Alternatively, You can store authentication parameters in settings.cfg for future use. This method as well as other transactions are described on ADS-API page.

Please, note that change_account_key and every other transaction sent to network is paid. Besides, there is group of free transactions which read blockchain network status. All fees are enlisted in Fees table.

Blockchain Operator

Installation

Installation

  1. Make sure you're using PHP (+mongodb module) 7.1 or higher and have composer installed
  2. Clone repository: git clone https://github.com/adshares/ads-operator.git
  3. Create a configuration file .env based on .env.dist in the root of the application
  4. Create Behat configuration file behat.yml based on behat.yml.dist in the root of the application
  5. Install all dependencies using composer: composer install
  6. Add 127.0.0.1 ads-operator.ads entry to your hosts
Nginx
  • We assume that you've installed ADS Operator project in /ads-operator directory.

ads-operator.conf:


server {
    listen 80;

    server_name ads-operator.ads;
    root /ads-operator/public;

    index index.htm index.html index.php;

    location ~ /\.  {
        return 403;
    }

    location / {
        # try to serve file directly, fallback to rewrite
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }

    location = /favicon.ico  {
        log_not_found off;      
    }
}
`

Usage

Usage

Importer script

To import data run the command below:

./bin/console ads:import 

ADS Operator REST API

All endpoints are described on the API documentation page: http://OPERATOR_URL/api/doc (e.g. http://ads-operator.ads/api/doc)

Official documentation is still in progress.

Quality

Quality

To ensure the best quality we decided to use two approaches:

  • BDD - business cases (Behat)
  • TDD - unit tests (PHPUnit)

To run unit tests execute:

./vendor/bin/phpunit

To run BDD tests execute:

./vendor/bin/behat

Coding styles rules are ensured by several tools:

  • Sensio Security Checker
  • PHP Static Analysis Tool
  • PHP Codesniffer
  • PHP Parallel Lint

One command can be used to run all tools above:

composer qa-check

You can also run all commands separately:

  • security-checker security:check
  • parallel-lint --no-colors --blame --exclude vendor .
  • phpcs -s --standard=PHPCompatibility src tests
  • phpcs -s --standard=PSR2 src tests
  • phpstan --no-ansi --no-progress analyse -c phpstan.neon -l 7 src tests

Blockchain Operator Panel

Installation

Installation

  1. Make sure you're using PHP (+mongodb module) 7.1 or higher and have composer installed
  2. Clone repository: git clone https://github.com/adshares/ads-operator.git
  3. Create a configuration file .env based on .env.dist in the root of the application
  4. Create Behat configuration file behat.yml based on behat.yml.dist in the root of the application
  5. Install all dependencies using composer: composer install
  6. Add 127.0.0.1 ads-operator.ads entry to your hosts
Nginx
  • We assume that you've installed ADS Operator project in /ads-operator directory.

ads-operator.conf:


server {
    listen 80;

    server_name ads-operator.ads;
    root /ads-operator/public;

    index index.htm index.html index.php;

    location ~ /\.  {
        return 403;
    }

    location / {
        # try to serve file directly, fallback to rewrite
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }

    location = /favicon.ico  {
        log_not_found off;      
    }
}
`

Usage

Usage

Importer script

To import data run the command below:

./bin/console ads:import 

ADS Operator REST API

All endpoints are described on the API documentation page: http://OPERATOR_URL/api/doc (e.g. http://ads-operator.ads/api/doc)

Official documentation is still in progress.

Quality

Quality

To ensure the best quality we decided to use two approaches:

  • BDD - business cases (Behat)
  • TDD - unit tests (PHPUnit)

To run unit tests execute:

./vendor/bin/phpunit

To run BDD tests execute:

./vendor/bin/behat

Coding styles rules are ensured by several tools:

  • Sensio Security Checker
  • PHP Static Analysis Tool
  • PHP Codesniffer
  • PHP Parallel Lint

One command can be used to run all tools above:

composer qa-check

You can also run all commands separately:

  • security-checker security:check
  • parallel-lint --no-colors --blame --exclude vendor .
  • phpcs -s --standard=PHPCompatibility src tests
  • phpcs -s --standard=PSR2 src tests
  • phpstan --no-ansi --no-progress analyse -c phpstan.neon -l 7 src tests

AdServer

Home

Welcome to the adserver wiki!

List of available Adzone options

Adzone options can be provided by adding data-options attribute to zone HTML code (see example).

adblock_only - Serve adshares ads only when adblock is present

[Not supported yet!] min_cpm={value} - Server adshares ads only when expected CPM is at least {value}

If adzone options makes adshares ads unavailable backfill/fallback code will be displayed.

Example

<script src="http://example.com/-/find.js" async></script>

<!-- Serve only for adblock users with minimum expected CPM of $1.5 -->
<div class="xaabbccddeeff" data-options="adblock_only,min_cpm=1.5" data-zone="018ac5d9e1eb426abb20bbd52ce7911d" style="width:728px;height:90px;display: block;margin: 0 auto">
    <!--  style tag is only a container --> 
    <style type="app/backfill">      
        <!-- Render this code in other conditions -->
        <script async src="https://other.adnetwork.example.com/ads.js"></script>
        <div class="otherAdnetwork" data-zone="C-112233445566"></div>
        <!-- End of fallback/backfill code -->
    </style>
</div>

How to use Advertising Ecosystem Demo

Introduction

Advertising Ecosystem Demo (http://adshar.es/demo) was published in January 2019. It is a demo of key components of the Adshares ecosystem that features a user-friendly web interface. There are two panels available - one for advertisers and one for publishers. The selection dropdown is available in the upper left corner. Each of the panels offers a wide range of settings and options. Both, the advertisers and the publishers, also have access to history, as well as to e-mail and password settings.

There is also a demo website (http://adshar.es/demosite), which showcases how banners can be displayed on publishers' sites, depending on a device and window size.

Key components

Advertiser module

Defining campaigns, setting campaign budget and targeting. Before launching a campaign the advertiser has to transfer ADS to the account and provide a minimum amount for a 1-hour campaign. Once all is set, the campaign, along with all related information, is distributed across the network. Based on the results, funds are transferred every hour directly to the publisher.

Publisher module

Registering websites on which banners will be displayed, generating code to be placed on websites. The module automatically scans Adshares network in search of ads.

AdSelect module

Handling ads display. AdSelect learns based on interaction history, views, payments and credibility of the advertiser. The module optimises ads selection to maximise publishers' revenue. As soon as the advertisement is selected and the campaign is live, all events are passed to the Advertiser module and the Publisher module.

AdPay module

Calculating funds. Based on campaign results, the AdPay module decides once per hour how much should be transferred from the advertiser to the publisher. The transfer is made every hour, and the publisher can withdraw funds instantly. The advertiser sets the total budget for the entire campaign and the maximum budget for a specific event (CPM and CPC).

How to use the Demo - Advertisers

Before using the Advertiser module, it's necessary to join the Testnet. Then you must register on the platform and confirm your registration via email. The next step is the selection of Advertiser's panel, in which you will find all campaign settings. Before uploading your banners and going through the campaign settings, it's necessary to transfer ADS from the Testnet wallet to your account. Once your funds are on the account, you are good to go.

At this point, you need to create a new campaign, upload your banners and choose settings. Your ads will be displayed on our partners' websites. Once your campaign is up and running, you can check how each of the banners is performing and make some adjustments to the campaign in case it's needed. To achieve the best results, we advise to always upload banners in all formats supported by the platform.

All events are balanced on an hourly basis, and payments are made instantly, which helps optimising campaign settings.

How to use the Demo - Publishers

Once you register and confirm your registration via email, you need to select "Publisher" in the upper left corner. Next, you have to define a site you want to place banners on and then determine the ad unit. The last thing you need to do is to generate the code and place it on your website.

In case you placed your code on more than one website you can manage all sites from "My sites" page. There is also "My ad-units" page where you generate code based on banner dimensions.

Payments from advertisers are made on an hourly basis, which lets the publisher see immediate effects of campaigns and withdraw funds right away.

How to generate code and place it on a website - Publisher module

First, it is necessary to add at least one site on which ads will be displayed. To do so you need to hit the "Add new site" button in the upper right corner of the Publisher module and follow instructions. Once the site is added, it becomes visible on the bottom of the main dashboard.

To get the code to be placed on your website you need to click the website name and then the "Get code" button.

Code

The generated code must be copied and pasted on your website in a place of your choice.

Code

How to place an Ad Unit on a Wordpress website

The code can be generated and placed on a website in a way described above. Additionally, we developed a plugin for WordPress websites, which provides integration with Adshares AdServer for publishers. It makes the implementation even more straightforward and automates the process of placing the code on the website.

The installation is very simple. You just need to go to Your Website -> Plugins -> Add New, search for "Adshares" and click "Install Now". There is also an alternative installation for those who prefer to use Composer.

Once the plugin is installed, all you need to do is type in https://demo.adshares.net as "Server URL", log in into your Adshares account using your registration credentials, and select which ad units will be displayed. The plugin supports various options for position and visibility.

WordPress

In case of high demand for a similar plugin for other popular platforms, we may consider creating dedicated plugins. If you own a website based on a popular platform and would be in interested in such a plugin, please get in touch with us.

How to start adserver

Please follow instructions found here: https://github.com/adshares/installer

Conversions

Conversion link

A crucial part of conversion is passing information that the conversion took place. This can be achieved by making a HTTP request to the adserver. The common way to do it is to create an image element on a site. This image is usually a 1x1 px gif, which points to an adserver resource. The other option is to make a direct API call.

Each conversion has a unique conversion link.

In the basic mode, the link does not have any parameters. Such a link could be used as an src attribute of a HTML element. It could be used only once per impression.

Here’s a sample link.

http://localhost:8101/conversion/6d0bd92b28aa4deb811d6f9cf8aff96b.gif

In the advanced mode, the link has placeholders that should be filled.

Here’s a sample link.

http://localhost:8101/conversion/6d0bd92b28aa4deb811d6f9cf8aff96b.gif?value=value&nonce=nonce&ts=timestamp&sig=signature

Parameters:

  • value - how much the conversion is worth in US Dollars. This parameter is optional if the value was defined during the conversion
  • nonce - unique random value, which is used to distinguish two conversions of the same type
  • ts – the timestamp of the conversion creation
  • sig – the signature of passed parameters

Preparation of the conversion link in the advanced mode

Helper methods

The  urlSafeBase64Encode function encodes data to base64 format and replaces characters that are not allowed in the URL.

public static function urlSafeBase64Encode($string): string
{
    return str_replace(
        [
            '/',
            '+',
            '=',
        ],
        [
            '_',
            '-',
            '',
        ],
        base64_encode($string)
    );
}

The urlSafeBase64Decode function is a reverse function to the urlSafeBase64Encode. It replaces non-standard base64 characters and decodes base64 string.

public static function urlSafeBase64Decode(string $string): string
{
    return base64_decode(
        str_replace(
            [
                '_',
                '-',
            ],
            [
                '/',
                '+',
            ],
            $string
        )
    );
}

Generating the conversion link

Here’s a piece of code that generates the conversion link. This link must be generated for each conversion event.

private const CONVERSION_LINK_TEMPLATE = 'http://localhost:8101/conversion/6d0bd92b28aa4deb811d6f9cf8aff96b.gif?value=value&nonce=nonce&ts=timestamp&sig=signature';
private const CONVERSION_SECRET = 'gKH9a3UDEGn7F71NOWfuvw';

/**
 * @param string $value conversion value in US Dollars. If decimal part is needed, it should be separated with a dot
 *
 * @return string conversion link
 * @throws \Exception when function random_bytes is not available
 */
private function generateLink(string $value = ''): string
{
    $uuidStart = strrpos(self::CONVERSION_LINK_TEMPLATE, '/') + 1;
    $uuid = substr(self::CONVERSION_LINK_TEMPLATE, $uuidStart, 32);
    $nonce = Utils::urlSafeBase64Encode(random_bytes(16));
    $timestamp = time();

    $signature = Utils::urlSafeBase64Encode(
        hash('sha256', $uuid.Utils::urlSafeBase64Decode($nonce).$timestamp.$value.self::CONVERSION_SECRET, true)
    );

    return str_replace(
        [
            $value ? '=value' : 'value=value&',
            '=nonce',
            '=timestamp',
            '=signature',
        ],
        [
            $value ? '='.$value : '',
            '='.$nonce,
            '='.$timestamp,
            '='.$signature,
        ],
        self::CONVERSION_LINK_TEMPLATE
    );
}

The CONVERSION_LINK_TEMPLATE and CONVERSION_SECRET constants should be read from the conversion definition. They are unique for each conversion. The $value parameter is optional, in case it was defined in the conversion.

Direct API call

The direct API call from the advertiser’s backend to the adserver needs another parameter: cid. The cid parameter can be obtained during the first user visit on the advertiser’s site. It is the advertiser’s responsibility to store cid and connect it with a proper user. The cid parameter should be attached to other GET parameters of the advanced conversion link.

How to setup fallback backfill code

Adshares network can help you monetize your adblock traffic. Our solution can also increase your revenue based on regular traffic.

If you are already cooperating with other ad networks (e.g. Coinzilla, Cointraffic, Propeller Ads) you can use Adshares as an additional source of revenue. What’s important, you’ll be able to use Adshares simultaneously with other ad networks.

Here’s how it works:

Adshares ad units can be integrated with your site to serve part of the traffic (e.g. adblock traffic only). Once you implement the code, Adshares ad unit becomes the primary one, and other ad network’s ad unit becomes the fallback one.

For instance, Adshares ad unit can be used to serve adblock traffic using the adblock_only option. In case this option is used, the backfill code (i.e. other ad network’s ad unit) will be rendered for every user who is NOT using an ad blocker. Implementing Adshares code on your site will not affect your revenue from other ad networks in any way.

List of available adzone options

Example

The fallback code (i.e. other ad network’s ad unit) should be placed inside the zone div enclosed in the HTML comment.

<script src="http://example.com/-/find.js" async></script>

<!-- Serve only for adblock users -->
<div class="xaabbccddeeff" data-options="adblock_only" data-zone="018ac5d9e1eb426abb20bbd52ce7911d" style="width:728px;height:90px;display: block;margin: 0 auto">   
    <!--backfill
    <script async src="https://other.adnetwork.example.com/ads.js"></script>
    <div class="otherAdnetwork" data-zone="C-12345678"></div>
    -->
</div>

If using HTML comments is not possible, the backfill code can be placed inside the <style> tag with the app/backfill type.

<script src="http://example.com/-/find.js" async></script>

<!-- Serve only for adblock users -->
<div class="xaabbccddeeff" data-options="adblock_only" data-zone="018ac5d9e1eb426abb20bbd52ce7911d" style="width:728px;height:90px;display: block;margin: 0 auto">
    <!--  style tag is only a container --> 
    <style type="app/backfill">      
        <!-- Render this code in other conditions -->
        <script async src="https://other.adnetwork.example.com/ads.js"></script>
        <div class="otherAdnetwork" data-zone="C-12345678"></div>
        <!-- End of fallback/backfill code -->
    </style>
</div>

How to use Advertising Ecosystem

Please note that before using our decentralized advertising ecosystem you can try out the demo version. Adshares Advertising Ecosystem Demo can be used to get familiar with all the features of the platform. It is necessary to join Testnet before using the demo.

We have also created a demo website, which showcases how ad banners can be displayed on publishers' sites, depending on the device and the screen size.

Introduction

Adshares Advertising Ecosystem is the first genuinely decentralized advertising network for programmatic advertising, with AdServers being some of its key components.

The first step to join the Adshares network as a publisher or as an advertiser is setting up an account on the AdServer. After registering and logging in there are two panels available - one for advertisers and one for publishers. Each of the panels offers a wide range of settings and options. Both, the advertisers and the publishers, also have access to history, as well as to e-mail and password settings. Apart from AdServers the network consists of components listed and described below.

Key components

Advertiser module

Defining campaigns, setting campaign budget and targeting. Before launching a campaign the advertiser has to transfer ADS to the account and provide a minimum amount for a 1-hour campaign. Once all is set, the campaign, along with all related information, is distributed across the network. Based on the results, funds are transferred every hour directly to the publisher.

Publisher module

Registering websites on which banners will be displayed, generating code to be placed on websites. The module automatically scans the Adshares network in search of ads.

AdSelect module

Handling ads display. AdSelect learns based on interaction history, views, payments and credibility of the advertiser. The module optimizes ad selection to maximize publishers' revenue. As soon as the advertisement is selected and the campaign is live, all events are passed to the Advertiser module and the Publisher module.

AdPay module

Calculating funds. Based on campaign results, the AdPay module decides once per hour how much should be transferred from the advertiser to the publisher. The transfer is made every hour, and the publisher can withdraw funds instantly. The advertiser sets the total budget for the entire campaign and the maximum budget for a specific event (CPM and CPC).

How to use the AdServer – instruction for Advertisers

First, you need to register on the platform and confirm your registration via email. Before you start a new campaign you have add funds to your account. Simply click the "Add funds" button in the dropdown menu in the top right corner and follow the instructions. If you don't have ADS account yet, click here. The next step is the selection of Advertiser's dashboard, where you will find all campaign settings.

The entire process begins with creating a new campaign, choosing settings and uploading ad banners. After clicking the "Create new campaign" button located in the top menu it's necessary to enter some basic information, such as campaign name, max CPC/CPM, start/end date, etc. Next, you can set some optional targeting, and move on to creating your ad. It's possible to upload ad banners in HTML or jpg, png, and gif formats.

Your ads will be displayed on our partners' websites. Once your campaign is up and running, you can check how each of the banners is performing and make some adjustments to the campaign in case it's needed. To achieve the best results, we advise you to always upload banners in all formats supported by the platform.

All events are balanced on an hourly basis, and payments are made instantly, which helps optimize campaign settings.

How to use the AdServer – instruction for Publishers

Please be advised that the Adshares network supports only https-based sites and our ad units cannot be displayed on sites that do not use https.

Once you register and confirm your registration via email, you need to select "Publisher" in the upper left corner. Next, you have to click the "Add new site" button located in the upper right corner and define the site you want to place banner ads on.

Step1

Next, you need to select banner ad categories that you don’t want to display on your site. If you don’t exclude any categories, all available ads will be displayed on your site. You can also exclude specific banner ad types. Once you have selected all the exclusions, you can move on to setting the ad unit size. If you want to generate more than one ad unit, please click the “Create new ad unit” button in the bottom part of the site and pick the desired sizes.

Step2

Please check if all settings are correct and publish the site. Next, you need to get your code. Once you click the “Publish site” button you will be redirected to the main dashboard. Please click the site you have just added, then the "Get code" button, copy the code for each of the ad units and place it on your website.

Step5 Code

Payments from advertisers are made on an hourly basis, which lets the publisher see the immediate effects of campaigns and withdraw funds right away.

How to place an Ad Unit on a Wordpress website

The code can be generated and placed on a website in a way described above. Additionally, we developed a plugin for WordPress websites, which provides integration with Adshares AdServer for publishers. It makes the implementation even more straightforward and automates the process of placing the code on the website.

The installation is very simple. You just need to go to Your Website -> Plugins -> Add New, search for "Adshares" and click "Install Now". There is also an alternative installation for those who prefer to use Composer.

Once the plugin is installed, all you need to do is type in AdServer url address as "Server URL", log in into your Adshares account using your registration credentials, and select which ad units will be displayed. The plugin supports various options for position and visibility.

WordPress

In case of a high demand for a similar plugin for other popular platforms, we may consider creating dedicated plugins. If you own a website based on a popular platform and would be interested in such a plugin, please get in touch with us.

How to withdraw ADS coins from the platform

If you want to withdraw funds from the platform account you need to:

  • Log in to the platform
  • Select “Billing & Payments” from the dropdown menu in the upper right corner
  • Click the “Withdraw Funds” button
  • Enter the ADS account address you want to send your funds to. Please double-check if the address is correct
  • Enter the amount you want to withdraw
  • Add a message if necessary (e.g. when transferring funds to exchanges)
  • Click the “Withdraw” button

Once you send the transfer you will receive a confirmation link via email. Please remember to click the link within one hour, otherwise, the withdrawal will be canceled. Once the transfer is confirmed, it should take up to 15 minutes. It may take longer in case you’re depositing your funds to an exchange.

Click here to learn more about exchanges supporting ADS coins.


Please remember that it is necessary to include a message when transferring ADS coins TO a cryptocurrency exchange. The message to be copy-pasted is always provided by the exchange – please see a relevant part of the deposit section on your trading platform. It is not necessary to include a message when transferring ADS coins to your ADS Wallet or your ADS account on the platform.

List of active adservers

List of active adservers in Adshares Network.

You can create publisher and advertiser account there to earn money from your website or advertise your product. You can also start your own adserver. [[How to start adserver]]

Panel rebranding

This article describes how to change brand - dependent assets in adpanel project.

Requirements

This article assumes that the environmental variables are defined:

  • ADPANEL_PARENT_DIR - directory in which adpanel project is cloned
  • BRAND_ASSETS_DIR - directory in which custom assets will be stored. It should be placed outside project directory to ensure that files will not be deleted
  • COPY_BRAND_ASSETS - switch enabling assets change, should be Y for enable,

Collect assets

Brand - dependent assets are icons and logos in different sizes for different screens. They are stored inside adpanel src directory.

Copy project assets to own directory.

cp ${ADPANEL_PARENT_DIR}/adpanel/src/favicon* ${BRAND_ASSETS_DIR}
cp ${ADPANEL_PARENT_DIR}/adpanel/src/assets/images/logo* ${BRAND_ASSETS_DIR}

Customize assets

Content of image files can be changed. It is important to preserve file names and images' sizes in pixels.

Build adpanel

The adpanel project must be rebuild to properly replace Adshares assets with custom.

If you use interactive installer, you will be asked if you want to copy brand assets inside project directory. In case of automatic installer two environment variables should be set. They were mentioned in Requirements

  • COPY_BRAND_ASSETS should be Y
  • BRAND_ASSETS_DIR should be full path to assets directory

Files from custom assets directory will overwrite the standard files.

AdServer Panel

Home

Welcome to the adpanel wiki!

Testing

Maven command with default properties

mvn -Dwebdriver.remote=0 -Dwebdriver.remote.url="http://localhost:4444/wd/hub" -Dwebdriver.headless=0 verify

AdSelect

Home

Welcome to the adselect wiki!

Adselect

1) Zapytanie o campanie:

Request
[
        {
        "request_id": 0,
        "publisher_id": 1,
        "user_id": "yiwbeuylmikngkm7izhjwvqehtnjhg",
        "banner_size": "728x90",
        "keywords": {
            "tid": "yiwbeuylmikngkm7izhjwvqehtnjhg",
            "screen_width": 1920,
            "screen_height": 1080,
            "inframe": "no",
            "host": "website.priv",
            "path": "website.priv\/",
            "context_lorem ipsum": 1,
            "context_lipsum": 1,
            "context_lorem": 1,
            "context_ipsum": 1,
            "context_text": 1,
            "context_generate": 1,
            "context_generator": 1,
            "context_facts": 1,
            "context_information": 1,
            "context_what": 1,
            "locale": "pl",
            "browser_name": "chrome",
            "browser_version": "60.0",
            "platform_name": "win",
            "platform_version": "10",
            "device_type": "desktop",
            "geo_continent_code": "EU",
            "geo_country_code": "DE",
            "geo_country_code3": "DEU",
            "geo_country_name": "Germany",
            "geo_region": "05",
            "geo_city": "Frankfurt Am Main",
            "geo_postal_code": "60314",
            "geo_latitude": 50.11370086669922,
            "geo_longitude": 8.711899757385254,
            "zone": "website.priv\/1",
            "banner_size": "728x90"
        },
        "banner_filters": {
            "require": [],
            "exclude": []
        }
    },
]
Response
1) Wybieram takie banery, na ktorych mozna najwiecej zatobic
2) Nie mozna brac najlepszych reklam za kazdym razem (troche stochastyki tam dodac)
3) Wrzucam losowe nowe kampanie, zeby zobczyc czy da sie na nich zarobic
4) Dany uzytkownik nie powinien dostawac tej samej reklamy kilka razy

[
    {
        'request_id':,
        'banner_id':
    },
]

2) Update danych: 1) Campania update danych:


    [
    {
        "campaign_id": "adshares2.priv\/662223a0ca9a45e69d2012a874bfd260",
        "advertiser_id": "adshares2.priv\/1",
        "time_start": 1506337992,
        "time_end": 1508929992,
        "filters": {
            "require": [
                {
                    "keyword": "platform_name",
                    "filter": {
                        "type": "=",
                        "args": "linux"
                    }
                }
            ],
            "exclude": []
        },
        "keywords": {
            "source_host": "adshares2.priv",
            "adshares_address": "0001-00000002-BB2D",
            "landing_host": "example.com",
            "landing_url": "http:\/\/example.com\/"
        },
        "banners": [
            {
                "banner_id": "d9cb085e668b48eebf3a5a0e90a3af65",
                "keywords": {
                    "banner_size": "250x250",
                    "type": "image"
                }
            },
            {
                "banner_id": "fc19fe00bf8e47a1a6e36e08a59aacfe",
                "keywords": {
                    "banner_size": "468x60",
                    "type": "image"
                }
            }
        ]
    },
]

    2) Update banerow za ktore zostalo zaplacone lub nie

    [
    {
        "event_id": 1029,
        "banner_id": "24309404525f4125a16d255c49681129",
        "keywords": {
            "tid": "ca2581794c8b30890d18a33b89984959",
            "screen_width": 1920,
            "screen_height": 1080,
            "inframe": "no",
            "host": "website.priv",
            "path": "website.priv\/",
            "context_lorem ipsum": 1,
            "context_lipsum": 1,
            "context_lorem": 1,
            "context_ipsum": 1,
            "context_text": 1,
            "context_generate": 1,
            "context_generator": 1,
            "context_facts": 1,
            "context_information": 1,
            "context_what": 1,
            "locale": "pl",
            "browser_name": "chrome",
            "browser_version": "60.0",
            "platform_name": "win",
            "platform_version": "10",
            "device_type": "desktop",
            "geo_continent_code": "EU",
            "geo_country_code": "DE",
            "geo_country_code3": "DEU",
            "geo_country_name": "Germany",
            "geo_region": "05",
            "geo_city": "Frankfurt Am Main",
            "geo_postal_code": "60314",
            "geo_latitude": 50.11370086669922,
            "geo_longitude": 8.711899757385254
        },
        "paid_amount": 0,
        "user_id": "ca2581794c8b30890d18a33b89984959",
        "publisher_id": "asdasd"
    }
]

3) Format filtrow
    Filters:
    {
        'type':'and':
        'args':[]
    }

    {
        'type':'or':
        'args':[]
    }

    {
        'type':"="
        'args':''
    }

    {
        'type':">="
        'args':''
    }

    {
        'type':"<="
        'args':''
    }

    {
        'type':"<"
        'args':''
    }

    {
        'type':">"
        'args':''
    }

4) Format keyword:
Delimiter : _ - zagniezdzenie. Brak list.

Tests

After setup, pipenv link with virtual environment

ln -s `pipenv --venv` .venv

Run unit tests

pipenv run tests

AdPay

Home

Welcome to the adpay wiki!

Adpay

ADPAY 1) Kampania powinna zawierac informację jakie sa maksymalne kwoty za

  • campaign_id - id kampani
  • time_start - czas rozpoczecia kampani
  • time_end - czas zakoncznie kampani
  • filters - campaign filters
  • max_cpc - klikniecie (cpc - cost per click) danego baneru
  • max_cpm - wyswietlenie (cpm - cost per 1000 views) danego baneru
  • budget - godzinny budzet danej kampani

2) Kazdy event, ktory przychodzi zawiera informacje

  • event_id - id eventu
  • event_type - typ eventu (klikniecie - 1, wyswietlenie - 2 lub konwersja - 3)
  • user_id - id uzytkownika
  • event_value (max platnosc za konwersje, nie jest brana pod uwage kwota za click oraz wyswietlenie)
  • our_keywords - keywordy dostarczane przez adserver
  • their_keywords - keywordy dostarczane przez zewnętrzne serwery
  • banner_id - id banneru
  • advertiser_id - id reklamodawcy, do którego należy banner
  • timestamp - timestamp zdarzenia
  • human_score - definiuje czy user jest botem (wartos=0) lub czlowiekiem (wartosc = 1)

3) Filtrowanie eventow:

  • tylko eventy z niepustym user_id sa brane pod uwage podczas kalkulacji
  • tylko eventy, ktore przechodza przez filtry kampani na our_keywords

4) Określenie jakości użytkownika (per kampania)

  • Tworzymy table user_value z polami (user_id, max_score, max_user_human_score) user_id - id użytkownika, który klinął

    max_user_human_score - maksymalny human_score dla danego uzytkownika w okreslonym czasie kampani

    max_score - max([max_per_click, max_per_view, max_per_conversion]) ustawione dla kampani określa jaką maksymalną płatność w kampanii użytkownik może otrzymać w związku z eventami, które wykonał

  • Tabela jest zapełniana po wykoaniu płatności

5) Liczenie płatności za event

  • Okreśelenie wagi płątności dla użytkownika - Waga płatności to średnia arytmetyczna z iloczynu max_score*max_user_human_score z pięciu najbardzie podobnych użytkowników [liczenie podobienstwa uzytkownikow opisane jest w punkcie 6]
  • Określenie budżetu dla użytkownika - Do każdego z 50% użytkowników z najlepszymi wagami do płatności przypisujemy część budżetu kampani, który jest wprostproporcjonalny do wagi płatności danego użytkownika
  • Określenie płatności za event - Każdy event użytkownika jest opłacony będzie wyłącnzie z budżetu użytkownika. Płatność za event będzie wprostproporcjonalna do ilości danego eventu oraz max kwoty płatności za dany event.
  1. Podobienstwa uzytkownikow

    Tabele per uzytkownik

    • Dla kazdego uzytkownika trzymana jest infromacja keywordow z czestotliwoscia wystapien
    • Co wyswietlenie uzytkownika przeliczana jest jego baza czestotliwosci keywordow w nastepujacy sposob
      • updatowana jest wartosc czestotliosc z deckayem 1%
      • jesli wartosc czestotliwosci jest mniejsza niz 0.1%, dany keyword jest usuwany z bazy keywordow z czestotliwosciami

    Tabele globalne

    • Dla kazdego keywordu trzymana jest infrmacj o globalnej ilosci wyswietlen w danym okresie czasu i częstotliwości dla danego keywordu
    • Co 1000 wyswietlen przeliczana jest baza globalnych czestotliwosci w nastepujacy sposob

      • updetowana jest wartosc czestotliwosci z deckeyem 1%
      • zerowana jest informacja o wyswietleniach
      • jesli wartosc jest mniejsza niz 0.001% - dany keyword jest usuwany z bazy globalnych keywordow

      Wyliczanie profilu keywordow dla uzytkownika

    • Profile sa liczone periodycznie przed policzniem platnosci
    • Do profilu uzytkownika brane sa tylko te keywordy, ktore maja globalna czestotliwosc < 10%
    • Dla kazdego wyfilltrowanego keywordu liczony jest score keywordu wedlug wzoru score = [czestotliwosc keywordu uzytkownika]/(0.01 + czestotliwosc globalna keywordu)
    • Do profilu uzytkownika brane jest 50 keywordow posiadajacych najwyzszy wyliczony score

      Porownywanie uzytkownikow

    • Wartosc podobiensta to ilość wystepujacych tych samych keywordow w profilach uzytkownikow podzielona przez 50
  2. get_payemnts - get events payments from specific hour

Request

{ 'timestamp':timestamp }

Response

{
    'payments':[
        {'event_id':event_id1, 'amount':pay_amount1},
        {'event_id':event_id2, 'amount':pay_amount2},
     ]
}
  1. add_events - notify about event

Request

    [
    {
        "event_id": 1029,
        "banner_id": "24309404525f4125a16d255c49681129",
        "keywords": {
            "tid": "ca2581794c8b30890d18a33b89984959",
            "screen_width": 1920,
            "screen_height": 1080,
            "inframe": "no",
            "host": "website.priv",
            "path": "website.priv\/",
            "context_lorem ipsum": 1,
            "context_lipsum": 1,
            "context_lorem": 1,
            "context_ipsum": 1,
            "context_text": 1,
            "context_generate": 1,
            "context_generator": 1,
            "context_facts": 1,
            "context_information": 1,
            "context_what": 1,
            "locale": "pl",
            "browser_name": "chrome",
            "browser_version": "60.0",
            "platform_name": "win",
            "platform_version": "10",
            "device_type": "desktop",
            "geo_continent_code": "EU",
            "geo_country_code": "DE",
            "geo_country_code3": "DEU",
            "geo_country_name": "Germany",
            "geo_region": "05",
            "geo_city": "Frankfurt Am Main",
            "geo_postal_code": "60314",
            "geo_latitude": 50.11370086669922,
            "geo_longitude": 8.711899757385254
        },
        "paid_amount": 0,
        "user_id": "ca2581794c8b30890d18a33b89984959",
        "publisher_id": "asdasd"
    }
]

Response

{'result':True}
  1. campaign_delete - delete campaigns

Request

[
    camapaign_id1, 
    camapaign_id2
]

Response

{'result':True}
  1. campaign_update - create or update campaign

Request

[
    {
        "campaign_id": "adshares2.priv\/662223a0ca9a45e69d2012a874bfd260",
        "advertiser_id": "adshares2.priv\/1",
        "time_start": 1506337992,
        "time_end": 1508929992,
        "filters": {
            "require": [
                {
                    "keyword": "platform_name",
                    "filter": {
                        "type": "=",
                        "args": "linux"
                    }
                }
            ],
            "exclude": []
        },
        "banners": [
            {
                "banner_id": "d9cb085e668b48eebf3a5a0e90a3af65",
                "keywords": {
                    "banner_size": "250x250",
                    "type": "image"
                }
            },
            {
                "banner_id": "fc19fe00bf8e47a1a6e36e08a59aacfe",
                "keywords": {
                    "banner_size": "468x60",
                    "type": "image"
                }
            }
        ]
    },
]

Response

{'result':True}

Browser Wallet

Home

Welcome to the ads-browser-wallet wiki!

Build instruction

Building extension

Building extension

Download project

git clone https://github.com/adshares/ads-browser-wallet.git
cd ads-browser-wallet

Install Node.js and npm.

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

Install dependencies

npm install

Build distribution files

npm run build

Files will be saved in ads-browser-wallet/build directory.

Plugin was built successfully using:

  • Node.js v8.11.3
  • npm v6.2.0

Packing extension using chrome

Open chrome://extensions/ and click Pack Extension button.

Alternatively use command line

google-chrome --pack-extension=./build/

As a result dist.crx file should be generated.

If You have pem key, You should use it while packing next version of extension. Command line call takes key as --pack-extension-key parameter.

PHP Client

Home

Installation

We use SemVer for versioning. For the versions available, see the tags on this repository.

Several quick start options are available:

Usage

Initialize CliDriver (Command line Driver) with ADS blockchain credentials (account address, private key, node host and port).

$driver = new CliDriver($this->address, $this->secret, $this->host, $this->port);

Please, note that by default CliDriver uses ads as ADS blockchain client application and saves cache to ~/.ads directory. This behaviour can be overwritten with $driver->setCommand(string) and $driver->setWorkingDir(string) methods.

Initialize client with driver.

$client = new AdsClient($driver);

Call commands using created client. In current version client supports all block explorer commands and basic transaction.

Supported block explorer commands:

  • getAccount,
  • getAccounts,
  • getBlock,
  • getBlockIds,
  • getBroadcast,
  • getMe,
  • getMessage,
  • getMessageIds,
  • getTransaction.

    Supported transactions:

  • broadcast,
  • sendMany,
  • sendOne.

Tests

Tests are split into three categories: end-to-end, unit and coding style.

End-to-end tests

Aim of end to end test is to check integration between PHP ADS Client and ADS blockchain network. Therefore working network must be set and ADS client must be installed in system. Tests are placed in tests/E2E directory and can be run with PHPUnit.

Unit tests

Unit tests are placed in tests/Unit directory and can be run with PHPUnit.

Coding style tests

PHP Code Sniffer is used to check compatiblity with PHP language and PSR-2 standard.

./vendor/bin/phpcs -s --standard=PHPCompatibility src tests
./vendor/bin/phpcs -s --standard=PSR2 src tests

PHP Code Beautifier and Fixer can be used for automatic fix of PSR-2 incompatibility.

./vendor/bin/phpcbf -s --standard=PSR2 src tests

PHPStan is used for static analysis.

./vendor/bin/phpstan --no-ansi --no-progress analyse -c phpstan.neon -l 7 src tests

Installation

Moved to Installation

Usage

Moved to Usage

_Sidebar

Tests

Moved to Tests