Skip to content

Commit 70739f0

Browse files
committed
Added get_keys_accounts API method
1 parent fa8fb19 commit 70739f0

File tree

8 files changed

+130
-0
lines changed

8 files changed

+130
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Each API service will bind to a different IP address on the localhost, which can
4444
- `/v1/chain/get_currency_balances` runs on port 8901
4545
- `/v1/chain/get_accounts` runs on port 8902
4646
- `/v1/chain/get_blocks` runs on port 8903
47+
- `/v1/history/get_keys_accounts` runs on port 8904
4748
- `/v1/node/get_supported_apis` runs on port 8905
4849

4950
### nginx configuration
@@ -69,6 +70,10 @@ location /v1/chain/get_blocks$ {
6970
proxy_pass http://127.0.0.1:8903;
7071
}
7172
73+
location /v1/history/get_keys_accounts$ {
74+
proxy_pass http://127.0.0.1:8904;
75+
}
76+
7277
location /v1/node/get_supported_apis$ {
7378
proxy_pass http://127.0.0.1:8905;
7479
}

config/get_keys_accounts/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
GET_KEYS_ACCOUNTS_WORKERS=4
2+
GET_KEYS_ACCOUNTS_UPSTREAM_WORKERS=4
3+
GET_KEYS_ACCOUNTS_LIMIT=50

docker-compose.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ services:
1212
restart: on-failure
1313
volumes:
1414
- .:/src
15+
get_keys_accounts:
16+
build: ./services/get_keys_accounts
17+
env_file:
18+
- ./config/.env
19+
- ./config/get_keys_accounts/.env
20+
networks:
21+
- eosio_api_network
22+
ports:
23+
- "8904:8000"
24+
restart: on-failure
25+
volumes:
26+
- .:/src
1527
get_available_endpoints:
1628
build: ./services/get_available_endpoints
1729
env_file:
@@ -61,6 +73,7 @@ services:
6173
volumes:
6274
- .:/src
6375

76+
6477
networks:
6578
eosio_api_network:
6679
external: true

services/get_keys_accounts/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM python:3.7.0-slim
2+
3+
COPY requirements.txt /tmp/requirements.txt
4+
RUN pip3 install -r /tmp/requirements.txt
5+
6+
WORKDIR /src/services/get_keys_accounts
7+
8+
CMD ["gunicorn", "--reload", "-c", "config.py", "main:app"]

services/get_keys_accounts/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import os
2+
3+
bind = '0.0.0.0:8000'
4+
workers = os.environ['GET_KEYS_ACCOUNTS_WORKERS']

services/get_keys_accounts/main.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import asyncio
2+
import concurrent.futures
3+
import json
4+
import requests
5+
import os
6+
import sys
7+
import falcon
8+
9+
from functools import partial
10+
11+
# Load Environmental Variables
12+
max_workers = int(os.environ['GET_KEYS_ACCOUNTS_UPSTREAM_WORKERS'])
13+
max_results = int(os.environ['GET_KEYS_ACCOUNTS_LIMIT'])
14+
upstream = os.environ['UPSTREAM_API']
15+
16+
async def get_keys_accounts(public_keys):
17+
account_cache = {}
18+
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as pool:
19+
loop = asyncio.get_event_loop()
20+
futures = []
21+
# Create a future execution of the post request in the futures pool
22+
for public_key in public_keys:
23+
futures.append(
24+
loop.run_in_executor(
25+
pool,
26+
partial(
27+
requests.post,
28+
upstream + '/v1/history/get_key_accounts',
29+
json={
30+
"public_key": public_key
31+
}
32+
)
33+
)
34+
)
35+
results = {
36+
'account_names': [],
37+
'map': {}
38+
}
39+
# Await for all processes to complete
40+
for r in await asyncio.gather(*futures):
41+
if r.status_code == 200:
42+
body = json.loads(r.request.body)
43+
for account_name in r.json()['account_names']:
44+
if account_name not in account_cache:
45+
sys.stdout.flush()
46+
r = requests.post(upstream + '/v1/chain/get_account', json={
47+
"account_name": account_name
48+
})
49+
if r.status_code == 200:
50+
account_cache[account_name] = r.json()
51+
permissions = account_cache[account_name].get('permissions')
52+
for permission in permissions:
53+
for key in permission['required_auth']['keys']:
54+
if key['key'] == body['public_key']:
55+
account_authority = account_name + '@' + permission['perm_name']
56+
results['account_names'].append(account_authority)
57+
if body['public_key'] in results['map']:
58+
results['map'][body['public_key']].append(account_authority)
59+
else:
60+
results['map'][body['public_key']] = [account_authority]
61+
pass
62+
# Return results
63+
return results
64+
65+
class GetKeysAccounts:
66+
def on_get(self, req, resp):
67+
self.on_post(req, resp);
68+
def on_post(self, req, resp):
69+
# Process the request to retrieve the account name
70+
request = json.loads(req.stream.read())
71+
# Accounts to load
72+
public_keys = request.get('public_keys')
73+
# Throw exception if exceeding limit
74+
requested_public_keys = len(public_keys)
75+
if requested_public_keys > max_results:
76+
resp.body = json.dumps({
77+
"code": 500,
78+
"message": "Exceeded maximum number of requested accounts per request (requested {}, limit {})".format(requested_accounts, max_results)
79+
})
80+
else:
81+
# Establish session for retrieval
82+
with requests.Session() as session:
83+
# Launch async event loop for results
84+
loop = asyncio.get_event_loop()
85+
results = loop.run_until_complete(get_keys_accounts(public_keys))
86+
# Server the response
87+
resp.body = json.dumps(results)
88+
89+
# Launch falcon API
90+
app = falcon.API()
91+
app.add_route('/v1/history/get_keys_accounts', GetKeysAccounts())
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
falcon==1.4.1
2+
gunicorn==19.9.0
3+
requests==2.20.0

services/get_supported_apis/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
('/v1/chain/get_currency_balances', { 'account': 'developjesta' }, [
2626
('.', 'len')
2727
]),
28+
('/v1/history/get_keys_accounts', { 'public_keys': ['EOS81fk5ACMV4VTW9j2HGsVQaqnB7nhjCBNSpFax2Sp9PuEzf1eJQ'] }, [
29+
('account_names', 'exists')
30+
]),
2831
]
2932

3033
upstream = os.environ['UPSTREAM_API']

0 commit comments

Comments
 (0)