From 1b91d611edaa4132ead1e61b60899c67424f9e65 Mon Sep 17 00:00:00 2001 From: Churikova Tetiana Date: Fri, 2 Mar 2018 17:37:20 +0200 Subject: [PATCH 01/48] Dockerfile for openbounty tests --- test/Dockerfile | 7 +++++++ test/end-to-end/tests/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test/Dockerfile diff --git a/test/Dockerfile b/test/Dockerfile new file mode 100644 index 0000000..b1a431c --- /dev/null +++ b/test/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.6 +COPY end-to-end/requirements.txt /app/requirements.txt +WORKDIR /app +RUN pip3 install -r requirements.txt +COPY end-to-end /app +ENTRYPOINT ["python3"] +CMD ["-m", "pytest", "-m", "sanity"] \ No newline at end of file diff --git a/test/end-to-end/tests/__init__.py b/test/end-to-end/tests/__init__.py index 49b8c0e..42559c5 100644 --- a/test/end-to-end/tests/__init__.py +++ b/test/end-to-end/tests/__init__.py @@ -9,7 +9,7 @@ class TestData(object): # define here path to your config.ini file # example - config_example.ini - self.config.read('config.ini') + self.config.read("tests/config.ini") # self.issue['title'] is set in GithubPage::create_new_bounty # self.issue['id'] is set in GithubPage::create_new_bounty From 9b762c652774e074341a4a4d54d11ac4f6c51621 Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Sun, 11 Mar 2018 14:00:07 +0700 Subject: [PATCH 02/48] add link to riot to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de5fd30..811b008 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Status Open Bounty +[![Riot Chat Badge](https://img.shields.io/badge/join%20%23openbounty-riot-green.svg)](https://chat.status.im/#/room/#openbounty:status.im) Allows you to set bounties for Github issues, paid out in Ether or any ERC-20 token. From 3e4a76175ca5b10770dbced9b8dcb072134f13f4 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Thu, 15 Feb 2018 18:43:39 +0200 Subject: [PATCH 03/48] Remove unused fns --- src/clj/commiteth/eth/multisig_wallet.clj | 24 ----------------------- 1 file changed, 24 deletions(-) diff --git a/src/clj/commiteth/eth/multisig_wallet.clj b/src/clj/commiteth/eth/multisig_wallet.clj index f5393ab..f4b7bed 100644 --- a/src/clj/commiteth/eth/multisig_wallet.clj +++ b/src/clj/commiteth/eth/multisig_wallet.clj @@ -191,30 +191,6 @@ [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))) - -(defn get-owners - "Return vector of multisig owner addresses." - [bounty-addr] - (let [bounty-contract (load-bounty-contract bounty-addr) - owner-addresses (-> bounty-contract - (.getOwners) - .get)] - (if owner-addresses - (mapv #(.toString %) (.getValue owner-addresses)) - []))) - (defn uint256 [x] (org.web3j.abi.datatypes.generated.Uint256. x)) From b1b28db640494d59d8217c58f32f08b9180ba17f Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Thu, 15 Feb 2018 19:35:49 +0200 Subject: [PATCH 04/48] Add offline transaction signing --- src/clj/commiteth/eth/core.clj | 97 ++++++++++----------------------- src/clj/commiteth/eth/web3j.clj | 32 ++++++++++- 2 files changed, 59 insertions(+), 70 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index c4c8fa5..c8e3e82 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -3,6 +3,7 @@ [org.httpkit.client :refer [post]] [clojure.java.io :as io] [commiteth.config :refer [env]] + [commiteth.eth.web3j :as web3j] [clojure.string :refer [join]] [clojure.tools.logging :as log] [clojure.string :as str] @@ -14,6 +15,7 @@ (defn eth-password [] (:eth-password env)) (defn gas-estimate-factor [] (env :gas-estimate-factor 1.0)) (defn auto-gas-price? [] (env :auto-gas-price? false)) +(defn offline-signing? [] (env :offline-signing? false)) (defn eth-gasstation-gas-price [] @@ -49,8 +51,10 @@ :id request-id}) options {:headers {"content-type" "application/json"} :body body} - response (:body @(post (eth-rpc-url) options)) - result (json/read-str response :key-fn keyword)] + response @(post (eth-rpc-url) options) + _ (log/info "eth-rpc method:" method) + _ (log/info "eth-rpc response:" response) + result (json/read-str (:body response) :key-fn keyword)] (log/debug body "\n" result) (if (= (:id result) request-id) @@ -128,44 +132,6 @@ [account digits] (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 - :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 - "personal_sendTransaction" - [(if-not (nil? to) - (merge args {:to to}) - 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])) @@ -189,33 +155,30 @@ (defn execute [from contract method-id gas-limit & params] (let [data (apply format-call-params method-id params) - value (format "0x%x" 0)] - (send-transaction from contract value (merge - {:data data} - (when gas-limit - {:gas gas-limit}))))) - -(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)] - (send-transaction-using-from-account from-addr - to-addr - value - {:data data}))) - + gas-price (gas-price) + value (format "0x%x" 0) + params (cond-> {:data data + :from from + :value value} + gas-price + (merge {:gasPrice (integer->hex gas-price)}) + contract + (merge {:to contract})) + gas (if gas-limit gas-limit + (estimate-gas from contract value params)) + params (cond-> (assoc params :gas gas) + (offline-signing?) + (web3j/get-signed-tx (biginteger gas-price) + (hex->big-integer gas) + contract + data))] + (if (offline-signing?) + (eth-rpc + "eth_sendRawTransaction" + [params]) + (eth-rpc + "personal_sendTransaction" + [params (eth-password)])))) (defn hex-ch->num [ch] diff --git a/src/clj/commiteth/eth/web3j.clj b/src/clj/commiteth/eth/web3j.clj index 2bd33df..504444c 100644 --- a/src/clj/commiteth/eth/web3j.clj +++ b/src/clj/commiteth/eth/web3j.clj @@ -1,10 +1,14 @@ (ns commiteth.eth.web3j - (:require [commiteth.eth.core :as eth] - [commiteth.config :refer [env]]) + (:require [commiteth.config :refer [env]]) (:import [org.web3j protocol.Web3j protocol.http.HttpService + protocol.core.DefaultBlockParameterName + protocol.core.methods.response.EthGetTransactionCount + protocol.core.methods.request.RawTransaction + utils.Numeric crypto.Credentials + crypto.TransactionEncoder crypto.WalletUtils])) @@ -25,4 +29,26 @@ {:password password :file-path file-path}))))) (defn create-web3j [] - (Web3j/build (HttpService. (eth/eth-rpc-url)))) + (Web3j/build (HttpService. (env :eth-rpc-url "http://localhost:8545")))) + +(defn get-signed-tx [gas-price gas-limit to data] + "Create a sign a raw transaction. + 'From' argument is not needed as it's already + encoded in credentials. + See https://web3j.readthedocs.io/en/latest/transactions.html#offline-transaction-signing" + (let [web3j (create-web3j) + nonce (.. (.ethGetTransactionCount web3j + (env :eth-account) + DefaultBlockParameterName/LATEST) + sendAsync + get + getTransactionCount) + tx (RawTransaction/createTransaction + nonce + gas-price + gas-limit + to + data) + signed (TransactionEncoder/signMessage tx (creds)) + hex-string (Numeric/toHexString signed)] + hex-string)) From 5fd22660d27cad58d4c14b323f234dfbb6bd7946 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Thu, 15 Feb 2018 20:29:41 +0200 Subject: [PATCH 05/48] eth: Adjust format-param to prepend "0x"; use format-param in get-transaction-receipt fix execute fn to properly invoke get-signed-tx --- src/clj/commiteth/eth/core.clj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index c8e3e82..d9fffb6 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -132,15 +132,15 @@ [account digits] (hex->eth (get-balance-hex account) digits)) -(defn get-transaction-receipt - [hash] - (eth-rpc "eth_getTransactionReceipt" [hash])) - (defn- format-param [param] (if (number? param) (format "%064x" param) - (clojure.string/replace (format "%64s" (subs param 2)) " " "0"))) + (clojure.string/replace (format "0x%64s" (subs param 2)) " " "0"))) + +(defn get-transaction-receipt + [hash] + (eth-rpc "eth_getTransactionReceipt" [(format-param hash)])) (defn format-call-params [method-id & params] @@ -166,12 +166,12 @@ (merge {:to contract})) gas (if gas-limit gas-limit (estimate-gas from contract value params)) - params (cond-> (assoc params :gas gas) - (offline-signing?) + params (if (offline-signing?) (web3j/get-signed-tx (biginteger gas-price) (hex->big-integer gas) contract - data))] + data) + (assoc params :gas gas))] (if (offline-signing?) (eth-rpc "eth_sendRawTransaction" From 26973ae7d5ac5d1df0852d2f7fee2cf1189dd5d5 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 17:56:44 +0200 Subject: [PATCH 06/48] Do not prepend '0x' to params --- src/clj/commiteth/eth/core.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index d9fffb6..f6689a6 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -136,11 +136,11 @@ [param] (if (number? param) (format "%064x" param) - (clojure.string/replace (format "0x%64s" (subs param 2)) " " "0"))) + (clojure.string/replace (format "%64s" (subs param 2)) " " "0"))) (defn get-transaction-receipt [hash] - (eth-rpc "eth_getTransactionReceipt" [(format-param hash)])) + (eth-rpc "eth_getTransactionReceipt" [hash])) (defn format-call-params [method-id & params] From 6feeb66989b5b80dbe0dd8920496a69433c4e1e4 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 18:17:50 +0200 Subject: [PATCH 07/48] Add info about offline-signing? to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 811b008..da31f2e 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ eth-account | Ethereum account ID for the bot eth-password | Ethereum account password for the bot eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore` +offline-signing? | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to Infura tokenreg-base-format | Should be set to `:status` github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps From 327ef2ee6a34e5929cedbd9002eb264e5ef857fb Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 18:20:42 +0200 Subject: [PATCH 08/48] Add :offline-signing? option to dev config.edn --- env/dev/resources/config.edn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn index 571a6ae..caee4f4 100644 --- a/env/dev/resources/config.edn +++ b/env/dev/resources/config.edn @@ -14,6 +14,9 @@ :eth-rpc-url "http://localhost:8545" :eth-wallet-file "/some/location" + ;; Specifies whether to sign transactions before sending. Should be false for local Geth, true for remote Infura + :offline-signing? false + ;; address of token registry to be used ;; this is the default value for ropsten :tokenreg-addr "0x7d127a3e3b5e72cd8f15e7dee650abe4fcced2b9" From ad7e3554d1485be710e5f862da32b1b6faaeb8d0 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 19:09:26 +0200 Subject: [PATCH 09/48] Add docs on connecting to Infura --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da31f2e..364ead4 100644 --- a/README.md +++ b/README.md @@ -93,14 +93,22 @@ Follow the steps [here](https://developer.github.com/apps/building-github-apps/c ## Running -### Geth -Launch a local geth node with the bot account unlocked: +### Ethereum node +There are two options for connecting to an Ethereum node: either run a local node or connect to a remote one like Infura. + +#### Local + +In order to launch a local geth node with the bot account unlocked issue the following command: ``` #!/bin/bash geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port 50100 --ipcpath ~/.ropsten/geth.ipc --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpcapi db,eth,net,web3,personal --rpccorsdomain "https://wallet.ethereum.org" --unlock "0xYOUR_ADDR" --password <(echo "YOUR_PASSPHRASE") ``` +#### Remote +Specify Infura URL in `config.edn` under `:eth-rpc-url` key, and set `:offline-signing?` to true. + + ### CSS auto-compilation Launch the following command in a separate shell: From 3eb0e255efc00ba4fe72a2171494a67a4d92c96a Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 19:15:58 +0200 Subject: [PATCH 10/48] Add more detailed info on Infura signup. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 364ead4..a8b8e3d 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port ``` #### Remote -Specify Infura URL in `config.edn` under `:eth-rpc-url` key, and set `:offline-signing?` to true. +Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the network you're connecting to (Mainnet/Ropsten) into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing?` to true. ### CSS auto-compilation From 9e455d3a2f5326b76fe4a6fdda9234c6ff0254ae Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 16 Feb 2018 19:40:57 +0200 Subject: [PATCH 11/48] Remove trailing question marks for config variable names These might interfere with environment variables that are being merged in by cprop. --- README.md | 4 ++-- env/dev/resources/config.edn | 2 +- src/clj/commiteth/eth/core.clj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a8b8e3d..0c0fd58 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ eth-account | Ethereum account ID for the bot eth-password | Ethereum account password for the bot eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore` -offline-signing? | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to Infura +offline-signing | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to Infura tokenreg-base-format | Should be set to `:status` github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps @@ -106,7 +106,7 @@ geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port ``` #### Remote -Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the network you're connecting to (Mainnet/Ropsten) into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing?` to true. +Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the network you're connecting to (Mainnet/Ropsten) into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing` to true. ### CSS auto-compilation diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn index caee4f4..8fe98e0 100644 --- a/env/dev/resources/config.edn +++ b/env/dev/resources/config.edn @@ -15,7 +15,7 @@ :eth-wallet-file "/some/location" ;; Specifies whether to sign transactions before sending. Should be false for local Geth, true for remote Infura - :offline-signing? false + :offline-signing false ;; address of token registry to be used ;; this is the default value for ropsten diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index f6689a6..6cb6109 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -14,8 +14,8 @@ (defn eth-account [] (:eth-account env)) (defn eth-password [] (:eth-password env)) (defn gas-estimate-factor [] (env :gas-estimate-factor 1.0)) -(defn auto-gas-price? [] (env :auto-gas-price? false)) -(defn offline-signing? [] (env :offline-signing? false)) +(defn auto-gas-price? [] (env :auto-gas-price false)) +(defn offline-signing? [] (env :offline-signing false)) (defn eth-gasstation-gas-price [] From 711a2d00275a1b38f2802b6c6c65822a85db2efb Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 19 Feb 2018 13:24:26 +0200 Subject: [PATCH 12/48] Update README with more info on Geth vs Infura --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0c0fd58..4639887 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ eth-account | Ethereum account ID for the bot eth-password | Ethereum account password for the bot eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore` -offline-signing | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to Infura +offline-signing | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to e.g. Infura or any remote Geth node that does not unlock accounts tokenreg-base-format | Should be set to `:status` github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps @@ -94,7 +94,7 @@ Follow the steps [here](https://developer.github.com/apps/building-github-apps/c ## Running ### Ethereum node -There are two options for connecting to an Ethereum node: either run a local node or connect to a remote one like Infura. +There are two options for connecting to an Ethereum node: either run a local node with an unlocked account, or connect to a remote Geth node or Infura. We will be connecting to Ropsten which is a test Ethereum network. #### Local @@ -106,7 +106,7 @@ geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port ``` #### Remote -Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the network you're connecting to (Mainnet/Ropsten) into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing` to true. +Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the Ropsten network into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing` to true. ### CSS auto-compilation From 6a5c4500c06b5d2c85697f4eb0a77d671eb0cee7 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 19 Feb 2018 17:45:07 +0200 Subject: [PATCH 13/48] Remove web3j ns --- src/clj/commiteth/eth/core.clj | 55 +++++++++++++++++++++++++++++++-- src/clj/commiteth/eth/web3j.clj | 54 -------------------------------- 2 files changed, 52 insertions(+), 57 deletions(-) delete mode 100644 src/clj/commiteth/eth/web3j.clj diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index 6cb6109..5286c04 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -3,12 +3,21 @@ [org.httpkit.client :refer [post]] [clojure.java.io :as io] [commiteth.config :refer [env]] - [commiteth.eth.web3j :as web3j] [clojure.string :refer [join]] [clojure.tools.logging :as log] [clojure.string :as str] [pandect.core :as pandect] - [commiteth.util.util :refer [json-api-request]])) + [commiteth.util.util :refer [json-api-request]]) + (:import [org.web3j + protocol.Web3j + protocol.http.HttpService + protocol.core.DefaultBlockParameterName + protocol.core.methods.response.EthGetTransactionCount + protocol.core.methods.request.RawTransaction + utils.Numeric + crypto.Credentials + crypto.TransactionEncoder + crypto.WalletUtils])) (defn eth-rpc-url [] (env :eth-rpc-url "http://localhost:8545")) (defn eth-account [] (:eth-account env)) @@ -17,6 +26,46 @@ (defn auto-gas-price? [] (env :auto-gas-price false)) (defn offline-signing? [] (env :offline-signing false)) +(defn wallet-file-path [] + (env :eth-wallet-file)) + +(defn wallet-password [] + (env :eth-password)) + +(defn creds [] + (let [password (wallet-password) + file-path (wallet-file-path)] + (if (and password file-path) + (WalletUtils/loadCredentials + password + file-path) + (throw (ex-info "Make sure you provided proper credentials in appropriate resources/config.edn" + {:password password :file-path file-path}))))) + +(defn create-web3j [] + (Web3j/build (HttpService. (eth-rpc-url)))) + +(defn get-signed-tx [gas-price gas-limit to data] + "Create a sign a raw transaction. + 'From' argument is not needed as it's already + encoded in credentials. + See https://web3j.readthedocs.io/en/latest/transactions.html#offline-transaction-signing" + (let [web3j (create-web3j) + nonce (.. (.ethGetTransactionCount web3j + (env :eth-account) + DefaultBlockParameterName/LATEST) + sendAsync + get + getTransactionCount) + tx (RawTransaction/createTransaction + nonce + gas-price + gas-limit + to + data) + signed (TransactionEncoder/signMessage tx (creds)) + hex-string (Numeric/toHexString signed)] + hex-string)) (defn eth-gasstation-gas-price [] (let [data (json-api-request "https://ethgasstation.info/json/ethgasAPI.json") @@ -167,7 +216,7 @@ gas (if gas-limit gas-limit (estimate-gas from contract value params)) params (if (offline-signing?) - (web3j/get-signed-tx (biginteger gas-price) + (get-signed-tx (biginteger gas-price) (hex->big-integer gas) contract data) diff --git a/src/clj/commiteth/eth/web3j.clj b/src/clj/commiteth/eth/web3j.clj deleted file mode 100644 index 504444c..0000000 --- a/src/clj/commiteth/eth/web3j.clj +++ /dev/null @@ -1,54 +0,0 @@ -(ns commiteth.eth.web3j - (:require [commiteth.config :refer [env]]) - (:import [org.web3j - protocol.Web3j - protocol.http.HttpService - protocol.core.DefaultBlockParameterName - protocol.core.methods.response.EthGetTransactionCount - protocol.core.methods.request.RawTransaction - utils.Numeric - crypto.Credentials - crypto.TransactionEncoder - crypto.WalletUtils])) - - -(defn wallet-file-path [] - (env :eth-wallet-file)) - -(defn wallet-password [] - (env :eth-password)) - -(defn creds [] - (let [password (wallet-password) - file-path (wallet-file-path)] - (if (and password file-path) - (WalletUtils/loadCredentials - password - file-path) - (throw (ex-info "Make sure you provided proper credentials in appropriate resources/config.edn" - {:password password :file-path file-path}))))) - -(defn create-web3j [] - (Web3j/build (HttpService. (env :eth-rpc-url "http://localhost:8545")))) - -(defn get-signed-tx [gas-price gas-limit to data] - "Create a sign a raw transaction. - 'From' argument is not needed as it's already - encoded in credentials. - See https://web3j.readthedocs.io/en/latest/transactions.html#offline-transaction-signing" - (let [web3j (create-web3j) - nonce (.. (.ethGetTransactionCount web3j - (env :eth-account) - DefaultBlockParameterName/LATEST) - sendAsync - get - getTransactionCount) - tx (RawTransaction/createTransaction - nonce - gas-price - gas-limit - to - data) - signed (TransactionEncoder/signMessage tx (creds)) - hex-string (Numeric/toHexString signed)] - hex-string)) From 096741f946cbf0541229695b2ff9a16fb17c30f3 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 19 Feb 2018 17:59:56 +0200 Subject: [PATCH 14/48] Default offline-signing to true --- README.md | 2 +- src/clj/commiteth/eth/core.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4639887..ced4f88 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ eth-account | Ethereum account ID for the bot eth-password | Ethereum account password for the bot eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore` -offline-signing | Specifies whether to sign transactions locally before sending. Default is false. Set to true when connecting to e.g. Infura or any remote Geth node that does not unlock accounts +offline-signing | Specifies whether to sign transactions locally before sending. Default is true. Set to false when connecting to local Geth node that unlocks accounts tokenreg-base-format | Should be set to `:status` github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index 5286c04..97c5d6a 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -24,7 +24,7 @@ (defn eth-password [] (:eth-password env)) (defn gas-estimate-factor [] (env :gas-estimate-factor 1.0)) (defn auto-gas-price? [] (env :auto-gas-price false)) -(defn offline-signing? [] (env :offline-signing false)) +(defn offline-signing? [] (env :offline-signing true)) (defn wallet-file-path [] (env :eth-wallet-file)) From a72e2534fbed7878c1239087da5dc3898ea9bd66 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 20 Feb 2018 13:42:55 +0200 Subject: [PATCH 15/48] Change default value for offline signing to true in config --- env/dev/resources/config.edn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn index 8fe98e0..1f8248f 100644 --- a/env/dev/resources/config.edn +++ b/env/dev/resources/config.edn @@ -15,7 +15,7 @@ :eth-wallet-file "/some/location" ;; Specifies whether to sign transactions before sending. Should be false for local Geth, true for remote Infura - :offline-signing false + :offline-signing true ;; address of token registry to be used ;; this is the default value for ropsten From 0be2b5a184c5496a25f52b7acb0aa56eb13645f5 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 20 Feb 2018 13:58:28 +0200 Subject: [PATCH 16/48] Remove web3j reference --- src/clj/commiteth/eth/multisig_wallet.clj | 5 ++--- src/clj/commiteth/eth/token_registry.clj | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/clj/commiteth/eth/multisig_wallet.clj b/src/clj/commiteth/eth/multisig_wallet.clj index f4b7bed..48a42a9 100644 --- a/src/clj/commiteth/eth/multisig_wallet.clj +++ b/src/clj/commiteth/eth/multisig_wallet.clj @@ -1,8 +1,7 @@ (ns commiteth.eth.multisig-wallet - (:require [commiteth.eth.core :as eth] - [commiteth.config :refer [env]] - [commiteth.eth.web3j + (:require [commiteth.eth.core :as eth :refer [create-web3j creds]] + [commiteth.config :refer [env]] [clojure.tools.logging :as log] [commiteth.eth.token-data :as token-data]) (:import [org.web3j diff --git a/src/clj/commiteth/eth/token_registry.clj b/src/clj/commiteth/eth/token_registry.clj index 2d60cc9..9135f8d 100644 --- a/src/clj/commiteth/eth/token_registry.clj +++ b/src/clj/commiteth/eth/token_registry.clj @@ -1,6 +1,5 @@ (ns commiteth.eth.token-registry - (:require [commiteth.eth.core :as eth] - [commiteth.eth.web3j + (:require [commiteth.eth.core :as eth :refer [create-web3j creds]] [commiteth.config :refer [env]] [clojure.tools.logging :as log]) From 2245ddf1245361f6a22c734c52a905ba54c37171 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Fri, 23 Feb 2018 17:13:18 +0200 Subject: [PATCH 17/48] Comment out method and response logging --- src/clj/commiteth/eth/core.clj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index 97c5d6a..a8f7a4f 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -101,8 +101,6 @@ options {:headers {"content-type" "application/json"} :body body} response @(post (eth-rpc-url) options) - _ (log/info "eth-rpc method:" method) - _ (log/info "eth-rpc response:" response) result (json/read-str (:body response) :key-fn keyword)] (log/debug body "\n" result) From 79ac7624326cb7a226c2f6a19dba556c69291737 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 16:52:06 +0200 Subject: [PATCH 18/48] Use safe-read-str in order to catch JSON parsing exceptions --- src/clj/commiteth/eth/core.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index a8f7a4f..00daaeb 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -91,6 +91,21 @@ (gas-price-from-config))) (gas-price-from-config))) +(defn safe-read-str [s] + (if (nil? s) + (do + (log/error "JSON response is nil") + nil) + (try + (json/read-str s :key-fn keyword) + (catch Exception ex + (do (log/error "Exception when parsing json string:" + s + "message:" + ex) + + nil))))) + (defn eth-rpc [method params] (let [request-id (rand-int 4096) @@ -101,7 +116,7 @@ options {:headers {"content-type" "application/json"} :body body} response @(post (eth-rpc-url) options) - result (json/read-str (:body response) :key-fn keyword)] + result (safe-read-str (:body response))] (log/debug body "\n" result) (if (= (:id result) request-id) From f80e1ad0002794a5308991da9bbc976960152df8 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 16:54:14 +0200 Subject: [PATCH 19/48] Use testnet-token-data not on testnet --- src/clj/commiteth/eth/token_data.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clj/commiteth/eth/token_data.clj b/src/clj/commiteth/eth/token_data.clj index 06703f3..680953c 100644 --- a/src/clj/commiteth/eth/token_data.clj +++ b/src/clj/commiteth/eth/token_data.clj @@ -15,7 +15,7 @@ (defn update-data [] (let [test-data (env :testnet-token-data) token-data - (if (and (env :on-testnet true) + (if (and #_(env :on-testnet true) test-data) test-data (into {} From 3eede3ac9305fe9868fc036c30927c9b52b16f9d Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 16:54:38 +0200 Subject: [PATCH 20/48] Print OAuth access token to logs --- src/clj/commiteth/routes/redirect.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/clj/commiteth/routes/redirect.clj b/src/clj/commiteth/routes/redirect.clj index 01018fa..6aaaf2e 100644 --- a/src/clj/commiteth/routes/redirect.clj +++ b/src/clj/commiteth/routes/redirect.clj @@ -39,6 +39,7 @@ body (keywordize-keys (codec/form-decode (:body resp))) scope (:scope body) access-token (:access_token body)] + (log/info "access-token:" access-token) (log/debug "github sign-in callback, response body:" body) (if (:error body) ;; Why does Mist browser sends two redirects at the same time? The latter results in 401 error. From cd44e1596918c8e5795523561235d42ff19411ac Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 17:06:53 +0200 Subject: [PATCH 21/48] Add fn for fetching all issues labeles as bounty --- src/clj/commiteth/github/core.clj | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/clj/commiteth/github/core.clj b/src/clj/commiteth/github/core.clj index f6b4ea9..efe6551 100644 --- a/src/clj/commiteth/github/core.clj +++ b/src/clj/commiteth/github/core.clj @@ -3,6 +3,7 @@ [core :as tentacles] [repos :as repos] [oauth :as oauth] + [search :as search] [users :as users] [repos :as repos] [issues :as issues] @@ -27,6 +28,8 @@ (defn on-testnet? [] (env :on-testnet)) (defn webhook-secret [] (env :webhook-secret)) + + (defn authorize-url [scope] (let [params (codec/form-encode {:client_id (client-id) :redirect_uri (redirect-uri) @@ -360,3 +363,30 @@ (let [[owner repo] (str/split full-repo #"/")] (log/debug "creating bounty label" (str owner "/" repo) token) (issues/create-label owner repo "bounty" "fafad2" (auth-params token)))) + +(defn get-labeled-issues-for-repos [repos auth-params] + "Find all issues with a bounty label in provided repos" + (let [get-last-part (fn get-last-part [s] + (subs s (inc (str/last-index-of s "/")))) + get-issue-info (fn get-issue-info [issue] + (hash-map :owner r + :repo (get-last-part (:repository_url issue)) + :id (:id issue) + :number (:number issue) + :title (:title issue) + :url (:html_url issue) + :created_at (:created_at issue) + :closed_at (:closed_at issue))) + issues (for [r repos] + (loop [repo-issues [] i 1] + (let [params (into auth-params + {:sort "created" :order "desc" :page i}) + issues-page (-> (search/search-issues + nil + {:label "bounty" :user r :type "issue"} + params) + :items)] + (if (first issues-page) + (recur (into repo-issues (map get-issue-info issues-page)) (inc i)) + repo-issues))))] + (apply concat issues))) From 6fac1eee9aaa5c23e672996e07b3de00aacbea8f Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 17:14:08 +0200 Subject: [PATCH 22/48] Add exception handling inside doseq in scheduler tasks --- src/clj/commiteth/scheduler.clj | 292 ++++++++++++++++++-------------- 1 file changed, 164 insertions(+), 128 deletions(-) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 0c35df3..019c11b 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -15,43 +15,50 @@ [clj-time.periodic :refer [periodic-seq]] [chime :refer [chime-at]])) + (defn update-issue-contract-address "For each pending deployment: gets transaction receipt, updates db state (contract-address, comment-id) and posts github comment" [] + (log/info "In update-issue-contract-address") (doseq [{issue-id :issue_id transaction-hash :transaction_hash} (issues/list-pending-deployments)] - (log/debug "pending deployment:" transaction-hash) - (when-let [receipt (eth/get-transaction-receipt transaction-hash)] - (log/info "update-issue-contract-address: transaction receipt for issue #" - issue-id ": " receipt) - (if-let [contract-address (multisig/find-created-multisig-address receipt)] - (let [issue (issues/update-contract-address issue-id contract-address) - {owner :owner - repo :repo - comment-id :comment_id - issue-number :issue_number} issue - balance-eth-str (eth/get-balance-eth contract-address 6) - balance-eth (read-string balance-eth-str)] - (log/info "Updating comment image") - (bounties/update-bounty-comment-image issue-id - owner - repo - issue-number - contract-address - balance-eth - balance-eth-str - {}) - (log/info "Updating comment") - (github/update-comment owner - repo - comment-id - issue-number - contract-address - balance-eth - balance-eth-str - {})) - (log/error "Failed to find contract address in tx logs"))))) + (log/info "pending deployment:" transaction-hash) + (try + (when-let [receipt (eth/get-transaction-receipt transaction-hash)] + (log/info "update-issue-contract-address: transaction receipt for issue #" + issue-id ": " receipt) + (if-let [contract-address (multisig/find-created-multisig-address receipt)] + (let [issue (issues/update-contract-address issue-id contract-address) + {owner :owner + repo :repo + comment-id :comment_id + issue-number :issue_number} issue + balance-eth-str (eth/get-balance-eth contract-address 6) + balance-eth (read-string balance-eth-str)] + (log/info "Updating comment image") + (bounties/update-bounty-comment-image issue-id + owner + repo + issue-number + contract-address + balance-eth + balance-eth-str + {}) + (log/info "Updating comment") + (github/update-comment owner + repo + comment-id + issue-number + contract-address + balance-eth + balance-eth-str + {})) + (log/error "Failed to find contract address in tx logs"))) + (catch Throwable ex + (do (log/error "update-issue-contract-address exception:" ex) + (clojure.stacktrace/print-stack-trace ex))))) + (log/info "Exit update-issue-contract-address")) (defn deploy-contract [owner-address issue-id] @@ -85,6 +92,7 @@ (defn self-sign-bounty "Walks through all issues eligible for bounty payout and signs corresponding transaction" [] + (log/info "In self-sign-bounty") (doseq [{contract-address :contract_address issue-id :issue_id payout-address :payout_address @@ -94,35 +102,42 @@ issue-number :issue_number balance-eth :balance_eth tokens :tokens - winner-login :winner_login} (db-bounties/pending-bounties) - :let [value (eth/get-balance-hex contract-address)]] - (if (empty? payout-address) - (do - (log/error "Cannot sign pending bounty - winner has no payout address") - (github/update-merged-issue-comment owner - repo - comment-id - contract-address - (eth-decimal->str balance-eth) - tokens - winner-login - true)) - (let [execute-hash (multisig/send-all contract-address payout-address)] - (log/info "Payout self-signed, called sign-all(" contract-address payout-address ") tx:" execute-hash) - (db-bounties/update-execute-hash issue-id execute-hash) - (db-bounties/update-winner-login issue-id winner-login) - (github/update-merged-issue-comment owner - repo - comment-id - contract-address - (eth-decimal->str balance-eth) - tokens - winner-login - false))))) + winner-login :winner_login} (db-bounties/pending-bounties)] + (try + (let [value (eth/get-balance-hex contract-address)] + (if (empty? payout-address) + (do + (log/error "Cannot sign pending bounty - winner has no payout address") + (github/update-merged-issue-comment owner + repo + comment-id + contract-address + (eth-decimal->str balance-eth) + tokens + winner-login + true)) + (let [execute-hash (multisig/send-all contract-address payout-address)] + (log/info "Payout self-signed, called sign-all(" contract-address payout-address ") tx:" execute-hash) + (db-bounties/update-execute-hash issue-id execute-hash) + (db-bounties/update-winner-login issue-id winner-login) + (github/update-merged-issue-comment owner + repo + comment-id + contract-address + (eth-decimal->str balance-eth) + tokens + winner-login + false)))) + (catch Throwable ex + (do (log/error "self-sign-bounty exception:" ex) + (clojure.stacktrace/print-stack-trace ex))))) + (log/info "Exit self-sign-bounty") + ) (defn update-confirm-hash "Gets transaction receipt for each pending payout and updates DB confirm_hash with tranaction ID of commiteth bot account's confirmation." [] + (log/info "In update-confirm-hash") (doseq [{issue-id :issue_id execute-hash :execute_hash} (db-bounties/pending-payouts)] (log/info "pending payout:" execute-hash) @@ -130,7 +145,8 @@ (log/info "execution receipt for issue #" issue-id ": " receipt) (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] (log/info "confirm hash:" confirm-hash) - (db-bounties/update-confirm-hash issue-id confirm-hash))))) + (db-bounties/update-confirm-hash issue-id confirm-hash)))) + (log/info "Exit update-confirm-hash")) (defn update-watch-hash @@ -154,6 +170,7 @@ (defn update-payout-receipt "Gets transaction receipt for each confirmed payout and updates payout_hash" [] + (log/info "In update-payout-receipt") (doseq [{issue-id :issue_id payout-hash :payout_hash contract-address :contract_address @@ -167,32 +184,38 @@ payee-login :payee_login updated :updated} (db-bounties/confirmed-payouts)] (log/debug "confirmed payout:" payout-hash) - (if-let [receipt (eth/get-transaction-receipt payout-hash)] - (let [contract-tokens (multisig/token-balances contract-address) - contract-eth-balance (eth/get-balance-wei contract-address)] - (if (or - (some #(> (second %) 0.0) contract-tokens) - (> contract-eth-balance 0)) - (do - (log/info "Contract still has funds") - (when (multisig/is-confirmed? contract-address confirm-id) - (log/info "Detected bounty with funds and confirmed payout, calling executeTransaction") - (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] - (log/info "execute tx:" execute-tx-hash)))) + (try + (if-let [receipt (eth/get-transaction-receipt payout-hash)] + (let [contract-tokens (multisig/token-balances contract-address) + contract-eth-balance (eth/get-balance-wei contract-address)] + (if (or + (some #(> (second %) 0.0) contract-tokens) + (> contract-eth-balance 0)) + (do + (log/info "Contract still has funds") + (when (multisig/is-confirmed? contract-address confirm-id) + (log/info "Detected bounty with funds and confirmed payout, calling executeTransaction") + (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] + (log/info "execute tx:" execute-tx-hash)))) - (do - (log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt) - (db-bounties/update-payout-receipt issue-id receipt) - (github/update-paid-issue-comment owner - repo - comment-id - contract-address - (eth-decimal->str balance-eth) - tokens - payee-login)))) - (when (older-than-3h? updated) - (log/info "Resetting payout hash for issue" issue-id "as it has not been mined in 3h") - (db-bounties/reset-payout-hash issue-id))))) + (do + (log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt) + (db-bounties/update-payout-receipt issue-id receipt) + (github/update-paid-issue-comment owner + repo + comment-id + contract-address + (eth-decimal->str balance-eth) + tokens + payee-login)))) + (when (older-than-3h? updated) + (log/info "Resetting payout hash for issue" issue-id "as it has not been mined in 3h") + (db-bounties/reset-payout-hash issue-id))) + (catch Throwable ex + (do (log/error "update-payout-receipt exception:" ex) + (clojure.stacktrace/print-stack-trace ex))))) + (log/info "Exit update-payout-receipt") + ) (defn abs "(abs n) is the absolute value of n" @@ -213,17 +236,24 @@ (defn update-bounty-token-balances "Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts." [issue-id bounty-addr watch-hash] + (log/info "In update-bounty-token-balances for issue" issue-id) (doseq [[tla token-data] (token-data/as-map)] - (let [balance (multisig/token-balance bounty-addr tla)] - (when (> balance 0) - (do - (log/debug "bounty at" bounty-addr "has" balance "of token" tla) - (let [internal-balance (multisig/token-balance-in-bounty bounty-addr tla)] - (when (and (nil? watch-hash) - (not= balance internal-balance)) - (log/info "balances not in sync, calling watch") - (let [hash (multisig/watch-token bounty-addr tla)] - (db-bounties/update-watch-hash issue-id hash))))))))) + (try + (let [balance (multisig/token-balance bounty-addr tla)] + (when (> balance 0) + (do + (log/info "bounty at" bounty-addr "has" balance "of token" tla) + (let [internal-balance (multisig/token-balance-in-bounty bounty-addr tla)] + (when (and (nil? watch-hash) + (not= balance internal-balance)) + (log/info "balances not in sync, calling watch") + (let [hash (multisig/watch-token bounty-addr tla)] + (db-bounties/update-watch-hash issue-id hash))))))) + (catch Throwable ex + (do (log/error "update-bounty-token-balances exception:" ex) + (clojure.stacktrace/print-stack-trace ex))))) + (log/info "Exit update-bounty-token-balances")) + (defn update-contract-internal-balances "It is required in our current smart contract to manually update it's internal balance when some tokens have been added." @@ -263,6 +293,7 @@ (defn update-balances [] + (log/info "In update-balances") (doseq [{contract-address :contract_address owner :owner repo :repo @@ -271,43 +302,48 @@ db-balance-eth :balance_eth db-tokens :tokens issue-number :issue_number} (db-bounties/open-bounty-contracts)] - (when comment-id - (let [balance-eth-str (eth/get-balance-eth contract-address 6) - balance-eth (read-string balance-eth-str) - token-balances (multisig/token-balances contract-address)] - (log/debug "update-balances" balance-eth - balance-eth-str token-balances owner repo issue-number) + (try + (when comment-id + (let [balance-eth-str (eth/get-balance-eth contract-address 6) + balance-eth (read-string balance-eth-str) + token-balances (multisig/token-balances contract-address)] + (log/debug "update-balances" balance-eth + balance-eth-str token-balances owner repo issue-number) - (when (or - (not (float= db-balance-eth balance-eth)) - (not= db-tokens token-balances)) - (log/debug "balances differ") - (log/debug "ETH (db):" db-balance-eth (type db-balance-eth) ) - (log/debug "ETH (chain):" balance-eth (type balance-eth) ) - (log/debug "ETH cmp:" (float= db-balance-eth balance-eth)) - (log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens))) - (log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances))) - (log/debug "tokens cmp:" (= db-tokens token-balances)) + (when (or + (not (float= db-balance-eth balance-eth)) + (not= db-tokens token-balances)) + (log/debug "balances differ") + (log/debug "ETH (db):" db-balance-eth (type db-balance-eth) ) + (log/debug "ETH (chain):" balance-eth (type balance-eth) ) + (log/debug "ETH cmp:" (float= db-balance-eth balance-eth)) + (log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens))) + (log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances))) + (log/debug "tokens cmp:" (= db-tokens token-balances)) - (issues/update-eth-balance contract-address balance-eth) - (issues/update-token-balances contract-address token-balances) - (bounties/update-bounty-comment-image issue-id - owner - repo - issue-number - contract-address - balance-eth - balance-eth-str - token-balances) - (github/update-comment owner - repo - comment-id - issue-number - contract-address - balance-eth - balance-eth-str - token-balances) - (update-issue-usd-value contract-address)))))) + (issues/update-eth-balance contract-address balance-eth) + (issues/update-token-balances contract-address token-balances) + (bounties/update-bounty-comment-image issue-id + owner + repo + issue-number + contract-address + balance-eth + balance-eth-str + token-balances) + (github/update-comment owner + repo + comment-id + issue-number + contract-address + balance-eth + balance-eth-str + token-balances) + (update-issue-usd-value contract-address)))) + (catch Throwable ex + (do (log/error "update-balances exception:" ex) + (clojure.stacktrace/print-stack-trace ex))))) + (log/info "Exit update-balances")) (defn wrap-in-try-catch [func] @@ -323,7 +359,7 @@ (defn run-1-min-interval-tasks [time] (do - (log/debug "run-1-min-interval-tasks" time) + (log/info "run-1-min-interval-tasks" time) ;; TODO: disabled for now. looks like it may cause extraneus ;; contract deployments and costs (run-tasks From 6a9b9abf3e302b34a1f31173e1490341dfa87d28 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 26 Feb 2018 17:20:42 +0200 Subject: [PATCH 23/48] Fix compilation error --- src/clj/commiteth/github/core.clj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/clj/commiteth/github/core.clj b/src/clj/commiteth/github/core.clj index efe6551..93a4f56 100644 --- a/src/clj/commiteth/github/core.clj +++ b/src/clj/commiteth/github/core.clj @@ -368,7 +368,7 @@ "Find all issues with a bounty label in provided repos" (let [get-last-part (fn get-last-part [s] (subs s (inc (str/last-index-of s "/")))) - get-issue-info (fn get-issue-info [issue] + get-issue-info (fn get-issue-info [r issue] (hash-map :owner r :repo (get-last-part (:repository_url issue)) :id (:id issue) @@ -387,6 +387,8 @@ params) :items)] (if (first issues-page) - (recur (into repo-issues (map get-issue-info issues-page)) (inc i)) + (recur (into repo-issues + (map (partial get-issue-info r) issues-page)) + (inc i)) repo-issues))))] (apply concat issues))) From ef8683cf283b1e294dc76cc100c4049b1f30e1a9 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 6 Mar 2018 15:34:43 +0200 Subject: [PATCH 24/48] Change Jenkins node from linux to macos --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 219d449..4b24c0e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,4 +36,4 @@ def dockerreponame = "statusim/openbounty-app" // slackSend color: 'bad', message: REPO + ":" + BRANCH_NAME + ' failed to build. ' + env.BUILD_URL throw e } -} \ No newline at end of file +} From 39fc3d8f25182323a6c65b056b91a9b7ef530475 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 6 Mar 2018 15:41:13 +0200 Subject: [PATCH 25/48] Change Jenkins node from linux to master --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4b24c0e..c507979 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ #!/usr/bin/env groovy -node('linux') { +node('master') { checkout scm def dockerreponame = "statusim/openbounty-app" From 58cf339620333a2fe65b47ada88ef5889775a405 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 6 Mar 2018 15:42:16 +0200 Subject: [PATCH 26/48] Change Jenkins node from master to linux --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index c507979..4b24c0e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ #!/usr/bin/env groovy -node('master') { +node('linux') { checkout scm def dockerreponame = "statusim/openbounty-app" From 7b600f6f1255dda7cc3c3f270ad4bdea5c645b2c Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 6 Mar 2018 15:46:53 +0200 Subject: [PATCH 27/48] Remove superfluous update-token-balances logging --- src/clj/commiteth/scheduler.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 019c11b..f9c25dd 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -236,7 +236,7 @@ (defn update-bounty-token-balances "Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts." [issue-id bounty-addr watch-hash] - (log/info "In update-bounty-token-balances for issue" issue-id) + #_(log/info "In update-bounty-token-balances for issue" issue-id) (doseq [[tla token-data] (token-data/as-map)] (try (let [balance (multisig/token-balance bounty-addr tla)] @@ -252,7 +252,7 @@ (catch Throwable ex (do (log/error "update-bounty-token-balances exception:" ex) (clojure.stacktrace/print-stack-trace ex))))) - (log/info "Exit update-bounty-token-balances")) + #_(log/info "Exit update-bounty-token-balances")) (defn update-contract-internal-balances From 6bc607916c96927ede73f4ef303b2fd2f9ef73e7 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 6 Mar 2018 17:37:34 +0200 Subject: [PATCH 28/48] Install wkhtmltoimage for PNG generation --- Dockerfile | 5 +++++ html2png.sh | 3 +++ 2 files changed, 8 insertions(+) create mode 100755 html2png.sh diff --git a/Dockerfile b/Dockerfile index ce2947a..83164d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,12 @@ RUN lein uberjar FROM clojure WORKDIR /root/ +RUN apt-get update +RUN apt-get -y install xvfb +RUN apt-get -y install wkhtmltopdf + COPY --from=builder /usr/src/app/target/uberjar/commiteth.jar . +COPY html2png.sh . CMD [""] ENTRYPOINT ["/usr/bin/java", "-Duser.timezone=UTC", "-Dconf=config-test.edn", "-jar", "/root/commiteth.jar"] diff --git a/html2png.sh b/html2png.sh new file mode 100755 index 0000000..781d8d5 --- /dev/null +++ b/html2png.sh @@ -0,0 +1,3 @@ +#!/bin/bash -eu +# need to run wkhtmltoimage in quiet mode because it misuses stdout +xvfb-run -a -s "-screen 0 640x480x16" wkhtmltoimage -q "$@" 2>/dev/null From 5888d70801e818c02bc67c371339f2b379e969d4 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 17:31:47 +0200 Subject: [PATCH 29/48] Catch exceptions during token value formatting --- src/clj/commiteth/routes/services.clj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index d813962..43f1458 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -146,7 +146,11 @@ (defn prettify-bounty-items [bounty-items] - (let [renames {:user_name :display-name + (let [format-float (fn [balance] + (try + (format "%.2f" balance) + (catch java.util.IllegalFormatConversionException ex "0.00"))) + renames {:user_name :display-name :user_avatar_url :avatar-url :issue_title :issue-title :type :item-type @@ -164,7 +168,7 @@ (update :tokens (fn [tokens] (into {} (map (fn [[tla balance]] - [tla (format "%.2f" balance)]) + [tla (format-float balance)]) tokens))))) bounty-items))) From a7e2b60d833e540e8ed4f6cf3df919ff2a6536e8 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 17:35:38 +0200 Subject: [PATCH 30/48] Force convert long to float --- src/clj/commiteth/routes/services.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 43f1458..280ea7a 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -148,8 +148,8 @@ (defn prettify-bounty-items [bounty-items] (let [format-float (fn [balance] (try - (format "%.2f" balance) - (catch java.util.IllegalFormatConversionException ex "0.00"))) + (format "%.2f" (float balance)) + (catch Exception ex "0.00"))) renames {:user_name :display-name :user_avatar_url :avatar-url :issue_title :issue-title From ca5b7d7e7b407e9bb012e10fc3cacf746636438f Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 17:55:25 +0200 Subject: [PATCH 31/48] Log error message if token value cannot be parsed --- src/clj/commiteth/routes/services.clj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 280ea7a..9620b59 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -149,7 +149,10 @@ (let [format-float (fn [balance] (try (format "%.2f" (float balance)) - (catch Exception ex "0.00"))) + (catch Exception ex + (do + (log/error "Failed to convert token value:" balance) + "0.00")))) renames {:user_name :display-name :user_avatar_url :avatar-url :issue_title :issue-title From 36e4868294a68f88b025d6d0c7a127e809e99cc2 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 17:56:38 +0200 Subject: [PATCH 32/48] Substitute Exception with Throwable --- src/clj/commiteth/routes/services.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 9620b59..cfd8f51 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -149,7 +149,7 @@ (let [format-float (fn [balance] (try (format "%.2f" (float balance)) - (catch Exception ex + (catch Throwable ex (do (log/error "Failed to convert token value:" balance) "0.00")))) From 34f3913ff489d4ff9ef2dcedb3ba3d04a7483903 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 17:58:19 +0200 Subject: [PATCH 33/48] Use implicit do in catch --- src/clj/commiteth/routes/services.clj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index cfd8f51..e7b8f52 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -150,9 +150,8 @@ (try (format "%.2f" (float balance)) (catch Throwable ex - (do - (log/error "Failed to convert token value:" balance) - "0.00")))) + (log/error "Failed to convert token value:" balance) + "0.00"))) renames {:user_name :display-name :user_avatar_url :avatar-url :issue_title :issue-title From e540bd04ac7da7d2bf2543d5bb127193e13ded48 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Mon, 12 Mar 2018 18:21:49 +0200 Subject: [PATCH 34/48] Log issue details along with wrong token balance --- src/clj/commiteth/routes/services.clj | 52 +++++++++++++++------------ 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index e7b8f52..435b172 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -146,32 +146,40 @@ (defn prettify-bounty-items [bounty-items] - (let [format-float (fn [balance] - (try - (format "%.2f" (float balance)) - (catch Throwable ex - (log/error "Failed to convert token value:" balance) - "0.00"))) - renames {:user_name :display-name - :user_avatar_url :avatar-url - :issue_title :issue-title - :type :item-type - :repo_name :repo-name - :repo_owner :repo-owner - :issue_number :issue-number - :value_usd :value-usd - :claim_count :claim-count - :balance_eth :balance-eth - :user_has_address :user-has-address}] + (let [format-float (fn [bounty balance] + (try + (format "%.2f" (double balance)) + (catch Throwable ex + (log/error (str (:repo-owner bounty) + "/" + (:repo-name bounty) + "/" + (:issue-number bounty)) + "Failed to convert token value:" balance) + "0.00"))) + update-token-values (fn [bounty] + (->> bounty + :tokens + (map (fn [[tla balance]] + [tla (format-float bounty balance)])) + (into {}) + (assoc bounty :tokens))) + renames {:user_name :display-name + :user_avatar_url :avatar-url + :issue_title :issue-title + :type :item-type + :repo_name :repo-name + :repo_owner :repo-owner + :issue_number :issue-number + :value_usd :value-usd + :claim_count :claim-count + :balance_eth :balance-eth + :user_has_address :user-has-address}] (map #(-> % (rename-keys renames) (update :value-usd usd-decimal->str) (update :balance-eth eth-decimal->str) - (update :tokens (fn [tokens] - (into {} - (map (fn [[tla balance]] - [tla (format-float balance)]) - tokens))))) + update-token-values) bounty-items))) (defn activity-feed [] From 8b6d02d76f0321b502d70c87952f8662202c54fd Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 13 Mar 2018 13:32:23 +0200 Subject: [PATCH 35/48] Add map-float= for proper token balances comparison --- src/clj/commiteth/scheduler.clj | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index f9c25dd..90fc9cd 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -226,12 +226,6 @@ (neg? n) (- n) :else n)) -(defn float= - ([x y] (float= x y 0.0000001)) - ([x y epsilon] - (log/debug x y epsilon) - (let [scale (if (or (zero? x) (zero? y)) 1 (abs x))] - (<= (abs (- x y)) (* scale epsilon))))) (defn update-bounty-token-balances "Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts." @@ -291,6 +285,17 @@ (db-bounties/open-bounty-contracts)] (update-issue-usd-value bounty-addr))) +(defn float= + ([x y] (float= x y 0.0000001)) + ([x y epsilon] + (log/debug x y epsilon) + (let [scale (if (or (zero? x) (zero? y)) 1 (abs x))] + (<= (abs (- x y)) (* scale epsilon))))) + +(defn map-float= [m1 m2] + (and (= (set (keys m1)) (set (keys m2))) + (every? #(float= (get m1 %1) (get m2 %1)) (keys m1)))) + (defn update-balances [] (log/info "In update-balances") @@ -312,13 +317,13 @@ (when (or (not (float= db-balance-eth balance-eth)) - (not= db-tokens token-balances)) - (log/debug "balances differ") - (log/debug "ETH (db):" db-balance-eth (type db-balance-eth) ) - (log/debug "ETH (chain):" balance-eth (type balance-eth) ) - (log/debug "ETH cmp:" (float= db-balance-eth balance-eth)) - (log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens))) - (log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances))) + (not (map-float= db-tokens token-balances))) + (log/info "balances differ") + (log/info "ETH (db):" db-balance-eth (type db-balance-eth) ) + (log/info "ETH (chain):" balance-eth (type balance-eth) ) + (log/info "ETH cmp:" (float= db-balance-eth balance-eth)) + (log/info "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens))) + (log/info "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances))) (log/debug "tokens cmp:" (= db-tokens token-balances)) (issues/update-eth-balance contract-address balance-eth) From f8063e048f75933eb80913a93847ce53fa2e582b Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 13 Mar 2018 15:20:33 +0200 Subject: [PATCH 36/48] Convert to double instead of float --- src/clj/commiteth/github/core.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clj/commiteth/github/core.clj b/src/clj/commiteth/github/core.clj index 93a4f56..e51ce95 100644 --- a/src/clj/commiteth/github/core.clj +++ b/src/clj/commiteth/github/core.clj @@ -219,7 +219,7 @@ (str "Tokens: " (str/join " " (map (fn [[tla balance]] (format "%s: %.2f" (subs (str tla) 1) - (float balance))) + (double balance))) token-balances)) "\n"))) From 9d9ebefc301096fc475d2f122685e8d3e979d937 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Thu, 1 Mar 2018 16:55:44 +0200 Subject: [PATCH 37/48] [Fix #330] Do not handle claims for issues that have been merged already --- resources/sql/queries.sql | 8 ++++ src/clj/commiteth/db/issues.clj | 6 +++ src/clj/commiteth/routes/webhooks.clj | 64 ++++++++++++--------------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql index 1421ced..0673ca6 100644 --- a/resources/sql/queries.sql +++ b/resources/sql/queries.sql @@ -412,6 +412,14 @@ SELECT exists(SELECT 1 FROM issues WHERE issue_id = :issue_id); +-- :name get-issue :? :1 +-- :doc get issue from DB by repo-id and issue-number +SELECT issue_id, issue_number, is_open, winner_login, commit_sha +FROM issues +WHERE repo_id = :repo_id +AND issue_number = :issue_number; + + -- :name open-bounties :? :* -- :doc all open bounty issues diff --git a/src/clj/commiteth/db/issues.clj b/src/clj/commiteth/db/issues.clj index 834684f..a32634a 100644 --- a/src/clj/commiteth/db/issues.clj +++ b/src/clj/commiteth/db/issues.clj @@ -101,3 +101,9 @@ first :exists boolean))) + +(defn get-issue + [repo-id issue-number] + (jdbc/with-db-connection [con-db *db*] + (db/get-issue con-db {:repo_id repo-id + :issue_number issue-number}))) diff --git a/src/clj/commiteth/routes/webhooks.clj b/src/clj/commiteth/routes/webhooks.clj index 32997e1..8ab27bc 100644 --- a/src/clj/commiteth/routes/webhooks.clj +++ b/src/clj/commiteth/routes/webhooks.clj @@ -109,26 +109,17 @@ (extract pr-title)))) -(defn ensure-bounty-issue - "Checks if an issue has a bounty label attached and returns its number" - [user repo issue-number] - (when-let [issue (github/get-issue user repo issue-number)] - (when (bounties/has-bounty-label? issue) - issue-number))) - - (defn handle-claim - [user-id login name avatar_url owner repo repo-id bounty-issue-number pr-id pr-number head-sha merged? event-type] + [issue user-id login name avatar_url owner repo repo-id pr-id pr-number head-sha merged? event-type] (users/create-user user-id login name nil avatar_url) - (let [issue (github/get-issue owner repo bounty-issue-number) - open-or-edit? (contains? #{:opened :edited} event-type) + (let [open-or-edit? (contains? #{:opened :edited} event-type) close? (= :closed event-type) pr-data {:repo_id repo-id :pr_id pr-id :pr_number pr-number :user_id user-id - :issue_number bounty-issue-number - :issue_id (:id issue) + :issue_number (:issue_number issue) + :issue_id (:issue_id issue) :state event-type}] ;; TODO: in the opened case if the submitting user has no @@ -138,18 +129,18 @@ (cond open-or-edit? (do (log/info "PR with reference to bounty issue" - bounty-issue-number "opened") + (:issue_number issue) "opened") (pull-requests/save (merge pr-data {:state :opened :commit_sha head-sha}))) close? (if merged? (do (log/info "PR with reference to bounty issue" - bounty-issue-number "merged") + (:issue_number issue) "merged") (pull-requests/save (merge pr-data {:state :merged :commit_sha head-sha})) - (issues/update-commit-sha (:id issue) head-sha)) + (issues/update-commit-sha (:issue_id issue) head-sha)) (do (log/info "PR with reference to bounty issue" - bounty-issue-number "closed with no merge") + (:issue_number issue) "closed with no merge") (pull-requests/save (merge pr-data {:state :closed :commit_sha head-sha}))))))) @@ -177,26 +168,27 @@ pr-number :number pr-body :body pr-title :title} :pull_request}] - (log/debug "handle-pull-request-event" event-type owner repo repo-id login pr-body pr-title) - (log/debug (extract-issue-number pr-body pr-title)) - (if-let [bounty-issue-number (->> - (extract-issue-number pr-body pr-title) - (first) - (ensure-bounty-issue owner repo))] - (do - (log/debug "Referenced bounty issue found" owner repo bounty-issue-number) - (handle-claim user-id - login name - avatar_url - owner repo - repo-id - bounty-issue-number - pr-id - pr-number - head-sha - merged? - event-type)) + (log/info "handle-pull-request-event" event-type owner repo repo-id login pr-body pr-title) + (if-let [issue (some->> (extract-issue-number pr-body pr-title) + (first) + (issues/get-issue repo-id))] + (if-not (:commit_sha issue) ; no PR has been merged yet referencing this issue + (do + (log/info "Referenced bounty issue found" owner repo (:issue_number issue)) + (handle-claim issue + user-id + login name + avatar_url + owner repo + repo-id + pr-id + pr-number + head-sha + merged? + event-type)) + (log/info "PR for issue already merged")) (when (= :edited event-type) + ; Remove PR if it does not reference any issue (pull-requests/remove pr-id)))) From 3cdfa549b733eefa265187aa2194f3435850dddd Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Tue, 20 Feb 2018 17:52:40 +0100 Subject: [PATCH 38/48] fix #301: add basic stats to manage payouts screen --- resources/templates/home.html | 1 + src/cljs/commiteth/manage_payouts.cljs | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/resources/templates/home.html b/resources/templates/home.html index 590156e..6afe0ca 100644 --- a/resources/templates/home.html +++ b/resources/templates/home.html @@ -65,6 +65,7 @@ height="0" width="0" style="display:none;visibility:hidden"> src="https://www.facebook.com/tr?id=293089407869419&ev=PageView&noscript=1" /> +