367 lines
7.2 KiB
JavaScript
367 lines
7.2 KiB
JavaScript
const path = require("path");
|
|
require("dotenv").config({ path: path.resolve(__dirname, ".env") });
|
|
|
|
const express = require("express");
|
|
const axios = require("axios");
|
|
const cron = require("node-cron");
|
|
const { createClient } = require("@supabase/supabase-js");
|
|
|
|
// Setup
|
|
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);
|
|
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: {
|
|
address: process.env.TOKEN_ADDRESS,
|
|
page,
|
|
page_size: "100",
|
|
sort_by: "block_time",
|
|
sort_order: "desc",
|
|
},
|
|
headers: {
|
|
token: process.env.SOLSCAN_API_KEY,
|
|
},
|
|
};
|
|
|
|
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
|
|
app.listen(3000, () => {
|
|
console.log("Server running on port 3000");
|
|
});
|
|
// Start server end
|