Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/stable'
Browse files Browse the repository at this point in the history
  • Loading branch information
thelostone-mc committed Jan 28, 2021
2 parents d6830dd + 891b0f8 commit e4db16b
Show file tree
Hide file tree
Showing 13 changed files with 580 additions and 31 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ chatconfig/config.json
.pytest_cache/
app/cache/

# pip requirements, where the github repo is downloaded
src/

# Autogenerated Documentation
_build/
**/.vs
Expand Down
5 changes: 5 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,3 +884,8 @@ def callback(request):
# Match Payouts contract
MATCH_PAYOUTS_ABI = '[ { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" }, { "internalType": "address", "name": "_funder", "type": "address" }, { "internalType": "contract IERC20", "name": "_dai", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [], "name": "Finalized", "type": "event" }, { "anonymous": false, "inputs": [], "name": "Funded", "type": "event" }, { "anonymous": false, "inputs": [], "name": "FundingWithdrawn", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "PayoutAdded", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "PayoutClaimed", "type": "event" }, { "inputs": [ { "internalType": "address", "name": "_recipient", "type": "address" } ], "name": "claimMatchPayout", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "dai", "outputs": [ { "internalType": "contract IERC20", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "enablePayouts", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "finalize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "funder", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], "name": "payouts", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "internalType": "struct MatchPayouts.PayoutFields[]", "name": "_payouts", "type": "tuple[]" } ], "name": "setPayouts", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "state", "outputs": [ { "internalType": "enum MatchPayouts.State", "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "withdrawFunding", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]'
MATCH_PAYOUTS_ADDRESS = '0xf2354570bE2fB420832Fb7Ff6ff0AE0dF80CF2c6'

# BulkCheckout contract
# BulkCheckout parameters
BULK_CHECKOUT_ADDRESS = "0x7d655c57f71464B6f83811C55D84009Cd9f5221C" # same address on mainnet and rinkeby
BULK_CHECKOUT_ABI = '[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"dest","type":"address"},{"indexed":true,"internalType":"address","name":"donor","type":"address"}],"name":"DonationSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"dest","type":"address"}],"name":"TokenWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"dest","type":"address"}],"internalType":"struct BulkCheckout.Donation[]","name":"_donations","type":"tuple[]"}],"name":"donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_dest","type":"address"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_dest","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
Binary file modified app/assets/v2/images/products/chat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
150 changes: 150 additions & 0 deletions app/assets/v2/js/grants/ingest-missing-contributions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* @notice Vue component for ingesting contributions that were missed during checkout
* @dev See more at: https://github.com/gitcoinco/web/issues/7744
*/

let appIngestContributions;

Vue.component('grants-ingest-contributions', {
delimiters: [ '[[', ']]' ],

data: function() {
return {
form: {
txHash: undefined, // user transaction hash, used to ingest L1 donations
userAddress: undefined // user address, used to ingest zkSync (L2) donations
},
errors: {}, // keys are errors that occurred
submitted: false // true if form has been submitted and we are waiting on response
};
},

methods: {
checkForm() {
this.submitted = true;
this.errors = {};
let isValidTxHash;
let isValidAddress;

// Validate that at least one of txHash and userAddress is provided
const { txHash, userAddress } = this.form;
const isFormComplete = txHash || userAddress;

if (!isFormComplete) {
// Form was not filled out
this.$set(this.errors, 'invalidForm', 'Please enter a valid transaction hash or a valid wallet address');
} else {
// Form was filled out, so validate the inputs
isValidTxHash = txHash && txHash.length === 66 && txHash.startsWith('0x');
isValidAddress = ethers.utils.isAddress(userAddress);

if (txHash && !isValidTxHash) {
this.$set(this.errors, 'txHash', 'Please enter a valid transaction hash');
}
if (userAddress && !isValidAddress) {
this.$set(this.errors, 'address', 'Please enter a valid address');
}
}

if (Object.keys(this.errors).length) {
return false; // there are errors the user must correct
}

return {
txHash: isValidTxHash ? txHash : '',
// getAddress returns checksum address required by web3py, and throws if address is invalid
userAddress: isValidAddress ? ethers.utils.getAddress(userAddress) : ''
};
},

async ingest(event) {
try {
event.preventDefault();

// Return if form is not valid
const formParams = this.checkForm();

if (!formParams) {
return;
}

// Send POST requests to ingest contributions
const { txHash, userAddress } = formParams;
const csrfmiddlewaretoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
const url = '/grants/ingest';
const headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' };
const payload = {
csrfmiddlewaretoken,
txHash,
userAddress,
network: document.web3network || 'mainnet'
};
const postParams = {
method: 'POST',
headers,
body: new URLSearchParams(payload)
};

// Send saveSubscription request
const res = await fetch(url, postParams);
const json = await res.json();

// Notify user of success status, and clear form if successful
console.log('ingestion response: ', json);
if (!json.success) {
console.log('ingestion failed');
this.submitted = false;
throw new Error('Your transactions could not be processed, please try again');
} else {
console.log('ingestion successful');
_alert('Your contributions have been added successfully!', 'success');
this.resetForm();
}
} catch (e) {
this.handleError(e);
}
},

resetForm() {
this.form.txHash = undefined;
this.form.userAddress = undefined;
this.errors = {};
this.submitted = false;
},

handleError(err) {
console.error(err); // eslint-disable-line no-console
let message = 'There was an error';

if (err.message)
message = err.message;
else if (err.msg)
message = err.msg;
else if (typeof err === 'string')
message = err;

_alert(message, 'error');
this.submitted = false;
}
},

watch: {
deep: true,
form: {
deep: true,
handler(newVal, oldVal) {
this.checkForm();
this.submitted = false;
this.errors = {};
}
}
}
});

if (document.getElementById('gc-grants-ingest-contributions')) {

appIngestContributions = new Vue({
delimiters: [ '[[', ']]' ],
el: '#gc-grants-ingest-contributions'
});
}
2 changes: 1 addition & 1 deletion app/dashboard/templates/board/ptokens.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ <h4 class="h5 font-weight-semibold my-3">
</div>
</div>
<div>
<button @click="setSelectedRequest(token)" data-toggle="modal" data-target="#redemptionCompleteModal" class="btn btn-sm m-2 btn-gc-blue" :disabled="key === disabledBtn" >Complete</button>
<button v-if="token.requester == current_user" @click="setSelectedRequest(token)" data-toggle="modal" data-target="#redemptionCompleteModal" class="btn btn-sm m-2 btn-gc-blue" :disabled="key === disabledBtn" >Complete</button>
<button @click="cancel(token.id)" class="btn btn-sm btn-outline-gc-blue m-2" :disabled="key === disabledBtn">Cancel</button>
</div>
</div>
Expand Down
22 changes: 10 additions & 12 deletions app/dashboard/templates/bounty/new_bounty.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,17 @@ <h1 class="text-center">Fund Issue</h1>
<input type="radio" name="bounty_chain" id="1_chain" value="1" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/ethereum.svg' %}" alt="" width="16"> ETH
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '0'}">
<input type="radio" name="bounty_chain" id="0_chain" value="0" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/bitcoin.svg' %}" alt="" width="20"> BTC
</label>
<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '0'}">
<input type="radio" name="bounty_chain" id="0_chain" value="0" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/bitcoin.svg' %}" alt="" width="20"> BTC
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '666'}">
<input type="radio" name="bounty_chain" id="666_chain" value="666" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/paypal.svg' %}" alt="" width="16"> PayPal
</label>

{% if is_staff %}
<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '56'}">
<input type="radio" name="bounty_chain" id="56_chain" value="56" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/binance.svg' %}" alt="" width="16"> Binance
</label>
{% endif %}
<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '666'}">
<input type="radio" name="bounty_chain" id="666_chain" value="666" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/paypal.svg' %}" alt="" width="16"> PayPal
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '56'}">
<input type="radio" name="bounty_chain" id="56_chain" value="56" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/binance.svg' %}" alt="" width="16"> Binance
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '1000'}">
<input type="radio" name="bounty_chain" id="1000_chain" value="1000" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/harmony.svg' %}" alt="" width="16"> Harmony
Expand Down
24 changes: 11 additions & 13 deletions app/dashboard/templates/dashboard/hackathon/new_bounty.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,17 @@ <h1 class="text-center">Fund Prize</h1>
<input type="radio" name="bounty_chain" id="1_chain" value="1" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/ethereum.svg' %}" alt="" width="16"> ETH
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '0'}">
<input type="radio" name="bounty_chain" id="0_chain" value="0" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/bitcoin.svg' %}" alt="" width="20"> BTC
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '666'}">
<input type="radio" name="bounty_chain" id="666_chain" value="666" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/paypal.svg' %}" alt="" width="16"> PayPal
</label>

{% if is_staff %}
<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '56'}">
<input type="radio" name="bounty_chain" id="56_chain" value="56" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/binance.svg' %}" alt="" width="16"> Binance
</label>
{% endif %}
<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '0'}">
<input type="radio" name="bounty_chain" id="0_chain" value="0" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/bitcoin.svg' %}" alt="" width="20"> BTC
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '666'}">
<input type="radio" name="bounty_chain" id="666_chain" value="666" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/paypal.svg' %}" alt="" width="16"> PayPal
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '56'}">
<input type="radio" name="bounty_chain" id="56_chain" value="56" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/binance.svg' %}" alt="" width="16"> Binance
</label>

<label class="btn btn-radio chain-btn d-flex align-items-center mr-2 mb-2 font-weight-bold py-2 px-4" :class="{'active': chainId === '1000'}">
<input type="radio" name="bounty_chain" id="1000_chain" value="1000" v-model="chainId"><img class="mr-2" src="{% static 'v2/images/chains/harmony.svg' %}" alt="" width="16"> Harmony
Expand Down
Loading

0 comments on commit e4db16b

Please sign in to comment.