Skip to content

Commit

Permalink
Merge pull request #532 from arconnectio/staging
Browse files Browse the repository at this point in the history
ArConnect 1.20.1
  • Loading branch information
nicholaswma authored Oct 30, 2024
2 parents 52a74f3 + 9275ca3 commit cac5a5f
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 103 deletions.
6 changes: 3 additions & 3 deletions assets/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,7 @@
"description": "Not connected indicator"
},
"not_connected_text": {
"message": "\"Connect / Disconnect\" is an indicator for when your ArConnect wallet is connected to an Arweave or AO application. For regular use like sending, receiving, checking balances, etc., ArConnect will always show disconnected.",
"message": "\"Connect / Disconnect\" is a label for when your ArConnect wallet is connected to an Arweave or AO dapp. For regular use like sending, receiving, checking balances, etc., ArConnect will always show disconnected.",
"description": "Not connected indicator explainer"
},
"disconnect": {
Expand Down Expand Up @@ -2009,11 +2009,11 @@
"description": "Popup description about ao token transfer learn more"
},
"ao_degraded": {
"message": "Unable to connect to AO Token Process",
"message": "Token balance error",
"description": "ao degraded title text"
},
"ao_degraded_description": {
"message": "AO balance will be available when <br/>network issues are resolved.",
"message": "Oops, ArConnect is unable to fetch your token balance. Please try again later.",
"description": "ao degraded description text"
},
"network_issue": {
Expand Down
4 changes: 2 additions & 2 deletions assets/_locales/zh_CN/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1999,11 +1999,11 @@
"description": "Popup description about ao token transfer learn more"
},
"ao_degraded": {
"message": "无法连接到 AO 令牌进程",
"message": "代币余额错误",
"description": "ao degraded title text"
},
"ao_degraded_description": {
"message": "网络问题解决后,AO 余额将可用",
"message": "ArConnect 无法获取您的代币余额。这只是一个用户界面问题。请稍后重试",
"description": "ao degraded description text"
},
"network_issue": {
Expand Down
37 changes: 13 additions & 24 deletions src/components/popup/Token.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
formatFiatBalance,
formatTokenBalance,
balanceToFractioned
} from "~tokens/currency";
import { formatFiatBalance, balanceToFractioned } from "~tokens/currency";
import {
type MouseEventHandler,
useEffect,
Expand All @@ -23,8 +19,6 @@ import * as viewblock from "~lib/viewblock";
import Squircle from "~components/Squircle";
import useSetting from "~settings/hook";
import styled from "styled-components";
import Arweave from "arweave";
import { useGateway } from "~gateways/wayfinder";
import aoLogo from "url:/assets/ecosystem/ao-logo.svg";
import { getUserAvatar } from "~lib/avatar";
import { formatBalance } from "~utils/format";
Expand All @@ -34,6 +28,7 @@ import BigNumber from "bignumber.js";
import JSConfetti from "js-confetti";
import browser from "webextension-polyfill";
import { AO_NATIVE_TOKEN } from "~utils/ao_import";
import { useBalance } from "~wallets/hooks";

export default function Token({ onClick, ...props }: Props) {
const ref = useRef(null);
Expand Down Expand Up @@ -166,13 +161,13 @@ export default function Token({ onClick, ...props }: Props) {
{props?.loading ? (
<Skeleton width="80px" height="20px" />
) : props?.error ? (
<TooltipV2 content={DegradedMessage} position="left">
<MessageTooltip content={DegradedMessage} position="left">
<WarningIcon />
</TooltipV2>
</MessageTooltip>
) : props?.networkError ? (
<TooltipV2 content={NetworkErrorMessage} position="left">
<MessageTooltip content={NetworkErrorMessage} position="left">
<NetworkErrorIcon />
</TooltipV2>
</MessageTooltip>
) : (
<>
{showTooltip ? (
Expand Down Expand Up @@ -373,6 +368,10 @@ const BalanceTooltip = styled(TooltipV2)`
margin-right: 1rem;
`;

const MessageTooltip = styled(TooltipV2)`
max-width: 290px;
`;

const Image = styled.img`
width: 16px;
padding: 0 8px;
Expand Down Expand Up @@ -486,33 +485,23 @@ export function ArToken({ onClick }: ArTokenProps) {
});

// load ar balance
const [balance, setBalance] = useState(BigNumber("0"));
const [fiatBalance, setFiatBalance] = useState(BigNumber("0"));
const [displayBalance, setDisplayBalance] = useState("0");
const [totalBalance, setTotalBalance] = useState("");
const [showTooltip, setShowTooltip] = useState(false);

// memoized requirements to ensure stability
const requirements = useMemo(() => ({ ensureStake: true }), []);
const gateway = useGateway(requirements);
const balance = useBalance();

useEffect(() => {
(async () => {
if (!activeAddress) return;

const arweave = new Arweave(gateway);

// fetch balance
const winstonBalance = await arweave.wallets.getBalance(activeAddress);
const arBalance = BigNumber(arweave.ar.winstonToAr(winstonBalance));
setBalance(arBalance);

const formattedBalance = formatBalance(arBalance);
const formattedBalance = formatBalance(balance);
setTotalBalance(formattedBalance.tooltipBalance);
setShowTooltip(formattedBalance.showTooltip);
setDisplayBalance(formattedBalance.displayBalance);
})();
}, [activeAddress, gateway]);
}, [activeAddress, balance]);

useEffect(() => {
setFiatBalance(balance.multipliedBy(price));
Expand Down
38 changes: 23 additions & 15 deletions src/components/popup/home/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Loading, TooltipV2 } from "@arconnect/components";
import { useEffect, useMemo, useState, type HTMLProps } from "react";
import { useStorage } from "@plasmohq/storage/hook";
import { ExtensionStorage } from "~utils/storage";
import { useHistory } from "~utils/hash_router";
import { useBalance } from "~wallets/hooks";
import { getArPrice } from "~lib/coingecko";
import { getAppURL } from "~utils/format";
Expand All @@ -25,8 +24,8 @@ import styled from "styled-components";
import Arweave from "arweave";
import { removeDecryptionKey } from "~wallets/auth";
import { findGateway } from "~gateways/wayfinder";
import type { Gateway } from "~gateways/gateway";
import BigNumber from "bignumber.js";
import { retryWithDelay, retryWithDelayAndTimeout } from "~utils/retry";

export default function Balance() {
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -103,8 +102,7 @@ export default function Balance() {
(async () => {
if (!activeAddress) return;
setLoading(true);
const gateway = await findGateway({ graphql: true });
const history = await balanceHistory(activeAddress, gateway);
const history = await balanceHistory(activeAddress);

setHistoricalBalance(history);
setLoading(false);
Expand Down Expand Up @@ -192,8 +190,9 @@ export default function Balance() {
);
}

async function balanceHistory(address: string, gateway: Gateway) {
const arweave = new Arweave(gateway);
async function balanceHistory(address: string) {
const gateway = await findGateway({ graphql: true });
let arweave = new Arweave(gateway);
let minHeight = 0;
try {
const { height } = await arweave.network.getInfo();
Expand All @@ -203,8 +202,9 @@ async function balanceHistory(address: string, gateway: Gateway) {

// find txs coming in and going out
const inTxs = (
await gql(
`
await retryWithDelay(() =>
gql(
`
query($recipient: String!, $minHeight: Int!) {
transactions(recipients: [$recipient], first: 100, bundledIn: null, block: {min: $minHeight}) {
edges {
Expand All @@ -226,13 +226,15 @@ async function balanceHistory(address: string, gateway: Gateway) {
}
}
`,
{ recipient: address, minHeight }
{ recipient: address, minHeight }
)
)
).data.transactions.edges;

const outTxs = (
await gql(
`
await retryWithDelay(() =>
gql(
`
query($owner: String!, $minHeight: Int!) {
transactions(owners: [$owner], first: 100, bundledIn: null, block: {min: $minHeight}) {
edges {
Expand All @@ -254,7 +256,8 @@ async function balanceHistory(address: string, gateway: Gateway) {
}
}
`,
{ owner: address, minHeight }
{ owner: address, minHeight }
)
)
).data.transactions.edges;

Expand All @@ -266,9 +269,14 @@ async function balanceHistory(address: string, gateway: Gateway) {
.sort((a, b) => b.block.timestamp - a.block.timestamp); // Sort by newest to oldest

// Get the current balance
let balance = BigNumber(
arweave.ar.winstonToAr(await arweave.wallets.getBalance(address))
);
const winstonBalance = await retryWithDelayAndTimeout(async () => {
const gateway = await findGateway({});
arweave = new Arweave(gateway);
const balance = await arweave.wallets.getBalance(address);
if (isNaN(+balance)) throw new Error("Balance is invalid");
return balance;
});
let balance = BigNumber(arweave.ar.winstonToAr(winstonBalance));

// Initialize the result array with the current balance
const res = [balance.toNumber()];
Expand Down
15 changes: 7 additions & 8 deletions src/components/popup/home/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,13 @@ export default function Transactions() {
: "Pending"}
</Secondary>
</Section>
{transaction.transactionType !== "printArchive" && (
<Section alignRight>
<Main>{getFormattedAmount(transaction)}</Main>
<Secondary>
{getFormattedFiatAmount(transaction, arPrice, currency)}
</Secondary>
</Section>
)}

<Section alignRight>
<Main>{getFormattedAmount(transaction)}</Main>
<Secondary>
{getFormattedFiatAmount(transaction, arPrice, currency)}
</Secondary>
</Section>
</Transaction>
</TransactionItem>
))
Expand Down
15 changes: 14 additions & 1 deletion src/lib/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export const getFormattedAmount = (transaction: ExtendedTransaction) => {
}).toFixed()} ${transaction.aoInfo.tickerName}`;
}
return "";
case "printArchive":
return `${parseFloat(transaction.node.fee.ar).toFixed(3)} AR`;
default:
return "";
}
Expand All @@ -154,11 +156,22 @@ export const getFormattedFiatAmount = (
currency: string
) => {
try {
if (transaction.node.quantity) {
if (
transaction.node.quantity &&
transaction.transactionType !== "printArchive"
) {
const fiatBalance = BigNumber(transaction.node.quantity.ar).multipliedBy(
arPrice
);
return formatFiatBalance(fiatBalance, currency);
} else if (
transaction.node.fee &&
transaction.transactionType === "printArchive"
) {
const fiatBalance = BigNumber(transaction.node.fee.ar).multipliedBy(
arPrice
);
return formatFiatBalance(fiatBalance, currency);
}
} catch {}
return "";
Expand Down
3 changes: 3 additions & 0 deletions src/notifications/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export type RawTransaction = {
quantity: {
ar: string;
};
fee: {
ar: string;
};
block: {
timestamp: number;
height: number;
Expand Down
1 change: 1 addition & 0 deletions src/notifications/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ query ($address: String!) {
recipient
owner { address }
quantity { ar }
fee { ar }
block { timestamp, height }
tags {
name
Expand Down
6 changes: 6 additions & 0 deletions src/routes/popup/transaction/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,12 @@ export default function Transaction({ id: rawId, gw, message }: Props) {
</div>
</PropertyValue>
</TransactionProperty>
<TransactionProperty>
<PropertyName>
{browser.i18n.getMessage("transaction_fee")}
</PropertyName>
<PropertyValue>{transaction.fee.ar} AR</PropertyValue>
</TransactionProperty>
{!message && (
<TransactionProperty>
<PropertyName>
Expand Down
39 changes: 1 addition & 38 deletions src/tokens/aoTokens/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
Id,
Owner
} from "./ao";
import { withRetry } from "~utils/retry";

/** Tokens storage name */
const AO_TOKENS = "ao_tokens";
Expand All @@ -36,44 +37,6 @@ const gateway = {
protocol: "https"
};

/**
* Generic retry function for any async operation.
* @param fn - The async function to be retried.
* @param maxRetries - Maximum retry attempts.
* @param retryDelay - Delay between retries in milliseconds.
* @returns A promise of the type that the async function returns.
*/
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
retryDelay: number = 100
): Promise<T> {
let lastError: any;

const delay = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt < maxRetries) {
const waitTime = Math.pow(2, attempt - 1) * retryDelay;
console.log(`Attempt ${attempt} failed, retrying in ${waitTime}ms...`);
await delay(waitTime);
} else {
console.error(
`All ${maxRetries} attempts failed. Last error:`,
lastError
);
}
}
}

throw lastError;
}

async function getTokenInfo(id: string): Promise<TokenInfo> {
const body = {
Id,
Expand Down
Loading

0 comments on commit cac5a5f

Please sign in to comment.