Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "groundcontrol",
"version": "3.0.1",
"version": "3.1.0",
"description": "GroundControl push server API",
"devDependencies": {
"@types/node": "18.7.16",
Expand Down
81 changes: 81 additions & 0 deletions src/address-ignore-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
export const ADDRESS_IGNORE_LIST = [
"1NXNHZr6Pbzi3VStcgaxwEhspTWNXQ3Q4G",
"bc1qee7hk4a3k3km7j8hwclm0pkl76dhhgxay5nevu",
"bc1qclyfsxuu8vcwq38yygs5zrskwacq8sjlyvk9mx",
"bc1qltxjty7xfrnkzlrhmxpcekknr3uncne8sht7rn",
"bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej",
"bc1qw8wrek2m7nlqldll66ajnwr9mh64syvkt67zlu",
"1111111111111111111114oLvT2",
"1BrasiLb2KMbdtuhb1chAVnS2FvcNGfV9J",
"1GQdrgqAbkeEPUef1UpiTc4X1mUHMcyuGW",
"1KHwtS5mn7NMUm7Ls7Y1XwxLqMriLdaGbX",
"bc1q7cyrfmck2ffu2ud3rn5l5a8yv6f0chkp0zpemf",
"bc1qwfgdjyy95aay2686fn74h6a4nu9eev6np7q4fn204dkj3274frlqrskvx0",
"bc1qm34lsc65zpw79lxes69zkqmk6ee3ewf0j77s3h",
"bc1qrnn4wfhgz2e0etek66sh3n9l6k99alxk044mhr",
"13nCMaHDNRGM29UfMMkhUQjHkVYY1ZyrpU",
"bc1qel7tps3wu6zqztaanczvt76hffwh7k06jd8r9xh2v3ztpa5ty5dsz358ys",
"bc1qyzxdu4px4jy8gwhcj82zpv7qzhvc0fvumgnh0r",
"bc1qyemk24czaa6a2nr89nrz775ewvptxg7yfe750u",
"bc1qq904ynep5mvwpjxdlyecgeupg22dm8am6cfvgq",
"37biYvTEcBVMoR1NGkPTGvHUuLTrzcLpiv",
"bc1qq9tk3uhcx58y5qvmzs50nhs49m0pdkmrfpkzs4",
"1Kr6QSydW9bFQG1mXiPNNu6WpJGmUa9i1g",
"3DGxAYYUA61WrrdbBac8Ra9eA9peAQwTJF",
"bc1qmgj3w0aw5455y9s4zfhts2kxm4qstwyjx5f907",
"bc1qgrxsrmrhsapvh9addyx6sh8j4rw0sn9xtur9uq",
"bc1qp3f7vnmuj4pjxpfvkvf7yznac9h9r5arlv4fpv",
"bc1qnsupj8eqya02nm8v6tmk93zslu2e2z8chlmcej",
"bc1qt5m8xeclsja4lkfvl2nvmrt6z9vg60sd8w2kc6",
"bc1qsatlphjcgvzlt9xhsgn0dnjus5jgwg83dr05c6",
"bc1quq29mutxkgxmjfdr7ayj3zd9ad0ld5mrhh89l2",
"bc1qe9nagya0tvfhvymt8sejwedlukwq4a094h6ht9",
"1GrwDkr33gT6LuumniYjKEGjTLhsL5kmqC",
"33WSGLeVoEpuZDjB54HKZ1y5YsERELoVNq",
"3A8n8rwMnHnt2BqnjW4R73eZCMcUDTpYvv",
"bc1qns9f7yfx3ry9lj6yz7c9er0vwa0ye2eklpzqfw",
"38XnPvu9PmonFU9WouPXUjYbW91wa5MerL",
"1Bo8hs81QwnR6A3oFBXcWNZXgtwpfgByb3",
"37Z6neB2wDC3hsPDHLy2n2kFahNNU3eos8",
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE",
"36XWTfSYJJz3WSNPZVZ3q3aa5eFuJHR9nu",
"bc1qc8ee9860cdnkyej0ag5hf49pcx7uvz89lkwpr9",
"bc1q7ug4w4as2sefar89q057hnmxkakp58a25535ttlmurn6cncs8tms4e7gp2",
"3JodN7GmkHdPgKj9G7HCkn9NDLhrcWCjVN",
"bc1qujepl0k5n0ga2e86yskvxa6auehpf6dlf84dx0",
"bc1qg9lgqyukp2rup5x4frrz7hhw7988k5q26luakm",
"3JSdUu1ivm3rqMvuCTAdAj6Dc2hdVhHiEe",
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"bc1qr35hws365juz5rtlsjtvmulu97957kqvr3zpw3",
"bc1qzlcvh2k3xs2jyzvya7xmx8l2ylpt259txy7wnd",
"bc1qprdf80adfz7aekh5nejjfrp3jksc8r929svpxk",
"35iMHbUZeTssxBodiHwEEkb32jpBfVueEL",
"3QiETomgUhPu573ZvhXbdofq7y5ocNS1ie",
"3HcEUguUZ4vyyMAPWDPUDjLqz882jXwMfV",
"3J7cUjBZxvGRCwFBz3q23zAsnhFfZrDSSU",
"bc1qamgjuxaywqls56h7rg7afga3m6rgqwfkew688k",
"1G47mSr3oANXMafVrR8UC4pzV7FEAzo3r9",
"17StnGroPUsNXBq4AVJQ1fqGftoFZh3zva",
"1FWQiwK27EnGXb6BiBMRLJvunJQZZPMcGd",
"16r7U7GqbVPeKukgfd3mUN9LCkuoKbfpXM",
"bc1q22hp7n28whk5h94z93vm05hfx2zxs8ca9gglk7",
"bc1q0wu0tqp2u3rtunjl0h0rsl9pvf86acy6sep63st0lp7lgg67ykzqeq89pn",
"bc1qryhgpmfv03qjhhp2dj8nw8g4ewg08jzmgy3cyx",
"bc1quhruqrghgcca950rvhtrg7cpd7u8k6svpzgzmrjy8xyukacl5lkq0r8l2d",
"bc1q0s6rca52mjumq8fjuz4j6ka5h9jhq57esyd40r",
"bc1qjguxrqjx9qnpmklzymdr0y6mqxrth9d3swzdpr",
"bc1qr4dl5wa7kl8yu792dceg9z5knl2gkn220lk7a9",
"1Dy8gSw3Zbpatr4bGn7zR4phNX18XuTD56",
"bc1qcdqj2smprre85c78d942wx5tauw5n7uw92r7wr",
"bc1qmhq4sgtchfgh6ul75x3rsuegt55mef0zx3ehm2",
"bc1qws8yeyfxzykuq7tevwwxezyv3ad99emlyy9uls",
"bc1q42kvqt0e3f27qhd2ucnprarl5ywpuj7tu0h9v2",
"bc1q5k9tyr30xhmvmnj2z2cx0psprz44ksnmpuw7q8",
"bc1qfpeps3wcmzk422hvm5jeq5lelnqlzznjwyfy69",
"bc1qfy4ck4xpu3vg2226ew9jssly6xvc8w5xhjkzxz",
"bc1q9yn6zdkjjlh0z5y6sqpdvwq7pwkeh5r0ka28ad",
"bc1qpsys7sfk5u7ue3lffwzszzvffhtku78kr0vva4",
"bc1q0qfzuge7vr5s2xkczrjkccmxemlyyn8mhx298v",
"bc1pz454nh8mdcq093zfcc4qe2hw5ejha98k3e6n9apqkhemqv9w5kuqh2xcst",
"bc1qynygs8d3ju9cpum9pepmh94qk57tf67paka78g",
];
190 changes: 14 additions & 176 deletions src/controller/GroundController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { PushLog } from "../entity/PushLog";
import { KeyValue } from "../entity/KeyValue";
import dataSource from "../data-source";
import { paths, components } from "../openapi/api";
import { ADDRESS_IGNORE_LIST } from "../address-ignore-list";
require("dotenv").config();
const pck = require("../../package.json");
if (!process.env.JAWSDB_MARIA_URL || !process.env.GOOGLE_KEY_FILE || !process.env.APNS_P8 || !process.env.APNS_TOPIC || !process.env.APPLE_TEAM_ID || !process.env.APNS_P8_KID || !process.env.GOOGLE_PROJECT_ID) {
Expand All @@ -18,195 +19,32 @@ if (!process.env.JAWSDB_MARIA_URL || !process.env.GOOGLE_KEY_FILE || !process.en

const LAST_PROCESSED_BLOCK = "LAST_PROCESSED_BLOCK";

const ADDRESS_IGNORE_LIST = [
"1NXNHZr6Pbzi3VStcgaxwEhspTWNXQ3Q4G",
"bc1qee7hk4a3k3km7j8hwclm0pkl76dhhgxay5nevu",
"bc1qclyfsxuu8vcwq38yygs5zrskwacq8sjlyvk9mx",
"bc1qltxjty7xfrnkzlrhmxpcekknr3uncne8sht7rn",
"bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej",
"bc1qw8wrek2m7nlqldll66ajnwr9mh64syvkt67zlu",
"1111111111111111111114oLvT2",
"1BrasiLb2KMbdtuhb1chAVnS2FvcNGfV9J",
"1GQdrgqAbkeEPUef1UpiTc4X1mUHMcyuGW",
"1KHwtS5mn7NMUm7Ls7Y1XwxLqMriLdaGbX",
"bc1q7cyrfmck2ffu2ud3rn5l5a8yv6f0chkp0zpemf",
"bc1qwfgdjyy95aay2686fn74h6a4nu9eev6np7q4fn204dkj3274frlqrskvx0",
"bc1qm34lsc65zpw79lxes69zkqmk6ee3ewf0j77s3h",
"bc1qrnn4wfhgz2e0etek66sh3n9l6k99alxk044mhr",
"13nCMaHDNRGM29UfMMkhUQjHkVYY1ZyrpU",
"bc1qel7tps3wu6zqztaanczvt76hffwh7k06jd8r9xh2v3ztpa5ty5dsz358ys",
"bc1qyzxdu4px4jy8gwhcj82zpv7qzhvc0fvumgnh0r",
"bc1qyemk24czaa6a2nr89nrz775ewvptxg7yfe750u",
"bc1qq904ynep5mvwpjxdlyecgeupg22dm8am6cfvgq",
"37biYvTEcBVMoR1NGkPTGvHUuLTrzcLpiv",
"bc1qq9tk3uhcx58y5qvmzs50nhs49m0pdkmrfpkzs4",
"1Kr6QSydW9bFQG1mXiPNNu6WpJGmUa9i1g",
"3DGxAYYUA61WrrdbBac8Ra9eA9peAQwTJF",
"bc1qmgj3w0aw5455y9s4zfhts2kxm4qstwyjx5f907",
"bc1qgrxsrmrhsapvh9addyx6sh8j4rw0sn9xtur9uq",
"bc1qp3f7vnmuj4pjxpfvkvf7yznac9h9r5arlv4fpv",
"bc1qnsupj8eqya02nm8v6tmk93zslu2e2z8chlmcej",
"bc1qt5m8xeclsja4lkfvl2nvmrt6z9vg60sd8w2kc6",
"bc1qsatlphjcgvzlt9xhsgn0dnjus5jgwg83dr05c6",
"bc1quq29mutxkgxmjfdr7ayj3zd9ad0ld5mrhh89l2",
"bc1qe9nagya0tvfhvymt8sejwedlukwq4a094h6ht9",
"1GrwDkr33gT6LuumniYjKEGjTLhsL5kmqC",
"33WSGLeVoEpuZDjB54HKZ1y5YsERELoVNq",
"3A8n8rwMnHnt2BqnjW4R73eZCMcUDTpYvv",
"bc1qns9f7yfx3ry9lj6yz7c9er0vwa0ye2eklpzqfw",
"38XnPvu9PmonFU9WouPXUjYbW91wa5MerL",
"1Bo8hs81QwnR6A3oFBXcWNZXgtwpfgByb3",
"37Z6neB2wDC3hsPDHLy2n2kFahNNU3eos8",
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE",
"36XWTfSYJJz3WSNPZVZ3q3aa5eFuJHR9nu",
"bc1qc8ee9860cdnkyej0ag5hf49pcx7uvz89lkwpr9",
"bc1q7ug4w4as2sefar89q057hnmxkakp58a25535ttlmurn6cncs8tms4e7gp2",
"3JodN7GmkHdPgKj9G7HCkn9NDLhrcWCjVN",
"bc1qujepl0k5n0ga2e86yskvxa6auehpf6dlf84dx0",
"bc1qg9lgqyukp2rup5x4frrz7hhw7988k5q26luakm",
"3JSdUu1ivm3rqMvuCTAdAj6Dc2hdVhHiEe",
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"bc1qr35hws365juz5rtlsjtvmulu97957kqvr3zpw3",
"bc1qzlcvh2k3xs2jyzvya7xmx8l2ylpt259txy7wnd",
"bc1qprdf80adfz7aekh5nejjfrp3jksc8r929svpxk",
"35iMHbUZeTssxBodiHwEEkb32jpBfVueEL",
"3QiETomgUhPu573ZvhXbdofq7y5ocNS1ie",
"3HcEUguUZ4vyyMAPWDPUDjLqz882jXwMfV",
"3J7cUjBZxvGRCwFBz3q23zAsnhFfZrDSSU",
"bc1qamgjuxaywqls56h7rg7afga3m6rgqwfkew688k",
"1G47mSr3oANXMafVrR8UC4pzV7FEAzo3r9",
"17StnGroPUsNXBq4AVJQ1fqGftoFZh3zva",
"1FWQiwK27EnGXb6BiBMRLJvunJQZZPMcGd",
"16r7U7GqbVPeKukgfd3mUN9LCkuoKbfpXM",
"bc1q22hp7n28whk5h94z93vm05hfx2zxs8ca9gglk7",
"bc1q0wu0tqp2u3rtunjl0h0rsl9pvf86acy6sep63st0lp7lgg67ykzqeq89pn",
"bc1qryhgpmfv03qjhhp2dj8nw8g4ewg08jzmgy3cyx",
"bc1quhruqrghgcca950rvhtrg7cpd7u8k6svpzgzmrjy8xyukacl5lkq0r8l2d",
"bc1q0s6rca52mjumq8fjuz4j6ka5h9jhq57esyd40r",
"bc1qjguxrqjx9qnpmklzymdr0y6mqxrth9d3swzdpr",
"bc1qr4dl5wa7kl8yu792dceg9z5knl2gkn220lk7a9",
"1Dy8gSw3Zbpatr4bGn7zR4phNX18XuTD56",
"bc1qcdqj2smprre85c78d942wx5tauw5n7uw92r7wr",
"bc1qmhq4sgtchfgh6ul75x3rsuegt55mef0zx3ehm2",
"bc1qws8yeyfxzykuq7tevwwxezyv3ad99emlyy9uls",
"bc1q42kvqt0e3f27qhd2ucnprarl5ywpuj7tu0h9v2",
"bc1q5k9tyr30xhmvmnj2z2cx0psprz44ksnmpuw7q8",
"bc1qfpeps3wcmzk422hvm5jeq5lelnqlzznjwyfy69",
"bc1qfy4ck4xpu3vg2226ew9jssly6xvc8w5xhjkzxz",
"bc1q9yn6zdkjjlh0z5y6sqpdvwq7pwkeh5r0ka28ad",
"bc1qpsys7sfk5u7ue3lffwzszzvffhtku78kr0vva4",
"bc1q0qfzuge7vr5s2xkczrjkccmxemlyyn8mhx298v",
"bc1pz454nh8mdcq093zfcc4qe2hw5ejha98k3e6n9apqkhemqv9w5kuqh2xcst",
"bc1qynygs8d3ju9cpum9pepmh94qk57tf67paka78g",
];

let connection: DataSource;

const pushLogPurge = () => {
console.log("purging PushLog...");
let today = new Date();
connection
.createQueryBuilder()
.delete()
.from(PushLog)
.where("created <= :currentDate", { currentDate: new Date(today.getTime() - 3 * 24 * 60 * 60 * 1000) })
.execute()
.then(() => console.log("PushLog purged ok"))
.catch((error) => console.log("error purging PushLog:", error));
};

const purgeOldTxidSubscriptions = () => {
console.log("purging TokenToTxid...");
let today = new Date();
connection
.createQueryBuilder()
.delete()
.from(TokenToTxid)
.where("created <= :currentDate", { currentDate: new Date(today.getTime() - 3 * 30 * 24 * 60 * 60 * 1000) }) // 3 mo
.execute()
.then(() => console.log("TokenToTxid purged ok"))
.catch((error) => console.log("error purging TokenToTxid:", error));
};

const purgeIgnoredAddressesSubscriptions = () => {
console.log("Purging addresses subscriptions...");
connection
.createQueryBuilder()
.delete()
.from(TokenToAddress)
.where("address IN (:...id)", { id: ADDRESS_IGNORE_LIST })
.execute()
.then(() => console.log("Addresses subscriptions purged ok"))
.catch((error) => console.log("error purging addresses subscriptions:", error));
};

const killSleepingMySQLProcesses = () => {
console.log("Checking for sleeping MySQL processes...");

// Query to find processes sleeping for more than 3600 seconds
const query = `
SELECT id, user, host, db, command, time, state, info
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 3600 AND id != CONNECTION_ID()
`;

connection
.query(query)
.then((sleepingProcesses: any[]) => {
if (sleepingProcesses.length > 0) {
console.log(`Found ${sleepingProcesses.length} sleeping processes older than 1 hour`);

// Kill each sleeping process
const killPromises = sleepingProcesses.map((process) => {
console.log(`Killing process ID ${process.id} (user: ${process.user}, host: ${process.host}, sleeping for ${process.time}s)`);
return connection
.query(`KILL ${process.id}`)
.then(() => console.log(`Successfully killed process ${process.id}`))
.catch((error) => console.log(`Error killing process ${process.id}:`, error.message));
});

return Promise.all(killPromises);
} else {
console.log("No sleeping processes found that are older than 1 hour");
}
})
.catch((error) => {
console.log("Error checking sleeping processes:", error.message);
});
};

dataSource.initialize().then((c) => {
console.log("db connected");
connection = c;
purgeIgnoredAddressesSubscriptions();
pushLogPurge();
purgeOldTxidSubscriptions();
killSleepingMySQLProcesses();
setInterval(pushLogPurge, 3600 * 1000);
setInterval(killSleepingMySQLProcesses, 3600 * 1000); // Run every hour
});

export class GroundController {
private _tokenToAddressRepository;
private _tokenToHashRepository;
private _tokenToTxidRepository;
private _tokenConfigurationRepository;
private _sendQueueRepository;
private _connection: DataSource;

constructor(connection: DataSource) {
this._connection = connection;
}

get tokenToAddressRepository() {
if (this._tokenToAddressRepository) {
return this._tokenToAddressRepository;
}

this._tokenToAddressRepository = connection.getRepository(TokenToAddress);
this._tokenToAddressRepository = this._connection.getRepository(TokenToAddress);
return this._tokenToAddressRepository;
}

get tokenToHashRepository() {
if (this._tokenToHashRepository) {
return this._tokenToHashRepository;
}
this._tokenToHashRepository = connection.getRepository(TokenToHash);
this._tokenToHashRepository = this._connection.getRepository(TokenToHash);
return this._tokenToHashRepository;
}

Expand All @@ -215,7 +53,7 @@ export class GroundController {
return this._tokenToTxidRepository;
}

this._tokenToTxidRepository = connection.getRepository(TokenToTxid);
this._tokenToTxidRepository = this._connection.getRepository(TokenToTxid);
return this._tokenToTxidRepository;
}

Expand All @@ -224,7 +62,7 @@ export class GroundController {
return this._tokenConfigurationRepository;
}

this._tokenConfigurationRepository = connection.getRepository(TokenConfiguration);
this._tokenConfigurationRepository = this._connection.getRepository(TokenConfiguration);
return this._tokenConfigurationRepository;
}

Expand All @@ -233,7 +71,7 @@ export class GroundController {
return this._sendQueueRepository;
}

this._sendQueueRepository = connection.getRepository(SendQueue);
this._sendQueueRepository = this._connection.getRepository(SendQueue);
return this._sendQueueRepository;
}

Expand Down Expand Up @@ -395,13 +233,13 @@ export class GroundController {
}

async ping(request: Request, response: Response, next: NextFunction) {
const keyValueRepository = connection.getRepository(KeyValue);
const sendQueueRepository = connection.getRepository(SendQueue);
const keyValueRepository = this._connection.getRepository(KeyValue);
const sendQueueRepository = this._connection.getRepository(SendQueue);
const keyVal = await keyValueRepository.findOneBy({ key: LAST_PROCESSED_BLOCK });
const send_queue_size = await sendQueueRepository.count();

const ts = new Date(+new Date() - 1000 * 3600 * 24).toISOString();
const sent_24h = await connection.createQueryBuilder(PushLog, "PushLog").where("PushLog.created >= :ts", { ts }).getCount();
const sent_24h = await this._connection.createQueryBuilder(PushLog, "PushLog").where("PushLog.created >= :ts", { ts }).getCount();

const serverInfo: paths["/ping"]["get"]["responses"]["200"]["content"]["application/json"] = {
name: pck.name,
Expand Down
Loading