diff --git a/src/components/popup/Route.tsx b/src/components/popup/Route.tsx
index 6aa301a3..2902ea07 100644
--- a/src/components/popup/Route.tsx
+++ b/src/components/popup/Route.tsx
@@ -8,13 +8,15 @@ import styled from "styled-components";
*/
const Route: typeof BaseRoute = ({ path, component, children }) => {
const [matches, params] = useRoute(path);
+ if (!matches) return null;
+
const routeContent = component
? createElement(component, { params })
: typeof children === "function"
? children(params)
: children;
- return matches ? {routeContent} : null;
+ return {routeContent};
};
const PageWrapper = styled(motion.main)`
diff --git a/src/components/popup/home/Transactions.tsx b/src/components/popup/home/Transactions.tsx
index 8e24e4d7..7d41067e 100644
--- a/src/components/popup/home/Transactions.tsx
+++ b/src/components/popup/home/Transactions.tsx
@@ -16,7 +16,7 @@ import {
import { useHistory } from "~utils/hash_router";
import { getArPrice } from "~lib/coingecko";
import useSetting from "~settings/hook";
-import { suggestedGateways } from "~gateways/gateway";
+import { printTxWorkingGateways, txHistoryGateways } from "~gateways/gateway";
import { Spacer } from "@arconnect/components";
import { Heading, ViewAll, TokenCount } from "../Title";
import {
@@ -29,6 +29,7 @@ import {
type ExtendedTransaction
} from "~lib/transactions";
import BigNumber from "bignumber.js";
+import { retryWithDelay } from "~utils/retry";
export default function Transactions() {
const [transactions, fetchTransactions] = useState([]);
@@ -65,8 +66,24 @@ export default function Transactions() {
rawAoReceived,
rawPrintArchive
] = await Promise.allSettled(
- queries.map((query) =>
- gql(query, { address: activeAddress }, suggestedGateways[1])
+ queries.map((query, index) =>
+ retryWithDelay(async (attempt) => {
+ const data = await gql(
+ query,
+ { address: activeAddress },
+ index !== 4
+ ? txHistoryGateways[attempt % txHistoryGateways.length]
+ : printTxWorkingGateways[
+ attempt % printTxWorkingGateways.length
+ ]
+ );
+ if (data?.data === null && (data as any)?.errors?.length > 0) {
+ throw new Error(
+ (data as any)?.errors?.[0]?.message || "GraphQL Error"
+ );
+ }
+ return data;
+ }, 2)
)
);
@@ -122,6 +139,16 @@ export default function Transactions() {
}
});
+ combinedTransactions = combinedTransactions.reduce(
+ (acc, transaction) => {
+ if (!acc.some((t) => t.node.id === transaction.node.id)) {
+ acc.push(transaction);
+ }
+ return acc;
+ },
+ [] as ExtendedTransaction[]
+ );
+
fetchTransactions(combinedTransactions);
}
} catch (error) {
diff --git a/src/gateways/gateway.ts b/src/gateways/gateway.ts
index 183b6f75..e4227d33 100644
--- a/src/gateways/gateway.ts
+++ b/src/gateways/gateway.ts
@@ -24,7 +24,7 @@ export const suggestedGateways: Gateway[] = [
protocol: "https"
},
{
- host: "arweave.live",
+ host: "g8way.io",
port: 443,
protocol: "https"
}
@@ -49,4 +49,33 @@ export const fallbackGateway = {
protocol: "https"
};
+export const printTxWorkingGateways: Gateway[] = [
+ {
+ host: "arweave-search.goldsky.com",
+ port: 443,
+ protocol: "https"
+ },
+ {
+ host: "permagate.io",
+ port: 443,
+ protocol: "https"
+ },
+ {
+ host: "ar-io.dev",
+ port: 443,
+ protocol: "https"
+ },
+ {
+ host: "arweave.dev",
+ port: 443,
+ protocol: "https"
+ }
+];
+
+export const txHistoryGateways = [
+ suggestedGateways[1],
+ suggestedGateways[0],
+ suggestedGateways[3]
+];
+
export const defaultGateway = suggestedGateways[0];
diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts
index 7e747f05..295e17e4 100644
--- a/src/lib/transactions.ts
+++ b/src/lib/transactions.ts
@@ -1,7 +1,7 @@
import type GQLResultInterface from "ar-gql/dist/faces";
import type { GQLEdgeInterface } from "ar-gql/dist/faces";
import type { RawTransaction } from "~notifications/api";
-import type { TokenInfo } from "~tokens/aoTokens/ao";
+import { timeoutPromise, type TokenInfo } from "~tokens/aoTokens/ao";
import { formatAddress } from "~utils/format";
import { ExtensionStorage } from "~utils/storage";
import { getTokenInfo } from "~tokens/aoTokens/router";
@@ -91,7 +91,10 @@ const processAoTransaction = async (
transaction: GQLEdgeInterface,
type: string
) => {
- const tokenData = await fetchTokenByProcessId(transaction.node.recipient);
+ const tokenData = await timeoutPromise(
+ fetchTokenByProcessId(transaction.node.recipient),
+ 10000
+ ).catch(() => null);
const quantityTag = transaction.node.tags.find(
(tag) => tag.name === "Quantity"
);
diff --git a/src/notifications/utils.ts b/src/notifications/utils.ts
index f306a99d..581e4c86 100644
--- a/src/notifications/utils.ts
+++ b/src/notifications/utils.ts
@@ -287,6 +287,7 @@ query ($address: String!, $after: String) {
recipient
owner { address }
quantity { ar }
+ fee { ar }
block { timestamp, height }
tags {
name
diff --git a/src/popup.tsx b/src/popup.tsx
index f9b8c6c0..fefead63 100644
--- a/src/popup.tsx
+++ b/src/popup.tsx
@@ -3,7 +3,7 @@ import styled from "styled-components";
import { useHashLocation } from "~utils/hash_router";
import { syncLabels, useSetUp } from "~wallets";
import { useEffect, useState } from "react";
-import { Router } from "wouter";
+import { Router, Switch } from "wouter";
import HistoryProvider from "~components/popup/HistoryProvider";
@@ -122,17 +122,21 @@ export default function Popup() {
{(params: { url: string }) => }
-
- {(params: { id: string }) => }
-
-
+
+
+
+ {(params: { id: string }) => }
+
+
-
- {(params: { address: string }) => (
-
- )}
-
-
+
+
+
+ {(params: { address: string }) => (
+
+ )}
+
+
{
return hasNextPages[idx]
- ? gql(
- query,
- { address: activeAddress, after: cursors[idx] },
- suggestedGateways[1]
- )
+ ? retryWithDelay(async (attempt) => {
+ const data = await gql(
+ query,
+ { address: activeAddress, after: cursors[idx] },
+ idx !== 4
+ ? txHistoryGateways[attempt % txHistoryGateways.length]
+ : printTxWorkingGateways[
+ attempt % printTxWorkingGateways.length
+ ]
+ );
+ if (
+ data?.data === null &&
+ (data as any)?.errors?.length > 0
+ ) {
+ throw new Error(
+ (data as any)?.errors?.[0]?.message || "GraphQL Error"
+ );
+ }
+ return data;
+ }, 2)
: ({
data: {
transactions: {
@@ -228,18 +244,16 @@ export default function Transactions() {
: "Pending"}
- {transaction.transactionType !== "printArchive" && (
-
- {getFormattedAmount(transaction)}
-
- {getFormattedFiatAmount(
- transaction,
- arPrice,
- currency
- )}
-
-
- )}
+
+ {getFormattedAmount(transaction)}
+
+ {getFormattedFiatAmount(
+ transaction,
+ arPrice,
+ currency
+ )}
+
+
))}
diff --git a/src/utils/retry.ts b/src/utils/retry.ts
index 60193365..13f4b16d 100644
--- a/src/utils/retry.ts
+++ b/src/utils/retry.ts
@@ -6,7 +6,7 @@
* @return A Promise that resolves with the result of the function or rejects after all attempts fail.
*/
export async function retryWithDelay(
- fn: () => Promise,
+ fn: (attemp: number) => Promise,
maxAttempts: number = 3,
delay: number = 1000
): Promise {
@@ -14,7 +14,7 @@ export async function retryWithDelay(
const attempt = async (): Promise => {
try {
- return await fn();
+ return await fn(attempts);
} catch (error) {
attempts += 1;
if (attempts < maxAttempts) {