From 881e79477f5b7eb2cf935e0c8be05ec899a0c0b9 Mon Sep 17 00:00:00 2001 From: Teemu Patja Date: Wed, 23 Aug 2017 15:11:46 +0300 Subject: [PATCH] Utility functions for transferring ETH and tokens * implemented some util functions to transfer ETH and ERC20 tokens for aiding testing * add and improve doctrings --- src/clj/commiteth/eth/core.clj | 48 +++++++++++++++++++++++ src/clj/commiteth/eth/multisig_wallet.clj | 27 ++++++++++--- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index 78c661d..37de53b 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -30,6 +30,7 @@ response (:body @(post (eth-rpc-url) options)) result (json/read-str response :key-fn keyword)] (log/debug body "\n" result) + (if (= (:id result) request-id) (:result result) (do @@ -57,6 +58,11 @@ [wei] (/ wei 1000000000000000000)) +(defn eth->wei + [eth] + (biginteger (* eth 1000000000000000000))) + + (defn hex->eth [hex digits] (->> hex hex->big-integer from-wei double (format (str "%." digits "f")))) @@ -74,6 +80,7 @@ (hex->eth (get-balance-hex account) digits)) (defn send-transaction + "Send transaction using default commiteth bot account." [from to value & [params]] (let [args (merge params {:from from @@ -91,6 +98,25 @@ args) (eth-password)]))) +(defn send-transaction-using-from-account + "Send transaction using account address in parameter from. Assumes + account has been unlocked." + [from to value & [params]] + (let [args (merge params + {:from from + :value value} + (when-not (nil? (gas-price)) + {:gasPrice (integer->hex (gas-price))}) + (when-not (contains? params :gas) + {:gas + (estimate-gas from to value params)}))] + (log/debug "args:" args) + (eth-rpc + "eth_sendTransaction" + [(if-not (nil? to) + (merge args {:to to}) + args)]))) + (defn get-transaction-receipt [hash] (eth-rpc "eth_getTransactionReceipt" [hash])) @@ -117,6 +143,28 @@ value (format "0x%x" 0)] (send-transaction from contract value {:data data}))) +(defn execute-using-addr + [from-addr from-passphrase contract method-id & params] + (eth-rpc "personal_unlockAccount" [from-addr from-passphrase 30]) + (let [data (apply format-call-params method-id params) + value (format "0x%x" 0)] + (send-transaction-using-from-account from-addr + contract + value + {:data data}))) + +(defn transfer-eth + "Transfer amount-wei of ETH from from-addr to to-addr." + [from-addr from-passphrase to-addr amount-wei] + (eth-rpc "personal_unlockAccount" [from-addr from-passphrase 30]) + (let [data "0x" + value (integer->hex amount-wei)] + (println "value" value) + (send-transaction-using-from-account from-addr + to-addr + value + {:data data}))) + (defn hex-ch->num [ch] diff --git a/src/clj/commiteth/eth/multisig_wallet.clj b/src/clj/commiteth/eth/multisig_wallet.clj index 7d5bfa1..eb8f28c 100644 --- a/src/clj/commiteth/eth/multisig_wallet.clj +++ b/src/clj/commiteth/eth/multisig_wallet.clj @@ -19,7 +19,8 @@ :get-token-list "getTokenList()" :create "create(address[],uint256)" :watch "watch(address)" - :balance-of "balanceOf(address)"}))) + :balance-of "balanceOf(address)" + :transfer "transfer(address,uint256)"}))) (def topics {:factory-create (eth/event-sig->topic-id "Create(address,address)") @@ -120,7 +121,7 @@ (BigInteger/valueOf 500000))) (defn convert-token-value - "Convert given value to decimal using given token's base" + "Convert given value to decimal using given token's base." [value token] (let [token-details (token-data/token-info token) token-base (:base token-details)] @@ -130,7 +131,8 @@ (defn token-balance-in-bounty - "Query (internal) ERC20 token balance from bounty contract for given token TLA" + "Query (internal) ERC20 token balance from bounty contract for given + token TLA." [bounty-addr token] (let [bounty-contract (load-bounty-contract bounty-addr) token-address (get-token-address token) @@ -142,7 +144,8 @@ (convert-token-value token)))) (defn token-balance - "Query balance of given ERC20 token TLA for given address from ERC20 contract" + "Query balance of given ERC20 token TLA for given address from ERC20 + contract." [bounty-addr token] (let [token-address (get-token-address token)] @@ -154,7 +157,8 @@ (defn token-balances - "Get a given bounty contract's token balances. Assumes contract's internal balances have been updated" + "Get a given bounty contract's token balances. Assumes contract's + internal balances have been updated." [bounty-addr] (let [bounty-contract (load-bounty-contract bounty-addr) token-addresses (-> bounty-contract @@ -168,3 +172,16 @@ (assert tla) [tla (token-balance bounty-addr tla)])) addrs))) {}))) + +(defn transfer-tokens + "Transfer mount of given ERC20 token from from-addr to + to-addr. Connected geth needs to have keys for the account and + passphrase needs to be supplied. Returns transaction ID." + [from-addr from-passphrase token to-addr amount] + (let [token-addr (get-token-address token)] + (eth/execute-using-addr from-addr + from-passphrase + token-addr + (method-ids :transfer) + to-addr + amount)))