Skip to content
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

ArConnect 1.18.3 #481

Merged
merged 8 commits into from
Oct 1, 2024
22 changes: 13 additions & 9 deletions src/api/modules/sign_data_item/sign_data_item.background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,22 @@ const background: ModuleFunction<number[]> = async (
)
) {
try {
const tags = dataItem?.tags || [];
const quantityTag = tags.find((tag) => tag.name === "Quantity");
const quantityTag = dataItem.tags?.find((tag) => tag.name === "Quantity");
if (quantityTag) {
const quantity = BigNumber(quantityTag.value).toFixed(
0,
BigNumber.ROUND_FLOOR
);
if (!isNaN(+quantity)) {
quantityTag.value = quantity;
const quantityBigNum = BigNumber(quantityTag.value);

// Ensure the quantity is a valid positive non-zero number (greater than 0)
if (!quantityBigNum.isPositive() || quantityBigNum.isZero()) {
throw new Error("INVALID_QUANTITY");
}

quantityTag.value = quantityBigNum.toFixed(0, BigNumber.ROUND_FLOOR);
}
} catch {}
} catch (e) {
if (e?.message === "INVALID_QUANTITY") {
throw new Error("Quantity must be a valid positive non-zero number.");
}
}
try {
await authenticate({
type: "signDataItem",
Expand Down
8 changes: 3 additions & 5 deletions src/components/popup/HistoryProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type PropsWithChildren, useEffect, useState } from "react";
import { getDecryptionKey, isExpired } from "~wallets/auth";
import { getDecryptionKey } from "~wallets/auth";
import { useLocation } from "wouter";
import {
type BackAction,
Expand Down Expand Up @@ -28,14 +28,12 @@ export default function HistoryProvider({ children }: PropsWithChildren<{}>) {
};

// redirect to unlock if decryiption
// key is not available or if the password
// has expired and needs to be reset
// key is not available
useEffect(() => {
(async () => {
const decryptionKey = await getDecryptionKey();
const expired = await isExpired();

if (!decryptionKey || expired) {
if (!decryptionKey) {
push("/unlock");
}
})();
Expand Down
53 changes: 33 additions & 20 deletions src/components/popup/home/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ export default function Balance() {
}

useEffect(() => {
if (parseFloat(balance.toString()) !== historicalBalance[0]) {
if (
balance.toNumber() !== historicalBalance[historicalBalance.length - 1]
) {
setLoading(true);
} else {
setLoading(false);
Expand Down Expand Up @@ -198,13 +200,19 @@ export default function Balance() {

async function balanceHistory(address: string, gateway: Gateway) {
const arweave = new Arweave(gateway);
let minHeight = 0;
try {
const { height } = await arweave.network.getInfo();
// blocks per day - 720
minHeight = height - 720 * 30;
} catch {}

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

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

// sort txs
// Merge and sort transactions in descending order (newest first)
const txs = inTxs
.concat(outTxs)
.map((edge) => edge.node)
.filter((tx) => !!tx?.block?.timestamp)
.sort((a, b) => a.block.timestamp - b.block.timestamp);
.filter((tx) => !!tx?.block?.timestamp) // Filter out transactions without a timestamp
.sort((a, b) => b.block.timestamp - a.block.timestamp); // Sort by newest to oldest

// get initial balance
let balance = parseFloat(
// Get the current balance
let balance = BigNumber(
arweave.ar.winstonToAr(await arweave.wallets.getBalance(address))
);

const res = [balance];
// Initialize the result array with the current balance
const res = [balance.toNumber()];

// go back in time by tx and calculate
// historical balance
// Process transactions from newest to oldest, adjusting the balance
for (const tx of txs) {
balance -= parseFloat(tx.fee.ar);

if (tx.owner.address === address) {
balance -= parseFloat(tx.quantity.ar);
// Outgoing transaction: add back the transaction amount and fee (since we are reversing)
balance = balance.plus(tx.quantity.ar).plus(tx.fee.ar);
} else {
balance += parseFloat(tx.quantity.ar);
// Incoming transaction: subtract the amount received
balance = balance.minus(tx.quantity.ar);
}

res.push(balance);
// Push the balance at that point in time
res.push(balance.toNumber());
}

// Reverse the result array to have chronological order for the line chart (oldest to newest)
res.reverse();

return res;
}

Expand Down
9 changes: 7 additions & 2 deletions src/components/popup/home/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
sortFn,
type ExtendedTransaction
} from "~lib/transactions";
import BigNumber from "bignumber.js";

export default function Transactions() {
const [transactions, fetchTransactions] = useState<ExtendedTransaction[]>([]);
Expand Down Expand Up @@ -62,8 +63,12 @@ export default function Transactions() {
)
);

const sent = await processTransactions(rawSent, "sent");
const received = await processTransactions(rawReceived, "received");
let sent = await processTransactions(rawSent, "sent");
sent = sent.filter((tx) => BigNumber(tx.node.quantity.ar).gt(0));
let received = await processTransactions(rawReceived, "received");
received = received.filter((tx) =>
BigNumber(tx.node.quantity.ar).gt(0)
);
const aoSent = await processTransactions(rawAoSent, "aoSent", true);
const aoReceived = await processTransactions(
rawAoReceived,
Expand Down
9 changes: 6 additions & 3 deletions src/lib/ao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ export class AOProcess {
this.processId = processId;
this.ao = connect({
GRAPHQL_URL:
connectionConfig?.GATEWAY_URL ??
joinUrl({ url: defaultConfig.GATEWAY_URL, path: "graphql" }),
CU_URL: connectionConfig?.GATEWAY_URL ?? defaultConfig.CU_URL,
connectionConfig?.GRAPHQL_URL ??
joinUrl({
url: connectionConfig?.GATEWAY_URL ?? defaultConfig.GATEWAY_URL,
path: "graphql"
}),
CU_URL: connectionConfig?.CU_URL ?? defaultConfig.CU_URL,
MU_URL: connectionConfig?.MU_URL ?? defaultConfig.MU_URL,
GATEWAY_URL: connectionConfig?.GATEWAY_URL ?? defaultConfig.GATEWAY_URL
});
Expand Down
28 changes: 24 additions & 4 deletions src/notifications/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
combineAndSortTransactions,
processTransactions
} from "./utils";
import BigNumber from "bignumber.js";

export type RawTransaction = {
node: {
Expand Down Expand Up @@ -87,13 +88,15 @@ export async function notificationsHandler(alarmInfo?: Alarms.Alarm) {
query: !aoNotificationSetting.includes("allTxns")
? AR_RECEIVER_QUERY
: ALL_AR_RECEIVER_QUERY,
variables: { address }
variables: { address },
isAllTxns: aoNotificationSetting.includes("allTxns")
},
{
query: !aoNotificationSetting.includes("allTxns")
? AR_SENT_QUERY
: ALL_AR_SENT_QUERY,
variables: { address }
variables: { address },
isAllTxns: aoNotificationSetting.includes("allTxns")
}
]
);
Expand Down Expand Up @@ -181,15 +184,32 @@ const arNotificationsHandler = async (
address: string,
lastStoredHeight: number,
notificationSetting: boolean,
queriesConfig: { query: string; variables: Record<string, any> }[]
queriesConfig: {
query: string;
variables: Record<string, any>;
isAllTxns?: boolean;
}[]
): Promise<ArNotificationsHandlerReturnType> => {
try {
let transactionDiff = [];

const queries = queriesConfig.map((config) =>
gql(config.query, config.variables, suggestedGateways[1])
);
const responses = await Promise.all(queries);
let responses = await Promise.all(queries);
responses = responses.map((response, index) => {
if (
typeof queriesConfig[index].isAllTxns === "boolean" &&
!queriesConfig[index].isAllTxns
) {
response.data.transactions.edges =
response.data.transactions.edges.filter((edge) =>
BigNumber(edge.node.quantity.ar).gt(0)
);
}
return response;
});

const combinedTransactions = combineAndSortTransactions(responses);

const enrichedTransactions = processTransactions(
Expand Down
9 changes: 4 additions & 5 deletions src/notifications/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

export const AR_RECEIVER_QUERY = `
query ($address: String!) {
transactions(first: 10, recipients: [$address], tags: [{ name: "Type", values: ["Transfer"] }]) {

transactions(first: 10, recipients: [$address], bundledIn: null) {
edges {
cursor
node {
Expand All @@ -23,7 +22,7 @@ query ($address: String!) {
`;

export const AR_SENT_QUERY = `query ($address: String!) {
transactions(first: 10, owners: [$address], tags: [{ name: "Type", values: ["Transfer"] }]) {
transactions(first: 10, owners: [$address], bundledIn: null) {
edges {
cursor
node {
Expand Down Expand Up @@ -136,7 +135,7 @@ export const ALL_AR_SENT_QUERY = `query ($address: String!) {

export const AR_RECEIVER_QUERY_WITH_CURSOR = `
query ($address: String!, $after: String) {
transactions(first: 10, recipients: [$address], tags: [{ name: "Type", values: ["Transfer"] }], after: $after) {
transactions(first: 10, recipients: [$address], bundledIn: null, after: $after) {
pageInfo {
hasNextPage
}
Expand All @@ -160,7 +159,7 @@ query ($address: String!, $after: String) {

export const AR_SENT_QUERY_WITH_CURSOR = `
query ($address: String!, $after: String) {
transactions(first: 10, owners: [$address], tags: [{ name: "Type", values: ["Transfer"] }], after: $after) {
transactions(first: 10, owners: [$address], bundledIn: null, after: $after) {
pageInfo {
hasNextPage
}
Expand Down
18 changes: 5 additions & 13 deletions src/routes/popup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WalletHeader from "~components/popup/WalletHeader";
import NoBalance from "~components/popup/home/NoBalance";
import Balance from "~components/popup/home/Balance";
import { AnnouncementPopup } from "./announcement";
import { getDecryptionKey, isExpired } from "~wallets/auth";
import { getDecryptionKey } from "~wallets/auth";
import { useHistory } from "~utils/hash_router";
import {
trackEvent,
Expand Down Expand Up @@ -87,19 +87,11 @@ export default function Home() {
}, [activeAddress, assets, aoTokens]);

useEffect(() => {
// check if password is expired here
const checkExpiration = async () => {
const expired = await isExpired();
// delete expiration from storage here or in unlock page
if (expired) {
ExtensionStorage.remove("password_expires");
push("/unlock");
} else {
await trackEvent(EventType.LOGIN, {});
await trackPage(PageType.HOME);
}
const trackEventAndPage = async () => {
await trackEvent(EventType.LOGIN, {});
await trackPage(PageType.HOME);
};
checkExpiration();
trackEventAndPage();

// schedule import ao tokens
scheduleImportAoTokens();
Expand Down
10 changes: 3 additions & 7 deletions src/routes/popup/transaction/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ import { TempTransactionStorage } from "~utils/storage";
import { useContact } from "~contacts/hooks";
import { EventType, PageType, trackEvent, trackPage } from "~utils/analytics";
import BigNumber from "bignumber.js";
import { Token } from "ao-tokens";
import { fetchTokenByProcessId } from "~lib/transactions";
import type { TokenInfo } from "~tokens/aoTokens/ao";

// pull contacts and check if to address is in contacts

Expand Down Expand Up @@ -161,11 +159,9 @@ export default function Transaction({ id: rawId, gw, message }: Props) {
);

if (aoQuantity) {
let tokenInfo;
tokenInfo = await fetchTokenByProcessId(data.transaction.recipient);
if (!tokenInfo) {
tokenInfo = (await Token(data.transaction.recipient)).info;
}
const tokenInfo = await fetchTokenByProcessId(
data.transaction.recipient
);
if (tokenInfo) {
const amount = balanceToFractioned(aoQuantity.value, {
id: data.transaction.recipient,
Expand Down
8 changes: 6 additions & 2 deletions src/routes/popup/transaction/transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
getFullMonthName,
getTransactionDescription
} from "~lib/transactions";
import BigNumber from "bignumber.js";

const defaultCursors = ["", "", "", ""];
const defaultHasNextPages = [true, true, true, true];
Expand Down Expand Up @@ -85,8 +86,8 @@ export default function Transactions() {
})
);

const sent = await processTransactions(rawSent, "sent");
const received = await processTransactions(rawReceived, "received");
let sent = await processTransactions(rawSent, "sent");
let received = await processTransactions(rawReceived, "received");
const aoSent = await processTransactions(rawAoSent, "aoSent", true);
const aoReceived = await processTransactions(
rawAoReceived,
Expand All @@ -100,6 +101,9 @@ export default function Transactions() {
)
);

sent = sent.filter((tx) => BigNumber(tx.node.quantity.ar).gt(0));
received = received.filter((tx) => BigNumber(tx.node.quantity.ar).gt(0));

setHasNextPages(
[rawReceived, rawSent, rawAoSent, rawAoReceived].map(
(result) =>
Expand Down
Loading
Loading