Skip to content

Instantly share code, notes, and snippets.

@ZaK3939
Created June 11, 2023 10:44
Show Gist options
  • Save ZaK3939/04b1863b3f28bad35537ab148a9ca577 to your computer and use it in GitHub Desktop.
Save ZaK3939/04b1863b3f28bad35537ab148a9ca577 to your computer and use it in GitHub Desktop.
import { secretId } from "@env";
import { notVerifyResponse, successResponse } from "@object-helpers/apiResponse";
import { createCoupon, generateHashBuffer, serializeCoupon } from "@object-helpers/coupons";
import { getSecret } from "@object-helpers/phiUtils";
import { getSigKeyfromKMS } from "@utility/getSigKeyfromKMS";
import { simpleRateLimit } from "@utility/rateLimiter";
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import axios from "axios";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
dayjs.extend(utc);
const getMultipleLogic = (count: number): number[] => {
let logicArr: number[] = [];
if (count >= 10) {
logicArr = [1, 2, 3];
} else if (count >= 5) {
logicArr = [1, 2];
} else if (count >= 1) {
logicArr = [1];
}
return logicArr;
};
export async function countTransactions(address: string, apiKey: string): Promise<number> {
try {
const getURL = `https://api.polygonscan.com/api?module=account&action=txlist&address=${address}&startblock=0&endblock=99999999&sort=desc&apikey=${apiKey}`;
console.log("getURL:", getURL);
const response = await axios.get(getURL);
if (response.data.message === "NOTOK") {
console.error("Error retrieving transactions:", response.data.message);
return 0;
}
const targetDate = dayjs.utc().format("YYYY-MM-DD");
const transactions = response.data.result;
const startOfDay = dayjs.utc(targetDate).startOf("day");
const endOfDay = dayjs.utc(targetDate).endOf("day");
let count = 0;
for (const tx of transactions) {
const txDate = dayjs.unix(tx.timeStamp);
if (txDate.isBefore(startOfDay)) {
break;
}
if (txDate.isAfter(startOfDay) && txDate.isBefore(endOfDay) && tx.isError === "0" && tx.from === address) {
count++;
}
}
console.log(`Address ${address} has made ${count} successful transactions on ${targetDate}.`);
return count;
} catch (error) {
console.error("Error:", error);
return 0;
}
}
const RESPONSE_HEADERS = {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type,Authorization,access-token",
};
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
const queryParams = event.queryStringParameters ? event.queryStringParameters : {};
console.log("start dailyquest, params: " + JSON.stringify(queryParams));
if (!queryParams.address) {
return {
statusCode: 500,
headers: RESPONSE_HEADERS,
body: JSON.stringify({ result: "bad request" }),
};
}
let counter = 0;
let polygonscanApiKey;
try {
const secret = await getSecret(secretId);
polygonscanApiKey = secret.POLYGONSCAN_API_KEY;
const address = queryParams.address.toLowerCase();
const allow = await simpleRateLimit(address, "transaction-verify", 60000);
console.log(allow);
if (!allow) {
return {
statusCode: 429,
headers: RESPONSE_HEADERS,
body: JSON.stringify({ result: "rate limited. come back in 1 minutes" }),
};
}
counter = await countTransactions(address, polygonscanApiKey);
console.log("counter:", counter);
const coupons = [];
let logicIds = [];
if (queryParams.logicid) {
logicIds.push(parseInt(queryParams.logicid, 10));
} else {
logicIds = getMultipleLogic(counter);
}
const secretkey = await getSigKeyfromKMS(secret.CiphertextBlob);
const todayDate = parseInt(dayjs.utc().format("YYYYMMDD"), 10);
for (const logicid of logicIds) {
const hashBuffer = generateHashBuffer(["uint32", "uint16", "address"], [todayDate, logicid, address]);
console.log("create buffer with", todayDate, logicid, address);
const signerPvtKey = Buffer.from(secretkey, "hex");
const coupon = createCoupon(hashBuffer, signerPvtKey);
coupons.push({
logic: logicid,
coupon: serializeCoupon(coupon),
});
}
if (coupons.length > 0) {
const responseBody = JSON.stringify({
message: "verify",
counter,
day: todayDate,
coupons: coupons.map(coupon => ({ logic: coupon.logic, coupon: coupon.coupon })),
});
return successResponse(responseBody);
}
} catch (err) {
console.error(err);
}
return notVerifyResponse;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment