Аккаунт в блокчейне это структура содержащая некоторый набор данных связанных с аккаунтом - ключи, метаданные, балансы.
Пример
{
"id": "1.2.17",
"membership_expiration_date": "1969-12-31T23:59:59",
"registrar": "1.2.17",
"referrer": "1.2.17",
"lifetime_referrer": "1.2.17",
"network_fee_percentage": 2000,
"lifetime_referrer_fee_percentage": 8000,
"referrer_rewards_percentage": 0,
"name": "nathan",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
1
]
],
"address_auths": []
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
1
]
],
"address_auths": []
},
"options": {
"memo_key": "XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
"voting_account": "1.2.5",
"num_witness": 0,
"num_committee": 0,
"votes": [],
"extensions": []
},
"statistics": "2.6.17",
"whitelisting_accounts": [],
"blacklisting_accounts": [],
"whitelisted_accounts": [],
"blacklisted_accounts": [],
"cashback_vb": "1.13.8",
"owner_special_authority": [
0,
{}
],
"active_special_authority": [
0,
{}
],
"top_n_control_flags": 0
},
"statistics": {
"id": "2.6.17",
"owner": "1.2.17",
"most_recent_op": "2.9.4454",
"total_ops": 3608,
"removed_ops": 2608,
"total_core_in_orders": 0,
"lifetime_fees_paid": 1732888636,
"pending_fees": 0,
"pending_vested_fees": 500001
},
"registrar_name": "nathan",
"referrer_name": "nathan",
"lifetime_referrer_name": "nathan",
"votes": [],
"cashback_balance": {
"id": "1.13.8",
"owner": "1.2.17",
"balance": {
"amount": 1404631566,
"asset_id": "1.3.0"
},
"policy": [
1,
{
"vesting_seconds": 31536000,
"start_claim": "1970-01-01T00:00:00",
"coin_seconds_earned": "43009156104525000",
"coin_seconds_earned_last_update": "2018-07-05T18:10:00"
}
]
},
"balances": [
{
"id": "2.5.1",
"owner": "1.2.17",
"asset_type": "1.3.0",
"balance": "999978435986363"
},
{
"id": "2.5.160",
"owner": "1.2.17",
"asset_type": "1.3.8",
"balance": 1000000000
},
{
"id": "2.5.43",
"owner": "1.2.17",
"asset_type": "1.3.9",
"balance": "74970117938"
}
],
"vesting_balances": [
{
"id": "1.13.8",
"owner": "1.2.17",
"balance": {
"amount": 1404631566,
"asset_id": "1.3.0"
},
"policy": [
1,
{
"vesting_seconds": 31536000,
"start_claim": "1970-01-01T00:00:00",
"coin_seconds_earned": "43009156104525000",
"coin_seconds_earned_last_update": "2018-07-05T18:10:00"
}
]
}
],
"limit_orders": [],
"call_orders": [],
"settle_orders": [],
"proposals": [],
"assets": [
"1.3.1",
"1.3.2",
"1.3.3",
"1.3.4",
"1.3.5",
"1.3.6",
"1.3.7",
"1.3.8",
"1.3.9",
"1.3.10"
],
"withdraws": []
}
Балансы - это так же сущности. Они создаются и прикрепляются к аккаунту в момент, когда пользователю впервые начисляется тот или иной токен.
Пример
{
"id": "2.5.1",
"owner": "1.2.17",
"asset_type": "1.3.0",
"balance": "999978435986363"
}
Токены бывают 2х типов - Smart Assets (те, что занимаются под залог основного токена или другими смартами) и UIA (User Issued Assets) (те что пользователь может печатать сам).
Так же есть Core токен. Это основной токен системы. Он больше похоже на UIA, но напечатан один раз. Вся ком-са в блокчейне рассчитывается относительно него.
Пример
{
"id": 1,
"jsonrpc": "2.0",
"result": [
{
"id": "1.3.0",
"symbol": "XZEN",
"precision": 5,
"issuer": "1.2.3",
"options": {
"max_supply": "1000000000000000",
"market_fee_percent": 0,
"max_market_fee": "1000000000000000",
"issuer_permissions": 0,
"flags": 0,
"core_exchange_rate": {
"base": {
"amount": 1,
"asset_id": "1.3.0"
},
"quote": {
"amount": 1,
"asset_id": "1.3.0"
}
},
"whitelist_authorities": [],
"blacklist_authorities": [],
"whitelist_markets": [],
"blacklist_markets": [],
"description": "",
"extensions": []
},
"dynamic_asset_data_id": "2.3.0"
}
]
}
Для этого используются следующие свойства. Идентификатор пользователя это число вида 1.2.x - где x это номер пользователя в системе. С каждым новым пользователем это чисто увеличивается. Счет ведется от нуля.
Нода предоставляет апи запрос для получения общего кол-ва аккаунтов в системе:
Пример запроса
curl -X POST -H "Content-Type: application/json" -d '{"method":"call","params":[0,"get_account_count",[]],"id":1}' "https://api.xzen.graphenelab.org/ws"
Ответ
{"id":1,"jsonrpc":"2.0","result":185}
Используя это значение, можно пройтись bulk-запросами перебирая все аккаунты.
Пример запроса
curl -X POST -H "Content-Type: application/json" -d '{"method":"call","params":[0,"get_full_accounts",[["1.2.0", "1.2.17"], true]],"id":1}' "https://api.xzen.graphenelab.org/ws"
Ответ
{
"id": 1,
"jsonrpc": "2.0",
"result": [
[
"1.2.0",
{
"account": {
"id": "1.2.0",
"membership_expiration_date": "1969-12-31T23:59:59",
"registrar": "1.2.0",
"referrer": "1.2.0",
"lifetime_referrer": "1.2.0",
"network_fee_percentage": 2000,
"lifetime_referrer_fee_percentage": 8000,
"referrer_rewards_percentage": 0,
"name": "committee-account",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [],
"address_auths": []
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [],
"address_auths": []
},
"options": {
"memo_key": "XZEN1111111111111111111111111111111114T1Anm",
"voting_account": "1.2.5",
"num_witness": 0,
"num_committee": 0,
"votes": [],
"extensions": []
},
"statistics": "2.6.0",
"whitelisting_accounts": [],
"blacklisting_accounts": [],
"whitelisted_accounts": [],
"blacklisted_accounts": [],
"owner_special_authority": [
0,
{}
],
"active_special_authority": [
0,
{}
],
"top_n_control_flags": 0
},
"statistics": {
"id": "2.6.0",
"owner": "1.2.0",
"most_recent_op": "2.9.0",
"total_ops": 0,
"removed_ops": 0,
"total_core_in_orders": 0,
"lifetime_fees_paid": 0,
"pending_fees": 0,
"pending_vested_fees": 0
},
"registrar_name": "committee-account",
"referrer_name": "committee-account",
"lifetime_referrer_name": "committee-account",
"votes": [],
"balances": [
{
"id": "2.5.0",
"owner": "1.2.0",
"asset_type": "1.3.0",
"balance": 0
}
],
"vesting_balances": [],
"limit_orders": [],
"call_orders": [],
"settle_orders": [],
"proposals": [],
"assets": [],
"withdraws": []
}
],
[
"1.2.17",
{
"account": {
"id": "1.2.17",
"membership_expiration_date": "1969-12-31T23:59:59",
"registrar": "1.2.17",
"referrer": "1.2.17",
"lifetime_referrer": "1.2.17",
"network_fee_percentage": 2000,
"lifetime_referrer_fee_percentage": 8000,
"referrer_rewards_percentage": 0,
"name": "nathan",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
1
]
],
"address_auths": []
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
1
]
],
"address_auths": []
},
"options": {
"memo_key": "XZEN5QKLKJL5YHtCSkey95FCxhcUSg1fr4N9Ke8CdS5AKVnZCwr3gS",
"voting_account": "1.2.5",
"num_witness": 0,
"num_committee": 0,
"votes": [],
"extensions": []
},
"statistics": "2.6.17",
"whitelisting_accounts": [],
"blacklisting_accounts": [],
"whitelisted_accounts": [],
"blacklisted_accounts": [],
"cashback_vb": "1.13.8",
"owner_special_authority": [
0,
{}
],
"active_special_authority": [
0,
{}
],
"top_n_control_flags": 0
},
"statistics": {
"id": "2.6.17",
"owner": "1.2.17",
"most_recent_op": "2.9.4470",
"total_ops": 3624,
"removed_ops": 2624,
"total_core_in_orders": 0,
"lifetime_fees_paid": 1738888648,
"pending_fees": 0,
"pending_vested_fees": 2000004
},
"registrar_name": "nathan",
"referrer_name": "nathan",
"lifetime_referrer_name": "nathan",
"votes": [],
"cashback_balance": {
"id": "1.13.8",
"owner": "1.2.17",
"balance": {
"amount": 1409431578,
"asset_id": "1.3.0"
},
"policy": [
1,
{
"vesting_seconds": 31536000,
"start_claim": "1970-01-01T00:00:00",
"coin_seconds_earned": "43161794891370000",
"coin_seconds_earned_last_update": "2018-07-05T18:25:00"
}
]
},
"balances": [
{
"id": "2.5.1",
"owner": "1.2.17",
"asset_type": "1.3.0",
"balance": "999978428486348"
},
{
"id": "2.5.160",
"owner": "1.2.17",
"asset_type": "1.3.8",
"balance": 1000000000
},
{
"id": "2.5.43",
"owner": "1.2.17",
"asset_type": "1.3.9",
"balance": "74970117938"
}
],
"vesting_balances": [
{
"id": "1.13.8",
"owner": "1.2.17",
"balance": {
"amount": 1409431578,
"asset_id": "1.3.0"
},
"policy": [
1,
{
"vesting_seconds": 31536000,
"start_claim": "1970-01-01T00:00:00",
"coin_seconds_earned": "43161794891370000",
"coin_seconds_earned_last_update": "2018-07-05T18:25:00"
}
]
}
],
"limit_orders": [],
"call_orders": [],
"settle_orders": [],
"proposals": [],
"assets": [
"1.3.1",
"1.3.2",
"1.3.3",
"1.3.4",
"1.3.5",
"1.3.6",
"1.3.7",
"1.3.8",
"1.3.9",
"1.3.10"
],
"withdraws": []
}
]
]
}
Этот запрос возвращает максимальную информацию по текущему состоянию аккаунтов, включая текущие балансы. В балансах возвращаются идентификаторы токенов. Чтобы получить их название, нужно разово выполнить запрос:
{"method":"call","params":[0,"get_assets",[["1.3.0", "1.3.1"]]],"id":1}
перечислив неизвестные токены.
вероятно это стоит сделать отдельным сервисом?
Курсы можно брать с https://www.cryptocompare.com/api#introduction