Skip to content

Commit

Permalink
Merge pull request #16 from Apillon/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
MoMannn authored Feb 16, 2024
2 parents b4e28eb + 21e1689 commit c7a852f
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 84 deletions.
62 changes: 32 additions & 30 deletions backend/src/cron.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { CronJob } from "cron";
import { AirdropStatus } from "./models/user";
import { dateToSqlString } from "./lib/sql-utils";
import { SqlModelStatus } from "./models/base-sql-model";
import { MysqlConnectionManager } from "./lib/mysql-connection-manager";
import { SmtpSendTemplate } from "./lib/node-mailer";
import { env } from "./config/env";
import { generateEmailAirdropToken } from "./lib/jwt";
import { LogType, writeLog } from "./lib/logger";
import { CronJob } from 'cron';
import { AirdropStatus } from './models/user';
import { dateToSqlString } from './lib/sql-utils';
import { SqlModelStatus } from './models/base-sql-model';
import { MysqlConnectionManager } from './lib/mysql-connection-manager';
import { SmtpSendTemplate } from './lib/node-mailer';
import { env } from './config/env';
import { generateEmailAirdropToken } from './lib/jwt';
import { LogType, writeLog } from './lib/logger';

export class Cron {
private cronJobs: CronJob[] = [];

constructor() {
this.cronJobs.push(new CronJob("* * * * *", this.sendEmail, null, false));
this.cronJobs.push(new CronJob('* * * * *', this.sendEmail, null, false));
if (env.MAX_SUPPLY > 0) {
this.cronJobs.push(
new CronJob("* * * * *", this.processExpiredClaims, null, false)
new CronJob('* * * * *', this.processExpiredClaims, null, false)
);
}
}
Expand Down Expand Up @@ -78,8 +78,8 @@ export class Cron {
const token = await generateEmailAirdropToken(users[i].email);
await SmtpSendTemplate(
[users[i].email],
"Claim your NFT",
"en-airdrop-claim",
'Claim your NFT',
'en-airdrop-claim',
{
appUrl: env.APP_URL,
link: `${env.APP_URL}/claim?token=${token}`,
Expand All @@ -95,8 +95,8 @@ export class Cron {
//Currently, waiting line for airdrop is full.Send info email and set appropriate status
await SmtpSendTemplate(
[users[i].email],
"You are in waiting line for NFT claim",
"en-airdrop-waiting-line",
'You are in waiting line for NFT claim',
'en-airdrop-waiting-line',
{
appUrl: env.APP_URL,
}
Expand All @@ -108,7 +108,7 @@ export class Cron {
);
}
} catch (e) {
writeLog(LogType.ERROR, e, "cron.ts", "sendEmail");
writeLog(LogType.ERROR, e, 'cron.ts', 'sendEmail');
updates.push(
`(${users[i].id}, '${users[i].email}', ${
AirdropStatus.EMAIL_ERROR
Expand All @@ -120,7 +120,7 @@ export class Cron {
if (updates.length > 0) {
const sql = `
INSERT INTO user (id, email, airdrop_status, email_sent_time)
VALUES ${updates.join(",")}
VALUES ${updates.join(',')}
ON DUPLICATE KEY UPDATE
airdrop_status = VALUES(airdrop_status),
email_sent_time = VALUES(email_sent_time)`;
Expand All @@ -130,7 +130,7 @@ export class Cron {

await mysql.commit(conn);
} catch (e) {
writeLog(LogType.ERROR, e, "cron.ts", "sendEmail");
writeLog(LogType.ERROR, e, 'cron.ts', 'sendEmail');
await mysql.rollback(conn);
}
}
Expand Down Expand Up @@ -159,15 +159,15 @@ export class Cron {
await mysql.paramExecute(
`UPDATE user
SET airdrop_status = ${AirdropStatus.AIRDROP_CLAIM_EXPIRED}
WHERE id IN (${usersWithExpiredClaim.join(",")})
WHERE id IN (${usersWithExpiredClaim.join(',')})
;
`,
null,
conn
);
console.info(
usersWithExpiredClaim.length +
" users updated to AIRDROP_CLAIM_EXPIRED"
' users updated to AIRDROP_CLAIM_EXPIRED'
);

//Get users in waiting line and set their airdrop status to PENDING, so that they will recieve email for claim
Expand All @@ -187,44 +187,46 @@ export class Cron {
)[0] as Array<any>;

console.info(
"Num of users in waiting line: " + usersInWaitingLine.length
'Num of users in waiting line: ' + usersInWaitingLine.length
);

if (usersInWaitingLine.length) {
await conn.execute(
await mysql.paramExecute(
`UPDATE user
SET
airdrop_status = ${AirdropStatus.EMAIL_SENT},
email_sent_time = NOW()
WHERE id IN (${usersInWaitingLine.map((x) => x.id).join(",")})
WHERE id IN (${usersInWaitingLine.map((x) => x.id).join(',')})
;
`,
null,
conn
);
console.info(
usersInWaitingLine.map((x) => x.id).join(",") +
" should me moved from waiting line. Sending emails...."
usersInWaitingLine.map((x) => x.id).join(',') +
' should me moved from waiting line. Sending emails....'
);

for (const user of usersInWaitingLine) {
try {
const token = await generateEmailAirdropToken(user.email);
await SmtpSendTemplate(
[user.email],
"Claim your NFT",
"en-airdrop-claim",
'Claim your NFT',
'en-airdrop-claim',
{
link: `${env.APP_URL}/claim?token=${token}`,
}
);
} catch (err) {
await conn.execute(
await mysql.paramExecute(
`UPDATE user
SET airdrop_status = ${AirdropStatus.EMAIL_ERROR},
WHERE id = ${user.id})
;
`
`,
null,
conn
);
}
}
Expand All @@ -233,7 +235,7 @@ export class Cron {

await mysql.commit(conn);
} catch (e) {
writeLog(LogType.ERROR, e, "cron.ts", "processExpiredClaims");
writeLog(LogType.ERROR, e, 'cron.ts', 'processExpiredClaims');
await mysql.rollback(conn);
}
}
Expand Down
16 changes: 8 additions & 8 deletions backend/src/routes/admin-login.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Application } from "express";
import { NextFunction, Request, Response } from "../http";
import { RouteErrorCode } from "../config/values";
import { ResourceError } from "../lib/errors";
import { Identity } from "@apillon/sdk";
import { generateAdminAuthToken } from "../lib/jwt";
import { Application } from 'express';
import { NextFunction, Request, Response } from '../http';
import { RouteErrorCode } from '../config/values';
import { ResourceError } from '../lib/errors';
import { Identity } from '@apillon/sdk';
import { generateAdminAuthToken } from '../lib/jwt';

/**
* Installs new route on the provided application.
* @param app ExpressJS application.
*/
export function inject(app: Application) {
app.post("/login", (req: Request, res: Response, next: NextFunction) => {
app.post('/login', (req: Request, res: Response, next: NextFunction) => {
resolve(req, res).catch(next);
});
}
Expand All @@ -32,7 +32,7 @@ export async function resolve(req: Request, res: Response): Promise<void> {
walletAddress: body.address,
signature: body.signature,
signatureValidityMinutes: 10,
message: `test\n${body.timestamp}`,
message: `Sign to verify and mint your free Ment NFT!\n${body.timestamp}`,
timestamp: body.timestamp,
});

Expand Down
39 changes: 15 additions & 24 deletions backend/src/routes/claim-airdrop.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import { Application } from "express";
import { NextFunction, Request, Response } from "../http";
import { RouteErrorCode, ValidatorErrorCode } from "../config/values";
import { ResourceError } from "../lib/errors";
import { readEmailAirdropToken } from "../lib/jwt";
import { AirdropStatus, User } from "../models/user";
import { Identity, LogLevel, Nft } from "@apillon/sdk";
import { LogType, writeLog } from "../lib/logger";
import { env } from "../config/env";
import { Application } from 'express';
import { NextFunction, Request, Response } from '../http';
import { RouteErrorCode, ValidatorErrorCode } from '../config/values';
import { ResourceError } from '../lib/errors';
import { readEmailAirdropToken } from '../lib/jwt';
import { AirdropStatus, User } from '../models/user';
import { Identity, LogLevel, Nft } from '@apillon/sdk';
import { LogType, writeLog } from '../lib/logger';
import { env } from '../config/env';

/**∂
* Installs new route on the provided application.
* @param app ExpressJS application.
*/
export function inject(app: Application) {
app.post(
"/users/claim",
(req: Request, res: Response, next: NextFunction) => {
resolve(req, res).catch(next);
}
);
app.post('/users/claim', (req: Request, res: Response, next: NextFunction) => {
resolve(req, res).catch(next);
});
}

export async function resolve(req: Request, res: Response): Promise<void> {
Expand All @@ -33,7 +30,7 @@ export async function resolve(req: Request, res: Response): Promise<void> {
walletAddress: body.address,
signature: body.signature,
signatureValidityMinutes: 10,
message: `test\n${body.timestamp}`,
message: `Sign to verify and mint your free Ment NFT!\n${body.timestamp}`,
timestamp: body.timestamp,
});

Expand Down Expand Up @@ -86,20 +83,14 @@ export async function resolve(req: Request, res: Response): Promise<void> {
? AirdropStatus.AIRDROP_COMPLETED
: AirdropStatus.AIRDROP_ERROR;
} catch (e) {
writeLog(
LogType.ERROR,
"Error creating airdrop",
"claim-airdrop.ts",
"resolve",
e
);
writeLog(LogType.ERROR, 'Error creating airdrop', 'claim-airdrop.ts', 'resolve', e);
user.airdrop_status = AirdropStatus.AIRDROP_ERROR;
}

await user.update();
if (response && response.success) {
return res.respond(200, {
success: "ok",
success: 'ok',
transactionHash: response.transactionHash,
});
} else {
Expand Down
18 changes: 9 additions & 9 deletions backend/src/tests/routes/admin-login.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import {
createContextAndStartServer,
Stage,
stopServerAndCloseMySqlContext,
} from "../helpers/context";
import * as request from "supertest";
import { setupTestDatabase, clearTestDatabase } from "../helpers/migrations";
import { HDNodeWallet, Wallet } from "ethers";
import { Identity } from "@apillon/sdk";
} from '../helpers/context';
import * as request from 'supertest';
import { setupTestDatabase, clearTestDatabase } from '../helpers/migrations';
import { HDNodeWallet, Wallet } from 'ethers';
import { Identity } from '@apillon/sdk';
let stage: Stage;
let adminWallet: HDNodeWallet;

describe("admin login", () => {
describe('admin login', () => {
beforeAll(async () => {
adminWallet = Wallet.createRandom();
stage = await createContextAndStartServer({
Expand All @@ -24,16 +24,16 @@ describe("admin login", () => {
await stopServerAndCloseMySqlContext(stage);
});

test("login", async () => {
test('login', async () => {
const timestamp = new Date().getTime();
const message = `test\n${timestamp}`;
const message = `Sign to verify and mint your free Ment NFT!\n${timestamp}`;

const identity = new Identity();
const signature = await adminWallet.signMessage(message);

const data = { signature, timestamp };

const res = await request(stage.app).post("/login").send(data);
const res = await request(stage.app).post('/login').send(data);

expect(res.status).toBe(200);
});
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/parts/ConnectWallet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
:loading="loading || isLoading"
@click="modalWalletVisible = true"
>
Connect wallet
Connect your wallet
</Btn>
</div>

Expand Down Expand Up @@ -105,7 +105,7 @@ async function login() {
}
const timestamp = new Date().getTime();
const message = 'test';
const message = 'Sign to verify and mint your free Ment NFT!';
const signature = await walletClient.value.signMessage({
message: `${message}\n${timestamp}`,
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/parts/Table/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const columns = createColumns();
function addItem(user: UserInterface) {
if (!validateEmail(newUser.value.email)) {
message.warning('Please enter a valid email address');
message.warning('Please enter a valid email address.');
return;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/parts/form/Upload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const hasRequiredColumns = computed<boolean>(() =>
function uploadFileRequest({ file, onError, onFinish }: UploadCustomRequestOptions) {
if (file.type !== 'text/csv' && file.type !== 'application/vnd.ms-excel') {
console.warn(file.type);
message.warning('File must be of type CSV');
message.warning('File must be of CSV type.');
/** Mark file as failed */
onError();
Expand Down
12 changes: 6 additions & 6 deletions frontend/pages/claim.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ async function claimAirdrop() {
await connect({ connector: connectors.value[0] });
if (!walletClient.value) {
message.error('Could not connect with wallet');
message.error('Could not connect with your wallet.');
loading.value = false;
return;
}
}
const signature = await walletClient.value.signMessage({ message: `test\n${timestamp}` });
const signature = await walletClient.value.signMessage({ message: `Sign to verify and mint your free Ment NFT!\n${timestamp}` });
const res = await $api.post<ClaimResponse>('/users/claim', {
jwt: query.token?.toString() || '',
signature,
Expand All @@ -57,11 +57,11 @@ async function claimAirdrop() {
txWait.hash.value = res.data.transactionHash as Address;
console.debug('Transaction', txWait.hash.value);
message.info('Minting of your NFT has begun.');
message.info('Minting of your MENT token has begun.');
const receipt = await txWait.wait();
console.debug(receipt);
message.success('You successfully claimed NFT');
message.success("You've successfully claimed your MENT token.");
if (receipt.data?.to && receipt.data?.logs[0].topics[3]) {
const nftId = Number(receipt.data?.logs[0].topics[3]);
Expand Down Expand Up @@ -100,8 +100,8 @@ async function loadNft(contract: Address, id: number, transactionHash: string) {
<div v-if="!isConnected" class="my-8 text-center">
<h3 class="mb-6">Almost there!</h3>
<p>
But first, connect compatible digital wallet. This step is crucial for securely receiving
and managing the MENT token you’ll about to receive.
But first, connect a compatible digital wallet. This step is crucial
for securely receiving and managing the MENT token you’re about to receive.
</p>
</div>

Expand Down
2 changes: 1 addition & 1 deletion frontend/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ useHead({
<span class="mb-2 inline-block text-xs font-bold uppercase tracking-[0.2em] text-info"
>The Shape of MENT to Come</span
>
<h1>Sign up and win your MENT token</h1>
<h1>Sign up and win one of 200 MENT tokens</h1>

<p class="body-lg mb-6">
By signing up, you’ll be in the game for the hottest perks in the form of MENT token
Expand Down
Loading

0 comments on commit c7a852f

Please sign in to comment.