add eth-server

This commit is contained in:
William Luke 2021-11-02 18:50:14 +03:00
parent f28ba1098f
commit f265108485
8 changed files with 187 additions and 56 deletions

View File

@ -9,13 +9,14 @@ import logging
# external imports # external imports
import celery import celery
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from hexathon import strip_0x
# local imports # local imports
from cic_eth.api.base import ApiBase from cic_eth.api.base import ApiBase
from cic_eth.enum import LockEnum from cic_eth.enum import LockEnum
from hexathon import strip_0x
app = celery.current_app app = celery.current_app
print(app.backend)
#logg = logging.getLogger(__name__) #logg = logging.getLogger(__name__)
logg = logging.getLogger() logg = logging.getLogger()
@ -488,9 +489,9 @@ class Api(ApiBase):
s_balance_incoming.link(s_balance_outgoing) s_balance_incoming.link(s_balance_outgoing)
last_in_chain = s_balance_outgoing last_in_chain = s_balance_outgoing
one = celery.chain(s_tokens, s_balance) one = s_tokens | s_balance
two = celery.chain(s_tokens, s_balance_incoming) two = s_tokens | s_balance_incoming
three = celery.chain(s_tokens, s_balance_outgoing) three = s_tokens | s_balance_outgoing
t = None t = None
if self.callback_param != None: if self.callback_param != None:
@ -500,7 +501,7 @@ class Api(ApiBase):
t = celery.chord([one, two, three])(s_result) t = celery.chord([one, two, three])(s_result)
else: else:
# TODO: Chord is inefficient with only one chain, but assemble_balances must be able to handle different structures in order to avoid chord # TODO: Chord is inefficient with only one chain, but assemble_balances must be able to handle different structures in order to avoid chord
one = celery.chain(s_tokens, s_balance) one = s_tokens | s_balance
if self.callback_param != None: if self.callback_param != None:
s_result.link(self.callback_success).on_error(self.callback_error) s_result.link(self.callback_success).on_error(self.callback_error)
t = celery.chord([one])(s_result) t = celery.chord([one])(s_result)

View File

@ -1,11 +1,18 @@
from cic_eth.graphql.schema import schema import os
import cic_eth.cli
from cic_eth.graphql.config import config
from flask import Flask from flask import Flask
from flask_graphql import GraphQLView from flask_graphql import GraphQLView
from cic_eth.graphql.schema import schema
app = cic_eth.cli.CeleryApp.from_config(config)
app.set_default()
print(app)
def create_app(): def create_app():
app = Flask(__name__) flask_app = Flask(__name__)
app.add_url_rule(
flask_app.add_url_rule(
'/graphql', '/graphql',
view_func=GraphQLView.as_view( view_func=GraphQLView.as_view(
'graphql', 'graphql',
@ -13,12 +20,12 @@ def create_app():
graphiql=True graphiql=True
) )
) )
@app.route("/") @flask_app.route("/")
def test(): def test():
return "Test ok!" return "Test ok!"
return app return flask_app
if __name__ == "__main__": if __name__ == "__main__":
app = create_app() flask_app = create_app()
app.run(host='0.0.0.0', port=5000) flask_app.run(host='0.0.0.0', port=5000, debug=True)

View File

@ -0,0 +1,10 @@
import cic_eth.cli
arg_flags = cic_eth.cli.argflag_std_base
local_arg_flags = cic_eth.cli.argflag_local_taskcallback
argparser = cic_eth.cli.ArgumentParser(arg_flags)
argparser.process_local_flags(local_arg_flags)
args = argparser.parse_args()
config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags)

View File

@ -1,41 +1,26 @@
# standard imports # standard imports
import json import json
import logging
import sys import sys
import uuid import uuid
import celery
import cic_eth.cli
import redis import redis
from cic_eth.api.api_task import Api from cic_eth.api.api_task import Api
from cic_eth.graphql.config import config
from graphene import (Boolean, Field, Float, Int, List, Mutation, ObjectType, from graphene import (Boolean, Field, Float, Int, List, Mutation, ObjectType,
Schema, String) Schema, String)
arg_flags = cic_eth.cli.argflag_std_base
local_arg_flags = cic_eth.cli.argflag_local_taskcallback
argparser = cic_eth.cli.ArgumentParser(arg_flags)
argparser.process_local_flags(local_arg_flags)
args = argparser.parse_args()
config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags)
celery_app = celery.Celery(backend=config.get('CELERY_RESULT_URL'), broker=config.get('CELERY_BROKER_URL'))
chain_spec = config.get('CHAIN_SPEC') chain_spec = config.get('CHAIN_SPEC')
redis_host = config.get('REDIS_HOST') redis_host = config.get('REDIS_HOST')
redis_port = config.get('REDIS_PORT') redis_port = config.get('REDIS_PORT')
redis_db = config.get('REDIS_DB') redis_db = config.get('REDIS_DB')
celery_queue = config.get('CELERY_QUEUE') celery_queue = config.get('CELERY_QUEUE')
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)
def init_api(redis_channel: str):
api = Api(
chain_spec,
queue=celery_queue,
callback_param='{}:{}:{}:{}'.format(
redis_host, redis_port, redis_db, redis_channel),
callback_task='cic_eth.callbacks.redis.redis',
callback_queue=celery_queue,
)
return api
def call(method, *args): def call(method, *args):
@ -45,9 +30,15 @@ def call(method, *args):
ps.subscribe(redis_channel) ps.subscribe(redis_channel)
ps.get_message() # Subscription Object ps.get_message() # Subscription Object
print(f"Channel init {redis_channel}") print(f"Channel init {redis_channel}")
api = init_api(redis_channel)
print(args) print(args)
api = Api(
chain_spec,
queue=celery_queue,
callback_param='{}:{}:{}:{}'.format(
redis_host, redis_port, redis_db, redis_channel),
callback_task='cic_eth.callbacks.redis.redis',
callback_queue=celery_queue,
)
getattr(api, method)(*args) getattr(api, method)(*args)
ps.get_message() # returns None !? ps.get_message() # returns None !?
@ -58,6 +49,7 @@ def call(method, *args):
'got no new address from cic-eth before timeout: {}\n'.format(e)) 'got no new address from cic-eth before timeout: {}\n'.format(e))
sys.exit(1) sys.exit(1)
ps.unsubscribe() ps.unsubscribe()
print(o)
m = json.loads(o['data']) m = json.loads(o['data'])
return m["result"] return m["result"]
@ -82,12 +74,19 @@ class TokenBalance(ObjectType):
return str(int(parent.balance_network) + int(parent.balance_incoming) - int(parent.balance_outgoing)) return str(int(parent.balance_network) + int(parent.balance_incoming) - int(parent.balance_outgoing))
class Query(ObjectType): class Query(ObjectType):
default_token = Field(Token) default_token = Field(Token)
def resolve_default_token(parent, info): def resolve_default_token(parent, info):
# always pass an object for `me` field # always pass an object for `me` field
data = call('default_token') api = Api(
chain_spec,
queue=celery_queue,
)
task = api.default_token()
data = task.get()
print(data) print(data)
return Token(**data) return Token(**data)
@ -95,8 +94,14 @@ class Query(ObjectType):
token_symbol=String(), include_pending=Boolean()) token_symbol=String(), include_pending=Boolean())
def resolve_balance(root, info, address, token_symbol, include_pending=True): def resolve_balance(root, info, address, token_symbol, include_pending=True):
data = call('balance', address, token_symbol, include_pending) api = Api(
print(data) chain_spec,
queue=celery_queue,
)
task = api.balance(address=address, token_symbol=token_symbol, include_pending=include_pending)
data = task.get() #api call('balance', address, token_symbol, include_pending)
log.debug(data)
print(data, file=sys.stdout)
#[{'address': '3ff776b6f888980def9d4220858803f9dc5e341e', 'converters': [], 'balance_network': 0}] #[{'address': '3ff776b6f888980def9d4220858803f9dc5e341e', 'converters': [], 'balance_network': 0}]
return map(lambda token: TokenBalance( return map(lambda token: TokenBalance(
address=token.get("address"), address=token.get("address"),
@ -111,7 +116,13 @@ class Query(ObjectType):
required=True), limit=Int(default_value=10)) required=True), limit=Int(default_value=10))
def resolve_transactions(root, info, address, limit): def resolve_transactions(root, info, address, limit):
data = call('list', address, limit)
api = Api(
chain_spec,
queue=celery_queue,
)
task = api.list(address=address, limit=limit)
data = task.get()
print(data) print(data)
#[{'address': '3ff776b6f888980def9d4220858803f9dc5e341e', 'converters': [], 'balance_network': 0}] #[{'address': '3ff776b6f888980def9d4220858803f9dc5e341e', 'converters': [], 'balance_network': 0}]
return "test" return "test"
@ -126,8 +137,12 @@ class CreateAccount(Mutation):
def mutate(root, info, password, register=True): def mutate(root, info, password, register=True):
print(password, register) print(password, register)
api = Api(
chain_spec,
queue=celery_queue,
)
address = call('create_account', password, register) address = call('create_account',password, register)
return CreateAccount(address=f"0x{address}") return CreateAccount(address=f"0x{address}")
@ -145,10 +160,10 @@ class Transfer(Mutation):
value, value,
token_symbol): token_symbol):
print(from_address, to_address, value, token_symbol) print(from_address, to_address, value, token_symbol)
api = Api(
redis_channel = str(uuid.uuid4()) chain_spec,
queue=celery_queue,
api = init_api(redis_channel) )
t = api.transfer(from_address, to_address, t = api.transfer(from_address, to_address,
int(value * (10**6)), token_symbol) int(value * (10**6)), token_symbol)
print(f"t {t}") print(f"t {t}")
@ -172,12 +187,15 @@ class TransferFrom(Mutation):
to_address, to_address,
value, value,
token_symbol, spender_address): token_symbol, spender_address):
api = Api(
data = call('transfer_from', from_address, chain_spec,
to_address, queue=celery_queue,
value, )
token_symbol, spender_address) task = api.transfer_from(from_address=from_address,
return data to_address=to_address,
value=value,
token_symbol=token_symbol, spender_address=spender_address)
return task.get()
class MyMutations(ObjectType): class MyMutations(ObjectType):

View File

@ -8,7 +8,6 @@ from urllib.parse import parse_qsl, urlparse
import cic_eth.cli import cic_eth.cli
import redis import redis
from cic_eth.api.api_task import Api
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
@ -22,6 +21,7 @@ args = argparser.parse_args()
config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags) config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags)
celery_app = cic_eth.cli.CeleryApp.from_config(config) celery_app = cic_eth.cli.CeleryApp.from_config(config)
from cic_eth.api.api_task import Api
# uwsgi application # uwsgi application

View File

@ -2,6 +2,7 @@ celery==4.4.7
chainlib-eth>=0.0.10a16,<0.1.0 chainlib-eth>=0.0.10a16,<0.1.0
semver==2.13.0 semver==2.13.0
crypto-dev-signer>=0.4.15rc2,<0.5.0 crypto-dev-signer>=0.4.15rc2,<0.5.0
uwsgi==2.0.19.1
graphene>=2.0 graphene>=2.0
flask>=2.0.2 flask>=2.0.2
Flask-GraphQL>=2.0.1 Flask-GraphQL>=2.0.1

View File

@ -121,8 +121,6 @@ services:
# queue handling for outgoing transactions and incoming transactions # queue handling for outgoing transactions and incoming transactions
cic-eth-tasker: cic-eth-tasker:
image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}/cic-eth:${TAG:-latest} image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}/cic-eth:${TAG:-latest}
ports:
- 5000:5000
build: build:
context: apps/cic-eth context: apps/cic-eth
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
@ -170,6 +168,53 @@ services:
set +a set +a
./start_tasker.sh --aux-all -q cic-eth -vv ./start_tasker.sh --aux-all -q cic-eth -vv
cic-eth-server:
image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}/cic-eth:${TAG:-latest}
ports:
- 5000:5000
build:
context: apps/cic-eth
dockerfile: docker/Dockerfile
args:
DOCKER_REGISTRY: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}
PIP_INDEX_URL: ${PIP_INDEX_URL:-https://pypi.org/simple}
EXTRA_PIP_INDEX_URL: ${EXTRA_PIP_INDEX_URL:-https://pip.grassrootseconomics.net:8433}
EXTRA_PIP_ARGS: $EXTRA_PIP_ARGS
environment:
CIC_REGISTRY_ADDRESS: $CIC_REGISTRY_ADDRESS
RPC_PROVIDER: ${RPC_PROVIDER:-http://evm:8545}
CHAIN_SPEC: ${CHAIN_SPEC:-evm:byzantium:8996:bloxberg}
DATABASE_HOST: ${DATABASE_HOST:-postgres}
DATABASE_PORT: ${DATABASE_PORT:-5432}
DATABASE_NAME: ${DATABASE_NAME:-cic_eth}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-tralala}
DATABASE_USER: ${DATABASE_USER:-grassroots}
DATABASE_ENGINE: ${DATABASE_ENGINE:-postgres}
DATABASE_DRIVER: ${DATABASE_DRIVER:-psycopg2}
DATABASE_DEBUG: ${DATABASE_DEBUG:-0}
DATABASE_POOL_SIZE: 0
REDIS_PORT: 6379
REDIS_HOST: redis
CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis}
CELERY_RESULT_URL: ${CELERY_RESULT_URL:-redis://redis}
CELERY_DEBUG: ${CELERY_DEBUG:-1}
SIGNER_PROVIDER: ${SIGNER_PROVIDER:-http://cic-signer:8000}
SIGNER_SECRET: ${SIGNER_SECRET:-deadbeef}
TASKS_TRACE_QUEUE_STATUS: ${TASKS_TRACE_QUEUE_STATUS:-1}
restart: unless-stopped
depends_on:
- cic-eth-tasker
volumes:
- signer-data:/run/crypto-dev-signer
- contract-config:/tmp/cic/config/:ro
command:
- /bin/bash
- -c
- |
set -a
if [[ -f /tmp/cic/config/env_reset ]]; then source /tmp/cic/config/env_reset; fi
set +a
python /root/cic_eth/graphql/app.py -vv
cic-eth-tracker: cic-eth-tracker:
image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}/cic-eth:${TAG:-latest} image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics}/cic-eth:${TAG:-latest}

49
test.sh Normal file
View File

@ -0,0 +1,49 @@
# 0000
# 0001
# 0010
# 0011
# 0100
# 0101
# 0111
# 1000
# 1001
# 1010
# 1011
# 1100
# 1101
# 1111
RUN_MASK=31
LAST_BIT_POS=5
RUN_MASK_HIGHEST=0
for ((i=$LAST_BIT_POS; i>0; i--)); do
b=$((2**$((i-1))))
if [ $((b & $RUN_MASK)) -gt 0 ]; then
RUN_MASK_HIGHEST=$i
break
fi
done
echo $RUN_MASK_HIGHEST
bit=1
for ((i=0; i<$LAST_BIT_POS; i++)); do
runlevel="RUNLEVEL $bit"
if [[ $((RUN_MASK & $bit)) -eq ${bit} ]]; then
s="$runlevel - ${description[$i]}"
>&2 echo -e "\033[;96mRUNNING $s\033[;39m"
# source $((i+1))_${files[$i]}.sh
if [ $? -ne "0" ]; then
>&2 echo -e "\033[;31mFAILED $s\033[;39m"
exit 1;
fi
>&2 echo -e "\033[;32mSUCCEEDED $s\033[;39m"
>&2 echo -e "\033[;96mConfiguration state after $runlevel execution\033[;39m"
# confini-dump --schema-dir ./config
fi
bit=$((bit*2))
done