diff --git a/duniterpy/api/bma/api.py b/duniterpy/api/bma/api.py index 808b0f1d37cf1cd36ba437d6440c0d49e4b82b8e..c23c59149142d75c080bf31a2474eaf1a5fd459f 100644 --- a/duniterpy/api/bma/api.py +++ b/duniterpy/api/bma/api.py @@ -18,8 +18,10 @@ # Inso <insomniak.fr at gmail.com> -import aiohttp, json, logging, jsonschema -import warnings +import aiohttp +import json +import logging +import jsonschema from ..errors import DuniterError logger = logging.getLogger("duniter") @@ -140,7 +142,8 @@ class API(object): """ Requests GET wrapper in order to use API parameters. - :params str path: the request path + :param str path: the request path + :rtype: aiohttp.ClientResponse """ logging.debug("Request : {0}".format(self.reverse_url("http", path))) with aiohttp.Timeout(15): @@ -159,6 +162,7 @@ class API(object): Requests POST wrapper in order to use API parameters. :param str path: the request path + :rtype: aiohttp.ClientResponse """ if 'self_' in kwargs: kwargs['self'] = kwargs.pop('self_') @@ -172,13 +176,12 @@ class API(object): ) return response - def connect_ws(self, session, path): + def connect_ws(self, path): """ Connect to a websocket in order to use API parameters - :param aiohttp.ClientSession session: the session of the connection :param str path: the url path - :return: + :rtype: aiohttp.ClientWebSocketResponse """ url = self.reverse_url("ws", path) - return session.ws_connect(url) + return self.connection_handler.session.ws_connect(url) diff --git a/duniterpy/api/bma/blockchain.py b/duniterpy/api/bma/blockchain.py index b0f1c2423a873f6a82d81b470df285abf5d5bc5a..3257f9c94620d1709a03a80aa0b54b89c7169b77 100644 --- a/duniterpy/api/bma/blockchain.py +++ b/duniterpy/api/bma/blockchain.py @@ -177,8 +177,8 @@ async def parameters(connection): """ GET the blockchain parameters used by this node - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ schema = { "type": "object", @@ -245,12 +245,13 @@ async def parameters(connection): r = await client.requests_get('/parameters') return await client.parse_response(r, schema) -async def membership(connection, **kwargs): +async def memberships(connection, search): """ - GET/POST a Membership document + GET list of Membership documents for UID/Public key - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str search: UID/Public key + :rtype: dict """ schema = { "type": "object", @@ -292,31 +293,38 @@ async def membership(connection, **kwargs): }, "required": ["pubkey", "uid", "sigDate", "memberships"] } - client = API(connection, URL_PATH) - if 'membership' in kwargs: - r = await client.requests_post('/membership') - else: - r = await client.requests_get('/memberships/%s' % kwargs[0]) + r = await client.requests_get('/memberships/%s' % search) return await client.parse_response(r, schema) +async def membership(connection, membership): + """ + POST a Membership document + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str membership: Membership signed raw document + :rtype: dict + """ + client = API(connection, URL_PATH) + + return await client.requests_post('/membership', membership=membership) + async def block(connection, number=0, block=None, signature=None): """ GET/POST a block from/to the blockchain - :param API.ConnectionHandler connection: Connection handler instance + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance :param int number: Block number to get :param dict block: Block document to post :param str signature: Signature of the block document issuer - :return: dict + :rtype: dict """ client = API(connection, URL_PATH) # POST block if block is not None and signature is not None: - r = await client.requests_post('/block', block=block, signature=signature) - return r + return await client.requests_post('/block', block=block, signature=signature) # GET block r = await client.requests_get('/block/%d' % number) @@ -326,8 +334,8 @@ async def current(connection): """ GET, return last accepted block - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -340,10 +348,10 @@ async def blocks(connection, count, start): """ GET list of blocks from the blockchain - :param API.ConnectionHandler connection: Connection handler instance + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance :param int count: Number of blocks :param int start: First block number - :return: list + :rtype: list """ schema = { @@ -361,9 +369,9 @@ async def hardship(connection, pubkey): """ GET hardship level for given member's public key for writing next block - :param API.ConnectionHandler connection: Connection handler instance + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance :param str pubkey: Public key of the member - :return: dict + :rtype: dict """ schema = { "type": "object", @@ -386,8 +394,8 @@ async def newcomers(connection): """ GET, return block numbers containing newcomers - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -398,8 +406,8 @@ async def certifications(connection): """ GET, return block numbers containing certifications - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -410,8 +418,8 @@ async def joiners(connection): """ GET, return block numbers containing joiners - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -422,8 +430,8 @@ async def actives(connection): """ GET, return block numbers containing actives - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -434,8 +442,8 @@ async def leavers(connection): """ GET, return block numbers containing leavers - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -446,8 +454,8 @@ async def excluded(connection): """ GET, return block numbers containing excluded - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) @@ -458,8 +466,8 @@ async def ud(connection): """ GET, return block numbers containing universal dividend - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) r = await client.requests_get('/with/ud') @@ -469,8 +477,8 @@ async def tx(connection): """ GET, return block numbers containing transactions - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ client = API(connection, URL_PATH) diff --git a/duniterpy/api/bma/network.py b/duniterpy/api/bma/network.py new file mode 100644 index 0000000000000000000000000000000000000000..3dee7d6aa175661165bf0fe03e94f419de7e6066 --- /dev/null +++ b/duniterpy/api/bma/network.py @@ -0,0 +1,149 @@ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Authors: +# Caner Candan <caner@candan.fr>, http://caner.candan.fr +# + +from duniterpy.api.bma import API, logging + +logger = logging.getLogger("duniter/network") + +URL_PATH = 'network' + +async def peering(connection): + """ + GET peering information about a peer + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict + """ + schema = { + "type": "object", + "properties": { + "version": { + "type": ["number", "string"] + }, + "currency": { + "type": "string" + }, + "pubkey": { + "type": "string" + }, + "endpoints": { + "type": "array", + "items": { + "type": "string" + } + }, + "signature": { + "type": "string" + } + }, + "required": ["version", "currency", "pubkey", "endpoints", "signature"] + } + + client = API(connection, URL_PATH) + r = await client.requests_get('/peering') + return await client.parse_response(r, schema) + +async def peers(connection, entry=None, signature=None): + """ + GET peering entries of every node inside the currency network + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param duniterpy.documents.peer.Peer entry: Peer document + :param str signature: Signature of the document issuer + :rtype: dict + """ + schema = { + "type": ["object"], + "properties": { + "depth": { + "type": "number" + }, + "nodesCount": { + "type": "number" + }, + "leavesCount": { + "type": "number" + }, + "root": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "value": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "pubkey": { + "type": "string" + }, + "endpoints": { + "type": "array", + "items": { + "type": "string" + } + }, + "signature": { + "type": "string" + } + }, + "required": ["version", "currency", "pubkey", "endpoints", "signature"] + } + }, + "oneOf": [ + { + "required": ["depth", "nodesCount", "leavesCount", "root"] + }, + { + "required": ["hash", "value"] + } + ] + } + + client = API(connection, URL_PATH) + # POST Peer + if entry is not None and signature is not None: + r = await client.requests_post('/peering/peers', entry=entry, signature=signature) + return r + + # GET Peers + r = await client.requests_get('/peering/peers') + return await client.parse_response(r, schema) + +# async def status(connection): +# """ +# NOT DOCUMENTED IN BMA API DOCUMENTATION +# POST a network status document to this node in order notify of its status +# +# :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance +# :param duniterpy.documents.peer.Peer entry: Peer document +# :param str signature: Signature of the document issuer +# :rtype: dict +# """ +# +# async def __post__(self, session, **kwargs): +# assert 'status' in kwargs +# assert 'signature' in kwargs +# +# r = await self.requests_post(session, '/status', **kwargs) +# return r diff --git a/duniterpy/api/bma/network/__init__.py b/duniterpy/api/bma/network/__init__.py deleted file mode 100644 index d9cef75a4f8e07ca7e94f20aab8266bb34137c9f..0000000000000000000000000000000000000000 --- a/duniterpy/api/bma/network/__init__.py +++ /dev/null @@ -1,60 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("duniter/network") - - -class Network(API): - def __init__(self, connection_handler, module='network'): - super(Network, self).__init__(connection_handler, module) - - -class Peering(Network): - """GET peering information about a peer.""" - schema = { - "type": "object", - "properties": { - "version": { - "type": ["number", "string"] - }, - "currency": { - "type": "string" - }, - "pubkey": { - "type": "string" - }, - "endpoints": { - "type": "array", - "items": { - "type": "string" - } - }, - "signature": { - "type": "string" - } - }, - "required": ["version", "currency", "pubkey", "endpoints", "signature"] - } - - async def __get__(self, session, **kwargs): - r = await self.requests_get(session, '/peering', **kwargs) - return (await self.parse_response(r)) - -from . import peering diff --git a/duniterpy/api/bma/network/peering.py b/duniterpy/api/bma/network/peering.py deleted file mode 100644 index c860d6923fd45579bb7ee7ada5cb2db1a039044b..0000000000000000000000000000000000000000 --- a/duniterpy/api/bma/network/peering.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from duniterpy.api.bma.network import Network, logging - -logger = logging.getLogger("duniter/network/peering") - - -class Base(Network): - def __init__(self, connection_handler): - super(Base, self).__init__(connection_handler, 'network/peering') - - -class Peers(Base): - """GET peering entries of every node inside the currency network.""" - schema = { - "type": ["object"], - "properties": { - "depth": { - "type": "number" - }, - "nodesCount": { - "type": "number" - }, - "leavesCount": { - "type": "number" - }, - "root": { - "type": "string" - }, - "hash": { - "type": "string" - }, - "value": { - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "currency": { - "type": "string" - }, - "pubkey": { - "type": "string" - }, - "endpoints": { - "type": "array", - "items": { - "type": "string" - } - }, - "signature": { - "type": "string" - } - }, - "required": ["version", "currency", "pubkey", "endpoints", "signature"] - } - }, - "oneOf": [ - { - "required": ["depth", "nodesCount", "leavesCount", "root"] - }, - { - "required": ["hash", "value"] - } - ] - } - - async def __get__(self, session, **kwargs): - """creates a generator with one peering entry per iteration.""" - - r = await self.requests_get(session, '/peers', **kwargs) - return (await self.parse_response(r)) - - async def __post__(self, session, **kwargs): - assert 'entry' in kwargs - assert 'signature' in kwargs - - r = await self.requests_post(session, '/peers', **kwargs) - return r - - -class Status(Base): - """POST a network status document to this node in order notify of its status.""" - - async def __post__(self, session, **kwargs): - assert 'status' in kwargs - assert 'signature' in kwargs - - r = await self.requests_post(session, '/status', **kwargs) - return r diff --git a/duniterpy/api/bma/node.py b/duniterpy/api/bma/node.py index c3589921d485fb824eb65c4b784517bac4f6866e..cd48e1b1e5ecc18374bc30510651c82fa9b17c62 100644 --- a/duniterpy/api/bma/node.py +++ b/duniterpy/api/bma/node.py @@ -26,8 +26,8 @@ async def summary(connection): """ GET Certification data over a member - :param API.ConnectionHandler connection: Connection handler instance - :return: dict + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict """ schema = { "type": "object", @@ -51,5 +51,6 @@ async def summary(connection): "required": ["duniter"] } client = API(connection, URL_PATH) + r = await client.requests_get('/summary') return await client.parse_response(r, schema) diff --git a/duniterpy/api/bma/tx.py b/duniterpy/api/bma/tx.py new file mode 100644 index 0000000000000000000000000000000000000000..339872e02759e83100ee359b5e482d41f31760df --- /dev/null +++ b/duniterpy/api/bma/tx.py @@ -0,0 +1,267 @@ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Authors: +# Caner Candan <caner@candan.fr>, http://caner.candan.fr +# + +from duniterpy.api.bma import API, logging + +logger = logging.getLogger("duniter/tx") + +URL_PATH = 'tx' + +HISTORY_SCHEMA = { + "type": "object", + "properties": { + "currency": { + "type": "string" + }, + "pubkey": { + "type": "string" + }, + "history": { + "type": "object", + "properties": { + "sent": { + "$ref": "#/definitions/transaction_data" + }, + "received": { + "$ref": "#/definitions/transaction_data" + }, + "sending": { + "$ref": "#/definitions/transactioning_data" + }, + "receiving": { + "$ref": "#/definitions/transactioning_data" + }, + }, + "required": ["sent", "received", "sending", "receiving"] + } + }, + "definitions": { + "transaction_data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "type": "number" + }, + "issuers": { + "type": "array", + "items": { + "type": "string" + } + }, + "inputs": { + "type": "array", + "items": { + "type": "string" + } + }, + "outputs": { + "type": "array", + "items": { + "type": "string" + } + }, + "unlocks": { + "type": "array", + "items": { + "type": "string" + } + }, + "comment": { + "type": "string" + }, + "signatures": { + "type": "array", + "items": { + "type": "string" + } + }, + "hash": { + "type": "string" + }, + "block_number": { + "type": "number" + }, + "time": { + "type": "number" + } + }, + "required": ["version", "issuers", "inputs", "outputs", + "comment", "signatures", "hash", "block_number", "time"] + } + }, + "transactioning_data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "type": "number" + }, + "issuers": { + "type": "array", + "items": { + "type": "string" + } + }, + "inputs": { + "type": "array", + "items": { + "type": "string" + } + }, + "outputs": { + "type": "array", + "items": { + "type": "string" + } + }, + "unlocks": { + "type": "array", + "items": { + "type": "string" + } + }, + "comment": { + "type": "string" + }, + "signatures": { + "type": "array", + "items": { + "type": "string" + } + }, + "hash": { + "type": "string" + }, + }, + "required": ["version", "issuers", "inputs", "outputs", + "comment", "signatures", "hash"] + } + } + }, + "required": ["currency", "pubkey", "history"] +} + +async def history(connection, pubkey): + """ + Get transactions history of public key + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str pubkey: Public key + :rtype: dict + """ + + client = API(connection, URL_PATH) + + r = await client.requests_get( '/history/%s' % pubkey) + return await client.parse_response(r, HISTORY_SCHEMA) + +async def process(connection, transaction): + """ + POST a transaction + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param duniterpy.documents.Transaction transaction: Transaction document + :rtype: aiohttp.ClientResponse + """ + client = API(connection, URL_PATH) + + r = await client.requests_post('/process', transaction=transaction) + return r + + +async def sources(connection, pubkey): + """ + GET transaction sources + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str pubkey: Public key + :rtype: dict + """ + schema = { + "type": "object", + "properties": { + "currency": { + "type": "string" + }, + "pubkey": { + "type": "string" + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "noffset": { + "type": "number" + }, + "identifier": { + "type": "string" + }, + "amount": { + "type": "number" + }, + "base": { + "type": "number" + } + }, + "required": ["type", "noffset", "identifier", "amount", "base"] + } + } + }, + "required": ["currency", "pubkey", "sources"] + } + client = API(connection, URL_PATH) + + r = await client.requests_get( '/sources/%s' % pubkey) + return await client.parse_response(r, schema) + +async def blocks(connection, pubkey, start, end): + """ + GET public key transactions history between start and end block number + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str pubkey: Public key + :param int start: Start from block number + :param int end: End to block number + :return: dict + """ + client = API(connection, URL_PATH) + + r = await client.requests_get('/history/%s/blocks/%s/%s' % (pubkey, start, end)) + return await client.parse_response(r, HISTORY_SCHEMA) + +async def times(connection, pubkey, start, end): + """ + GET public key transactions history between start and end timestamp + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str pubkey: Public key + :param int start: Start from timestamp + :param int end: End to timestamp + :return: dict + """ + client = API(connection, URL_PATH) + + r = await client.requests_get('/history/%s/times/%s/%s' % (pubkey, start, end)) + return await client.parse_response(r, HISTORY_SCHEMA) diff --git a/duniterpy/api/bma/tx/__init__.py b/duniterpy/api/bma/tx/__init__.py deleted file mode 100644 index 91bf2d048ecf71843bf991fc8f8a8dad9704804a..0000000000000000000000000000000000000000 --- a/duniterpy/api/bma/tx/__init__.py +++ /dev/null @@ -1,237 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("duniter/tx") - - -class Tx(API): - def __init__(self, connection_handler, module='tx'): - super(Tx, self).__init__(connection_handler, module) - - -class History(Tx): - """Get transaction sources.""" - schema = { - "type": "object", - "properties": { - "currency": { - "type": "string" - }, - "pubkey": { - "type": "string" - }, - "history": { - "type": "object", - "properties": { - "sent": { - "$ref": "#/definitions/transaction_data" - }, - "received": { - "$ref": "#/definitions/transaction_data" - }, - "sending": { - "$ref": "#/definitions/transactioning_data" - }, - "receiving": { - "$ref": "#/definitions/transactioning_data" - }, - }, - "required": ["sent", "received", "sending", "receiving"] - } - }, - "definitions": { - "transaction_data": { - "type": "array", - "items": { - "type": "object", - "properties": { - "version": { - "type": "number" - }, - "issuers": { - "type": "array", - "items": { - "type": "string" - } - }, - "inputs": { - "type": "array", - "items": { - "type": "string" - } - }, - "outputs": { - "type": "array", - "items": { - "type": "string" - } - }, - "unlocks": { - "type": "array", - "items": { - "type": "string" - } - }, - "comment": { - "type": "string" - }, - "signatures": { - "type": "array", - "items": { - "type": "string" - } - }, - "hash": { - "type": "string" - }, - "block_number": { - "type": "number" - }, - "time": { - "type": "number" - } - }, - "required": ["version", "issuers", "inputs", "outputs", - "comment", "signatures", "hash", "block_number", "time"] - } - }, - "transactioning_data": { - "type": "array", - "items": { - "type": "object", - "properties": { - "version": { - "type": "number" - }, - "issuers": { - "type": "array", - "items": { - "type": "string" - } - }, - "inputs": { - "type": "array", - "items": { - "type": "string" - } - }, - "outputs": { - "type": "array", - "items": { - "type": "string" - } - }, - "unlocks": { - "type": "array", - "items": { - "type": "string" - } - }, - "comment": { - "type": "string" - }, - "signatures": { - "type": "array", - "items": { - "type": "string" - } - }, - "hash": { - "type": "string" - }, - }, - "required": ["version", "issuers", "inputs", "outputs", - "comment", "signatures", "hash"] - } - } - }, - "required": ["currency", "pubkey", "history"] - } - - def __init__(self, conn_handler, pubkey, module='tx'): - super(Tx, self).__init__(conn_handler, module) - self.pubkey = pubkey - - async def __get__(self, session, **kwargs): - assert self.pubkey is not None - r = await self.requests_get(session, '/history/%s' % self.pubkey, **kwargs) - return await self.parse_response(r) - - -class Process(Tx): - """POST a transaction.""" - - async def __post__(self, session, **kwargs): - assert 'transaction' in kwargs - - r = await self.requests_post(session, '/process', **kwargs) - return r - - -class Sources(Tx): - """Get transaction sources.""" - schema = { - "type": "object", - "properties": { - "currency": { - "type": "string" - }, - "pubkey": { - "type": "string" - }, - "sources": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "noffset": { - "type": "number" - }, - "identifier": { - "type": "string" - }, - "amount": { - "type": "number" - }, - "base": { - "type": "number" - } - }, - "required": ["type", "noffset", "identifier", "amount", "base"] - } - } - }, - "required": ["currency", "pubkey", "sources"] - } - - def __init__(self, connection_handler, pubkey, module='tx'): - super(Tx, self).__init__(connection_handler, module) - self.pubkey = pubkey - - async def __get__(self, session, **kwargs): - assert self.pubkey is not None - r = await self.requests_get(session, '/sources/%s' % self.pubkey, **kwargs) - return await self.parse_response(r) - - -from . import history diff --git a/duniterpy/api/bma/tx/history.py b/duniterpy/api/bma/tx/history.py deleted file mode 100644 index 9fac472491a3f0ec510327ad46cf1ec3f1d8f8b3..0000000000000000000000000000000000000000 --- a/duniterpy/api/bma/tx/history.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from duniterpy.api.bma.tx import History, logging - -logger = logging.getLogger("duniter/tx") - - -class Blocks(History): - - schema = History.schema - - def __init__(self, conn_handler, pubkey, from_, to_, module='tx'): - super(Blocks, self).__init__(conn_handler, pubkey, module) - self.from_ = from_ - self.to_ = to_ - - async def __get__(self, session, **kwargs): - r = await self.requests_get(session, '/history/%s/blocks/%s/%s' % (self.pubkey, self.from_, self.to_), **kwargs) - return await self.parse_response(r) \ No newline at end of file diff --git a/duniterpy/api/bma/ud.py b/duniterpy/api/bma/ud.py index d0baacddabe018a82da7be06ecf97f0be218c328..3b08c222728a9e6deb0829f0452a34f8126dc9f9 100644 --- a/duniterpy/api/bma/ud.py +++ b/duniterpy/api/bma/ud.py @@ -16,24 +16,64 @@ # Caner Candan <caner@candan.fr>, http://caner.candan.fr # -from duniterpy.api.bma import API, logging +from duniterpy.api.bma import logging, API logger = logging.getLogger("duniter/ud") +URL_PATH = 'ud' -class Ud(API): - def __init__(self, conn_handler, module='ud'): - super(Ud, self).__init__(conn_handler, module) +async def history(connection, pubkey): + """ + Get UD history of a member account + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str pubkey: Public key of the member -class History(Ud): - """Get UD history.""" + :rtype: dict + """ + schema = { + "type": "object", + "properties": { + "currency": { + "type": "string" + }, + "pubkey": { + "type": "string" + }, + "history": { + "type": "object", + "properties": { + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "block_number": { + "type": "number" + }, - def __init__(self, conn_handler, pubkey, module='ud'): - super(Ud, self).__init__(conn_handler, module) - self.pubkey = pubkey + "consumed": { + "type": "boolean" + }, + "time": { + "type": "number" + }, + "amount": { + "type": "number" + }, + "base": { + "type": "number" + }, + } + } + } + } + } + }, + "required": ["currency", "pubkey", "history"] + } - async def __get__(self, session, **kwargs): - assert self.pubkey is not None - r = await self.requests_get(session, '/history/%s' % self.pubkey, **kwargs) - return await r.json() + client = API(connection, URL_PATH) + + r = await client.requests_get('/history/%s' % pubkey) + return await client.parse_response(r, schema) diff --git a/duniterpy/api/bma/wot.py b/duniterpy/api/bma/wot.py index a96e6dfef4c4203382ac29eb8649f169e82e982c..e57d2198676e7c77021bbf5ff44b850064f40a4a 100644 --- a/duniterpy/api/bma/wot.py +++ b/duniterpy/api/bma/wot.py @@ -15,49 +15,59 @@ # Authors: # Caner Candan <caner@candan.fr>, http://caner.candan.fr # - from duniterpy.api.bma import API, logging logger = logging.getLogger("duniter/wot") +URL_PATH = 'wot' -class WOT(API): - def __init__(self, connection_handler, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - -class Add(WOT): - """POST Identity data.""" - - async def __post__(self, session, **kwargs): - assert 'identity' in kwargs - - r = await self.requests_post(session, '/add', **kwargs) - return r +async def add(connection, identity): + """ + POST identity document + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param duniterpy.documents.certification.Identity identity: Identity document + :rtype: aiohttp.ClientResponse + """ + client = API(connection, URL_PATH) -class Certify(WOT): - """POST Certification data.""" + r = await client.requests_post('/add', identity=identity) + return r - async def __post__(self, session, **kwargs): - assert 'cert' in kwargs +async def certify(connection, certification): + """ + POST certification document - r = await self.requests_post(session, '/certify', **kwargs) - return r + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param duniterpy.documents.certification.Certification certification: Certification document + :rtype: aiohttp.ClientResponse + """ + client = API(connection, URL_PATH) + r = await client.requests_post('/certify', cert=certification) + return r -class Revoke(WOT): - """POST Public key data.""" +async def revoke(connection, revocation): + """ + POST revocation document - async def __post__(self, session, **kwargs): - assert 'revocation' in kwargs + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param duniterpy.documents.certification.Revocation revocation: Certification document + :rtype: aiohttp.ClientResponse + """ + client = API(connection, URL_PATH) - r = await self.requests_post(session, '/revoke', **kwargs) - return r + r = await client.requests_post('/revoke', revocation=revocation) + return r +async def lookup(connection, search): + """ + GET UID/Public key data -class Lookup(WOT): - """GET Public key data.""" + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str search: UID or public key + :rtype: dict + """ schema = { "type": "object", "definitions": { @@ -158,127 +168,121 @@ class Lookup(WOT): "required": ["partial", "results"] } - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search + client = API(connection, URL_PATH) - async def __get__(self, session, **kwargs): - assert self.search is not None + r = await client.requests_get('/lookup/%s' % search) + return await client.parse_response(r, schema) - r = await self.requests_get(session, '/lookup/%s' % self.search, **kwargs) - return await self.parse_response(r) - -class CertifiersOf(WOT): - """GET Certification data over a member.""" - - schema = { - "type": "object", - "properties": { - "pubkey": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "isMember": { - "type": "boolean" - }, - "certifications": { - "type": "array", - "items": { - "type": "object", - "properties": { - "pubkey": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "cert_time": { - "type": "object", - "properties": { - "block": { - "type": "number" - }, - "medianTime": { - "type": "number" - } +CERTIFICATIONS_SCHEMA = { + "type": "object", + "properties": { + "pubkey": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "isMember": { + "type": "boolean" + }, + "certifications": { + "type": "array", + "items": { + "type": "object", + "properties": { + "pubkey": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "cert_time": { + "type": "object", + "properties": { + "block": { + "type": "number" }, - "required": ["block", "medianTime"] - }, - "sigDate": { - "type": "string" + "medianTime": { + "type": "number" + } }, - "written": { - "oneOf": [ - { - "type": "object", - "properties": { - "number": { - "type": "number", - }, - "hash": { - "type": "string" - } + "required": ["block", "medianTime"] + }, + "sigDate": { + "type": "string" + }, + "written": { + "oneOf": [ + { + "type": "object", + "properties": { + "number": { + "type": "number", }, - "required": ["number", "hash"] + "hash": { + "type": "string" + } }, - { - "type": "null" - } - ] - }, - "isMember": { - "type": "boolean" - }, - "wasMember": { - "type": "boolean" - }, - "signature": { - "type": "string" - } + "required": ["number", "hash"] + }, + { + "type": "null" + } + ] }, - "required": ["pubkey", "uid", "cert_time", "sigDate", - "written", "wasMember", "isMember", "signature"] - } + "isMember": { + "type": "boolean" + }, + "wasMember": { + "type": "boolean" + }, + "signature": { + "type": "string" + } + }, + "required": ["pubkey", "uid", "cert_time", "sigDate", + "written", "wasMember", "isMember", "signature"] } - }, - "required": ["pubkey", "uid", "isMember", "certifications"] - } - - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search - - async def __get__(self, session, **kwargs): - assert self.search is not None - - r = await self.requests_get(session, '/certifiers-of/%s' % self.search, **kwargs) - return await self.parse_response(r) + } + }, + "required": ["pubkey", "uid", "isMember", "certifications"] +} +async def certifiers_of(connection, search): + """ + GET UID/Public key certifiers -class CertifiedBy(WOT): - """GET Certification data from a member.""" + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str search: UID or public key + :rtype: dict + """ - schema = CertifiersOf.schema + client = API(connection, URL_PATH) - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) + r = await client.requests_get('/certifiers-of/%s' % search) + return await client.parse_response(r, CERTIFICATIONS_SCHEMA) - self.search = search +async def certified_by(connection, search): + """ + GET identities certified by UID/Public key - async def __get__(self, session, **kwargs): - assert self.search is not None + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str search: UID or public key + :rtype: dict + """ + client = API(connection, URL_PATH) - r = await self.requests_get(session, '/certified-by/%s' % self.search, **kwargs) - return await self.parse_response(r) + r = await client.requests_get('/certified-by/%s' % search) + return await client.parse_response(r, CERTIFICATIONS_SCHEMA) +async def members(connection): + """ + GET list of all current members of the Web of Trust -class Members(WOT): - """GET List all current members of the Web of Trust.""" + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: dict + """ schema = { "type": "object", "properties": { @@ -298,17 +302,19 @@ class Members(WOT): "required": ["results"] } - def __init__(self, connection_handler, module='wot'): - super(WOT, self).__init__(connection_handler, module) + client = API(connection, URL_PATH) - async def __get__(self, session, **kwargs): - r = await self.requests_get(session, '/members', **kwargs) - return await self.parse_response(r) + r = await client.requests_get('/members') + return await client.parse_response(r, schema) -class Requirements(WOT): +async def requirements(connection, search): """ - Get list of requirements for a given pubkey + GET list of requirements for a given UID/Public key + + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :param str search: UID or public key + :rtype: dict """ schema = { "type": "object", @@ -364,13 +370,7 @@ class Requirements(WOT): } } - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search - - async def __get__(self, session, **kwargs): - assert self.search is not None + client = API(connection, URL_PATH) - r = await self.requests_get(session, '/requirements/%s' % self.search, **kwargs) - return await self.parse_response(r) + r = await client.requests_get('/requirements/%s' % search) + return await client.parse_response(r, schema) diff --git a/duniterpy/api/bma/ws.py b/duniterpy/api/bma/ws.py index 535b7c6611c5a7e49648b464f525331f0cfc1fcd..e9ae237181ab509078a64ee4a6f261384b5d3757 100644 --- a/duniterpy/api/bma/ws.py +++ b/duniterpy/api/bma/ws.py @@ -21,23 +21,28 @@ from duniterpy.api.bma.blockchain import BLOCK_SCHEMA logger = logging.getLogger("duniter/ws") +URL_PATH = 'ws' -class Websocket(API): - def __init__(self, connection_handler, module='ws'): - super(Websocket, self).__init__(connection_handler, module) +def block(connection): + """ + Connect to block websocket -class Block(Websocket): - """Connect to block websocket.""" + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: aiohttp.ClientWebSocketResponse + """ schema = BLOCK_SCHEMA + client = API(connection, URL_PATH) + return client.connect_ws('/block') - def connect(self, session): - r = self.connect_ws(session, '/block') - return r +def peer(connection): + """ + Connect to peer websocket -class Peer(Websocket): - """Connect to block websocket.""" + :param duniterpy.api.bma.ConnectionHandler connection: Connection handler instance + :rtype: aiohttp.ClientWebSocketResponse + """ schema = { "type": "object", "properties": { @@ -62,7 +67,5 @@ class Peer(Websocket): }, "required": ["version", "currency", "pubkey", "endpoints", "signature"] } - - def connect(self, session): - r = self.connect_ws(session, '/peer') - return r + client = API(connection, URL_PATH) + return client.connect_ws('/peer') diff --git a/duniterpy/documents/__init__.py b/duniterpy/documents/__init__.py index 44cfdc7b90dbe76fbb9c064a5615c916614b1733..66b1e3a919f109d1d4268ea8a8270ebb871cc1ca 100644 --- a/duniterpy/documents/__init__.py +++ b/duniterpy/documents/__init__.py @@ -1,8 +1,8 @@ from .block import Block, BlockUID, block_uid -from .certification import SelfCertification, Certification, Revocation +from .certification import Identity, Certification, Revocation from .membership import Membership from .peer import endpoint, BMAEndpoint, UnknownEndpoint, Peer from .transaction import SimpleTransaction, Transaction from .document import Document, MalformedDocumentError -from . import constants \ No newline at end of file +from . import constants diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py index a02640bf6a26c7a628eccabd915b768c233b69b7..8b300a0f450d0cefd34d6be6f3f6b0fb01312670 100644 --- a/duniterpy/documents/block.py +++ b/duniterpy/documents/block.py @@ -1,5 +1,5 @@ from .document import Document, MalformedDocumentError -from .certification import SelfCertification, Certification, Revocation +from .certification import Identity, Certification, Revocation from .membership import Membership from .transaction import Transaction from .constants import pubkey_regex, block_id_regex, block_hash_regex @@ -207,7 +207,7 @@ The class Block handles Block documents. :param str prev_issuer: the previous block issuer :param tuple parameters: the parameters of the currency. Should only be present in block 0. :param int members_count: the number of members found in this block - :param list[duniterpy.documents.SelfCertification] identities: the self certifications declared in this block + :param list[duniterpy.documents.Identity] identities: the self certifications declared in this block :param list[duniterpy.documents.Membership] joiners: the joiners memberships via "IN" documents :param list[duniterpy.documents.Membership] actives: renewed memberships via "IN" documents :param list[duniterpy.documents.Membership] leavers: the leavers memberships via "OUT" documents @@ -256,7 +256,7 @@ The class Block handles Block documents. @property def blockUID(self): return BlockUID(self.number, self.sha_hash) - + @classmethod def from_signed_raw(cls, signed_raw): lines = signed_raw.splitlines(True) @@ -340,7 +340,7 @@ The class Block handles Block documents. if Block.re_identities.match(lines[n]) is not None: n += 1 while Block.re_joiners.match(lines[n]) is None: - selfcert = SelfCertification.from_inline(version, currency, lines[n]) + selfcert = Identity.from_inline(version, currency, lines[n]) identities.append(selfcert) n += 1 @@ -501,4 +501,4 @@ PreviousIssuer: {1}\n".format(self.prev_hash, self.prev_issuer) doc += "Nonce: {0}\n".format(self.noonce) - return doc \ No newline at end of file + return doc diff --git a/duniterpy/documents/certification.py b/duniterpy/documents/certification.py index d3b9ebf5e1212c0e6b4e7359e33a596c2ad4f304..79516eb3f8e6393f64be84f5d0fcefec0603254f 100644 --- a/duniterpy/documents/certification.py +++ b/duniterpy/documents/certification.py @@ -6,7 +6,7 @@ from .document import Document, MalformedDocumentError from .constants import pubkey_regex, signature_regex, block_id_regex, block_uid_regex -class SelfCertification(Document): +class Identity(Document): """ A document describing a self certification. """ @@ -41,7 +41,7 @@ class SelfCertification(Document): def from_inline(cls, version, currency, inline): from .block import BlockUID - selfcert_data = SelfCertification.re_inline.match(inline) + selfcert_data = Identity.re_inline.match(inline) if selfcert_data is None: raise MalformedDocumentError("Inline self certification") pubkey = selfcert_data.group(1) @@ -130,7 +130,7 @@ class Certification(Document): def raw(self, selfcert): """ - :param SelfCertification selfcert: + :param Identity selfcert: :return: """ return """Version: {version} @@ -273,7 +273,7 @@ class Revocation(Document): signature = Revocation.parse_field("IdtySignature", lines[n]) n += 1 - return SelfCertification(version, currency, issuer, unique_id, timestamp, signature) + return Identity(version, currency, issuer, unique_id, timestamp, signature) def inline(self): return "{0}:{1}".format(self.pubkey, self.signatures[0]) @@ -281,7 +281,7 @@ class Revocation(Document): def raw(self, selfcert): """ - :param SelfCertification selfcert: + :param Identity selfcert: :return: """ return """Version: {version} diff --git a/duniterpy/documents/peer.py b/duniterpy/documents/peer.py index 595bdf35bc049f4810a971318d4f1accc3b65170..131b033ae5cc425cb68840d226490fa228f72657 100644 --- a/duniterpy/documents/peer.py +++ b/duniterpy/documents/peer.py @@ -179,6 +179,12 @@ class BMAEndpoint(Endpoint): PORT=(" {0}".format(self.port) if self.port else "")) def conn_handler(self, session=None): + """ + Return connection handler instance for the endpoint + + :param aiohttp.ClientSession session: AIOHTTP client session instance + :rtype: ConnectionHandler + """ if self.server: return ConnectionHandler(self.server, self.port, session) elif self.ipv4: diff --git a/examples/create_and_publish_identity.py b/examples/create_and_publish_identity.py index 2bd1fae18aead9d9033a36cf695a7f54589272aa..c783766744625dc5f39eb9c539c128e4aefe72ef 100644 --- a/examples/create_and_publish_identity.py +++ b/examples/create_and_publish_identity.py @@ -2,7 +2,7 @@ import asyncio import aiohttp import duniterpy.api.bma as bma -from duniterpy.documents import BMAEndpoint, BlockUID, SelfCertification +from duniterpy.documents import BMAEndpoint, BlockUID, Identity from duniterpy.key import SigningKey @@ -27,17 +27,6 @@ UID = "MyIdentity" # ( http://pythonhosted.org/aiohttp ) AIOHTTP_SESSION = aiohttp.ClientSession() -async def get_current_block(connection): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - - :rtype: dict - """ - # Here we request for the path blockchain/block/N - return await bma.blockchain.Current(connection).get(AIOHTTP_SESSION) - def get_identity_document(current_block, uid, salt, password): """ @@ -48,7 +37,7 @@ def get_identity_document(current_block, uid, salt, password): :param str salt: Passphrase of the account :param str password: Password of the account - :rtype: SelfCertification + :rtype: Identity """ # get current block BlockStamp @@ -58,7 +47,7 @@ def get_identity_document(current_block, uid, salt, password): key = SigningKey(salt, password) # create identity document - identity = SelfCertification( + identity = Identity( version=2, currency=current_block['currency'], pubkey=key.pubkey, @@ -80,7 +69,7 @@ async def main(): connection = BMAEndpoint.from_inline(BMA_ENDPOINT).conn_handler() # capture current block to get version and currency and blockstamp - current_block = await get_current_block(connection) + current_block = await bma.blockchain.current(connection) # load credentials from a text file salt, password = open(FROM_CREDENTIALS_FILE).readlines() @@ -92,8 +81,7 @@ async def main(): identity = get_identity_document(current_block, UID, salt, password) # send the identity document to the node - data = {identity: identity.signed_raw()} - response = await bma.wot.Add(connection).post(AIOHTTP_SESSION, **data) + response = await bma.wot.add(connection, identity.signed_raw()) print(response) diff --git a/examples/request_data.py b/examples/request_data.py index 247df20c59500cf5fed91ed313f43287810aa98e..4817e57eddb22fe81450f28b2177c21acfc898bf 100644 --- a/examples/request_data.py +++ b/examples/request_data.py @@ -35,8 +35,8 @@ async def main(): response = await bma.blockchain.current(connection) print(response) - # Get the block number 0 - response = await bma.blockchain.block(connection, number=10) + # Get the block number 10 + response = await bma.blockchain.block(connection, 10) print(response) with AIOHTTP_SESSION: diff --git a/examples/save_revoke_document.py b/examples/save_revoke_document.py index e47d94c90fb00b88f0bc1886c7d9b240a381b641..73d3d433c9ea2400555b76313c28e373c19220e2 100644 --- a/examples/save_revoke_document.py +++ b/examples/save_revoke_document.py @@ -1,7 +1,7 @@ import asyncio import aiohttp import duniterpy.api.bma as bma -from duniterpy.documents import BMAEndpoint, BlockUID, SelfCertification +from duniterpy.documents import BMAEndpoint, BlockUID, Identity from duniterpy.documents import Revocation from duniterpy.key import SigningKey @@ -34,17 +34,6 @@ AIOHTTP_SESSION = aiohttp.ClientSession() # Current protocole version PROTOCOL_VERSION = 2 -async def get_current_block(connection): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - - :rtype: dict - """ - # Here we request for the path blockchain/current - return await bma.blockchain.Current(connection).get(AIOHTTP_SESSION) - async def get_identity_document(connection, currency, pubkey): """ Get the SelfCertification document of the pubkey @@ -53,10 +42,10 @@ async def get_identity_document(connection, currency, pubkey): :param str currency: Currency name :param str pubkey: Public key - :rtype: SelfCertification + :rtype: Identity """ # Here we request for the path wot/lookup/pubkey - lookup_data = await bma.wot.Lookup(connection, pubkey).get(AIOHTTP_SESSION) + lookup_data = await bma.wot.lookup(connection, pubkey) # init vars uid = None @@ -74,7 +63,7 @@ async def get_identity_document(connection, currency, pubkey): signature = uid_data["self"] # return self-certification document - return SelfCertification( + return Identity( version=PROTOCOL_VERSION, currency=currency, pubkey=pubkey, @@ -88,7 +77,7 @@ async def get_revoke_document(identity, salt, password): """ Generate account revocation document for given identity - :param SelfCertification identity: Self Certification of the identity + :param Identity identity: Self Certification of the identity :param str salt: Salt :param str password: Password @@ -109,7 +98,7 @@ async def main(): connection = BMAEndpoint.from_inline(BMA_ENDPOINT).conn_handler() # capture current block to get currency name - current_block = await get_current_block(connection) + current_block = await bma.blockchain.current(connection) # create our SelfCertification document to sign the revoke document identity_document = await get_identity_document(connection, current_block['currency'], PUBKEY) diff --git a/examples/send_certification.py b/examples/send_certification.py index 9897138cd5c3ab4315a62216b13bf8ef6b485f00..42d890c21f0c86df0bdf2de95ca5cc9c14f6f7b2 100644 --- a/examples/send_certification.py +++ b/examples/send_certification.py @@ -1,7 +1,7 @@ import asyncio import aiohttp import duniterpy.api.bma as bma -from duniterpy.documents import BMAEndpoint, BlockUID, SelfCertification, Certification +from duniterpy.documents import BMAEndpoint, BlockUID, Identity, Certification from duniterpy.key import SigningKey @@ -25,33 +25,22 @@ TO_PUBKEY = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" ################################################ - # Latest duniter-python-api is asynchronous and you have to create an aiohttp session to send request # ( http://pythonhosted.org/aiohttp ) AIOHTTP_SESSION = aiohttp.ClientSession() -async def get_current_block(connection): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - :rtype: dict - """ - # Here we request for the path blockchain/block/N - return await bma.blockchain.Current(connection).get(AIOHTTP_SESSION) - async def get_identity_document(connection, current_block, pubkey): """ Get the identity document of the pubkey :param bma.api.ConnectionHandler connection: Connection handler :param dict current_block: Current block data - :param str pubkey: Public key + :param str pubkey: UID/Public key - :rtype: SelfCertification + :rtype: Identity """ # Here we request for the path wot/lookup/pubkey - lookup_data = await bma.wot.Lookup(connection, pubkey).get(AIOHTTP_SESSION) + lookup_data = await bma.wot.lookup(connection, pubkey) # init vars uid = None @@ -69,7 +58,7 @@ async def get_identity_document(connection, current_block, pubkey): signature = uid_data["self"] # return self-certification document - return SelfCertification( + return Identity( version=2, currency=current_block['currency'], pubkey=pubkey, @@ -84,7 +73,7 @@ def get_certification_document(current_block, self_cert_document, from_pubkey, s Create and return a Certification document :param dict current_block: Current block data - :param SelfCertification self_cert_document: SelfCertification document + :param Identity self_cert_document: SelfCertification document :param str from_pubkey: Pubkey of the certifier :param str salt: Secret salt (DO NOT SHOW IT ANYWHERE, IT IS SECRET !!!) :param str password: Secret password (DO NOT SHOW IT ANYWHERE, IT IS SECRET !!!) @@ -114,7 +103,7 @@ async def main(): connection = BMAEndpoint.from_inline(BMA_ENDPOINT).conn_handler() # capture current block to get version and currency and blockstamp - current_block = await get_current_block(connection) + current_block = await bma.blockchain.current(connection) # create our SelfCertification document to sign the Certification document identity = await get_identity_document(connection, current_block, TO_PUBKEY) @@ -129,8 +118,7 @@ async def main(): certification = get_certification_document(current_block, identity, FROM_PUBKEY, salt, password) # Here we request for the path wot/certify - data = {'cert': certification.signed_raw(identity)} - response = await bma.wot.Certify(connection).post(AIOHTTP_SESSION, **data) + response = await bma.wot.certify(connection, certification.signed_raw(identity)) print(response) diff --git a/examples/send_membership.py b/examples/send_membership.py index cc31ec7c5337a2616a0287d1838a85c06df4e1c6..171a35e92239390656369930dc234eaeb2926612 100644 --- a/examples/send_membership.py +++ b/examples/send_membership.py @@ -2,7 +2,7 @@ import asyncio import aiohttp import duniterpy.api.bma as bma -from duniterpy.documents import BMAEndpoint, BlockUID, SelfCertification, Membership +from duniterpy.documents import BMAEndpoint, BlockUID, Identity, Membership from duniterpy.key import SigningKey @@ -27,16 +27,6 @@ UID = "MyIdentity" # ( http://pythonhosted.org/aiohttp ) AIOHTTP_SESSION = aiohttp.ClientSession() -async def get_current_block(connection): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - :rtype: dict - """ - # Here we request for the path blockchain/block/N - return await bma.blockchain.Current(connection).get(AIOHTTP_SESSION) - def get_identity_document(current_block, uid, salt, password): """ @@ -47,7 +37,7 @@ def get_identity_document(current_block, uid, salt, password): :param str salt: Passphrase of the account :param str password: Password of the account - :rtype: SelfCertification + :rtype: Identity """ # get current block BlockStamp @@ -57,7 +47,7 @@ def get_identity_document(current_block, uid, salt, password): key = SigningKey(salt, password) # create identity document - identity = SelfCertification( + identity = Identity( version=2, currency=current_block['currency'], pubkey=key.pubkey, @@ -72,13 +62,13 @@ def get_identity_document(current_block, uid, salt, password): return identity -def get_membership_document(type, current_block, identity, salt, password): +def get_membership_document(mtype, current_block, identity, salt, password): """ Get a Membership document - :param str type: "IN" to ask for membership or "OUT" to cancel membership + :param str mtype: "IN" to ask for membership or "OUT" to cancel membership :param dict current_block: Current block data - :param SelfCertification identity: Identity document + :param Identity identity: Identity document :param str salt: Passphrase of the account :param str password: Password of the account @@ -97,7 +87,7 @@ def get_membership_document(type, current_block, identity, salt, password): currency=current_block['currency'], issuer=key.pubkey, membership_ts=timestamp, - membership_type=type, + membership_type=mtype, uid=identity.uid, identity_ts=identity.timestamp, signature=None @@ -116,7 +106,7 @@ async def main(): connection = BMAEndpoint.from_inline(BMA_ENDPOINT).conn_handler() # capture current block to get version and currency and blockstamp - current_block = await get_current_block(connection) + current_block = await bma.blockchain.current(connection) # load credentials from a text file salt, password = open(FROM_CREDENTIALS_FILE).readlines() @@ -131,8 +121,7 @@ async def main(): membership = get_membership_document("IN", current_block, identity, salt, password) # send the membership document to the node - data = {membership: membership.signed_raw()} - response = await bma.blockchain.Membership(connection).post(AIOHTTP_SESSION, **data) + response = await bma.blockchain.membership(connection, membership.signed_raw()) print(response) response.close() diff --git a/examples/send_transaction.py b/examples/send_transaction.py index 496516c5ba132d0311d8b9cfa99744c16839f2af..2bb237e8e7dd5b783e337a0756a351f23d2153c6 100644 --- a/examples/send_transaction.py +++ b/examples/send_transaction.py @@ -37,28 +37,6 @@ AIOHTTP_SESSION = aiohttp.ClientSession() # Version of the transaction document TRANSACTION_VERSION = 3 -async def get_current_block(connection): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - :rtype: dict - """ - # Here we request for the path blockchain/block/N - return await bma.blockchain.Current(connection).get(AIOHTTP_SESSION) - -async def get_sources(connection, pubkey): - """ - Get the current block data - - :param bma.api.ConnectionHandler connection: Connection handler - :param str pubkey: Public key of the sources account - - :rtype: dict - """ - # Here we request for the path blockchain/block/N - return await bma.tx.Sources(connection, pubkey).get(AIOHTTP_SESSION) - def get_transaction_document(current_block, source, from_pubkey, to_pubkey): """ @@ -130,9 +108,10 @@ async def main(): connection = BMAEndpoint.from_inline(BMA_ENDPOINT).conn_handler() # capture current block to get version and currency and blockstamp - current_block = await get_current_block(connection) + current_block = await bma.blockchain.current(connection) - response = await get_sources(connection, FROM_PUBKEY) + # capture sources of account + response = await bma.tx.sources(connection, FROM_PUBKEY) if len(response['sources']) == 0: print("no sources found for account %s" % FROM_PUBKEY) @@ -157,8 +136,7 @@ async def main(): transaction.sign([key]) # send the Transaction document to the node - data = {'transaction': transaction.signed_raw()} - response = await bma.tx.Process(connection).post(AIOHTTP_SESSION, **data) + response = await bma.tx.process(connection, transaction.signed_raw()) print(response) diff --git a/tests/documents/test_certification.py b/tests/documents/test_certification.py index 5bf7c2c2467b38793dded16cea742ad5f45b0d13..8ab4cc234f6c1045c79c4f261ce0ed65b0851765 100644 --- a/tests/documents/test_certification.py +++ b/tests/documents/test_certification.py @@ -5,7 +5,7 @@ Created on 6 déc. 2014 ''' import unittest -from duniterpy.documents.certification import SelfCertification, Certification, Revocation +from duniterpy.documents.certification import Identity, Certification, Revocation from duniterpy.documents import Block, BlockUID selfcert_inlines = ["HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\ @@ -31,13 +31,13 @@ class Test_Certification(unittest.TestCase): def test_self_certification_from_inline(self): version = 2 currency = "beta_brousouf" - selfcert = SelfCertification.from_inline(version, currency, selfcert_inlines[0]) + selfcert = Identity.from_inline(version, currency, selfcert_inlines[0]) self.assertEqual(selfcert.pubkey, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk") self.assertEqual(selfcert.signatures[0], "h/H8tDIEbfA4yxMQcvfOXVDQhi1sUa9qYtPKrM59Bulv97ouwbAvAsEkC1Uyit1IOpeAV+CQQs4IaAyjE8F1Cw==") self.assertEqual(str(selfcert.timestamp), "32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD") self.assertEqual(selfcert.uid, "lolcat") - selfcert = SelfCertification.from_inline(version, currency, selfcert_inlines[1]) + selfcert = Identity.from_inline(version, currency, selfcert_inlines[1]) self.assertEqual(selfcert.pubkey, "RdrHvL179Rw62UuyBrqy2M1crx7RPajaViBatS59EGS") self.assertEqual(selfcert.signatures[0], "Ah55O8cvdkGS4at6AGOKUjy+wrFwAq8iKRJ5xLIb6Xdi3M8WfGOUdMjwZA6GlSkdtlMgEhQPm+r2PMebxKrCBg==") self.assertEqual(str(selfcert.timestamp), "36-1076F10A7397715D2BEE82579861999EA1F274AC") @@ -51,7 +51,7 @@ class Test_Certification(unittest.TestCase): timestamp = BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD") signature = "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci" - selfcert = SelfCertification(version, currency, issuer, uid, timestamp, signature) + selfcert = Identity(version, currency, issuer, uid, timestamp, signature) result = """Version: 2 Type: Identity @@ -87,8 +87,8 @@ J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBf pubkey_to = "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd" timestamp = BlockUID(36, "1076F10A7397715D2BEE82579861999EA1F274AC") signature = "SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk" - selfcert = SelfCertification(version, currency, pubkey_to, "lolcat", - BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), + selfcert = Identity(version, currency, pubkey_to, "lolcat", + BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci") certification = Certification(version, currency, pubkey_from, pubkey_to, timestamp, signature) @@ -122,8 +122,8 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN pubkey = "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd" signature = "SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk" revokation = Revocation(version, currency, pubkey, signature) - selfcert = SelfCertification(version, currency, pubkey, "lolcat", - BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), + selfcert = Identity(version, currency, pubkey, "lolcat", + BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci") result = """Version: 2 @@ -149,4 +149,4 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN """ revocation = Revocation.from_signed_raw(signed_raw) selfcert = Revocation.extract_self_cert(signed_raw) - self.assertEqual(revocation.signed_raw(selfcert), signed_raw) \ No newline at end of file + self.assertEqual(revocation.signed_raw(selfcert), signed_raw)