-
Notifications
You must be signed in to change notification settings - Fork 10
Instructions for Exchanges
The purpose of this document is to describe how to interface your exchange with the VEE (VVV) blockchain step-by-step.
交易所对接指南(中文版)点击这里
In current stage, the standard hardware requirement is VPS with 2 CPU, 16GB of RAM and 1TB HHD.
The recommend requirement is Amazon Web Services (AWS) i3 large.
All Java 1.8 and Python runnable operating system are supported (including Ubuntu, CentOS, MacOS, Windows etc.).
The recommended operating system is Ubuntu 16.04 LTS (or above).
In this instruction, we'll take Ubuntu 16.04 for instance.
First of all, update the repository
$ sudo apt-get update
Install Java in your machine
$ sudo apt-get install openjdk-8-jdk
Check Java version (remove the old version Java if needed).
$ java -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-0ubuntu0.16.04.1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
Install Scala Build Tool (SBT) if you want to compile vee node project
$ echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
$ sudo apt-get update
$ sudo apt-get install sbt
Install Unzip and Git if your machine do not have this tool.
$ sudo apt-get install unzip
$ sudo apt-get install git-core
There is two ways to prepare to node program file. Choose the solution as you want.
Download source code from GitHub.
$ git clone https://github.com/excelsia/vee.git
$ cd VEE
Then compile by SBT. If you want to compile TestNet VEE node,
# Compile TestNet VEE node
$ sbt -Dnetwork=testnet packageAll
Or otherwise, if you want to compile MainNet VEE node,
# Compile MainNet VEE node
$ sbt packageAll
The compiled JAR file will be located at target/vee-all-[version].jar. Copy to your own path as you want. For example,
$ mkdir ../vee-node
$ cp target/vee-all-*.jar ../vee-node/
$ cd ../vee-node
If you do not want to compile souce code, you could download the lastest JAR from https://github.com/excelsia/vee/releases as well.
Choose vee-all-[version].jar and save to your own path as you want.
Set your configuration file.
# Vee node settings
vee {
# Path Settings
directory = <block data folder path>
# Application logging level. Could be DEBUG | INFO | WARN | ERROR. Default value is INFO.
logging-level = DEBUG
# P2P Network settings
network {
known-peers = ["<peer ip>:9923"]
black-list-residence-time = 30s
peers-broadcast-interval = 5s
connection-timeout = 30s
# Network address
# Node name to send during handshake. Comment this string out to set random node name.
# node-name = "My MAINNET node"
}
# Wallet settings
wallet {
# Password to protect wallet file
password = ""
# Wallet seed as BASE58 string
# seed = ""
}
# Blockchain settings
blockchain.type = TESTNET # Should be TESTNET or MAINNET
# Matcher settings
matcher.enable = no
# Minter settings
miner {
enable = yes
offline = no
quorum = 1
generation-delay = 1s
interval-after-last-block-then-generation-is-allowed = 120h
tf-like-scheduling = no
# Left to empty as default to minter address
reward-address = ""
}
# Node's REST API settings
rest-api {
# Enable/disable node's REST API
enable = yes
# Hash of API key string
api-key-hash = "9yJftYf774owgzSUAXc9REkNnTAV8TXxuBTHEX4oJQpZ"
}
checkpoints.public-key = "A9MX22tXpNdTTx5wBf3CunZz299c1nnca6kH3MzL312L"
}
-
The directory should be set to your own path.
-
It is better to choose more than 3 peers to fill the known-peers field. You could check known-peers via VEE explorer. Some known-peers for current reference:
# For TestNet known-peers = ["18.179.34.202:9923", "13.250.53.12:9923", "18.188.219.229:9923"] # For MainNet (contact us to get more known peers) known-peers = ["18.221.212.99:9921"]
-
The blockchain.type should be filled with TESTNET or MAINNET.
-
For security reason, it is better to set you own api-key-hash. You could check the hash by this command
curl -X POST -d '<your api key>' 'https://wallettestnet.vee.tech/api/utils/hash/secure'
-
Finnaly, we save the file, for example name it as "vee.conf".
$ screen -S vee-node
$ sudo java -jar vee*.jar vee.conf
Detach your screen by Ctrl + A + D
.
To inspect the screen
$ screen -x vee-node
Security warning: Every full node provides RESTful API for interaction with chain. The RESTful API service will use port 9922. For security reason, we suggest the exchange modify firewall rule and not open 9922 in public network, only for internal network using.
You could use the following method to call APIs.
If you use python to do integration, we strongly suggest you use pyvee project. The pyvee specification is here.
You could open http://<full node ip>:9922
in browser to find all APIs you can use.
Install curl for post http request if you do not have curl.
$ sudo apt-get install curl
To test connection, you could use
$ curl -X GET 'http://<full node ip>:9922/blocks/height'
If success, you will get more or less like the following response:
{
"height": 2400326
}
Use HTTP POST to call /addresses API.
$ curl -X POST --header 'Accept: application/json' --header 'api_key: <full node api key>' 'http://<full node ip>:9922/addresses'
If wallet is created, you will get address of the wallet in response:
{
"address": "AUBBmrf5cuBf9XrSaX98mxWmcNBwULqQhQK"
}
The created wallets will be stored in <block data folder path>/wallet/wallet.dat
. Remember to backup the file in schedule.
And you can recover a wallet from seed as well. To find the seed of wallet, use HTTP GET to call /addresses/seed/{address} with node API key. For example,
$ curl -X GET --header 'Accept: application/json' --header 'api_key: <full node api key>' 'http://<full node ip>:9922/addresses/seed/AU9KCwJm6mG9YxSb3LdjVi6LDwRGey1knfy'
Response:
{
"address": "AU9KCwJm6mG9YxSb3LdjVi6LDwRGey1knfy",
"seed": "GY7T8WpppuficZJs9CnEuntLkk4vXw7qkZ1SMtZ3qAas"
}
Once you known the seed, you can recover the wallet by wallet-generator
Use HTTP GET calling /addresses API to get all addresses:
$ curl -X GET 'http://<full node ip>:9922/addresses'
Response:
[
"ATy98tPdobDBKA35n5CJed6u3AmxKLT3TTV",
"ATys7iafCN4xHz9bJyKm4JNfKpk9f1uBBXT",
"AU1TFgjs3g1NMkXW5CGTGj96t8qijs6ScrP",
"ATubqbssJKtPfyebkmct4jv9YSue8xrhMLa",
"AU9KCwJm6mG9YxSb3LdjVi6LDwRGey1knfy",
"ATwMEAGfNhbRCRSApro8HWG2L65HMMa42KP",
"AU4rMtj3zEJesVQ94Az8ajncNMgtK6uzeHB",
"ATtdkLaHDPZQx3LsUfrKisRcrMkvfg18LGa",
"ATxa6h87rBrNYKDCkagageiPzTMFgcGmefA",
"AU8R9ri7eG968zuJuLQVLMiUzRNXvQwNPwE"
]
As more and more wallets created, it is better to query the wallet address with number limit. You can use HTTP GET /addresses/seq/{from}/{to} to get any range of addresses. For example:
$ curl -X GET 'http://<full node ip>:19922/addresses/seq/5/10'
Response:
[
"ATwMEAGfNhbRCRSApro8HWG2L65HMMa42KP",
"AU4rMtj3zEJesVQ94Az8ajncNMgtK6uzeHB",
"ATtdkLaHDPZQx3LsUfrKisRcrMkvfg18LGa",
"ATxa6h87rBrNYKDCkagageiPzTMFgcGmefA",
"AU8R9ri7eG968zuJuLQVLMiUzRNXvQwNPwE"
]
To check balance of address, use HTTP GET to call /addresses/balance/details/{address}
$ curl -X GET 'http://<full node ip>:9922/addresses/balance/details/AU8R9ri7eG968zuJuLQVLMiUzRNXvQwNPwE'
Response:
{
'address': 'AU8R9ri7eG968zuJuLQVLMiUzRNXvQwNPwE',
'regular': 109010000000, # regular balance
'available': 108910000000, # available balance (regular - leased out)
'effective': 108910000000, # effective balance (regular - leases out + leased in)
'mintingAverage': 108909964800, # for minter used
'height': 643936
}
The available
balance is the actual balance which wallet currently could use (100000000 = 1 VEE).
Use HTTP POST to call /vee/payment API.
$ curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'api_key: <full node api key>' -d '{ \
"amount": 100000000, \
"fee": 10000000, \
"feeScale": 100, \
"sender": "ATtRykARbyJS1RwNsA6Rn1Um3S7FuVSovHK", \
"attachment": "", \
"recipient": "ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX" \
}' 'http://<full node ip>:9922/vee/payment'
In request,
amount
is the payment amount. 100000000 = 1 VEE.
fee
is the transaction fee. The mininum transaction fee is 10000000(0.1 VEE).
feeScale
currently is a fixed value. It should be 100.
sender
is the sender wallet address.
recipient
is the recipient wallet address.
attachment
could be any text (max 140 characters) with base58 encoding.
Response:
{
"type": 2,
"id": "EoNQyNouEKg8pDcEEPY2dJL9FMQx61YFk1Sn5EJN8H7K",
"fee": 10000000,
"timestamp": 1544083814291691000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "3orvgyRKf45FRyiCkcA3CzAGDvyEpBpXZzYGEGZnpZK5",
"signature": "t1X2zmw5a2b9iaLgtsHyHKgEmKo6GCFuMFQsZNqj8ZkzpVbRKhWUttqUDfcjzcn5w7VgVVvf8cetr1mh2d2xypQ"
}
],
"recipient": "ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX",
"feeScale": 100,
"amount": 100000000,
"attachment": ""
}
Use HTTP GET to call /transactions/address/{address}/limit/{limit} API. For example,
$ curl -X GET --header 'Accept: application/json' 'http://<full node ip>:9922/transactions/address/ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX/limit/5'
Response:
[
[
{
"type": 2,
"id": "EoNQyNouEKg8pDcEEPY2dJL9FMQx61YFk1Sn5EJN8H7K",
"fee": 10000000,
"timestamp": 1544083814291691000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "3orvgyRKf45FRyiCkcA3CzAGDvyEpBpXZzYGEGZnpZK5",
"signature": "t1X2zmw5a2b9iaLgtsHyHKgEmKo6GCFuMFQsZNqj8ZkzpVbRKhWUttqUDfcjzcn5w7VgVVvf8cetr1mh2d2xypQ"
}
],
"recipient": "ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX",
"feeScale": 100,
"amount": 100000000,
"attachment": "",
"status": "Success",
"feeCharged": 10000000
},
{
"type": 4,
"id": "FiMiErppddPfFCmehu1ziKNTqyzBFsLRj6gh9y45JKKD",
"fee": 10000000,
"timestamp": 1543569020372515800,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV",
"signature": "2hpsVXZVs2Wmg5ixD8PqvMJoC3CAqgTqvapYkuFAxbLvoyXRu45q9HXZQyqCzHeiHocGFM8phPkmDuM566Xu59em"
}
],
"feeScale": 100,
"leaseId": "D8mGb2YSGyKr5Q3WATnpQP8JvyDdteXwieo5khwsTEyY",
"status": "Success",
"feeCharged": 10000000,
"lease": {
"type": 3,
"id": "D8mGb2YSGyKr5Q3WATnpQP8JvyDdteXwieo5khwsTEyY",
"fee": 10000000,
"timestamp": 1543569009108564000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV",
"signature": "8TDUgnkNbrPL6VMLFzDnhZvABfRqXitFX46mmvpohsdeRHKaNtWCs5C7m6avaUH2NjiFS7jGFov1CY5s3W8Zc5V"
}
],
"amount": 100000000,
"recipient": "AU6GsBinGPqW8zUuvmjgwpBNLfyyTU3p83Q",
"feeScale": 100
}
},
{
"type": 3,
"id": "D8mGb2YSGyKr5Q3WATnpQP8JvyDdteXwieo5khwsTEyY",
"fee": 10000000,
"timestamp": 1543569009108564000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV",
"signature": "8TDUgnkNbrPL6VMLFzDnhZvABfRqXitFX46mmvpohsdeRHKaNtWCs5C7m6avaUH2NjiFS7jGFov1CY5s3W8Zc5V"
}
],
"amount": 100000000,
"recipient": "AU6GsBinGPqW8zUuvmjgwpBNLfyyTU3p83Q",
"feeScale": 100,
"status": "Success",
"feeCharged": 10000000
},
{
"type": 2,
"id": "He17g3JXtbXgMiWCTGwnNMPfvfFH5tvyJfYZ7BiWGBZK",
"fee": 10000000,
"timestamp": 1543568995612184000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "CbUPwcCJaMqYSjZGXy4LrkTfV2ncP27Chqyd2QKXfJxn",
"signature": "24fNpVr8qjrKuDNd8JSeZgkSa4BuS44kxupiAYPHxCbbPMBs2DyT7VDnqAWsJkYZxXWadqiQs7HFxW9uVULrGAtt"
}
],
"recipient": "ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX",
"feeScale": 100,
"amount": 100000000,
"attachment": "",
"status": "Success",
"feeCharged": 10000000
},
{
"type": 2,
"id": "2FVTJUpUJAhZJWkVYHHCG4nRXkYqwQcKsGEK8uwx3A58",
"fee": 10000000,
"timestamp": 1543568982176328000,
"proofs": [
{
"proofType": "Curve25519",
"publicKey": "B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV",
"signature": "3DShPFQLidR1nbTKDrrhpp6SZdiL1hKtjYaGANzGuaWqjpGggPgtrCzw5XYXXktt2sFgWnmFVfTf4gNkmNPNyS2v"
}
],
"recipient": "AU6GsBinGPqW8zUuvmjgwpBNLfyyTU3p83Q",
"feeScale": 100,
"amount": 100000000,
"attachment": "",
"status": "Success",
"feeCharged": 10000000
}
]
]
Some common id of transaction types:
2 = Payment transaction
3 = Lease transaction
4 = Cancel lease transaction
5 = Minting transaction