Merge branch 'master' into develop
This commit is contained in:
commit
bcae011231
1007
LICENSE.md
1007
LICENSE.md
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
||||||
# commiteth
|
# Commiteth
|
||||||
|
|
||||||
Allows you to set bounties for Github issues, paid out in Ether.
|
Allows you to set bounties for Github issues, paid out in Ether.
|
||||||
|
|
||||||
|
@ -41,4 +41,4 @@ Open http://localhost:3449/cards.html
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under the [Mozilla Public License v2.0](https://github.com/status-im/commiteth/blob/master/LICENSE.md)
|
Licensed under the [Affero General Public License v3.0](https://github.com/status-im/commiteth/blob/master/LICENSE.md)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
[clj.qrgen "0.4.0"]
|
[clj.qrgen "0.4.0"]
|
||||||
[digest "1.4.5"]
|
[digest "1.4.5"]
|
||||||
[tentacles "0.5.1"]
|
[tentacles "0.5.1"]
|
||||||
[re-frisk "0.3.2"]
|
[re-frisk "0.4.4"]
|
||||||
[bk/ring-gzip "0.2.1"]
|
[bk/ring-gzip "0.2.1"]
|
||||||
[crypto-random "1.2.0"]
|
[crypto-random "1.2.0"]
|
||||||
[crypto-equality "1.0.0"]
|
[crypto-equality "1.0.0"]
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
CREATE OR REPLACE VIEW "public"."activity_feed_view" AS SELECT 'open-claim'::text AS type,
|
||||||
|
claims_view.issue_title,
|
||||||
|
claims_view.repo_name,
|
||||||
|
claims_view.repo_owner,
|
||||||
|
claims_view.issue_number,
|
||||||
|
claims_view.user_name,
|
||||||
|
claims_view.user_avatar_url,
|
||||||
|
claims_view.balance,
|
||||||
|
claims_view.updated
|
||||||
|
FROM claims_view
|
||||||
|
WHERE claims_view.pr_state in (0,1) AND claims_view.payout_receipt IS NULL
|
||||||
|
UNION
|
||||||
|
SELECT 'claim-payout'::text AS type,
|
||||||
|
claims_view.issue_title,
|
||||||
|
claims_view.repo_name,
|
||||||
|
claims_view.repo_owner,
|
||||||
|
claims_view.issue_number,
|
||||||
|
claims_view.user_name,
|
||||||
|
claims_view.user_avatar_url,
|
||||||
|
claims_view.balance,
|
||||||
|
claims_view.updated
|
||||||
|
FROM claims_view
|
||||||
|
WHERE claims_view.pr_state = 1 AND claims_view.payout_receipt IS NOT NULL
|
||||||
|
UNION
|
||||||
|
SELECT 'new-bounty'::text AS type,
|
||||||
|
bounties_view.issue_title,
|
||||||
|
bounties_view.repo_name,
|
||||||
|
bounties_view.repo_owner,
|
||||||
|
bounties_view.issue_number,
|
||||||
|
bounties_view.user_name,
|
||||||
|
bounties_view.user_avatar_url,
|
||||||
|
bounties_view.balance,
|
||||||
|
bounties_view.updated
|
||||||
|
FROM bounties_view
|
||||||
|
WHERE bounties_view.balance = 0::numeric AND bounties_view.payout_receipt IS NULL
|
||||||
|
UNION
|
||||||
|
SELECT 'balance-update'::text AS type,
|
||||||
|
bounties_view.issue_title,
|
||||||
|
bounties_view.repo_name,
|
||||||
|
bounties_view.repo_owner,
|
||||||
|
bounties_view.issue_number,
|
||||||
|
bounties_view.user_name,
|
||||||
|
bounties_view.user_avatar_url,
|
||||||
|
bounties_view.balance,
|
||||||
|
bounties_view.updated
|
||||||
|
FROM bounties_view
|
||||||
|
WHERE bounties_view.balance > 0::numeric AND bounties_view.payout_receipt IS NULL
|
||||||
|
ORDER BY updated DESC;
|
|
@ -206,6 +206,20 @@ SET
|
||||||
|
|
||||||
-- Bounties ------------------------------------------------------------------------
|
-- Bounties ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
-- :name pending-contracts :? :*
|
||||||
|
-- :doc bounty issues where deploy contract has failed
|
||||||
|
SELECT
|
||||||
|
i.issue_id AS issue_id,
|
||||||
|
u.address AS owner_address
|
||||||
|
FROM issues i, users u, repositories r
|
||||||
|
WHERE
|
||||||
|
r.user_id = u.id
|
||||||
|
AND i.repo_id = r.repo_id
|
||||||
|
AND i.transaction_hash IS NULL
|
||||||
|
AND i.contract_address IS NULL;
|
||||||
|
|
||||||
|
|
||||||
-- :name pending-bounties-list :? :*
|
-- :name pending-bounties-list :? :*
|
||||||
-- :doc lists all recently closed issues awaiting to be signed
|
-- :doc lists all recently closed issues awaiting to be signed
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
@ -38,5 +38,13 @@
|
||||||
var commitethVersion = "{{commitethVersion}}";
|
var commitethVersion = "{{commitethVersion}}";
|
||||||
</script>
|
</script>
|
||||||
{% script "/js/app.js" %}
|
{% script "/js/app.js" %}
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
ga('create', 'UA-79146816-2', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn pending-contracts
|
||||||
|
[]
|
||||||
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
|
(db/pending-contracts con-db)))
|
||||||
|
|
||||||
(defn list-owner-bounties
|
(defn list-owner-bounties
|
||||||
[owner]
|
[owner]
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
(defn authorize-url []
|
(defn authorize-url []
|
||||||
(let [params (codec/form-encode {:client_id (client-id)
|
(let [params (codec/form-encode {:client_id (client-id)
|
||||||
:redirect_uri (redirect-uri)
|
:redirect_uri (redirect-uri)
|
||||||
:scope "admin:repo_hook user:email admin:org_hook"
|
:scope "admin:repo_hook repo user:email admin:org_hook"
|
||||||
:allow_signup true
|
:allow_signup true
|
||||||
:state (str (UUID/randomUUID))})]
|
:state (str (UUID/randomUUID))})]
|
||||||
(str "https://github.com/login/oauth/authorize" "?" params)))
|
(str "https://github.com/login/oauth/authorize" "?" params)))
|
||||||
|
|
|
@ -43,6 +43,20 @@
|
||||||
balance
|
balance
|
||||||
balance-str))))))
|
balance-str))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn deploy-pending-contracts
|
||||||
|
"Under high-concurrency circumstances or in case geth is in defunct state, a bounty contract may not deploy successfully when the bounty label is addded to an issue. This function deploys such contracts."
|
||||||
|
[]
|
||||||
|
(doseq [{issue-id :issue_id
|
||||||
|
owner-address :owner_address} (db-bounties/pending-contracts)]
|
||||||
|
(log/debug "Trying to re-deploy failed bounty contract deployment, issue-id:" issue-id)
|
||||||
|
(let [transaction-hash (eth/deploy-contract owner-address)]
|
||||||
|
(if (nil? transaction-hash)
|
||||||
|
(log/error "Failed to deploy contract to" owner-address)
|
||||||
|
(log/info "Contract deployed, transaction-hash:"
|
||||||
|
transaction-hash ))
|
||||||
|
(issues/update-transaction-hash issue-id transaction-hash))))
|
||||||
|
|
||||||
(defn self-sign-bounty
|
(defn self-sign-bounty
|
||||||
"Walks through all issues eligible for bounty payout and signs corresponding transaction"
|
"Walks through all issues eligible for bounty payout and signs corresponding transaction"
|
||||||
[]
|
[]
|
||||||
|
@ -130,6 +144,7 @@
|
||||||
(defn run-periodic-tasks [time]
|
(defn run-periodic-tasks [time]
|
||||||
(do
|
(do
|
||||||
(log/debug "run-periodic-tasks" time)
|
(log/debug "run-periodic-tasks" time)
|
||||||
|
(deploy-pending-contracts)
|
||||||
(update-issue-contract-address)
|
(update-issue-contract-address)
|
||||||
(update-confirm-hash)
|
(update-confirm-hash)
|
||||||
(update-payout-receipt)
|
(update-payout-receipt)
|
||||||
|
|
|
@ -141,8 +141,9 @@
|
||||||
[:h3 "Top hunters"]
|
[:h3 "Top hunters"]
|
||||||
[top-hunters]]]]
|
[top-hunters]]]]
|
||||||
[:div.ui.divider]
|
[:div.ui.divider]
|
||||||
|
[:div.commiteth-footer "Built by " [:a {:href "https://status.im"} "Status"]
|
||||||
(when-not (= "unknown" version)
|
(when-not (= "unknown" version)
|
||||||
[:div.version-footer "Commit ETH version " [:a {:href (str "https://github.com/status-im/commiteth/commit/" version)} version]])]]]))
|
[:div.version-footer "version " [:a {:href (str "https://github.com/status-im/commiteth/commit/" version)} version]])]]]]))
|
||||||
|
|
||||||
(secretary/set-config! :prefix "#")
|
(secretary/set-config! :prefix "#")
|
||||||
|
|
||||||
|
|
|
@ -69,17 +69,6 @@
|
||||||
:redirect {:path "/logout"}}))
|
:redirect {:path "/logout"}}))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-fx
|
|
||||||
:save-payout-hash
|
|
||||||
(fn [{:keys [db]} [_ issue-id payout-hash]]
|
|
||||||
{:db db
|
|
||||||
:http {:method POST
|
|
||||||
:url (str/format "/api/user/bounty/%s/payout" issue-id)
|
|
||||||
:on-success #(dispatch [:payout-confirmed issue-id])
|
|
||||||
:on-error #(dispatch [:payout-confirm-failed issue-id])
|
|
||||||
:params {:payout-hash payout-hash}}}))
|
|
||||||
|
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:load-top-hunters
|
:load-top-hunters
|
||||||
(fn [{:keys [db]} [_]]
|
(fn [{:keys [db]} [_]]
|
||||||
|
@ -162,9 +151,7 @@
|
||||||
|
|
||||||
|
|
||||||
(defn update-repo-state [all-repos full-name data]
|
(defn update-repo-state [all-repos full-name data]
|
||||||
(println full-name)
|
|
||||||
(let [[owner repo-name] (js->clj (.split full-name "/"))]
|
(let [[owner repo-name] (js->clj (.split full-name "/"))]
|
||||||
(println "update-repo-busy-state" owner repo-name)
|
|
||||||
(update all-repos
|
(update all-repos
|
||||||
owner
|
owner
|
||||||
(fn [repos] (map (fn [repo] (if (= (:name repo) repo-name)
|
(fn [repos] (map (fn [repo] (if (= (:name repo) repo-name)
|
||||||
|
@ -177,7 +164,6 @@
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:toggle-repo
|
:toggle-repo
|
||||||
(fn [{:keys [db]} [_ repo]]
|
(fn [{:keys [db]} [_ repo]]
|
||||||
(println repo)
|
|
||||||
{:db (assoc db :repos (update-repo-state
|
{:db (assoc db :repos (update-repo-state
|
||||||
(:repos db)
|
(:repos db)
|
||||||
(:full_name repo)
|
(:full_name repo)
|
||||||
|
@ -194,7 +180,6 @@
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:repo-toggle-success
|
:repo-toggle-success
|
||||||
(fn [db [_ repo]]
|
(fn [db [_ repo]]
|
||||||
(println "repo-toggle-success" repo)
|
|
||||||
(assoc db :repos (update-repo-state (:repos db)
|
(assoc db :repos (update-repo-state (:repos db)
|
||||||
(:full_name repo)
|
(:full_name repo)
|
||||||
{:busy? false
|
{:busy? false
|
||||||
|
@ -203,7 +188,6 @@
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:repo-toggle-error
|
:repo-toggle-error
|
||||||
(fn [{:keys [db]} [_ repo response]]
|
(fn [{:keys [db]} [_ repo response]]
|
||||||
(println "repo-toggle-error" response)
|
|
||||||
{:db (assoc db :repos (update-repo-state (:repos db)
|
{:db (assoc db :repos (update-repo-state (:repos db)
|
||||||
(:full_name repo)
|
(:full_name repo)
|
||||||
{:busy? false}))
|
{:busy? false}))
|
||||||
|
@ -245,20 +229,31 @@
|
||||||
(dissoc db :updating-address)))
|
(dissoc db :updating-address)))
|
||||||
|
|
||||||
|
|
||||||
|
(reg-event-fx
|
||||||
|
:save-payout-hash
|
||||||
|
(fn [{:keys [db]} [_ issue-id payout-hash]]
|
||||||
|
{:db db
|
||||||
|
:http {:method POST
|
||||||
|
:url (str/format "/api/user/bounty/%s/payout" issue-id)
|
||||||
|
:on-success #(dispatch [:payout-confirmed issue-id])
|
||||||
|
:on-error #(dispatch [:payout-confirm-failed issue-id])
|
||||||
|
:params {:payout-hash payout-hash}}}))
|
||||||
|
|
||||||
|
|
||||||
(defn send-transaction-callback
|
(defn send-transaction-callback
|
||||||
[issue-id]
|
[issue-id]
|
||||||
(println "send-transaction-callback")
|
|
||||||
(fn [error payout-hash]
|
(fn [error payout-hash]
|
||||||
(println "send-transaction-callback fn")
|
|
||||||
(when error
|
(when error
|
||||||
|
(do
|
||||||
(dispatch [:set-flash-message
|
(dispatch [:set-flash-message
|
||||||
:error
|
:error
|
||||||
(str "Error sending transaction: " error)]))
|
(str "Error sending transaction: " error)])
|
||||||
|
(dispatch [:payout-confirm-failed issue-id])))
|
||||||
(when payout-hash
|
(when payout-hash
|
||||||
(dispatch [:save-payout-hash issue-id payout-hash]))))
|
(dispatch [:save-payout-hash issue-id payout-hash]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:confirm-payout
|
:confirm-payout
|
||||||
(fn [{:keys [db]} [_ {issue-id :issue_id
|
(fn [{:keys [db]} [_ {issue-id :issue_id
|
||||||
|
@ -270,27 +265,29 @@
|
||||||
:to contract-address
|
:to contract-address
|
||||||
:value 1
|
:value 1
|
||||||
:data (str "0x797af627" confirm-hash)}]
|
:data (str "0x797af627" confirm-hash)}]
|
||||||
(println "confirm-payout" owner-address contract-address)
|
|
||||||
(try
|
(try
|
||||||
(apply send-transaction-fn [(clj->js payload)
|
(apply send-transaction-fn [(clj->js payload)
|
||||||
(send-transaction-callback issue-id)])
|
(send-transaction-callback issue-id)])
|
||||||
{:db (assoc-in db [:owner-bounties issue-id :confirming?] true)}
|
{:db (assoc-in db [:owner-bounties issue-id :confirming?] true)}
|
||||||
(catch js/Error e
|
(catch js/Error e
|
||||||
{:db (assoc-in db [:owner-bounties issue-id :confirm-failed?] true)
|
{:db (assoc-in db [:owner-bounties issue-id :confirm-failed?] true)
|
||||||
:dispatch [:set-flash-message
|
:dispatch-n [[:payout-confirm-failed issue-id]
|
||||||
|
[:set-flash-message
|
||||||
:error
|
:error
|
||||||
(str "Failed to send transaction" e)]})))))
|
(str "Failed to send transaction" e)]]})))))
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-fx
|
||||||
:payout-confirmed
|
:payout-confirmed
|
||||||
(fn [db [_ issue-id]]
|
(fn [{:keys [db]} [_ issue-id]]
|
||||||
(-> db
|
{:dispatch [:load-owner-bounties]
|
||||||
(dissoc-in [:owner-bounties (:issue_id issue-id) :confirming?])
|
:db (-> db
|
||||||
(assoc-in [:owner-bounties (:issue_id issue-id) :confirmed?] true))))
|
(dissoc-in [:owner-bounties issue-id :confirming?])
|
||||||
|
(assoc-in [:owner-bounties issue-id :confirmed?] true))}))
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:payout-confirm-failed
|
:payout-confirm-failed
|
||||||
(fn [db [_ issue-id]]
|
(fn [db [_ issue-id]]
|
||||||
|
(println "payout-confirm-failed" issue-id)
|
||||||
(-> db
|
(-> db
|
||||||
(dissoc-in [:owner-bounties (:issue_id issue-id) :confirming?])
|
(dissoc-in [:owner-bounties issue-id :confirming?])
|
||||||
(assoc-in [:owner-bounties (:issue_id issue-id) :confirm-failed?] true))))
|
(assoc-in [:owner-bounties issue-id :confirm-failed?] true))))
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
[:div.ui.container.grid
|
[:div.ui.container.grid
|
||||||
[:div.ui.form.sixteen.wide.column
|
[:div.ui.form.sixteen.wide.column
|
||||||
[:h3 "Update address"]
|
[:h3 "Update address"]
|
||||||
[:p "Placeholder text for explaining what an Ethereum address is."]
|
[:p "Insert your Ethereum address in hex format."]
|
||||||
[:div.field
|
[:div.field
|
||||||
(if-not (empty? web3-accounts)
|
(if-not (empty? web3-accounts)
|
||||||
[dropdown {:class "address-input"} "Select address"
|
[dropdown {:class "address-input"} "Select address"
|
||||||
|
|
|
@ -326,8 +326,19 @@ span.dropdown.icon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-footer {
|
.commiteth-footer {
|
||||||
color: #a8aab1;
|
color: #a8aab1;
|
||||||
|
line-height: 1.8em;
|
||||||
|
a {
|
||||||
|
&:hover {
|
||||||
|
color: #a8aab1!important;
|
||||||
|
}
|
||||||
|
color: #a8aab1!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.version-footer {
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
a {
|
a {
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
Loading…
Reference in New Issue