367 lines
7.2 KiB
JavaScript
Raw Permalink Normal View History

2025-03-01 16:05:18 +07:00
const path = require("path");
2025-03-01 17:40:31 +07:00
require("dotenv").config({ path: path.resolve(__dirname, ".env") });
2025-03-01 16:05:18 +07:00
const express = require("express");
const axios = require("axios");
const cron = require("node-cron");
const { createClient } = require("@supabase/supabase-js");
// Setup
2025-03-01 17:40:31 +07:00
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);
2025-03-01 16:05:18 +07:00
const app = express();
app.use(express.json());
// Setup end
// Fetch transactions from Solscan
const fetchSolscanTransactions = async (page = 1) => {
const requestOptions = {
method: "get",
url: "https://pro-api.solscan.io/v2.0/token/transfer",
params: {
2025-03-01 17:40:31 +07:00
address: process.env.TOKEN_ADDRESS,
2025-03-01 16:05:18 +07:00
page,
page_size: "100",
sort_by: "block_time",
sort_order: "desc",
},
headers: {
2025-03-01 17:40:31 +07:00
token: process.env.SOLSCAN_API_KEY,
2025-03-01 16:05:18 +07:00
},
};
try {
const response = await axios.request(requestOptions);
return response.data;
} catch (err) {
console.error("Error fetching transactions:", err.response ? err.response.data : err.message);
return [];
}
};
// Fetch transactions from Solscan end
// Star name generator
const prefixes = [
"Ar",
"Zor",
"Lys",
"Fen",
"Ther",
"Vor",
"Nyr",
"Xel",
"Pry",
"Kor",
"Vel",
"Jal",
"Mor",
"Quor",
"Sy",
"Ky",
"Tor",
"Or",
"Phor",
"Zyn",
"Aly",
"Sol",
"Dray",
"Hal",
"Lyn",
"Myr",
"Zan",
"Tyr",
"Val",
"Xyn",
"Ner",
"Cal",
"Gal",
"Bry",
"Cyr",
"Thal",
"Aer",
"Vey",
"Kry",
"Nor",
"Lor",
"Ael",
"Bro",
"Ceth",
"Fer",
"Ivor",
"Jul",
"Kael",
"Mal",
"Oth",
"Phel",
"Reva",
"Syth",
"Ul",
"Varn",
"Wren",
"Xyl",
"Yel",
"Zira",
"Xor",
"Arak",
"Tyl",
"Yor",
];
const middles = [
"va",
"the",
"ly",
"na",
"ri",
"lo",
"thra",
"ven",
"dra",
"ny",
"la",
"sha",
"nel",
"vi",
"nor",
"var",
"sel",
"yn",
"ar",
"ros",
"mar",
"car",
"mel",
"tre",
"bre",
"lin",
"fae",
"phy",
"ran",
"lys",
"thar",
"rae",
"dal",
"lor",
"mer",
"vin",
"pol",
"brey",
"xan",
"myl",
"tor",
"que",
"zil",
"wry",
"farn",
"pyr",
"teth",
"vyl",
"andor",
"selan",
"ord",
"ser",
"cral",
"zoth",
"bel",
"quol",
"rian",
"ber",
"myth",
"fyl",
"tain",
"os",
"roan",
"dril",
];
const suffixes = [
"nis",
"lon",
"ris",
"thon",
"eth",
"ion",
"lis",
"tis",
"on",
"is",
"ar",
"os",
"el",
"ra",
"in",
"us",
"ae",
"ys",
"al",
"vin",
"dor",
"tha",
"lor",
"ven",
"dra",
"nor",
"cal",
"vor",
"xan",
"tur",
"sel",
"ren",
"elis",
"queth",
"tyl",
"noris",
"myra",
"far",
"qan",
"cyr",
"oris",
"ythra",
"xanor",
"soris",
"zalor",
"fenal",
"arith",
"zyl",
"vhen",
"qeth",
"anthor",
"ryl",
"maris",
"quen",
"shon",
"ghal",
"valis",
"thyros",
"menor",
"xiros",
];
const generateStarName = async () => {
const prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
const middle = middles[Math.floor(Math.random() * middles.length)];
const suffix = suffixes[Math.floor(Math.random() * suffixes.length)];
let starName = `${prefix}${middle}${suffix}`;
// Check if starName already exists in the database
const { data } = await supabase.from("celestia-data").select("star_name").eq("star_name", starName);
if (data.length > 0) {
let counter = 1;
while (true) {
const newStarName = `${starName}${counter}`;
const { data: checkData } = await supabase
.from("celestia-data")
.select("star_name")
.eq("star_name", newStarName);
if (checkData.length === 0) {
starName = newStarName;
break;
}
counter++;
}
}
return starName;
};
// Star name generator end
// Store transaction to Supabase
const storeTransactionToSupabase = async (transaction) => {
const starName = await generateStarName();
const { trans_id, from_address, amount } = transaction;
const x = Math.floor(Math.random() * 11) - 5;
const y = Math.floor(Math.random() * 11) - 5;
const z = Math.floor(Math.random() * 11) - 5;
const { count, error: countError } = await supabase
.from("celestia-data")
.select("*", { count: "exact", head: true });
if (countError) {
console.error("Error counting rows:", countError);
return;
}
const transaction_id = count + 1;
const { data, error } = await supabase.from("celestia-data").insert([
{
transaction_signature: trans_id,
from_address: from_address,
amount: amount,
star_name: starName,
transaction_id: transaction_id,
transaction_url: `https://solscan.io/tx/${trans_id}`,
x: x,
y: y,
z: z,
},
]);
if (error) {
console.error("Error inserting transaction:", error);
} else {
console.log("Transaction added:", data);
}
};
// Store transaction to Supabase end
// Cron job
let isProcessing = false;
// Cron job to run every 1 minute
cron.schedule("*/1 * * * *", async () => {
if (isProcessing) {
console.log("Previous process still running, skipping this iteration");
return;
}
isProcessing = true;
console.log("Cron job triggered");
try {
const { data: latestRow } = await supabase
.from("celestia-data")
.select("transaction_signature")
.order("id", { ascending: false })
.limit(1);
const latestTransactionSignature = latestRow.length > 0 ? latestRow[0].transaction_signature : "";
let page = 1;
let foundExistingTransaction = false;
while (!foundExistingTransaction) {
const transactions = await fetchSolscanTransactions(page);
if (transactions.length === 0) {
console.log("No transactions found on page", page);
break;
}
for (let transaction of transactions.data) {
if (transaction.trans_id !== latestTransactionSignature) {
await storeTransactionToSupabase(transaction);
} else {
console.log("Transaction already exists:", transaction.trans_id);
foundExistingTransaction = true;
break;
}
}
if (!foundExistingTransaction) {
page++;
}
}
} catch (error) {
console.error("Error during cron job execution:", error.message);
console.error(error.stack);
} finally {
isProcessing = false;
}
});
// Cron job end
// Start server
2025-03-01 16:57:46 +07:00
app.listen(3000, () => {
2025-03-01 17:40:31 +07:00
console.log("Server running on port 3000");
2025-03-01 16:05:18 +07:00
});
// Start server end