diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b754f36d4e63d119fc0e0fce1c1bfca8046abf2..2612778ddb3c04b965a29bc40322eb2c0bae210b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ add_subdirectory(modules/cellframe-sdk/type/blocks) add_subdirectory(modules/cellframe-sdk/consensus/dag_poa) add_subdirectory(modules/cellframe-sdk/global-db) add_subdirectory(modules/cellframe-sdk/services/pos_delegate) +add_subdirectory(modules/cellframe-sdk/services/xchange) add_subdirectory(modules/cellframe-sdk/channel/chain-net) target_compile_options(dap_chain_common_python_module PRIVATE "-fpic") @@ -192,6 +193,7 @@ target_link_libraries(${PROJECT_NAME} cellframe-sdk dap_python_module dap_chain_cs_blocks_python_module dap_global_db_python_module dap_chain_net_srv_stake_pos_delegate_python_module + wrapping_dap_chain_net_srv_xchange dap_stream_ch_chain_net_python_module ${PYTHON_LIBRARIES} ) diff --git a/CellFrame/python-cellframe.c b/CellFrame/python-cellframe.c index 49809756756afafda0559467459ac5c68dfe5af8..04d4f1aa58275201a54414b1fc1db20875a5a7f6 100644 --- a/CellFrame/python-cellframe.c +++ b/CellFrame/python-cellframe.c @@ -604,7 +604,9 @@ PyMODINIT_FUNC PyInit_libCellFrame(void) /// Services PyType_Ready( &PyDapChainNetSrvStakePosDelegateObjectType ) < 0 || PyType_Ready( &PyDapStreamChChainValidatorTestObjectType ) < 0 || - // === Chain consensuses + PyType_Ready( &DapChainNetSrvXchangeObjectType ) < 0 || + PyType_Ready( &PyDapChainNetSrvXchangePriceObjectType ) < 0 || + // === Chain consensuses PyType_Ready( &DapChainCsDagPoaObjectType ) < 0 || PyType_Ready(&DapChainCsBlockType) < 0 || PyType_Ready(&DapChainCsDagType) < 0 || @@ -678,6 +680,7 @@ PyMODINIT_FUNC PyInit_libCellFrame(void) PyObject *servicesModule = PyModule_Create(&CellframeServicesPythonModule); PyModule_AddObject(servicesModule, "StakePosDelegate", (PyObject*)&PyDapChainNetSrvStakePosDelegateObjectType); + PyModule_AddObject(servicesModule, "Xchange", (PyObject*)&DapChainNetSrvXchangeObjectType); PyModule_AddObject(servicesModule, "StreamChChainValidatorTest", (PyObject*)&PyDapStreamChChainValidatorTestObjectType); PyObject *csModule = PyModule_Create(&CellframeConsensusPythonModule); @@ -692,6 +695,7 @@ PyMODINIT_FUNC PyInit_libCellFrame(void) PyModule_AddStringConstant(cellframeModule, "__author__", "Alexey Stratulat <alexey.stratulat@demlabs.net>"); PyModule_AddStringConstant(cellframeModule, "__version__", DAP_VERSION); CellFrame_error = PyErr_NewException("CellFrame.error", NULL, NULL); + CellFrame_Xchange_error = PyErr_NewException("CellFrame.Service.XchangeError", NULL, NULL); PyModule_AddObject(cellframeModule, "error", CellFrame_error); PyModule_AddObject(cellframeModule, "AppCli", (PyObject*)&DapAppCliObjectType); PyModule_AddObject(cellframeModule, "AppCliServer", (PyObject*)&DapChainNodeCliObjectType); diff --git a/include/python-cellframe.h b/include/python-cellframe.h index 9f95ac66dd6c7dc1223d4d32398637c62988ccae..403f7fc80279a20241d40daf304adfb4d685bb03 100644 --- a/include/python-cellframe.h +++ b/include/python-cellframe.h @@ -105,6 +105,8 @@ BOOL WINAPI consoleHandler(DWORD); #include "wrapping_dap_http_simple.h" #include "wrapping_dap_http_header.h" #include "wrapping_dap_chain_net_srv_stake_pos_delegate.h" +#include "wrapping_dap_chain_net_srv_xchange.h" +#include "wrapping_dap_chain_net_srv_xchange_price.h" #ifdef DAP_SUPPORT_PYTHON_PLUGINS #include "../modules/plugins/include/dap_plugins_python_app_context.h" #endif // DAP_SUPPORT_PYTHON_PLUGINS diff --git a/modules/cellframe-sdk/services/xchange/CMakeLists.txt b/modules/cellframe-sdk/services/xchange/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..907daadab388be7350e8f38250f5d7e139f870d0 --- /dev/null +++ b/modules/cellframe-sdk/services/xchange/CMakeLists.txt @@ -0,0 +1,18 @@ +project(wrapping_dap_chain_net_srv_xchange C) + +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_COLOR_MAKEFILE ON) +set(CMAKE_C_STANDARD 11) +add_definitions("-fpic") +add_definitions("-DDAP_LOG_MT") + +file (GLOB DAP_SRV_XCHANGE_PYTHON_SRCS ./*.c) +file (GLOB DAP_SRV_XCHANGE_PYTHON_HEADERS include/*.h) + +include_directories(${PYTHON_INCLUDE_DIR} include/) + +add_library(${PROJECT_NAME} STATIC ${DAP_SRV_XCHANGE_PYTHON_SRCS} ${DAP_SRV_XCHANGE_PYTHON_HEADERS}) + +target_link_libraries(${PROJECT_NAME} dap_chain_python_module) + +target_include_directories(${PROJECT_NAME} PUBLIC include/) diff --git a/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange.h b/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange.h new file mode 100644 index 0000000000000000000000000000000000000000..850fc6f3f43da5b09048eb0fcfd1148911718df5 --- /dev/null +++ b/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange.h @@ -0,0 +1,37 @@ +/* + * Authors: + * Alexey Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * CellFrame https://cellframe.net + * Sources https://gitlab.demlabs.net/cellframe + * Copyright (c) 2017-2024 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <Python.h> + +typedef struct PyDapChainNetSrvXchange{ + PyObject_HEAD +}PyDapChainNetSrvXchangeObject; + +static PyObject *CellFrame_Xchange_error; + +PyObject *wrapping_dap_chain_net_srv_xchange_get_prices(PyObject *self, PyObject *argv); +PyObject *wrapping_dap_chain_net_srv_xchange_create(PyObject *self, PyObject *argv); +PyObject *wrapping_dap_chain_net_srv_xchange_remove(PyObject *self, PyObject *argv); + +extern PyTypeObject DapChainNetSrvXchangeObjectType; \ No newline at end of file diff --git a/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange_price.h b/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange_price.h new file mode 100644 index 0000000000000000000000000000000000000000..3264df5c513b61ba3688e038fd115734354d0117 --- /dev/null +++ b/modules/cellframe-sdk/services/xchange/include/wrapping_dap_chain_net_srv_xchange_price.h @@ -0,0 +1,51 @@ +/* + * Authors: + * Alexey Stratulat <alexey.stratulat@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * CellFrame https://cellframe.net + * Sources https://gitlab.demlabs.net/cellframe + * Copyright (c) 2017-2024 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <Python.h> +#include "dap_chain_net_srv_xchange.h" + +typedef struct PyDapChainNetSrvXchangePrice { + PyObject_HEAD + dap_chain_net_srv_xchange_price_t *price; +}PyDapChainNetSrvXchangePriceObject; + +static PyObject *CellFrame_Xchange_Price_error; + +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_wallet_str(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_token_sell(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_datoshi_sell(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_net(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_token_buy(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_datoshi_buy(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_rate(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_fee(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_tx_hash(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_order_hash(PyObject *self, void *closure); +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_wallet_key(PyObject *self, void *closure); + +PyObject *wrapping_dap_chain_net_srv_xchange_price_create_object(dap_chain_net_srv_xchange_price_t *a_price); + +PyObject *wrapping_dap_chain_net_srv_xchange_price_purchase(PyObject *self, PyObject *argv); + +extern PyTypeObject PyDapChainNetSrvXchangePriceObjectType; diff --git a/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange.c b/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange.c new file mode 100644 index 0000000000000000000000000000000000000000..776a56510fcce59f5d858b0d9cc3a34691604535 --- /dev/null +++ b/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange.c @@ -0,0 +1,190 @@ +#include "wrapping_dap_chain_net_srv_xchange.h" +#include "wrapping_dap_chain_net_srv_xchange_price.h" +#include "dap_chain_net_srv_xchange.h" +#include "dap_chain_wallet_python.h" +#include "libdap_chain_net_python.h" +#include "libdap-python.h" + +PyMethodDef DapChainNetSrvXchangeMethods[] = { + { + "getPrices", + wrapping_dap_chain_net_srv_xchange_get_prices, + METH_VARARGS | METH_STATIC, + "The function receives a list of prices for exchange; if there are no prices, then an empty list is returned."}, + { + "createExchange", + wrapping_dap_chain_net_srv_xchange_create, + METH_VARARGS | METH_STATIC, + "The function creates a base transaction and an exchange order." + }, + { + "removeExchange", + wrapping_dap_chain_net_srv_xchange_remove, + METH_VARARGS | METH_STATIC, + "This function deletes an exchange order." + }, + {NULL, NULL, 0, NULL} +}; + +PyObject *wrapping_dap_chain_net_srv_xchange_get_prices(PyObject *self, PyObject *argv){ + (void)self; + PyObject *obj_net; + if (!PyArg_ParseTuple(argv, "O", &obj_net)) { + return NULL; + } + dap_list_t *l_list_prices = dap_chain_net_srv_xchange_get_prices(((PyDapChainNetObject*)obj_net)->chain_net); + dap_list_t *tmp = l_list_prices; + PyObject *obj_list_price = PyList_New(0); + while (tmp) { + dap_chain_net_srv_xchange_price_t *l_price = (dap_chain_net_srv_xchange_price_t*)tmp->data; + PyObject *l_obj_price = wrapping_dap_chain_net_srv_xchange_price_create_object(l_price); + PyList_Append(obj_list_price, l_obj_price); + Py_XDECREF(l_obj_price); + tmp = tmp->next; + } + dap_list_free(l_list_prices); + return obj_list_price; +} + +PyObject *wrapping_dap_chain_net_srv_xchange_create(PyObject *self, PyObject *argv) { + (void)self; + PyObject *obj_net; + const char *l_token_sell; + const char *l_token_buy; + PyObject *obj_value_sell; + PyObject *obj_rate; + PyObject *obj_fee; + PyObject *obj_wallet; + if (!PyArg_ParseTuple(argv, "OssOOOO", &obj_net, &l_token_sell, &l_token_buy, &obj_value_sell, &obj_rate, &obj_fee, + &obj_wallet)) { + return NULL; + } + dap_chain_net_t *l_net = ((PyDapChainNetObject*)obj_net)->chain_net; + uint256_t l_value_sell = ((DapMathObject*)obj_value_sell)->value; + uint256_t l_rate = ((DapMathObject*)obj_rate)->value; + uint256_t l_fee = ((DapMathObject*)obj_fee)->value; + dap_chain_wallet_t *l_wallet = ((PyDapChainWalletObject*)obj_wallet)->wallet; + char *l_hash_ret = NULL; + int l_ret_code = dap_chain_net_srv_xchange_create(l_net, l_token_buy, l_token_sell, l_value_sell, l_rate, l_fee, + l_wallet, &l_hash_ret); + switch (l_ret_code) { + case XCHANGE_CREATE_ERROR_OK:{ + return Py_BuildValue("s", l_hash_ret); + } + case XCHANGE_CREATE_ERROR_INVALID_ARGUMENT:{ + PyErr_SetString(CellFrame_Xchange_error, "One of the input arguments is not set correctly."); + return NULL; + } + case XCHANGE_CREATE_ERROR_TOKEN_TICKER_SELL_IS_NOT_FOUND_LEDGER:{ + char *l_ret = dap_strdup_printf("The token ticker '%s', which is intended for sale, " + "was not found in the ledger.", l_token_sell); + PyErr_SetString(CellFrame_Xchange_error, l_ret); + DAP_DELETE(l_ret); + return NULL; + } + case XCHANGE_CREATE_ERROR_TOKEN_TICKER_BUY_IS_NOT_FOUND_LEDGER:{ + char *l_ret = dap_strdup_printf("The token ticker '%s', which is intended for buy, " + "was not found in the ledger.", l_token_buy); + PyErr_SetString(CellFrame_Xchange_error, l_ret); + DAP_DELETE(l_ret); + return NULL; + } + case XCHANGE_CREATE_ERROR_RATE_IS_ZERO:{ + PyErr_SetString(CellFrame_Xchange_error, "Rate is zero"); + return NULL; + } + case XCHANGE_CREATE_ERROR_FEE_IS_ZERO:{ + PyErr_SetString(CellFrame_Xchange_error, "Fee is zero"); + return NULL; + } + case XCHANGE_CREATE_ERROR_VALUE_SELL_IS_ZERO: { + PyErr_SetString(CellFrame_Xchange_error, "Value sell is zero"); + return NULL; + } + case XCHANGE_CREATE_ERROR_INTEGER_OVERFLOW_WITH_SUM_OF_VALUE_AND_FEE:{ + PyErr_SetString(CellFrame_Xchange_error, "An overflow occurred when adding the transaction " + "value and commission."); + return NULL; + } + case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_FOR_FEE_IN_SPECIFIED_WALLET:{ + PyErr_SetString(CellFrame_Xchange_error, "There are not enough token funds in the wallet to " + "create an fee."); + return NULL; + } + case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET:{ + PyErr_SetString(CellFrame_Xchange_error, "There are not enough token funds in the wallet to " + "create an exchange order."); + return NULL; + } + case XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED:{ + PyErr_SetString(CellFrame_Xchange_error, "Memory allocated"); + return NULL; + } + case XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION: { + PyErr_SetString(CellFrame_Xchange_error, "Failed to create conditional exchange transaction."); + return NULL; + } + case XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL: { + PyErr_SetString(CellFrame_Xchange_error, "The created conditional exchange transaction " + "could not be posted to the mempool."); + return NULL; + } + default: { + char *l_ret = dap_strdup_printf("An error occurred with an unknown code: %d.", l_ret_code); + PyErr_SetString(CellFrame_Xchange_error, l_ret); + DAP_DELETE(l_ret); + return NULL; + } + } +} + +PyObject *wrapping_dap_chain_net_srv_xchange_remove(PyObject *self, PyObject *argv){ + (void)self; + PyObject *obj_net; + PyObject *obj_fee; + PyObject *obj_wallet; + PyObject *obj_tx_hash; + if (!PyArg_ParseTuple(argv, "OOOO", &obj_net, &obj_tx_hash, &obj_fee, &obj_wallet)) + return NULL; + char *l_tx_hash_out = NULL; + int l_ret_code = dap_chain_net_srv_xchange_remove(((PyDapChainNetObject*)obj_net)->chain_net, + ((PyDapHashFastObject*)obj_tx_hash)->hash_fast, + ((DapMathObject*)obj_fee)->value, + ((PyDapChainWalletObject*)obj_wallet)->wallet, &l_tx_hash_out); + switch (l_ret_code) { + case XCHANGE_REMOVE_ERROR_OK:{ + return Py_BuildValue("s", l_tx_hash_out); + } + case XCHANGE_REMOVE_ERROR_INVALID_ARGUMENT: { + PyErr_SetString(CellFrame_Xchange_error, "One of the input arguments is not set correctly."); + return NULL; + } + case XCHANGE_REMOVE_ERROR_FEE_IS_ZERO: { + PyErr_SetString(CellFrame_Xchange_error, "Fee is zero."); + return NULL; + } + case XCHANGE_REMOVE_ERROR_CAN_NOT_FIND_TX: { + PyErr_SetString(CellFrame_Xchange_error, "Specified order not found."); + return NULL; + } + case XCHANGE_REMOVE_ERROR_CAN_NOT_CREATE_PRICE: { + PyErr_SetString(CellFrame_Xchange_error, "Can't create price object from order."); + return NULL; + } + case XCHANGE_REMOVE_ERROR_CAN_NOT_INVALIDATE_TX: { + PyErr_SetString(CellFrame_Xchange_error, "Can't create invalidate transaction."); + return NULL; + } + default: { + char *l_ret = dap_strdup_printf("An error occurred with an unknown code: %d.", l_ret_code); + PyErr_SetString(CellFrame_Xchange_error, l_ret); + DAP_DELETE(l_ret); + return NULL; + } + } +} + +PyTypeObject DapChainNetSrvXchangeObjectType = DAP_PY_TYPE_OBJECT( + "CellFrame.Service.Xchange", + sizeof(PyDapChainNetSrvXchangeObject), "Object for work service xchange", + .tp_methods = DapChainNetSrvXchangeMethods); \ No newline at end of file diff --git a/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange_price.c b/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange_price.c new file mode 100644 index 0000000000000000000000000000000000000000..115cba65f21f41ea123dc63d32dcac5f73af3e65 --- /dev/null +++ b/modules/cellframe-sdk/services/xchange/wrapping_dap_chain_net_srv_xchange_price.c @@ -0,0 +1,171 @@ +#include "wrapping_dap_chain_net_srv_xchange_price.h" +#include "libdap-python.h" +#include "libdap_chain_net_python.h" +#include "libdap_crypto_key_python.h" +#include "dap_chain_wallet_python.h" + +#define PRICE(a) ((PyDapChainNetSrvXchangePriceObject*)a)->price + +PyGetSetDef DapChainNetSrvXchangePriceGetSetDef[] = { + {"walletStr", (getter)wrapping_dap_chain_net_srv_xchange_price_get_wallet_str, NULL, NULL, NULL}, + {"tokenSell", (getter)wrapping_dap_chain_net_srv_xchange_price_get_token_sell, NULL, NULL, NULL}, + {"datoshiSell", (getter)wrapping_dap_chain_net_srv_xchange_price_get_datoshi_sell, NULL, NULL, NULL}, + {"net", (getter)wrapping_dap_chain_net_srv_xchange_price_get_net, NULL, NULL, NULL}, + {"tokenBuy", (getter)wrapping_dap_chain_net_srv_xchange_price_get_token_buy, NULL, NULL, NULL}, + {"datoshiBuy", (getter) wrapping_dap_chain_net_srv_xchange_price_get_datoshi_buy, NULL, NULL, NULL}, + {"rate", (getter)wrapping_dap_chain_net_srv_xchange_price_get_rate, NULL, NULL, NULL}, + {"fee", (getter)wrapping_dap_chain_net_srv_xchange_price_get_fee, NULL, NULL, NULL}, + {"txHash", (getter)wrapping_dap_chain_net_srv_xchange_price_get_tx_hash, NULL, NULL, NULL}, + {"orderHash", (getter)wrapping_dap_chain_net_srv_xchange_price_get_order_hash, NULL, NULL, NULL}, + {"walletKey", (getter)wrapping_dap_chain_net_srv_xchange_price_get_wallet_key, NULL, NULL, NULL}, + {} +}; + +PyMethodDef DapChainNetSrvXchangePriceMethods[] = { + { + "purchase", + wrapping_dap_chain_net_srv_xchange_price_purchase, + METH_VARARGS, + "Function for partial or full purchase of an order." + }, + {NULL} +}; + +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_wallet_str(PyObject *self, void *closure){ + UNUSED(closure); + return Py_BuildValue("s", PRICE(self)->wallet_str); +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_token_sell(PyObject *self, void *closure){ + UNUSED(closure); + return Py_BuildValue("s", PRICE(self)->token_sell); +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_datoshi_sell(PyObject *self, void *closure){ + UNUSED(closure); + DapMathObject *obj_math = PyObject_NEW(DapMathObject, &DapMathObjectType); + obj_math->value = PRICE(self)->datoshi_sell; + return (PyObject*)obj_math; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_net(PyObject *self, void *closure){ + UNUSED(closure); + PyDapChainNetObject *obj_net = PyObject_NEW(PyDapChainNetObject, &DapChainNetObjectType); + obj_net->chain_net = PRICE(self)->net; + return (PyObject*)obj_net; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_token_buy(PyObject *self, void *closure){ + UNUSED(closure); + return Py_BuildValue("s", PRICE(self)->token_buy); +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_datoshi_buy(PyObject *self, void *closure){ + UNUSED(closure); + DapMathObject *obj_math = PyObject_New(DapMathObject, &DapMathObjectType); + obj_math->value = PRICE(self)->datoshi_buy; + return (PyObject*)obj_math; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_rate(PyObject *self, void *closure){ + UNUSED(closure); + DapMathObject *obj_math = PyObject_New(DapMathObject, &DapMathObjectType); + obj_math->value = PRICE(self)->rate; + return (PyObject*)obj_math; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_fee(PyObject *self, void *closure){ + UNUSED(closure); + DapMathObject *obj_math = PyObject_New(DapMathObject, &DapMathObjectType); + obj_math->value = PRICE(self)->fee; + return (PyObject*)obj_math; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_tx_hash(PyObject *self, void *closure){ + UNUSED(closure); + PyDapHashFastObject *obj_hash = PyObject_NEW(PyDapHashFastObject, &DapHashFastObjectType); + obj_hash->hash_fast = DAP_NEW(dap_chain_hash_fast_t); + dap_chain_hash_fast_t l_hf = PRICE(self)->tx_hash; + memcpy(obj_hash->hash_fast, &l_hf, sizeof(dap_chain_hash_fast_t)); + obj_hash->origin = true; + return (PyObject*)obj_hash; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_order_hash(PyObject *self, void *closure){ + UNUSED(closure); + PyDapHashFastObject *obj_hash = PyObject_NEW(PyDapHashFastObject, &DapHashFastObjectType); + obj_hash->hash_fast = DAP_NEW(dap_chain_hash_fast_t); + dap_chain_hash_fast_t l_hf = PRICE(self)->order_hash; + memcpy(obj_hash->hash_fast, &l_hf, sizeof(dap_chain_hash_fast_t)); + obj_hash->origin = true; + return (PyObject*)obj_hash; +} +PyObject *wrapping_dap_chain_net_srv_xchange_price_get_wallet_key(PyObject *self, void *closure){ + UNUSED(closure); + PyCryptoKeyObject *obj_key = PyObject_New(PyCryptoKeyObject, &PyCryptoKeyObjectType); + obj_key->key = PRICE(self)->wallet_key; + return (PyObject*)obj_key; +} + +PyTypeObject PyDapChainNetSrvXchangePriceObjectType = DAP_PY_TYPE_OBJECT( + "CellFrame.Service.Xchange.Price", sizeof(PyDapChainNetSrvXchangePriceObject), + "Price from service xchange", + .tp_getset = DapChainNetSrvXchangePriceGetSetDef, + .tp_methods = DapChainNetSrvXchangePriceMethods); + +PyObject *wrapping_dap_chain_net_srv_xchange_price_create_object(dap_chain_net_srv_xchange_price_t *a_price) { + PyDapChainNetSrvXchangePriceObject *self = PyObject_New(PyDapChainNetSrvXchangePriceObject, &PyDapChainNetSrvXchangePriceObjectType); + self->price = a_price; + return (PyObject*)self; +} + +PyObject *wrapping_dap_chain_net_srv_xchange_price_purchase(PyObject *self, PyObject *argv){ + PyObject *obj_wallet, *obj_fee, *obj_value; + if (!PyArg_ParseTuple(argv, "OOO", &obj_value, &obj_fee, &obj_wallet)) { + return NULL; + } + if (!DapMathObject_Check(obj_value)) { + PyErr_SetString(PyExc_AttributeError, "The first argument was passed incorrectly. This must be " + "an instance of an object of type Math."); + return NULL; + } + if (!DapMathObject_Check(obj_fee)) { + PyErr_SetString(PyExc_AttributeError, "The second argument was passed incorrectly. This must be " + "an instance of an object of type Math."); + return NULL; + } + if (!PyDapChainWalletObject_Check(obj_wallet)) { + PyErr_SetString(PyExc_AttributeError, "The third parameter to the function passed an incorrect " + "argument. This must be an instance of the Wallet class."); + return NULL; + } + char *l_ret_tx_hash = NULL; + dap_chain_net_srv_xchange_price_t *l_price = PRICE(self); + int l_ret_code = dap_chain_net_srv_xchange_purchase(l_price->net, &l_price->order_hash, + ((DapMathObject*)obj_value)->value, + ((DapMathObject*)obj_fee)->value, + ((PyDapChainWalletObject*)obj_wallet)->wallet, + &l_ret_tx_hash); + switch (l_ret_code) { + case XCHANGE_PURCHASE_ERROR_OK: { + return Py_BuildValue("s", l_ret_tx_hash); + } + case XCHANGE_PURCHASE_ERROR_INVALID_ARGUMENT: { + PyErr_SetString(CellFrame_Xchange_Price_error, "An internal error occurred in the order " + "purchase function; not all arguments were passed."); + return NULL; + } + case XCHANGE_PURCHASE_ERROR_SPECIFIED_ORDER_NOT_FOUND: { + PyErr_SetString(CellFrame_Xchange_Price_error, "An error occurred: the order was not found " + "for the hash specified in the price list."); + return NULL; + } + case XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_PRICE: { + PyErr_SetString(CellFrame_Xchange_Price_error, "An error occurred. It was not possible to " + "create a new price list to create an exchange transaction."); + return NULL; + } + case XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_EXCHANGE_TX: { + PyErr_SetString(CellFrame_Xchange_Price_error, "An error occurred: it was not possible to " + "create an exchange transaction."); + return NULL; + } + default: { + char *l_ret = dap_strdup_printf("An error occurred with an unknown code: %d.", l_ret_code); + PyErr_SetString(CellFrame_Xchange_Price_error, l_ret); + DAP_DELETE(l_ret); + return NULL; + } + } +} \ No newline at end of file diff --git a/modules/dap-sdk/core/src/math_python.h b/modules/dap-sdk/core/src/math_python.h index 61ca605dd80086a8712bef60cfd1321900f04982..cf660396fc21b66075cf27f2aedff2bac23def2b 100644 --- a/modules/dap-sdk/core/src/math_python.h +++ b/modules/dap-sdk/core/src/math_python.h @@ -46,3 +46,7 @@ PyObject *wrapping_dap_math_get_coins(PyObject *self, void *closure); PyObject *wrapping_dap_math_get_balance(PyObject *self, void *closure); extern PyTypeObject DapMathObjectType; + +DAP_STATIC_INLINE bool DapMathObject_Check(PyObject *obj_math){ + return PyObject_TypeCheck(obj_math, &DapMathObjectType) == 0 ? true : false; +}