Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
115 changes: 100 additions & 15 deletions packages/invoice-dashboard/src/lib/dashboard/invoice-view.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { toast } from "svelte-sonner";
import { getBalance } from "@wagmi/core";
import type { GetAccountReturnType } from "@wagmi/core";
import {
approveErc20,
Expand Down Expand Up @@ -90,6 +91,8 @@
];
let status = checkStatus(requestData || request);
let hasEnoughBalance = false;
let userBalance = "0";
let isSigningTransaction = false;
Expand Down Expand Up @@ -151,6 +154,12 @@
}
}
$: {
if (account && network) {
checkBalance();
}
}
$: {
account = account;
network = request?.currencyInfo?.network || "mainnet";
Expand Down Expand Up @@ -252,6 +261,7 @@
statuses = baseStatuses;
status = checkStatus(requestData || request);
await checkBalance();
} catch (err: any) {
console.error("Error while checking invoice: ", err);
if (String(err).includes("Unsupported payment")) {
Expand Down Expand Up @@ -469,6 +479,58 @@
: value;
}
function formatBalance(value: number, maxDecimals: number = 4): string {
return Number.isInteger(value)
? value.toString()
: value.toFixed(maxDecimals);
}
async function checkBalance() {
try {
if (!address || !paymentCurrencies[0] || !network) {
console.log("Missing required parameters for balance check:", {
address,
paymentCurrency: paymentCurrencies[0],
network,
});
return;
}
const invoiceNetworkId = Number(getNetworkIdFromNetworkName(network));
if (account.chainId !== invoiceNetworkId) {
hasEnoughBalance = false;
console.log("Wrong network - balance check skipped");
return;
}
if (paymentCurrencies[0]?.type === Types.RequestLogic.CURRENCY.ERC20) {
const balance = await getBalance(wagmiConfig, {
address,
token: paymentCurrencies[0].address as `0x${string}`,
chainId: invoiceNetworkId,
});
const balanceNum = Number(balance.formatted);
userBalance = formatBalance(balanceNum);
hasEnoughBalance = balance.value >= BigInt(request.expectedAmount);
} else {
const balance = await getBalance(wagmiConfig, {
address,
chainId: invoiceNetworkId,
});
const balanceNum = Number(balance.formatted);
userBalance = formatBalance(balanceNum);
hasEnoughBalance = balance.value >= BigInt(request.expectedAmount);
}
} catch (err) {
console.error("Error checking balance:", err);
hasEnoughBalance = false;
userBalance = "0";
}
}
const currentStatusIndex = statuses.length - 1;
async function handlePayment() {
try {
await switchNetworkIfNeeded(network || "mainnet");
Expand Down Expand Up @@ -776,20 +838,28 @@
</div>
</div>
{/if}
{#if !isPayee && !unsupportedNetwork && !isPaid && !isSigningTransaction}
<Button
className="pay-button"
type="button"
text={!correctChain
? "Switch Network"
: !approved &&
paymentCurrencies[0]?.type === Types.RequestLogic.CURRENCY.ERC20
? "Approve"
: "Pay Now"}
padding="px-[12px] py-[6px]"
onClick={handlePayment}
/>
{/if}
<div class="invoice-view-actions">
{#if !isPayee && !unsupportedNetwork && !isPaid && !isRequestPayed && !isSigningTransaction}
{#if !hasEnoughBalance}
<div class="balance-warning">
Insufficient funds: {userBalance}
{paymentCurrencies[0]?.symbol || "ETH"}
</div>
{/if}
<Button
type="button"
text={!correctChain
? "Switch Network"
: !approved &&
paymentCurrencies[0]?.type === Types.RequestLogic.CURRENCY.ERC20
? "Approve"
: "Pay Now"}
padding="px-[12px] py-[6px]"
onClick={handlePayment}
disabled={!hasEnoughBalance}
/>
{/if}
</div>

{#if unsupportedNetwork}
<div class="unsupported-network">Unsupported payment network!</div>
Expand Down Expand Up @@ -995,7 +1065,6 @@
flex-direction: column;
gap: 10px;
width: 100%;
margin-bottom: 32px;
}
.status {
Expand Down Expand Up @@ -1091,6 +1160,7 @@
display: flex;
align-items: center;
gap: 0.25rem;
justify-content: end;
}
:global(.invoice-view-actions button) {
Expand Down Expand Up @@ -1158,6 +1228,21 @@
text-decoration: underline;
}
.balance-warning {
color: #ef4444;
font-size: 0.875rem;
padding: 0.5rem;
border-radius: 0.375rem;
background-color: #fee2e2;
margin-right: 0.5rem;
}
:global(.invoice-view-actions button[disabled]) {
opacity: 0.5;
cursor: not-allowed;
background-color: #71717a !important;
}
:global(.pay-button) {
padding: 8px 12px !important;
width: fit-content;
Expand Down
55 changes: 22 additions & 33 deletions packages/invoice-dashboard/src/lib/view-requests.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,8 @@
export let requestNetwork: RequestNetwork | null | undefined;
export let currencies: CurrencyTypes.CurrencyInput[] = [];

let cipherProvider:
| (CipherProviderTypes.ICipherProvider & {
getSessionSignatures: (
signer: ethers.Signer,
walletAddress: `0x${string}`
) => Promise<any>;
})
| undefined;
let cipherProvider: CipherProviderTypes.ICipherProvider | undefined =
requestNetwork?.getCipherProvider();

let sliderValueForDecryption = JSON.parse(
localStorage?.getItem("isDecryptionEnabled") ?? "false"
Expand Down Expand Up @@ -102,27 +96,18 @@
let sortOrder = "desc";
let sortColumn = "timestamp";

let previousAddress: string | undefined;

$: {
if (wagmiConfig) {
const newAccount = getAccount(wagmiConfig);
if (newAccount?.address !== previousAddress) {
account = newAccount;
previousAddress = newAccount?.address;

if (newAccount?.address) {
tick().then(() => {
enableDecryption();
getRequests();
});
} else {
requests = [];
activeRequest = undefined;
previousWalletAddress = undefined;
previousNetwork = undefined;
}
}
account = getAccount(wagmiConfig);
}
}

$: {
if (account?.address) {
tick().then(() => {
enableDecryption();
getRequests();
});
}
}

Expand All @@ -131,11 +116,9 @@
onMount(() => {
unwatchAccount = watchAccount(wagmiConfig, {
onChange(data) {
if (data?.address !== previousAddress) {
if (data?.address !== account?.address) {
account = data;
previousAddress = data?.address;

if (data?.address) {
if (account?.address) {
getRequests();
} else {
requests = [];
Expand All @@ -152,7 +135,13 @@
if (typeof unwatchAccount === "function") unwatchAccount();
});

$: cipherProvider = undefined;
$: cipherProvider =
requestNetwork?.getCipherProvider() as CipherProviderTypes.ICipherProvider & {
getSessionSignatures: (
signer: ethers.Signer,
walletAddress: `0x${string}`
) => Promise<any>;
};

$: {
signer = account?.address;
Expand Down Expand Up @@ -355,7 +344,7 @@
BigInt(request.expectedAmount),
currencyInfo?.decimals ?? 18
),
currencySymbol: currencyInfo?.symbol,
currencySymbol: currencyInfo!.symbol,
paymentCurrencies,
};
}
Expand Down
4 changes: 1 addition & 3 deletions shared/utils/formatAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ export const formatAddress = (
first: number = 6,
last: number = 4
): string => {
if (!checkAddress(address)) {
console.error("Invalid address!");
}
if (!address) return "";

return `${address.slice(0, first)}...${address.slice(-last)}`;
};
Loading