8000 Finish zkSync recovery page by mds1 · Pull Request #7623 · gitcoinco/web · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Finish zkSync recovery page #7623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 103 additions & 36 deletions app/assets/v2/js/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -1607,14 +1607,20 @@ Vue.component('grants-cart', {

// Dispatch donations ------------------------------------------------------------------------
for (let i = 0; i < donationSignatures.length; i += 1) {
this.currentTxNumber += 1;
console.log(` Sending transfer ${i + 1} of ${donationSignatures.length}...`);
const transfer = await zksync.wallet.submitSignedTransaction(donationSignatures[i], this.syncProvider);
try {
this.currentTxNumber += 1;
console.log(` Sending transfer ${i + 1} of ${donationSignatures.length}...`);
const transfer = await zksync.wallet.submitSignedTransaction(donationSignatures[i], this.syncProvider);

console.log(` Transfer ${i + 1} sent`, transfer);
const receipt = await transfer.awaitReceipt();
console.log(` Transfer ${i + 1} sent`, transfer);
const receipt = await transfer.awaitReceipt();

console.log(` ✅ Got transfer ${i + 1} receipt`, receipt);
console.log(` ✅ Got transfer ${i + 1} receipt`, receipt);
} catch (e) {
// Prevent failed transfer from blocking the rest
console.error(e);
continue;
}
}

// Transfer any remaining tokens to user's main wallet ---------------------------------------
Expand Down Expand Up @@ -1677,6 +1683,7 @@ Vue.component('grants-cart', {
// Everything worked successfully, so let's not throw an error here because the user's
// donations did succeed. Instead, there is just small excess funds left in the account
console.error(e);
continue;
}
}

Expand Down Expand Up @@ -1980,6 +1987,48 @@ Vue.component('grants-cart', {
}
},

/**
* @notice Step 1: Initialize app state and login to zkSync via Gitcoin, then send cart txs.
* This is a special flow to handle incomplete checkouts.
*/
async zkSyncLoginGitcoinFlowRecovery() {
try {
this.zkSyncCheckoutStep1Status = 'pending';

// Set contract to deposit through based on number of tokens used. We do this to save
// gas costs by avoiding the overhead of the batch deposit contract if the user is only
// donating one token
const numberOfCurrencies = Object.keys(this.donationsToGrants).length;

this.depositContractToUse = numberOfCurrencies === 1
? this.depositContractToUse = this.zkSyncContractAddress
: this.depositContractToUse = batchZkSyncDepositContractAddress;

// Prompt for user's signature to login to zkSync
this.gitcoinSyncWallet = await this.zkSyncLoginGitcoin();

// Manually set status steps
this.zkSyncCheckoutStep1Status = 'complete';
this.zkSyncCheckoutStep2Status = 'complete';
this.zkSyncCheckoutStep3Status = 'pending';
this.zkSyncCheckoutFlowStep = 2; // Steps 0 and 1 are skipped here

// Do the transfers
await this.checkAndRegisterSigningKey(this.gitcoinSyncWallet);
let nonce = await this.getGitcoinSyncWalletNonce();
const donationSignatures = await this.generateTransferSignatures(nonce);

await this.dispatchSignedTransfers(donationSignatures);
console.log('✅✅✅ Checkout complete!');

// Final processing
await this.setInterruptStatus(null, this.userAddress);
await this.finalizeCheckout();
} catch (e) {
this.zkSyncCheckoutStep1Status = 'not-started';
}
},

/**
* @notice Step 2: Sign in to zkSync directly (Flow A) OR get ERC20 approvals (Flow B)
*/
Expand Down Expand Up @@ -2406,24 +2455,27 @@ Vue.component('grants-cart', {
* @notice Final shared steps between Flow A and Flow B
*/
async finishZkSyncTransfersAllFlows() {
// Unlock deterministic wallet's zkSync account
await this.checkAndRegisterSigningKey(this.gitcoinSyncWallet);

// Fetch the expected nonce from the network. We cannot assume it's zero because this may
// not be the user's first checkout
let nonce = await this.getGitcoinSyncWalletNonce();
try {
// Unlock deterministic wallet's zkSync account
await this.checkAndRegisterSigningKey(this.gitcoinSyncWallet);

// Fetch the expected nonce from the network. We cannot assume it's zero because this may
// not be the user's first checkout
let nonce = await this.getGitcoinSyncWalletNonce();

// Generate signatures
const donationSignatures = await this.generateTransferSignatures(nonce);
// Generate signatures
const donationSignatures = await this.generateTransferSignatures(nonce);

// Dispatch the transfers
await this.dispatchSignedTransfers(donationSignatures);
console.log('✅✅✅ Checkout complete!');
// Dispatch the transfers
await this.dispatchSignedTransfers(donationSignatures);
console.log('✅✅✅ Checkout complete!');

// Final processing
await this.setInterruptStatus(null, this.userAddress);
await this.finalizeCheckout();
// Final processing
await this.setInterruptStatus(null, this.userAddress);
await this.finalizeCheckout();
} catch (e) {
this.handleError(e);
}
},

/**
Expand Down Expand Up @@ -2546,22 +2598,6 @@ Vue.component('grants-cart', {
},

async mounted() {
// Skip everything here if we are on the zksync-recovery page
if (window.location.pathname.includes('zksync-recovery')) {
window.addEventListener('dataWalletReady', async(e) => {
try {
await needWalletConnection();
this.selectedNetwork = document.web3network;
this.userAddress = (await web3.eth.getAccounts())[0];
await this.setupZkSync();
} catch (e) {
console.error(e);
}
}, false);
return;
}


this.fetchBrightIDStatus();
const urlParams = new URLSearchParams(window.location.search);

Expand Down Expand Up @@ -2598,6 +2634,37 @@ Vue.component('grants-cart', {
CartData.setCart(grantData);
this.grantData = grantData;

// Overwrite grantData if zksync-recovery page
if (window.location.pathname.includes('zksync-recovery')) {
window.addEventListener('dataWalletReady', async(e) => {
try {
// Connect wallet and setup zkSync
await needWalletConnection();
this.selectedNetwork = document.web3network;
this.userAddress = (await web3.eth.getAccounts())[0];
await this.setupZkSync();

// Get list of grants with the expected validator comment
const response = await fetch('get-interrupted-contributions');
const incompleteContributions = await response.json();

// Convert into localStorage format
this.grantData = incompleteContributions.contributions.map((grant) => {
this.gitcoinFactorRaw = 100 * grant.amount_per_period_to_gitcoin / grant.amount_per_period;
return {
grant_admin_address: grant.admin_address,
grant_clr_prediction_curve: [],
grant_donation_amount: grant.amount_per_period,
grant_donation_currency: grant.token_symbol
};
});

} catch (e) {
this.handleError(e);
}
}, false);
}

// Initialize array of empty comments
this.comments = this.grantData.map(grant => undefined);

Expand Down
16 changes: 5 additions & 11 deletions app/grants/templates/grants/zksync-recovery.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ <h1 class="col-auto text-left font-bigger-2 black" style="font-weight: bold; mar
</div>
<div class="col-4">
<button v-if="zkSyncCheckoutStep1Status === 'not-started'"
class="btn btn-gc-blue button--full shadow-none" @click="zkSyncLoginGitcoinFlow"
class="btn btn-gc-blue button--full shadow-none" @click="zkSyncLoginGitcoinFlowRecovery"
>
Sign in
</button>
Expand All @@ -112,16 +112,11 @@ <h1 class="col-auto text-left font-bigger-2 black" style="font-weight: bold; mar
Step 2
</div>
<div>
Claim your funds
That's it! Hang tight while we do the rest
</div>
</div>
<div class="col-4">
<button v-if="zkSyncCheckoutStep3Status === 'not-started'"
class="btn btn-gc-blue button--full shadow-none" @click="returnZkSyncFunds"
>
Claim
</button>
<div v-else-if="zkSyncCheckoutStep3Status === 'pending'">
<div v-if="zkSyncCheckoutStep3Status === 'pending'">
<span class="text-medium-dark-grey">
<i class="fas fa-spinner fa-spin"></i>
Processing
Expand All @@ -146,9 +141,8 @@ <h5>What is this?</h5>
Due to bugs during the checkout process, occasionally zkSync contributions
did not make it to the grant receipients and instead were left in your
<a href="https://github.com/gitcoinco/web/blob/master/docs/GRANTS.md" target="_blank">Gitcoin zkSync wallet</a>.
We've covered the lost funds (maybe???????????) to make sure that
grant receipients received those contributions, so you can use this tool
to claim the remaining funds. Afterwards they will be accessible to you at
Use this tool to send the stuck funds to the grant recipients, and any
leftover funds will be accessible to you
<a href="https://wallet.zksync.io" target="_blank">https://wallet.zksync.io</a>.
</p>
</div>
Expand Down
3 changes: 2 additions & 1 deletion app/grants/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
grant_new, grant_new_whitelabel, grants, grants_addr_as_json, grants_bulk_add, grants_by_grant_type,
grants_cart_view, grants_clr, grants_stats_view, invoice, leaderboard, new_matching_partner, profile, quickstart,
remove_grant_from_collection, save_collection, subscription_cancel, toggle_grant_favorite, verify_grant,
zksync_get_interrupt_status, zksync_set_interrupt_status, grants_zksync_recovery_view
zksync_get_interrupt_status, zksync_set_interrupt_status, grants_zksync_recovery_view, get_interrupted_contributions
)

app_name = 'grants'
Expand Down Expand Up @@ -68,6 +68,7 @@
path('cart/bulk-add/<str:grant_str>', grants_bulk_add, name='grants_bulk_add'),
path('cart', grants_cart_view, name='cart'),
path('zksync-recovery', grants_zksync_recovery_view, name='zksync_recovery'),
path('get-interrupted-contributions', get_interrupted_contributions, name='get_interrupted_contributions'),
path('<slug:grant_type>', grants_by_grant_type, name='grants_by_category2'),
path('<slug:grant_type>/', grants_by_grant_type, name='grants_by_category'),
path('v1/api/clr', grants_clr, name='grants_clr'),
Expand Down
18 changes: 18 additions & 0 deletions app/grants/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,24 @@ def clr_grants(request, round_num):

return grants_by_grant_clr(request, clr_round)

@login_required
def get_interrupted_contributions(request):
all_contributions = Contribution.objects.filter(profile_for_clr=request.user.profile)
user_contributions = []

for contribution in all_contributions:
validator_comment = contribution.validator_comment
is_zksync = "zkSync" in validator_comment
tx_not_found = "Transaction not found, unknown reason" in validator_comment
deposit_no_transfer = "Found deposit but no transfer" in validator_comment
if is_zksync and (tx_not_found or deposit_no_transfer):
user_contributions.append(contribution.normalized_data)

return JsonResponse({
'success': True,
'contributions': user_contributions
})


def get_grants(request):
grants = []
Expand Down
0