parent
d9db6b442f
commit
6b5790fde7
|
@ -411,9 +411,19 @@ SELECT
|
|||
i.issue_number AS issue_number,
|
||||
i.is_open AS is_open,
|
||||
i.winner_login AS winner_login,
|
||||
i.transaction_hash AS transaction_hash,
|
||||
i.contract_address AS contract_address,
|
||||
i.confirm_hash AS confirm_hash,
|
||||
i.execute_hash AS execute_hash,
|
||||
i.payout_hash AS payout_hash,
|
||||
i.watch_hash AS watch_hash,
|
||||
i.payout_receipt AS payout_receipt,
|
||||
i.commit_sha AS commit_sha,
|
||||
i.title AS title,
|
||||
i.comment_id AS comment_id,
|
||||
i.balance_eth AS balance_eth,
|
||||
i.tokens AS tokens,
|
||||
i.value_usd AS value_usd,
|
||||
i.repo_id AS repo_id,
|
||||
r.owner AS owner,
|
||||
r.repo AS repo
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns commiteth.bounties
|
||||
(:require [commiteth.db.issues :as issues]
|
||||
[commiteth.db.bounties :as db-bounties]
|
||||
[commiteth.db.users :as users]
|
||||
[commiteth.db.repositories :as repos]
|
||||
[commiteth.eth.core :as eth]
|
||||
|
@ -21,7 +22,50 @@
|
|||
(let [labels (:labels issue)]
|
||||
(some #(= label-name (:name %)) labels)))
|
||||
|
||||
(defn deploy-contract [owner-address issue-id]
|
||||
(defn transition [{:keys [issue-id tx-info] :as bounty} state]
|
||||
(let [bounty-not= (fn [current db]
|
||||
(some #(not= (%1 current) (%1 db))
|
||||
(disj (set (keys current)) :tx-info)))
|
||||
bounty-from-db (issues/get-issue-by-id issue-id)
|
||||
bounty (and (bounty-not= bounty bounty-from-db)
|
||||
(merge bounty-from-db bounty))]
|
||||
(when bounty
|
||||
(case state
|
||||
:deploying
|
||||
(tracker/track-tx! tx-info)
|
||||
|
||||
:opened
|
||||
(do
|
||||
(tracker/untrack-tx! {:issue-id (:issue-id bounty)
|
||||
:tx-hash (:transaction-hash bounty)
|
||||
:result (:contract-address bounty)
|
||||
:type :deploy})
|
||||
(github/update-bounty-comment-image bounty))
|
||||
|
||||
:pending-sob-confirmation
|
||||
(tracker/track-tx! tx-info)
|
||||
|
||||
:pending-maintainer-confirmation
|
||||
(tracker/untrack-tx! tx-info)
|
||||
|
||||
:paid-with-receipt
|
||||
(db-bounties/update-payout-receipt issue-id (:payout-receipt bounty))
|
||||
|
||||
:watch-set
|
||||
(tracker/track-tx! tx-info)
|
||||
|
||||
:watch-reset
|
||||
(tracker/untrack-tx! tx-info)
|
||||
|
||||
:update-balances
|
||||
(issues/update-balances (:contract-address bounty)
|
||||
(:balance-eth bounty)
|
||||
(:tokens bounty)
|
||||
(:value-usd bounty))
|
||||
|
||||
)
|
||||
(github/update-comment bounty state))))
|
||||
(defn deploy-contract [owner-address issue-id]
|
||||
(if (empty? owner-address)
|
||||
(log/errorf "issue %s: Unable to deploy bounty contract because repo owner has no Ethereum addres" issue-id)
|
||||
(try
|
||||
|
@ -30,8 +74,8 @@
|
|||
:internal-tx-id [:deploy issue-id]})]
|
||||
(do
|
||||
(log/infof "issue %s: Contract deployed, transaction-hash: %s" issue-id (:tx-hash tx-info))
|
||||
(github/update-comment (into tx-info [:issue-id issue-id]))
|
||||
(tracker/track-tx! tx-info))
|
||||
(transition {:issue-id issue-id
|
||||
:tx-info tx-info} :deploying))
|
||||
(log/errorf "issue %s Failed to deploy contract to %s" issue-id owner-address))
|
||||
(catch Exception ex (log/errorf ex "issue %s: deploy-contract exception" issue-id)))))
|
||||
|
||||
|
@ -106,6 +150,7 @@
|
|||
(if-let [merged-or-paid? (or (:winner_login bounty)
|
||||
(:payout_hash bounty))]
|
||||
(cond
|
||||
(:payout_receipt bounty) :paid-with-receipt
|
||||
(:payout_hash bounty) :paid
|
||||
(nil? (:payout_address bounty)) :pending-contributor-address
|
||||
;; `confirm_hash` is set by us as soon as a PR is merged and the
|
||||
|
@ -121,6 +166,8 @@
|
|||
(seq (:tokens bounty)) :funded
|
||||
(:contract_address bounty) :opened))))
|
||||
|
||||
|
||||
|
||||
(comment
|
||||
(def user 97496)
|
||||
|
||||
|
|
|
@ -62,8 +62,42 @@
|
|||
(:tx-hash @current-tx) (:type @current-tx))
|
||||
(reset! current-tx nil)))
|
||||
|
||||
)
|
||||
|
||||
(defrecord ParallelTxTracker [current-txs]
|
||||
ITxTracker
|
||||
(try-reserve-nonce [this]
|
||||
(let [nonce (get-nonce)
|
||||
monitored-nonces (set (keys current-txs))
|
||||
first-available-nonce (some #(if (monitored-nonces %1) nil %1) (iterate inc nonce))]
|
||||
(swap! current-txs assoc nonce nil)))
|
||||
|
||||
(drop-nonce [this nonce]
|
||||
(swap! current-txs dissoc nonce))
|
||||
|
||||
(track-tx [this tx-info]
|
||||
(swap! current-txs update (:nonce tx-info) merge tx-info))
|
||||
|
||||
(untrack-tx [this tx-info]
|
||||
(when (contains? (set (keys current-txs)) (:nonce tx-info))
|
||||
(swap! current-txs dissoc (:nonce tx-info))))
|
||||
|
||||
(prune-txs [this unmined-txs]
|
||||
(swap! current-txs
|
||||
(fn [txs]
|
||||
(let [unmined-tx-hashes (set (map :tx-hash unmined-txs))
|
||||
time-threshold (t/minus (t/now) (t/minutes 10))
|
||||
nonces-to-remove
|
||||
(->> txs
|
||||
vals
|
||||
(filter #(or (unmined-tx-hashes (:tx-hash %1))
|
||||
(and (:timestamp %1)
|
||||
(t/before? (:timestamp %1) time-threshold))))
|
||||
(map :nonce))]
|
||||
(apply dissoc txs nonces-to-remove)))))
|
||||
)
|
||||
|
||||
|
||||
(def tx-tracker (SequentialTxTracker. (atom nil)))
|
||||
|
||||
(defn try-reserve-nonce! []
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
(str "Contract address: [" addr "](" url-base "/address/" addr ")\n")))
|
||||
|
||||
(defn generate-open-comment
|
||||
[owner repo issue-number contract-address eth-balance eth-balance-str tokens]
|
||||
[owner repo issue-number contract-address eth-balance tokens]
|
||||
(let [image-url (md-image "QR Code" (get-qr-url owner repo issue-number eth-balance))
|
||||
site-url (md-url (server-address) (server-address))]
|
||||
(format (str "Current balance: %s ETH\n"
|
||||
|
@ -247,14 +247,14 @@
|
|||
(if (on-testnet?)
|
||||
"To fund it, send test ETH or test ERC20/ERC223 tokens to the contract address."
|
||||
"To fund it, send ETH or ERC20/ERC223 tokens to the contract address."))
|
||||
eth-balance-str image-url site-url)))
|
||||
eth-balance image-url site-url)))
|
||||
|
||||
(defn learn-more-text []
|
||||
(let [site-url (md-url (server-address) (server-address))]
|
||||
(format "Visit %s to learn more.\n" site-url)))
|
||||
|
||||
(defn generate-merged-comment
|
||||
[contract-address eth-balance-str tokens winner-login winner-address-missing?]
|
||||
[contract-address eth-balance tokens winner-login winner-address-missing?]
|
||||
(format (str "Balance: %s ETH\n"
|
||||
(token-balances-text tokens)
|
||||
(contract-addr-text contract-address)
|
||||
|
@ -264,7 +264,7 @@
|
|||
"Pending maintainer confirmation") "\n")
|
||||
"Winner: %s\n"
|
||||
(learn-more-text))
|
||||
eth-balance-str winner-login))
|
||||
eth-balance winner-login))
|
||||
|
||||
(defn generate-paid-comment
|
||||
[contract-address eth-balance-str tokens payee-login]
|
||||
|
@ -294,16 +294,16 @@
|
|||
:otp))]
|
||||
(assoc req :body (json/generate-string (or raw-query proper-query)))))
|
||||
|
||||
(defn update-bounty-comment-image [issue-id owner repo issue-number contract-address eth-balance eth-balance-str tokens]
|
||||
(let [hash (github-comment-hash owner repo issue-number eth-balance)
|
||||
(defn update-bounty-comment-image [{:keys [issue-id owner repo issue-number contract-address balance-eth tokens]}]
|
||||
(let [hash (github-comment-hash owner repo issue-number balance-eth)
|
||||
issue-url (str owner "/" repo "/issues/" (str issue-number))
|
||||
png-data (png-rendering/gen-comment-image
|
||||
contract-address
|
||||
eth-balance-str
|
||||
balance-eth
|
||||
tokens
|
||||
issue-url)]
|
||||
(log/debug "update-bounty-comment-image" issue-id owner repo issue-number)
|
||||
(log/debug contract-address eth-balance-str)
|
||||
(log/debug contract-address balance-eth)
|
||||
(log/debug "hash" hash)
|
||||
|
||||
(if png-data
|
||||
|
@ -331,53 +331,43 @@
|
|||
(defn update-comment
|
||||
"Update comment for an open bounty issue"
|
||||
[{:keys [issue-id owner repo comment-id issue-number contract-address
|
||||
eth-balance eth-balance-str tokens
|
||||
balance-eth tokens
|
||||
payout-receipt
|
||||
winner-login winner-address transaction-hash] :as issue}]
|
||||
(let [state (cond (nil? comment-id) :deployed
|
||||
(not (nil? payout-receipt)) :paid
|
||||
(not (str/blank? winner-login)) :merged
|
||||
:else :open)
|
||||
comment (cond (= state :deployed)
|
||||
(generate-deploying-comment owner repo issue-number transaction-hash)
|
||||
(= state :open)
|
||||
(generate-open-comment owner
|
||||
repo
|
||||
issue-number
|
||||
contract-address
|
||||
eth-balance
|
||||
eth-balance-str
|
||||
tokens)
|
||||
(= state :merged)
|
||||
(generate-merged-comment contract-address
|
||||
eth-balance-str
|
||||
tokens
|
||||
winner-login
|
||||
(str/blank? winner-address))
|
||||
(= state :paid)
|
||||
(generate-paid-comment contract-address
|
||||
eth-balance-str
|
||||
tokens
|
||||
winner-login)
|
||||
)]
|
||||
(when (and (= state :merged) (empty? winner-address))
|
||||
(log/warn "issue %s: Cannot sign pending bounty - winner has no payout address" issue-id))
|
||||
(when (= :paid state)
|
||||
(db-bounties/update-payout-receipt issue-id payout-receipt))
|
||||
|
||||
(when (= :open state)
|
||||
(update-bounty-comment-image issue-id owner repo issue-number contract-address eth-balance eth-balance-str tokens))
|
||||
|
||||
winner-login winner-address transaction-hash] :as issue}
|
||||
state]
|
||||
(let [comment (case state
|
||||
:deploying
|
||||
(generate-deploying-comment owner repo issue-number transaction-hash)
|
||||
:opened
|
||||
(generate-open-comment owner
|
||||
repo
|
||||
issue-number
|
||||
contract-address
|
||||
balance-eth
|
||||
tokens)
|
||||
(:pending-maintainer-confirmation :pending-contributor-address)
|
||||
(generate-merged-comment contract-address
|
||||
balance-eth
|
||||
tokens
|
||||
winner-login
|
||||
(str/blank? winner-address))
|
||||
:paid-with-receipt
|
||||
(generate-paid-comment contract-address
|
||||
balance-eth
|
||||
tokens
|
||||
winner-login)
|
||||
:else nil)]
|
||||
(log/debug (str "Updating " owner "/" repo "/" issue-number
|
||||
" comment #" comment-id " with contents: " comment))
|
||||
(if (= state :deployed)
|
||||
(if (= state :deploying)
|
||||
(let [resp (issues/create-comment owner repo issue-number comment (self-auth-params))
|
||||
comment-id (:id resp)]
|
||||
(db-issues/update-comment-id issue-id comment-id))
|
||||
(let [req (make-patch-request "repos/%s/%s/issues/comments/%s"
|
||||
[owner repo comment-id]
|
||||
(assoc (self-auth-params) :body comment))]
|
||||
(tentacles/safe-parse (http/request req))))))
|
||||
(when comment
|
||||
(let [req (make-patch-request "repos/%s/%s/issues/comments/%s"
|
||||
[owner repo comment-id]
|
||||
(assoc (self-auth-params) :body comment))]
|
||||
(tentacles/safe-parse (http/request req)))))))
|
||||
|
||||
(defn get-issue
|
||||
[owner repo issue-number]
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
(:require [commiteth.eth.core :as eth]
|
||||
[commiteth.eth.multisig-wallet :as multisig]
|
||||
[commiteth.eth.token-data :as token-data]
|
||||
[commiteth.eth.tracker :as tracker]
|
||||
[commiteth.github.core :as github]
|
||||
[commiteth.db.issues :as issues]
|
||||
[commiteth.eth.tracker :as tracker]
|
||||
[commiteth.util.util :refer [to-map]]
|
||||
[taoensso.tufte :as tufte :refer (defnp p profiled profile)]
|
||||
[commiteth.db.bounties :as db-bounties]
|
||||
|
@ -46,34 +46,17 @@
|
|||
[]
|
||||
(log/info "In update-issue-contract-address")
|
||||
(p :update-issue-contract-address
|
||||
(doseq [{:keys [issue-id transaction-hash]} (issues/list-pending-deployments)]
|
||||
(log/infof "issue %s: pending deployment: %s" issue-id transaction-hash)
|
||||
(try
|
||||
(when-let [receipt (eth/get-transaction-receipt transaction-hash)]
|
||||
(log/infof "issue %s: update-issue-contract-address: tx receipt: %s" issue-id receipt)
|
||||
(if-let [contract-address (multisig/find-created-multisig-address receipt)]
|
||||
(let [_ (tracker/untrack-tx! {:issue-id issue-id
|
||||
:tx-hash transaction-hash
|
||||
:result contract-address
|
||||
:type :deploy})
|
||||
{:keys [owner repo comment-id issue-number] :as issue}
|
||||
(issues/get-issue-by-id issue-id)
|
||||
balance-eth-str (eth/get-balance-eth contract-address 6)
|
||||
balance-eth (read-string balance-eth-str)
|
||||
tokens {}]
|
||||
(log/infof "issue %s: Updating comment" issue-id)
|
||||
(github/update-comment (to-map issue-id
|
||||
owner
|
||||
repo
|
||||
comment-id
|
||||
issue-number
|
||||
contract-address
|
||||
balance-eth
|
||||
balance-eth-str
|
||||
tokens)))
|
||||
(log/errorf "issue %s: Failed to find contract address in tx logs" issue-id)))
|
||||
(catch Throwable ex
|
||||
(log/errorf ex "issue %s: update-issue-contract-address exception:" issue-id)))))
|
||||
(doseq [{:keys [issue-id transaction-hash] :as issue} (issues/list-pending-deployments)]
|
||||
(log/infof "issue %s: pending deployment: %s" issue-id transaction-hash)
|
||||
(try
|
||||
(when-let [receipt (eth/get-transaction-receipt transaction-hash)]
|
||||
(log/infof "issue %s: update-issue-contract-address: tx receipt: %s" issue-id receipt)
|
||||
(if-let [contract-address (multisig/find-created-multisig-address receipt)]
|
||||
(bounties/transition (assoc issue :contract-address contract-address)
|
||||
:opened)
|
||||
(log/errorf "issue %s: Failed to find contract address in tx logs" issue-id)))
|
||||
(catch Throwable ex
|
||||
(log/errorf ex "issue %s: update-issue-contract-address exception:" issue-id)))))
|
||||
(log/info "Exit update-issue-contract-address"))
|
||||
|
||||
|
||||
|
@ -102,15 +85,18 @@
|
|||
;; TODO(martin) delete this shortly after org-dashboard deploy
|
||||
;; as we're now setting `winner_login` when handling a new claims
|
||||
;; coming in via webhooks (see `commiteth.routes.webhooks/handle-claim`)
|
||||
(db-bounties/update-winner-login issue-id winner-login)
|
||||
(let [value (eth/get-balance-hex contract-address)]
|
||||
(when-not (empty? winner-address)
|
||||
(let [tx-info (multisig/send-all {:contract contract-address
|
||||
:payout-address winner-address
|
||||
:internal-tx-id [:execute issue-id]})]
|
||||
(log/infof "issue %s: Payout self-signed, called sign-all(%s) tx: %s" issue-id contract-address winner-address (:tx-hash tx-info))
|
||||
(tracker/track-tx! tx-info)
|
||||
(github/update-comment issue))))
|
||||
;(db-bounties/update-winner-login issue-id winner-login)
|
||||
(if (empty? winner-address)
|
||||
(do
|
||||
(log/warn "issue %s: Cannot sign pending bounty - winner has no payout address" issue-id)
|
||||
(bounties/transition {:issue-id issue-id} :pending-contributor-address))
|
||||
(let [tx-info (multisig/send-all {:contract contract-address
|
||||
:payout-address winner-address
|
||||
:internal-tx-id [:execute issue-id]})]
|
||||
(log/infof "issue %s: Payout self-signed, called sign-all(%s) tx: %s" issue-id contract-address winner-address (:tx-hash tx-info))
|
||||
(bounties/transition {:execute-hash (:tx-hash tx-info)
|
||||
:issue-id issue-id
|
||||
:tx-info tx-info} :pending-sob-confirmation)))
|
||||
(catch Throwable ex
|
||||
(log/error ex "issue %s: self-sign-bounty exception" issue-id)))))
|
||||
(log/info "Exit self-sign-bounty"))
|
||||
|
@ -127,10 +113,14 @@
|
|||
(log/infof "issue %s: execution receipt for issue " issue-id receipt)
|
||||
(when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)]
|
||||
(log/infof "issue %s: confirm hash:" issue-id confirm-hash)
|
||||
(tracker/untrack-tx! {:issue-id issue-id
|
||||
:tx-hash execute-hash
|
||||
:result confirm-hash
|
||||
:type :execute})))
|
||||
(bounties/transition {:issue-id issue-id
|
||||
:tx-info {:issue-id issue-id
|
||||
:tx-hash execute-hash
|
||||
:result confirm-hash
|
||||
:type :execute}}
|
||||
:pending-maintainer-confirmation)
|
||||
|
||||
))
|
||||
(catch Throwable ex
|
||||
(log/errorf ex "issue %s: update-confirm-hash exception:" issue-id))) )
|
||||
(log/info "Exit update-confirm-hash")))
|
||||
|
@ -144,10 +134,12 @@
|
|||
(log/infof "issue %s: pending watch call %s" issue-id watch-hash)
|
||||
(try
|
||||
(when-let [receipt (eth/get-transaction-receipt watch-hash)]
|
||||
(tracker/untrack-tx! {:issue-id issue-id
|
||||
:tx-hash watch-hash
|
||||
:result nil
|
||||
:type :watch}))
|
||||
(bounties/transition {:issue-id issue-id
|
||||
:tx-info
|
||||
{:issue-id issue-id
|
||||
:tx-hash watch-hash
|
||||
:result nil
|
||||
:type :watch}} :watch-reset))
|
||||
(catch Throwable ex
|
||||
(log/errorf ex "issue %s: update-watch-hash exception:" issue-id))
|
||||
))))
|
||||
|
@ -182,10 +174,9 @@
|
|||
(log/infof "issue %s: Detected bounty with funds and confirmed payout, calling executeTransaction" issue-id)
|
||||
(let [execute-tx-hash (multisig/execute-tx contract-address confirm-hash)]
|
||||
(log/infof "issue %s: execute tx: %s" issue-id execute-tx-hash))))
|
||||
|
||||
(do
|
||||
(log/infof "issue %s: Payout has succeeded, payout receipt %s" issue-id receipt)
|
||||
(github/update-comment (assoc issue :payout-receipt receipt)))))
|
||||
(bounties/transition (assoc issue :payout-receipt receipt) :paid-with-receipt))))
|
||||
(when (older-than-3h? updated)
|
||||
(log/warn "issue %s: Resetting payout hash for issue as it has not been mined in 3h" issue-id)
|
||||
(db-bounties/reset-payout-hash issue-id)))
|
||||
|
@ -222,7 +213,9 @@
|
|||
(let [tx-info (multisig/watch-token {:bounty-addr bounty-addr
|
||||
:token tla
|
||||
:internal-tx-id [:watch issue-id]})]
|
||||
(tracker/track-tx! tx-info)))))))
|
||||
(bounties/transition {:issue-id issue-id
|
||||
:tx-info tx-info}
|
||||
:watch-set)))))))
|
||||
(catch Throwable ex
|
||||
(log/error ex "bounty %s: update-bounty-token-balances exception" bounty-addr))))
|
||||
(log/info "Exit update-bounty-token-balances"))
|
||||
|
@ -278,12 +271,14 @@
|
|||
(log/info "tokens (db):" tokens (type tokens) (type (:SNT tokens)))
|
||||
(log/info "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances)))
|
||||
(log/debug "tokens cmp:" (= tokens token-balances))
|
||||
(bounties/transition {:issue-id issue-id
|
||||
:balance-eth current-balance-eth
|
||||
:tokens token-balances
|
||||
:value-usd (fiat-util/bounty-usd-value
|
||||
(merge token-balances {:ETH current-balance-eth}))} :update-balances)
|
||||
|
||||
(issues/update-balances contract-address
|
||||
current-balance-eth token-balances
|
||||
(fiat-util/bounty-usd-value
|
||||
(merge token-balances {:ETH current-balance-eth})))
|
||||
(github/update-comment issue))))
|
||||
|
||||
)))
|
||||
(catch Throwable ex
|
||||
(log/error ex "issue %s: update-balances exception" issue-id)))))
|
||||
(log/info "Exit update-balances"))
|
||||
|
|
Loading…
Reference in New Issue