Skip to content

Commit

Permalink
Merge branch 'main' into fork-SiegfriedBz--close-mobile-menu-on-selec…
Browse files Browse the repository at this point in the history
…t-lang
  • Loading branch information
fliebenberg authored Aug 2, 2024
2 parents 3d49e9c + 8b8b444 commit e48ebf2
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 63 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ next-env.d.ts

localhost:3000/
.env

# Script outputs
*/.scriptOutputs/
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# instead of duplicating the .gitignore file,
# but duplicating way is more IDE friendly

# fetchUsers json output
scripts/.scriptOutputs/

# dependencies
/node_modules
/.pnp
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"test": "vitest",
"test-integration": "playwright test",
"test-all": "npm run lint && npm run test && npm run test-integration",
"copy-pr": "node ./scripts/copy-pr.js"
"copy-pr": "node ./scripts/copy-pr.js",
"fetchUsers": "node ./scripts/fetchUsers.js"
},
"dependencies": {
"@mdx-js/loader": "^3.0.0",
Expand Down
147 changes: 147 additions & 0 deletions scripts/fetchUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
const fs = require("fs");
const path = require("path");

const fetchUsers = async () => {
// fetch all pairs
const pairsList = await fetchAllPairs();

// fetch all orders for all pairs
const allOrdersByPairs = await Promise.all(
pairsList.map((pair) => {
const { address, lastOrderId } = pair;
const orderIds = Array.from({ length: lastOrderId }, (_, i) => i + 1); // [1, ..., lastOrderId]

return fetchOrdersByPair(address, orderIds);
})
);
const allOrders = allOrdersByPairs.flat();

// Process orders to count wallet addresses
const usersDict = {};
for (let i = 0; i < allOrders.length; i++) {
const radixWalletAddress = allOrders[i].settlementAccount; // account address for this order
if (!radixWalletAddress) {
continue;
}
usersDict[radixWalletAddress] = usersDict[radixWalletAddress]
? usersDict[radixWalletAddress] + 1
: 1;
}

return {
usersDict: usersDict,
totalUsers: Object.keys(usersDict).length,
totalOrders: Object.values(usersDict).reduce((a, b) => a + b, 0),
};
};

//** Helpers */
// fetch all pairs
const fetchAllPairs = async () => {
try {
const allPairsResponse = await fetch(
"https://api.alphadex.net/v0/alphadex/pairs",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
}
);

if (!allPairsResponse.ok) {
throw new Error("Error while fetching pairs");
}

const allPairsData = await allPairsResponse.json();
const pairsList = allPairsData?.pairs || [];

return pairsList;
} catch (error) {
console.error("fetchAllPairs -> error", error);
return [];
}
};

// fetch orders
const fetchOrdersByPair = async (pairAddress, orderIds) => {
const allOrders = [];
const chunks = getChunkArray(orderIds, 99);

// fetch all orders by batches of 99 orders
for (const chunkOrderIds of chunks) {
try {
// eslint-disable-next-line no-console
console.log("Fetching batch for " + pairAddress);
const response = await fetch("https://api.alphadex.net/v0/pair/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ pairAddress, orderIds: chunkOrderIds }),
});

const data = await response.json();
allOrders.push(...data.orders);
} catch (err) {
// eslint-disable-next-line no-console
console.log(err);
}
}

return allOrders;
};

const getChunkArray = (array, size) => {
const chunkArray = [];
for (let i = 0; i < array.length; i += size) {
chunkArray.push(array.slice(i, i + size));
}

return chunkArray;
};

const getTimestampedFileName = () => {
// Get the current date and time
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
const hours = String(now.getHours()).padStart(2, "0");
const minutes = String(now.getMinutes()).padStart(2, "0");
const seconds = String(now.getSeconds()).padStart(2, "0");
// Format the filename
return `${year}-${month}-${day}_${hours}${minutes}${seconds}_fetchUsers-output.json`;
};

const getFilePath = () => {
const filename = getTimestampedFileName();
const directory = path.join(__dirname, ".scriptOutputs");
// Ensure the directory exists
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true });
}
// Return the full path for the file
return path.join(directory, filename);
};

const writeObjectToFile = (obj) => {
const jsonString = JSON.stringify(obj, null, 2);
const filePath = getFilePath();
fs.writeFile(filePath, jsonString, (err) => {
if (err) {
console.error("Error writing file:", err);
} else {
// eslint-disable-next-line no-console
console.log(`Successfully saved output to file: ${filePath}`);
}
});
};

// RUN SCRIPT
(async () => {
const result = await fetchUsers();
// eslint-disable-next-line no-console
console.log(result);
writeObjectToFile(result);
})();
29 changes: 29 additions & 0 deletions src/app/components/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
interface IProps {
width?: string;
height?: string;
className?: string;
}

export const SkeletonRectangle = ({
width = "w-20",
height = "h-16",
className = "bg-white/10",
}: IProps) => {
return (
<div
className={`skeleton ${className} ${height} ${width} rounded-lg`}
></div>
);
};

export const SkeletonCircle = ({
width = "w-16",
height = "h-16",
className = "bg-white/10",
}: IProps) => {
return (
<div
className={`skeleton ${className} ${width} ${height} shrink-0 rounded-full`}
></div>
);
};
15 changes: 5 additions & 10 deletions src/app/components/StatsWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,10 @@ const StatsWidget = () => {
})();
}, []);

// TODO: compute actual users with a script fetching all orders on adex.
// 1. google sheet data
// 1.1. socials data
const socials = kpiData?.socials;
const numOfIgFollowers = socials?.instagramFollowers ?? 0;
const numOfXFollowers = socials?.twitterFollowers ?? 0;
const numOfUTubeFollowers = socials?.youtubeSubscribers ?? 0;
const totalNumOfFollowers =
numOfIgFollowers + numOfXFollowers + numOfUTubeFollowers;
// 1.1. total users + total orders
const totalUsers = kpiData?.totalUsers;
// const totalOrders = kpiData?.totalOrders;

// 1.2. trade volume data - total & weekly - XRD & USD
const tradeVolume = kpiData?.tradeVolume;
Expand All @@ -53,10 +48,10 @@ const StatsWidget = () => {
return (
<div className="flex w-full opacity-80 flex-col gap-y-8 mx-auto justify-center items-center mt-8 mb-32">
{/* users */}
{totalNumOfFollowers ? (
{totalUsers ? (
<>
<AnimatedCounter
end={totalNumOfFollowers}
end={totalUsers}
decimals={0}
label={<span className="uppercase">{t("users_trust_us")}</span>}
wrapperClassName="w-full flex justify-center max-md:flex-col max-md:text-3xl md:text-4xl items-center gap-2 max-md:gap-4"
Expand Down
8 changes: 8 additions & 0 deletions src/app/kpis/kpis-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface KpiData {
uniqueVisitors: WeeklySnapshot[];
pageRequests: WeeklySnapshot[];
};
totalUsers: number;
totalOrders: number;
}

interface WeeklySnapshot {
Expand Down Expand Up @@ -113,6 +115,10 @@ function extractData(rawData: string): KpiData {
const instagramFollowers = extractNumbersFromRow(rows[7]).slice(-1)[0];
const twitterFollowers = extractNumbersFromRow(rows[6]).slice(-1)[0];

// Get User + Order Count
const totalUsers = extractNumbersFromRow(rows[2]).slice(-1)[0];
const totalOrders = extractNumbersFromRow(rows[3]).slice(-1)[0];

return {
tradeVolume: {
total: {
Expand All @@ -133,5 +139,7 @@ function extractData(rawData: string): KpiData {
twitterFollowers,
instagramFollowers,
},
totalUsers: totalUsers,
totalOrders: totalOrders,
} as KpiData;
}
Loading

0 comments on commit e48ebf2

Please sign in to comment.