Skip to content

Commit

Permalink
Withdrawal fixes (#255)
Browse files Browse the repository at this point in the history
* init commit

* fix for freelancer

* hire when the escrow balance is equal of greater of the total cost

* hire when the escrow balance is equal of greater of the total cost

* click deposit button

* add deposit success screen

* make multichain service a singleton

* make multichain service a singleton

* yarn lint fixes

* use npm run build

* install git

* use yarn build

* remove unused function

* dont open wallet unless needed

* disable continue button until the deposit is complete

* disable continue button until transfer completes

* fix bug on deposit

* rename balance to escrow balance

* show error message

* withdraw fixes

* show currency on milestone

* update milestone withdrawn onchain value

* fix for eth withdrawals

* show correct currency

* show nicer error messages

* show correct currency

* fix for eth fees

* fix typos

* show balance fixes

* fix for balance

* show correct project budget
  • Loading branch information
samelamin authored Nov 7, 2023
1 parent 071ed24 commit 3a6f770
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 159 deletions.
2 changes: 1 addition & 1 deletion src/components/Application/ApplicationOwnerHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ const ApplicationOwnerHeader = (props: ApplicationOwnerProps) => {
try {
setLoadingWallet('loading');
const balance = await getBalance(
user?.web3_address,
Currency.IMBU,
user,
user?.web3_address
);
setImbueBalance(balance.toLocaleString());
} catch (error) {
Expand Down
10 changes: 5 additions & 5 deletions src/components/Application/BriefOwnerHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ const BriefOwnerHeader = (props: BriefOwnerHeaderProps) => {
);
if (resp.status === 200 || resp.status === 201) {
const bl = await getBalance(
account.address,
application.currency_id,
user
user,
account.address
);
setBalance(bl);
} else {
Expand All @@ -117,15 +117,15 @@ const BriefOwnerHeader = (props: BriefOwnerHeaderProps) => {
try {
setLoadingWallet('loading');
const balance = await getBalance(
user?.web3_address,
application?.currency_id ?? Currency.IMBU,
user,
user?.web3_address,
application.id
);
const imbueBalance = await getBalance(
user?.web3_address,
Currency.IMBU,
user
user,
user?.web3_address
);
setBalance(balance.toLocaleString());
setImbueBalance(imbueBalance.toLocaleString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useState } from 'react';

import { ProgressBar } from '@/components/ProgressBar';

import { applicationStatusId, Project } from '@/model';
import { applicationStatusId, Currency, Project } from '@/model';

interface OngoingProjectProps {
projects: Project[];
Expand Down Expand Up @@ -105,7 +105,7 @@ const OngoingProject: React.FC<OngoingProjectProps> = ({ projects }) => {
</div>
<div className='flex pb-9 justify-between'>
<div className='flex space-x-5 text-sm text-imbue-purple-dark'>
<p>${project.required_funds}</p>
<p>{project.required_funds} ${Currency[project.currency_id]}</p>
<p>Fixed price</p>
</div>
</div>
Expand Down
68 changes: 39 additions & 29 deletions src/components/HirePopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';

import { sendNotification } from '@/utils';
import { ERC_20_ABI,getBalance, getEVMContract } from '@/utils/helper';
import { ERC_20_ABI, getBalance, getEVMContract } from '@/utils/helper';

import { Currency, OffchainProjectState } from '@/model';
import { changeBriefApplicationStatus } from '@/redux/services/briefService';
Expand Down Expand Up @@ -86,9 +86,9 @@ export const HirePopup = ({
const checkBalance = async () => {
setFreelancerImbueBalance('Checking Imbue Balance');
const balance = await getBalance(
freelancer.web3_address,
Currency.IMBU,
user
user,
freelancer.web3_address,
);

setFreelancerImbueBalance(balance);
Expand Down Expand Up @@ -244,15 +244,15 @@ export const HirePopup = ({
</div>
</div>
<div className='budget-value'>
${Number?.(totalCostWithoutFee?.toFixed?.(2))?.toLocaleString()}
{Number?.(totalCostWithoutFee?.toFixed?.(2))?.toLocaleString()} ${Currency[application.currencyId]}
</div>
</div>
<div className={`${styles.budgetInfo} mx-5`}>
<div className={styles.budgetDescription}>
<p className='text-lg'>Imbue Service Fee 5%</p>
</div>
<div className='budget-value'>
${Number?.(imbueFee?.toFixed?.(2))?.toLocaleString?.()}
{Number?.(imbueFee?.toFixed?.(2))?.toLocaleString?.()} ${Currency[application.currencyId]}
</div>
</div>
<div className={`${styles.budgetInfo} mx-5 !mb-3`}>
Expand All @@ -277,40 +277,50 @@ export const HirePopup = ({

const SecondContent = () => {
const depositIntoEscrow = async () => {

const transferAmount = totalCostWithoutFee - escrowBalance;
switch (application.currency_id) {
case Currency.ETH: {
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const transferAmount = ethers.parseEther((totalCostWithoutFee - escrowBalance).toPrecision(5).toString());
const depositTx = await signer.sendTransaction({ to: escrowAddress, value: transferAmount });
setDepositSuccess(true);
await provider.waitForTransaction(depositTx.hash, 1, 150000);
setDepositCompleted(true);
await updateEscrowInfo();
break;
const ethBalanceInWei = await provider.getBalance(signer.address);
const ethBalance = Number(ethers.formatEther(ethBalanceInWei));

if (ethBalance < transferAmount) {
setError({ message: `Insufficient $${Currency[application.currency_id]} balance in ${signer.address}` });
break;
}
else {
const transferAmountInWei = ethers.parseEther((transferAmount).toPrecision(5).toString());
const depositTx = await signer.sendTransaction({ to: escrowAddress, value: transferAmountInWei });
setDepositSuccess(true);
await provider.waitForTransaction(depositTx.hash, 1, 150000);
setDepositCompleted(true);
await updateEscrowInfo();
break;
}
}
case Currency.USDT: {

console.log("***** escrow address is ");
console.log(escrowAddress);
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const contract = await getEVMContract(application.currency_id);
console.log("***** contract is ");
console.log(contract);
if (!contract) {
setError({ message: "Contract address not found" });
break;
}
const token = new ethers.Contract(contract.address, ERC_20_ABI, signer);
const transferAmount = ethers.parseUnits((totalCostWithoutFee - escrowBalance).toPrecision(5).toString(), contract.decimals);
const depositTx = await token
.transfer(escrowAddress, transferAmount);
setDepositSuccess(true);
await provider.waitForTransaction(depositTx.hash, 1, 150000);
setDepositCompleted(true);
await updateEscrowInfo();
break;
const usdtBalance = Number(ethers.formatUnits(await token.balanceOf(signer.address), await token.decimals()));
if (usdtBalance < transferAmount) {
setError({ message: `Insufficient $${Currency[application.currency_id]} balance in ${signer.address}` });
} else {
const transferAmountInWei = ethers.parseUnits((transferAmount).toPrecision(5).toString(), contract.decimals);
const depositTx = await token
.transfer(escrowAddress, transferAmountInWei);
setDepositSuccess(true);
await provider.waitForTransaction(depositTx.hash, 1, 150000);
setDepositCompleted(true);
await updateEscrowInfo();
break;
}
}
}

Expand Down Expand Up @@ -486,13 +496,13 @@ export const HirePopup = ({
>
<div className='flex flex-col gap-4 w-1/2'>
<button
disabled={!depositCompleted}
onClick={() =>{setDepositSuccess(false); setstage(0)}}
disabled={!depositCompleted}
onClick={() => { setDepositSuccess(false); setstage(0) }}
className='primary-btn in-dark w-button w-full !m-0'
>


{depositCompleted ? "Continue" : "Waiting for deposit confirmation......." }
{depositCompleted ? "Continue" : "Waiting for deposit confirmation......."}
</button>
</div>
</SuccessScreen>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function SubmitMilestoneNotification(activity: any) {
{activity.data.sender.display_name?.split(' ')[0] || 'someone'}
</span>{' '}
has submitted a
<span className='text-lg text-imbue-purple'>milestone</span> for the{' '}
<span className='text-lg text-imbue-purple'> milestone</span> for the{' '}
<span className='text-lg text-imbue-purple'>project</span>. Take a
moment to review and provide your feedback.
</p>
Expand Down
9 changes: 3 additions & 6 deletions src/components/Project/ProjectBalance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,16 @@ const ProjectBalance = (props: ProjectBalanceType) => {
useEffect(() => {
const getAndSetBalace = async () => {
if (
!project?.escrow_address ||
currency_id === undefined ||
!user.id
currency_id === undefined
) return
setBalanceLoading(true)
try {
const balance = await getBalance(
project?.escrow_address,
currency_id,
user,
project.currency_id < 100 ? project?.escrow_address : undefined,
Number(project.id)
);

if (!balance && project.status_id !== OffchainProjectState.Completed) {
handlePopUpForUser();
}
Expand All @@ -77,7 +74,7 @@ const ProjectBalance = (props: ProjectBalanceType) => {
}

getAndSetBalace();
if (!currency_id) {
if (currency_id == undefined) {
setCurrency_id(project.currency_id);
}

Expand Down
6 changes: 3 additions & 3 deletions src/components/Project/V2/ExpandableMilestone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import BackDropLoader from '@/components/LoadingScreen/BackDropLoader';
import VoteModal from '@/components/ReviewModal/VoteModal';
import Web3WalletModal from '@/components/WalletModal/Web3WalletModal';

import { Milestone, OffchainProjectState, Project, User } from '@/model';
import { Currency, Milestone, OffchainProjectState, Project, User } from '@/model';
import ChainService, { ImbueChainEvent } from '@/redux/services/chainService';
import {
uploadMilestoneAttachments,
Expand Down Expand Up @@ -297,7 +297,7 @@ const ExpandableMilestone = (props: ExpandableMilestonProps) => {
if (withdrawResult.txError) {
setSuccess(false);
setError({ message: withdrawResult.errorMessage });
} else {
} else if(Number(withdrawResult.withdrawn) > 0) {
setSuccess(true);
setSuccessTitle('Withdraw successful');
}
Expand Down Expand Up @@ -365,7 +365,7 @@ const ExpandableMilestone = (props: ExpandableMilestonProps) => {
</p>
</div>
<p className='col-start-7 col-end-9 text-lg mr-10 ml-4'>
${milestone.amount}
{milestone.amount} ${Currency[project.currency_id]}
</p>
<p className='col-start-9 text-lg col-end-11 ml-4'>
{moment(milestone.modified).format('MMM Do YY')}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/api/payments/[id]/withdraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export default nextConnect()
const multichainService = await MultiChainService.build();
const withdrawnAmount = await multichainService.withdraw(projectId, coverFees);
if (withdrawnAmount > 0) {
return res.status(200).json({ WithdrawnAmount: withdrawnAmount });
return res.status(200).json(withdrawnAmount);
} else {
return res.status(501).json({ WithdrawnAmount: 0 });
return res.status(501).json("No available funds to withdraw");
}
} catch (e: any) {
return res.status(501).json(e.message);
Expand Down
25 changes: 20 additions & 5 deletions src/pages/api/project/[...id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ const syncProject = async (project: any, tx: any) => {
if (
firstPendingMilestoneChain === project.first_pending_milestone &&
project.project_in_milestone_voting ===
onChainProjectRes.projectInMilestoneVoting &&
onChainProjectRes.projectInMilestoneVoting &&
project.project_in_voting_of_no_confidence ===
onChainProjectRes.projectInVotingOfNoConfidence &&
onChainProjectRes.projectInVotingOfNoConfidence &&
!milestonesRequiresSync
)
return project;
Expand Down Expand Up @@ -269,17 +269,32 @@ const syncProject = async (project: any, tx: any) => {
// description: filter.clean(item.description),
// };
// });

// await models.insertMilestones(filterdMileStone, project.id)(tx);

const pkg: ProjectPkg = {
...updatedProject,
approvers: project.approvers,
milestones: project.milestones,
};

return pkg;
} else {
const userCompletedProjects: number[] = (await imbueApi.api.query.imbueProposals.completedProjects(
project.owner
)).toJSON() as number[];
const projectCompleted = userCompletedProjects.includes(project.chain_project_id);

if (projectCompleted) {
project.milestones.map(async (item: any) => {
await models.updateMilestone(
Number(projectId),
Number(item.milestone_index),
{ withdrawn_onchain: true }
)(tx);
});

}
return project;
}
} catch (error) {
Expand Down
12 changes: 6 additions & 6 deletions src/pages/briefs/[id]/applications/[applicationId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ const ApplicationPreview = (): JSX.Element => {
<h3 className='text-lg lg:text-[1.25rem] text-imbue-light-purple-two leading-[1.5] font-normal m-0 p-0'>
Projects&apos;s budget:{' '}
<span className=' text-imbue-purple-dark text-lg lg:text-[1.25rem]'>
$
{Number(application.total_cost_without_fee)?.toLocaleString()}

{Number(application.total_cost_without_fee)?.toLocaleString()} ${Currency[application.currency_id]}
</span>
</h3>
)}
Expand Down Expand Up @@ -590,10 +590,10 @@ const ApplicationPreview = (): JSX.Element => {
</>
) : (
<p className='text-[1rem] text-[#3B27C180] m-0'>
$

{Number(
milestones[index]?.amount?.toFixed(2)
)?.toLocaleString?.()}
)?.toLocaleString?.()} ${Currency[currencyId]}
</p>
)}

Expand Down Expand Up @@ -647,7 +647,7 @@ const ApplicationPreview = (): JSX.Element => {
</div>
</div>
<div className='budget-value text-xl text-imbue-purple-dark font-normal'>
${Number(totalCostWithoutFee?.toFixed?.(2)).toLocaleString()}
{Number(totalCostWithoutFee?.toFixed?.(2)).toLocaleString()} ${Currency[currencyId]}
</div>
</div>

Expand All @@ -658,7 +658,7 @@ const ApplicationPreview = (): JSX.Element => {
</h3>
</div>
<div className='budget-value text-[1.25rem] text-imbue-purple-dark font-normal'>
${Number(imbueFee?.toFixed?.(2))?.toLocaleString?.()}
{Number(imbueFee?.toFixed?.(2))?.toLocaleString?.()} ${Currency[currencyId]}
</div>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/pages/briefs/[id]/apply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ export const SubmitProposal = (): JSX.Element => {
</div>
</div>
<div className='budget-value text-[1.25rem] text-imbue-purple-dark font-normal'>
${Number(totalCostWithoutFee.toFixed(2)).toLocaleString()}
{Number(totalCostWithoutFee.toFixed(2)).toLocaleString()} ${Currency[currencyId]}
</div>
</div>

Expand All @@ -511,7 +511,7 @@ export const SubmitProposal = (): JSX.Element => {
</h3>
</div>
<div className='budget-value text-[1.25rem] text-imbue-purple-dark font-normal'>
${Number(imbueFee.toFixed(2)).toLocaleString()}
{Number(imbueFee.toFixed(2)).toLocaleString()} ${Currency[currencyId]}
</div>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/pages/projects/myprojects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useSelector } from 'react-redux';

import { ProgressBar } from '@/components/ProgressBar';

import { applicationStatusId, Project } from '@/model';
import { applicationStatusId, Currency, Project } from '@/model';
import { getFreelancerApplications } from '@/redux/services/freelancerService';
import { RootState } from '@/redux/store/store';

Expand Down Expand Up @@ -189,7 +189,7 @@ export default function Myprojects() {
</div>
<div className='flex pb-9 justify-between'>
<div className='flex space-x-5 text-sm text-imbue-purple-dark'>
<p>${project.required_funds}</p>
<p>{project.required_funds} ${Currency[project.currency_id]}</p>
<p>Fixed price</p>
</div>
</div>
Expand Down
Loading

0 comments on commit 3a6f770

Please sign in to comment.