From ba5aafd5cae6d966ee14dcd5713f78aaff9400c7 Mon Sep 17 00:00:00 2001 From: Artem Pikulin Date: Wed, 7 Feb 2018 13:45:38 +0700 Subject: [PATCH 1/2] Move etomic lib to SuperNet. --- .gitignore | 4 +- CMakeLists.txt | 1 + cpp-ethereum | 1 + iguana/exchanges/LP_etomic.c | 2 +- iguana/exchanges/etomicswap/CMakeLists.txt | 10 + iguana/exchanges/etomicswap/alice.c | 106 +++++++ iguana/exchanges/etomicswap/bob.c | 177 +++++++++++ iguana/exchanges/etomicswap/etomiccurl.c | 112 +++++++ iguana/exchanges/etomicswap/etomiccurl.h | 10 + iguana/exchanges/etomicswap/etomiclib.cpp | 334 +++++++++++++++++++++ iguana/exchanges/etomicswap/etomiclib.h | 131 ++++++++ 11 files changed, 886 insertions(+), 2 deletions(-) create mode 160000 cpp-ethereum create mode 100644 iguana/exchanges/etomicswap/CMakeLists.txt create mode 100644 iguana/exchanges/etomicswap/alice.c create mode 100644 iguana/exchanges/etomicswap/bob.c create mode 100644 iguana/exchanges/etomicswap/etomiccurl.c create mode 100644 iguana/exchanges/etomicswap/etomiccurl.h create mode 100644 iguana/exchanges/etomicswap/etomiclib.cpp create mode 100644 iguana/exchanges/etomicswap/etomiclib.h diff --git a/.gitignore b/.gitignore index 362b0b8e6..633253ec9 100755 --- a/.gitignore +++ b/.gitignore @@ -251,4 +251,6 @@ iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg_append.json iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg.json -build \ No newline at end of file +build + +.idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 43bac6ac0..e833ab65f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ project(SuperNET) include_directories("${CMAKE_SOURCE_DIR}") add_subdirectory(cpp-ethereum) add_subdirectory(iguana/exchanges) +add_subdirectory(iguana/exchanges/etomicswap) add_subdirectory(iguana/secp256k1) add_subdirectory(crypto777) add_subdirectory(crypto777/jpeg) \ No newline at end of file diff --git a/cpp-ethereum b/cpp-ethereum new file mode 160000 index 000000000..633c62c08 --- /dev/null +++ b/cpp-ethereum @@ -0,0 +1 @@ +Subproject commit 633c62c08bc73c7c3935c948a8d6c656a3659976 diff --git a/iguana/exchanges/LP_etomic.c b/iguana/exchanges/LP_etomic.c index 86e746edc..92641557f 100644 --- a/iguana/exchanges/LP_etomic.c +++ b/iguana/exchanges/LP_etomic.c @@ -21,7 +21,7 @@ // // Created by artem on 24.01.18. // -#include +#include "etomicswap/etomiclib.h" #define ETOMIC_ALICECONTRACT "0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c" #define ETOMIC_BOBCONTRACT "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2" diff --git a/iguana/exchanges/etomicswap/CMakeLists.txt b/iguana/exchanges/etomicswap/CMakeLists.txt new file mode 100644 index 000000000..0df98500a --- /dev/null +++ b/iguana/exchanges/etomicswap/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.9) +add_library(etomiclib etomiclib.cpp) +add_library(etomiccurl etomiccurl.c) +add_executable(alice alice.c) +add_executable(bob bob.c) +include_directories("${CMAKE_SOURCE_DIR}/cpp-ethereum") +target_link_libraries(etomiccurl PUBLIC curl libcrypto777) +target_link_libraries(etomiclib PUBLIC ethcore devcrypto devcore etomiccurl) +target_link_libraries(alice PUBLIC etomiclib) +target_link_libraries(bob PUBLIC etomiclib etomiccurl) \ No newline at end of file diff --git a/iguana/exchanges/etomicswap/alice.c b/iguana/exchanges/etomicswap/alice.c new file mode 100644 index 000000000..0b2508aac --- /dev/null +++ b/iguana/exchanges/etomicswap/alice.c @@ -0,0 +1,106 @@ +// +// Created by artem on 24.01.18. +// +#include +#include +#include +#include "etomiclib.h" +#include + +char* aliceContractAddress = "0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c"; +char* aliceAddress = "0x485d2cc2d13a9e12E4b53D606DB1c8adc884fB8a"; +char* bobAddress = "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41"; +char* tokenAddress = "0xc0eb7AeD740E1796992A08962c15661bDEB58003"; + +int main(int argc, char** argv) { + enum { INIT_ETH, INIT_ERC20, ALICE_CLAIMS, BOB_CLAIMS, ALICE_APPROVES_ERC20 }; + + if (argc < 2) { + return 1; + } + + int action = atoi(argv[1]); + char* result; + BasicTxData txData; + switch (action) + { + case INIT_ETH: + txData.amount = "1000000000000000000"; + txData.from = aliceAddress; + txData.to = aliceContractAddress; + txData.secretKey = getenv("ALICE_PK"); + + AliceSendsEthPaymentInput input = { + .dealId = argv[2], + .bobAddress = bobAddress, + .aliceHash = argv[3], + .bobHash = argv[4] + }; + + result = aliceSendsEthPayment(input, txData); + break; + case INIT_ERC20: + txData.amount = "0"; + txData.from = aliceAddress; + txData.to = aliceContractAddress; + txData.secretKey = getenv("ALICE_PK"); + + AliceSendsErc20PaymentInput input1 = { + .dealId = argv[2], + .bobAddress = bobAddress, + .aliceHash = argv[3], + .bobHash = argv[4], + .amount = "1000000000000000000", + .tokenAddress = tokenAddress + }; + + result = aliceSendsErc20Payment(input1, txData); + break; + case ALICE_CLAIMS: + txData.amount = "0"; + txData.from = aliceAddress; + txData.to = aliceContractAddress; + txData.secretKey = getenv("ALICE_PK"); + + AliceReclaimsAlicePaymentInput input2 = { + .dealId = argv[2], + .bobAddress = bobAddress, + .aliceHash = argv[3], + .bobSecret = argv[4], + .tokenAddress = argv[5], + .amount = "1000000000000000000" + }; + + result = aliceReclaimsAlicePayment(input2, txData); + break; + case BOB_CLAIMS: + txData.amount = "0"; + txData.from = bobAddress; + txData.to = aliceContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobSpendsAlicePaymentInput input3 = { + .dealId = argv[2], + .aliceAddress = aliceAddress, + .aliceSecret = argv[3], + .bobHash = argv[4], + .tokenAddress = argv[5], + .amount = "1000000000000000000" + }; + + result = bobSpendsAlicePayment(input3, txData); + break; + case ALICE_APPROVES_ERC20: + result = approveErc20( + "1000000000000000000", + "0x485d2cc2d13a9e12E4b53D606DB1c8adc884fB8a", + getenv("ALICE_PK") + ); + break; + default: + return 1; + } + printf("%s\n", result); + free(result); + return 0; +} diff --git a/iguana/exchanges/etomicswap/bob.c b/iguana/exchanges/etomicswap/bob.c new file mode 100644 index 000000000..a4d18d6df --- /dev/null +++ b/iguana/exchanges/etomicswap/bob.c @@ -0,0 +1,177 @@ +// +// Created by artem on 24.01.18. +// +#include +#include +#include +#include "etomiclib.h" +#include + +char* bobContractAddress = "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2"; +char* aliceAddress = "0x485d2cc2d13a9e12E4b53D606DB1c8adc884fB8a"; +char* bobAddress = "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41"; +char* tokenAddress = "0xc0eb7AeD740E1796992A08962c15661bDEB58003"; + +int main(int argc, char** argv) +{ + enum { + BOB_ETH_DEPOSIT, + BOB_ERC20_DEPOSIT, + BOB_CLAIMS_DEPOSIT, + ALICE_CLAIMS_DEPOSIT, + BOB_ETH_PAYMENT, + BOB_ERC20_PAYMENT, + BOB_CLAIMS_PAYMENT, + ALICE_CLAIMS_PAYMENT, + BOB_APPROVES_ERC20 + }; + if (argc < 3) { + return 1; + } + int action = atoi(argv[1]); + BasicTxData txData; + char* result; + switch (action) + { + case BOB_ETH_DEPOSIT: + txData.amount = "1000000000000000000"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobSendsEthDepositInput input = { + .aliceAddress = aliceAddress, + .depositId = argv[2], + .bobHash = argv[3] + }; + + result = bobSendsEthDeposit(input, txData); + break; + case BOB_ERC20_DEPOSIT: + txData.amount = "0"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobSendsErc20DepositInput input1 = { + .depositId = argv[2], + .amount = "1000000000000000000", + .aliceAddress = aliceAddress, + .bobHash = argv[3], + .tokenAddress = tokenAddress + }; + + result = bobSendsErc20Deposit(input1, txData); + break; + case BOB_CLAIMS_DEPOSIT: + txData.amount = "0"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobRefundsDepositInput input2 = { + .depositId = argv[2], + .amount = "1000000000000000000", + .aliceAddress = aliceAddress, + .tokenAddress = argv[3], + .aliceCanClaimAfter = argv[4], + .bobSecret = argv[5] + }; + + result = bobRefundsDeposit(input2, txData); + break; + case ALICE_CLAIMS_DEPOSIT: + txData.amount = "0"; + txData.from = aliceAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("ALICE_PK"); + + AliceClaimsBobDepositInput input3 = { + .depositId = argv[2], + .amount = "1000000000000000000", + .bobAddress = bobAddress, + .tokenAddress = argv[3], + .aliceCanClaimAfter = argv[4], + .bobHash = argv[5] + }; + + result = aliceClaimsBobDeposit(input3, txData); + break; + case BOB_ETH_PAYMENT: + txData.amount = "1000000000000000000"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobSendsEthPaymentInput input4 = { + .paymentId = argv[2], + .aliceHash = argv[3], + .aliceAddress = aliceAddress + }; + + result = bobSendsEthPayment(input4, txData); + break; + case BOB_ERC20_PAYMENT: + txData.amount = "0"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobSendsErc20PaymentInput input5 = { + .paymentId = argv[2], + .amount = "1000000000000000000", + .tokenAddress = tokenAddress, + .aliceAddress = aliceAddress, + .aliceHash = argv[3] + }; + + result = bobSendsErc20Payment(input5, txData); + break; + case BOB_CLAIMS_PAYMENT: + txData.amount = "0"; + txData.from = bobAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("BOB_PK"); + + BobReclaimsBobPaymentInput input6 = { + .paymentId = argv[2], + .aliceAddress = aliceAddress, + .amount = "1000000000000000000", + .tokenAddress = argv[3], + .bobCanClaimAfter = argv[4], + .aliceHash = argv[5] + }; + + result = bobReclaimsBobPayment(input6, txData); + break; + case ALICE_CLAIMS_PAYMENT: + txData.amount = "0"; + txData.from = aliceAddress; + txData.to = bobContractAddress; + txData.secretKey = getenv("ALICE_PK"); + + AliceSpendsBobPaymentInput input7 = { + .paymentId = argv[2], + .bobAddress = bobAddress, + .amount = "1000000000000000000", + .tokenAddress = argv[3], + .bobCanClaimAfter = argv[4], + .aliceSecret = argv[5] + }; + + result = aliceSpendsBobPayment(input7, txData); + break; + case BOB_APPROVES_ERC20: + result = approveErc20( + "10000000000000000000", + "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41", + getenv("BOB_PK") + ); + break; + default: + return 1; + } + printf("%s\n", result); + free(result); + return 0; +} diff --git a/iguana/exchanges/etomicswap/etomiccurl.c b/iguana/exchanges/etomicswap/etomiccurl.c new file mode 100644 index 000000000..9bb98ec31 --- /dev/null +++ b/iguana/exchanges/etomicswap/etomiccurl.c @@ -0,0 +1,112 @@ +#include "etomiccurl.h" +#include +#include +#include +#include "../../../includes/cJSON.h" + +static char* ethRpcUrl = "https://ropsten.infura.io/y07GHxUyTgeN2mdfOonu"; + +struct string { + char *ptr; + size_t len; +}; + +void init_eth_string(struct string *s) { + s->len = 0; + s->ptr = malloc(s->len+1); + if (s->ptr == NULL) { + fprintf(stderr, "malloc() failed\n"); + exit(EXIT_FAILURE); + } + s->ptr[0] = '\0'; +} + +size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) +{ + size_t new_len = s->len + size*nmemb; + s->ptr = realloc(s->ptr, new_len+1); + if (s->ptr == NULL) { + fprintf(stderr, "realloc() failed\n"); + exit(EXIT_FAILURE); + } + memcpy(s->ptr+s->len, ptr, size*nmemb); + s->ptr[new_len] = '\0'; + s->len = new_len; + + return size*nmemb; +} + +char* sendRequest(char* request) +{ + CURL *curl; + CURLcode res; + struct curl_slist *headers = NULL; + curl = curl_easy_init(); + if (curl) { + struct string s; + init_eth_string(&s); + + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); + curl_easy_setopt(curl, CURLOPT_URL, ethRpcUrl); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request); + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + /* Check for errors */ + if (res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + } + + /* always cleanup */ + curl_easy_cleanup(curl); + return s.ptr; + } else { + return NULL; + } +} + +char* sendRawTx(char* rawTx) +{ + char* string; + cJSON *request = cJSON_CreateObject(); + cJSON *params = cJSON_CreateArray(); + cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0")); + cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_sendRawTransaction")); + cJSON_AddItemToArray(params, cJSON_CreateString(rawTx)); + cJSON_AddItemToObject(request, "params", params); + cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2)); + string = cJSON_PrintUnformatted(request); + char* requestResult = sendRequest(string); + cJSON *json = cJSON_Parse(requestResult); + cJSON_Delete(request); + char* tmp = cJSON_GetObjectItem(json, "result")->valuestring; + char* txId = (char*)malloc(strlen(tmp) + 1); + strcpy(txId, tmp); + free(requestResult); + return txId; +} + +int getNonce(char* address) +{ + char* string; + cJSON *request = cJSON_CreateObject(); + cJSON *params = cJSON_CreateArray(); + cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0")); + cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_getTransactionCount")); + cJSON_AddItemToArray(params, cJSON_CreateString(address)); + cJSON_AddItemToArray(params, cJSON_CreateString("pending")); + cJSON_AddItemToObject(request, "params", params); + cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2)); + string = cJSON_PrintUnformatted(request); + char* requestResult = sendRequest(string); + cJSON_Delete(request); + cJSON *json = cJSON_Parse(requestResult); + int nonce = (int)strtol(cJSON_GetObjectItem(json, "result")->valuestring, NULL, 0); + cJSON_Delete(json); + free(requestResult); + return nonce; +} diff --git a/iguana/exchanges/etomicswap/etomiccurl.h b/iguana/exchanges/etomicswap/etomiccurl.h new file mode 100644 index 000000000..339f8bf19 --- /dev/null +++ b/iguana/exchanges/etomicswap/etomiccurl.h @@ -0,0 +1,10 @@ +#ifdef __cplusplus +extern "C"{ +#endif + +char* sendRawTx(char* rawTx); +int getNonce(char* address); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp new file mode 100644 index 000000000..cd8432e29 --- /dev/null +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -0,0 +1,334 @@ +// +// Created by artem on 24.01.18. +// +#include "etomiclib.h" +#include "etomiccurl.h" +#include +#include +#include +#include +using namespace dev; +using namespace dev::eth; + +char* stringStreamToChar(std::stringstream& ss) +{ + const std::string tmp = ss.str(); + auto result = (char*)malloc(strlen(tmp.c_str()) + 1); + strcpy(result, tmp.c_str()); + return result; +} + +TransactionSkeleton txDataToSkeleton(BasicTxData txData) +{ + TransactionSkeleton tx; + tx.from = jsToAddress(txData.from); + tx.to = jsToAddress(txData.to); + tx.value = jsToU256(txData.amount); + tx.gas = 300000; + tx.gasPrice = 100 * exp10<9>(); + tx.nonce = getNonce(txData.from); + return tx; +} + +char* signTx(TransactionSkeleton& tx, char* secret) +{ + Secret& secretKey = *(new Secret(secret)); + auto baseTx = new TransactionBase(tx, secretKey); + RLPStream& rlpStream = *(new RLPStream()); + baseTx->streamRLP(rlpStream); + std::stringstream& ss = *(new std::stringstream); + ss << rlpStream.out(); + return stringStreamToChar(ss); +} + +char* approveErc20(char* amount, char* from, char* secret) +{ + TransactionSkeleton tx; + tx.from = jsToAddress(from); + tx.to = jsToAddress("0xc0eb7AeD740E1796992A08962c15661bDEB58003"); + tx.value = 0; // exp10<18>(); + tx.gas = 300000; + tx.gasPrice = 100 * exp10<9>(); + tx.nonce = getNonce(from); + std::stringstream ss; + ss << "0x095ea7b3" + << "000000000000000000000000" + << toHex(jsToAddress("0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c")) + << toHex(toBigEndian(jsToU256(amount))); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, secret); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x47c7b6e2" + << toHex(jsToBytes(input.dealId)) + << "000000000000000000000000" + << toHex(jsToAddress(input.bobAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000" + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000"; + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x184db3bf" + << toHex(jsToBytes(input.dealId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << "000000000000000000000000" + << toHex(jsToAddress(input.bobAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000" + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000" + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x8b9a167a" + << toHex(jsToBytes(input.dealId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.bobAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000" + << "00000000000000000000000000000000000000000000000000000000000000c0" + << "0000000000000000000000000000000000000000000000000000000000000020" + << toHex(jsToBytes(input.bobSecret)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x392ec66b" + << toHex(jsToBytes(input.dealId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000" + << "00000000000000000000000000000000000000000000000000000000000000c0" + << "0000000000000000000000000000000000000000000000000000000000000020" + << toHex(jsToBytes(input.aliceSecret)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0xc2c5143f" + << toHex(jsToBytes(input.depositId)) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000"; + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0xce8bbe4b" + << toHex(jsToBytes(input.depositId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000" + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x1dbe6508" + << toHex(jsToBytes(input.depositId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << toHex(toBigEndian(jsToU256(input.aliceCanClaimAfter))) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << "00000000000000000000000000000000000000000000000000000000000000c0" + << "0000000000000000000000000000000000000000000000000000000000000020" + << toHex(jsToBytes(input.bobSecret)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x960173b5" + << toHex(jsToBytes(input.depositId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << toHex(toBigEndian(jsToU256(input.aliceCanClaimAfter))) + << "000000000000000000000000" + << toHex(jsToAddress(input.bobAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << toHex(jsToBytes(input.bobHash)) + << "000000000000000000000000"; + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0xcf36fe8e" + << toHex(jsToBytes(input.paymentId)) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000"; + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x34f64dfd" + << toHex(jsToBytes(input.paymentId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000" + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0xb7cc2312" + << toHex(jsToBytes(input.paymentId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << toHex(toBigEndian(jsToU256(input.bobCanClaimAfter))) + << "000000000000000000000000" + << toHex(jsToAddress(input.aliceAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << toHex(jsToBytes(input.aliceHash)) + << "000000000000000000000000"; + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss; + ss << "0x97004255" + << toHex(jsToBytes(input.paymentId)) + << toHex(toBigEndian(jsToU256(input.amount))) + << toHex(toBigEndian(jsToU256(input.bobCanClaimAfter))) + << "000000000000000000000000" + << toHex(jsToAddress(input.bobAddress)) + << "000000000000000000000000" + << toHex(jsToAddress(input.tokenAddress)) + << "00000000000000000000000000000000000000000000000000000000000000c0" + << "0000000000000000000000000000000000000000000000000000000000000020" + << toHex(jsToBytes(input.aliceSecret)); + tx.data = jsToBytes(ss.str()); + char* rawTx = signTx(tx, txData.secretKey); + char* result = sendRawTx(rawTx); + free(rawTx); + return result; +} + +char* privKey2Addr(char* privKey) +{ + Secret& secretKey = *(new Secret(privKey)); + std::stringstream& ss = *(new std::stringstream); + ss << "0x" << toAddress(secretKey); + return stringStreamToChar(ss); +}; + +char* pubKey2Addr(char* pubKey) +{ + Public& publicKey = *(new Public(pubKey)); + std::stringstream& ss = *(new std::stringstream); + ss << "0x" << toAddress(publicKey); + return stringStreamToChar(ss); +}; + +char* getPubKeyFromPriv(char* privKey) +{ + Public publicKey = toPublic(*(new Secret(privKey))); + std::stringstream& ss = *(new std::stringstream); + ss << "0x" << publicKey; + return stringStreamToChar(ss); +} diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h new file mode 100644 index 000000000..851a7ee11 --- /dev/null +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -0,0 +1,131 @@ +// +// Created by artem on 24.01.18. +// +#ifdef __cplusplus +extern "C" { +#endif +typedef struct { + char* from; + char* to; + char* amount; + char* secretKey; +} BasicTxData; + +typedef struct { + char* dealId; + char* bobAddress; + char* aliceHash; + char* bobHash; +} AliceSendsEthPaymentInput; + +typedef struct { + char* dealId; + char* amount; + char* tokenAddress; + char* bobAddress; + char* aliceHash; + char* bobHash; +} AliceSendsErc20PaymentInput; + +typedef struct { + char* dealId; + char* amount; + char* tokenAddress; + char* bobAddress; + char* aliceHash; + char* bobSecret; +} AliceReclaimsAlicePaymentInput; + +typedef struct { + char* dealId; + char* amount; + char* tokenAddress; + char* aliceAddress; + char* aliceSecret; + char* bobHash; +} BobSpendsAlicePaymentInput; + +typedef struct { + char* depositId; + char* aliceAddress; + char* bobHash; +} BobSendsEthDepositInput; + +typedef struct { + char* depositId; + char* amount; + char* tokenAddress; + char* aliceAddress; + char* bobHash; +} BobSendsErc20DepositInput; + +typedef struct { + char* depositId; + char* amount; + char* tokenAddress; + char* aliceAddress; + char* bobSecret; + char* aliceCanClaimAfter; +} BobRefundsDepositInput; + +typedef struct { + char* depositId; + char* amount; + char* tokenAddress; + char* bobAddress; + char* bobHash; + char* aliceCanClaimAfter; +} AliceClaimsBobDepositInput; + +typedef struct { + char* paymentId; + char* aliceAddress; + char* aliceHash; +} BobSendsEthPaymentInput; + +typedef struct { + char* paymentId; + char* amount; + char* tokenAddress; + char* aliceAddress; + char* aliceHash; +} BobSendsErc20PaymentInput; + +typedef struct { + char* paymentId; + char* amount; + char* tokenAddress; + char* aliceAddress; + char* aliceHash; + char* bobCanClaimAfter; +} BobReclaimsBobPaymentInput; + +typedef struct { + char* paymentId; + char* amount; + char* tokenAddress; + char* aliceSecret; + char* bobAddress; + char* bobCanClaimAfter; +} AliceSpendsBobPaymentInput; + +char* approveErc20(char* amount, char* from, char* secret); +char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData); +char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData); +char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData); +char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData); +char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData); +char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData); +char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData); +char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData); +char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData); +char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData); +char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData); +char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData); +char* privKey2Addr(char* privKey); +char* pubKey2Addr(char* pubKey); +char* getPubKeyFromPriv(char* privKey); +// Your prototype or Definition +#ifdef __cplusplus +} +#endif From b1ea433d0f75401793cb9c3b96f7ec8a3164ca65 Mon Sep 17 00:00:00 2001 From: Artem Pikulin Date: Wed, 7 Feb 2018 17:43:09 +0700 Subject: [PATCH 2/2] Add methods to get ETH and ERC20 balance. --- iguana/exchanges/etomicswap/bob.c | 35 +++++++++++++--- iguana/exchanges/etomicswap/etomiccurl.c | 50 +++++++++++++++++++++++ iguana/exchanges/etomicswap/etomiccurl.h | 2 + iguana/exchanges/etomicswap/etomiclib.cpp | 23 +++++++++++ iguana/exchanges/etomicswap/etomiclib.h | 4 ++ 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/iguana/exchanges/etomicswap/bob.c b/iguana/exchanges/etomicswap/bob.c index a4d18d6df..ede02320d 100644 --- a/iguana/exchanges/etomicswap/bob.c +++ b/iguana/exchanges/etomicswap/bob.c @@ -4,8 +4,8 @@ #include #include #include +#include #include "etomiclib.h" -#include char* bobContractAddress = "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2"; char* aliceAddress = "0x485d2cc2d13a9e12E4b53D606DB1c8adc884fB8a"; @@ -23,9 +23,11 @@ int main(int argc, char** argv) BOB_ERC20_PAYMENT, BOB_CLAIMS_PAYMENT, ALICE_CLAIMS_PAYMENT, - BOB_APPROVES_ERC20 + BOB_APPROVES_ERC20, + BOB_ETH_BALANCE, + BOB_ERC20_BALANCE, }; - if (argc < 3) { + if (argc < 2) { return 1; } int action = atoi(argv[1]); @@ -46,6 +48,8 @@ int main(int argc, char** argv) }; result = bobSendsEthDeposit(input, txData); + printf("%s\n", result); + free(result); break; case BOB_ERC20_DEPOSIT: txData.amount = "0"; @@ -62,6 +66,8 @@ int main(int argc, char** argv) }; result = bobSendsErc20Deposit(input1, txData); + printf("%s\n", result); + free(result); break; case BOB_CLAIMS_DEPOSIT: txData.amount = "0"; @@ -79,6 +85,8 @@ int main(int argc, char** argv) }; result = bobRefundsDeposit(input2, txData); + printf("%s\n", result); + free(result); break; case ALICE_CLAIMS_DEPOSIT: txData.amount = "0"; @@ -96,6 +104,8 @@ int main(int argc, char** argv) }; result = aliceClaimsBobDeposit(input3, txData); + printf("%s\n", result); + free(result); break; case BOB_ETH_PAYMENT: txData.amount = "1000000000000000000"; @@ -110,6 +120,8 @@ int main(int argc, char** argv) }; result = bobSendsEthPayment(input4, txData); + printf("%s\n", result); + free(result); break; case BOB_ERC20_PAYMENT: txData.amount = "0"; @@ -126,6 +138,8 @@ int main(int argc, char** argv) }; result = bobSendsErc20Payment(input5, txData); + printf("%s\n", result); + free(result); break; case BOB_CLAIMS_PAYMENT: txData.amount = "0"; @@ -143,6 +157,8 @@ int main(int argc, char** argv) }; result = bobReclaimsBobPayment(input6, txData); + printf("%s\n", result); + free(result); break; case ALICE_CLAIMS_PAYMENT: txData.amount = "0"; @@ -160,18 +176,27 @@ int main(int argc, char** argv) }; result = aliceSpendsBobPayment(input7, txData); + printf("%s\n", result); + free(result); break; case BOB_APPROVES_ERC20: result = approveErc20( "10000000000000000000", "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41", getenv("BOB_PK") + ); + printf("%s\n", result); + free(result); + break; + case BOB_ETH_BALANCE: + printf("%" PRIu64 "\n", getEthBalance(bobAddress)); + break; + case BOB_ERC20_BALANCE: + printf("%" PRIu64 "\n", getErc20Balance(bobAddress, tokenAddress)); break; default: return 1; } - printf("%s\n", result); - free(result); return 0; } diff --git a/iguana/exchanges/etomicswap/etomiccurl.c b/iguana/exchanges/etomicswap/etomiccurl.c index 9bb98ec31..f8e3958be 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.c +++ b/iguana/exchanges/etomicswap/etomiccurl.c @@ -86,6 +86,7 @@ char* sendRawTx(char* rawTx) char* tmp = cJSON_GetObjectItem(json, "result")->valuestring; char* txId = (char*)malloc(strlen(tmp) + 1); strcpy(txId, tmp); + cJSON_Delete(json); free(requestResult); return txId; } @@ -110,3 +111,52 @@ int getNonce(char* address) free(requestResult); return nonce; } + +char* getEthBalanceRequest(char* address) +{ + char* string; + cJSON *request = cJSON_CreateObject(); + cJSON *params = cJSON_CreateArray(); + cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0")); + cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_getBalance")); + cJSON_AddItemToArray(params, cJSON_CreateString(address)); + cJSON_AddItemToArray(params, cJSON_CreateString("latest")); + cJSON_AddItemToObject(request, "params", params); + cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2)); + string = cJSON_PrintUnformatted(request); + char* requestResult = sendRequest(string); + cJSON_Delete(request); + cJSON *json = cJSON_Parse(requestResult); + char* tmp = cJSON_GetObjectItem(json, "result")->valuestring; + char* balance = (char*)malloc(strlen(tmp) + 1); + strcpy(balance, tmp); + cJSON_Delete(json); + free(requestResult); + return balance; +} + +char* ethCall(char* to, const char* data) +{ + char* string; + cJSON *request = cJSON_CreateObject(); + cJSON *params = cJSON_CreateArray(); + cJSON *txObject = cJSON_CreateObject(); + cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0")); + cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_call")); + cJSON_AddStringToObject(txObject, "to", to); + cJSON_AddStringToObject(txObject, "data", data); + cJSON_AddItemToArray(params, txObject); + cJSON_AddItemToArray(params, cJSON_CreateString("latest")); + cJSON_AddItemToObject(request, "params", params); + cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2)); + string = cJSON_PrintUnformatted(request); + char* requestResult = sendRequest(string); + cJSON_Delete(request); + cJSON *json = cJSON_Parse(requestResult); + char* tmp = cJSON_GetObjectItem(json, "result")->valuestring; + char* balance = (char*)malloc(strlen(tmp) + 1); + strcpy(balance, tmp); + cJSON_Delete(json); + free(requestResult); + return balance; +} diff --git a/iguana/exchanges/etomicswap/etomiccurl.h b/iguana/exchanges/etomicswap/etomiccurl.h index 339f8bf19..54e71d4d5 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.h +++ b/iguana/exchanges/etomicswap/etomiccurl.h @@ -3,7 +3,9 @@ extern "C"{ #endif char* sendRawTx(char* rawTx); +char* ethCall(char* to, const char* data); int getNonce(char* address); +char* getEthBalanceRequest(char* address); #ifdef __cplusplus } diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp index cd8432e29..5e3fe6e2b 100644 --- a/iguana/exchanges/etomicswap/etomiclib.cpp +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -332,3 +332,26 @@ char* getPubKeyFromPriv(char* privKey) ss << "0x" << publicKey; return stringStreamToChar(ss); } + +uint64_t getEthBalance(char* address) +{ + char* hexBalance = getEthBalanceRequest(address); + // convert wei to satoshi + u256 balance = jsToU256(hexBalance) / exp10<10>(); + free(hexBalance); + return static_cast(balance); +} + +uint64_t getErc20Balance(char* address, char* tokenAddress) +{ + std::stringstream ss; + ss << "0x70a08231" + << "000000000000000000000000" + << toHex(jsToAddress(address)); + std::stringstream& resultStream = *(new std::stringstream); + char* hexBalance = ethCall(tokenAddress, ss.str().c_str()); + // convert wei to satoshi + u256 balance = jsToU256(hexBalance) / exp10<10>(); + free(hexBalance); + return static_cast(balance); +} diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h index 851a7ee11..a5267eb4a 100644 --- a/iguana/exchanges/etomicswap/etomiclib.h +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -1,6 +1,8 @@ // // Created by artem on 24.01.18. // +#include + #ifdef __cplusplus extern "C" { #endif @@ -125,6 +127,8 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData char* privKey2Addr(char* privKey); char* pubKey2Addr(char* pubKey); char* getPubKeyFromPriv(char* privKey); +uint64_t getEthBalance(char* address); +uint64_t getErc20Balance(char* address, char* tokenAddress); // Your prototype or Definition #ifdef __cplusplus }