diff --git a/.env.sample b/.env.sample index 59397999..34aa4b73 100644 --- a/.env.sample +++ b/.env.sample @@ -10,3 +10,5 @@ DATABASE_URL= ACCOUNT_PK=0x0574ba4998dd9aedf1c4d6e56b747b29256a795bc3846437d121cd64b972bdd8 NEXT_PUBLIC_OG_NFT_CONTRACT=0x3cb654f2f557a7f71a0c16d97c05a2dec62a0b744979d11afc95b804e1d7307 + +CRON_SECRET= diff --git a/next.config.mjs b/next.config.mjs index 83948dfc..9b833cdc 100755 --- a/next.config.mjs +++ b/next.config.mjs @@ -2,9 +2,9 @@ const nextConfig = { // output: 'export', compiler: { - removeConsole: { - exclude: ['error', 'debug'], - }, + // removeConsole: { + // exclude: ['error', 'debug'], + // }, }, async rewrites() { return [ @@ -62,7 +62,8 @@ const nextConfig = { }, { source: '/tnc/v1', - destination: 'https://github.com/strkfarm/static-assets/blob/177389cad715d69245c1b125df87f90318ac2d7b/tnc.pdf', + destination: + 'https://github.com/strkfarm/static-assets/blob/177389cad715d69245c1b125df87f90318ac2d7b/tnc.pdf', permanent: true, }, ]; diff --git a/prisma/migrations/20240818115638_init/migration.sql b/prisma/migrations/20240818115638_init/migration.sql deleted file mode 100644 index 08f2584e..00000000 --- a/prisma/migrations/20240818115638_init/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "email" TEXT NOT NULL, - "name" TEXT, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); diff --git a/prisma/migrations/20240818143249_updated_user_model/migration.sql b/prisma/migrations/20240818143249_updated_user_model/migration.sql deleted file mode 100644 index 978dd956..00000000 --- a/prisma/migrations/20240818143249_updated_user_model/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `email` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `name` on the `User` table. All the data in the column will be lost. - - A unique constraint covering the columns `[address]` on the table `User` will be added. If there are existing duplicate values, this will fail. - - Added the required column `address` to the `User` table without a default value. This is not possible if the table is not empty. - - Added the required column `message` to the `User` table without a default value. This is not possible if the table is not empty. - -*/ --- DropIndex -DROP INDEX "User_email_key"; - --- AlterTable -ALTER TABLE "User" DROP COLUMN "email", -DROP COLUMN "name", -ADD COLUMN "address" TEXT NOT NULL, -ADD COLUMN "message" TEXT NOT NULL, -ADD COLUMN "tncDocVersion" TEXT NOT NULL DEFAULT '1.0'; - --- CreateIndex -CREATE UNIQUE INDEX "User_address_key" ON "User"("address"); diff --git a/prisma/migrations/20240824114901_updated_user_model/migration.sql b/prisma/migrations/20240824114901_updated_user_model/migration.sql deleted file mode 100644 index 8a0bc979..00000000 --- a/prisma/migrations/20240824114901_updated_user_model/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[referralCode]` on the table `User` will be added. If there are existing duplicate values, this will fail. - - Added the required column `referralCode` to the `User` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "User" ADD COLUMN "referralCode" TEXT NOT NULL, -ALTER COLUMN "message" DROP NOT NULL, -ALTER COLUMN "tncDocVersion" DROP NOT NULL; - --- CreateIndex -CREATE UNIQUE INDEX "User_referralCode_key" ON "User"("referralCode"); diff --git a/prisma/migrations/20240824115758_updated_user_model/migration.sql b/prisma/migrations/20240824115758_updated_user_model/migration.sql deleted file mode 100644 index ea5ea2cf..00000000 --- a/prisma/migrations/20240824115758_updated_user_model/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "isTncSigned" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/migrations/20240824121027_updated_user_model/migration.sql b/prisma/migrations/20240824121027_updated_user_model/migration.sql deleted file mode 100644 index 5ec0b272..00000000 --- a/prisma/migrations/20240824121027_updated_user_model/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "User" ALTER COLUMN "isTncSigned" DROP NOT NULL; diff --git a/prisma/migrations/20240824132519_added_refree_model/migration.sql b/prisma/migrations/20240824132519_added_refree_model/migration.sql deleted file mode 100644 index 0f289923..00000000 --- a/prisma/migrations/20240824132519_added_refree_model/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "refreeCount" INTEGER DEFAULT 0; - --- CreateTable -CREATE TABLE "Refree" ( - "id" SERIAL NOT NULL, - "address" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "userId" INTEGER, - - CONSTRAINT "Refree_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Refree_address_key" ON "Refree"("address"); - --- AddForeignKey -ALTER TABLE "Refree" ADD CONSTRAINT "Refree_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20240825061257_updated_user_model/migration.sql b/prisma/migrations/20240825061257_updated_user_model/migration.sql deleted file mode 100644 index 9920d717..00000000 --- a/prisma/migrations/20240825061257_updated_user_model/migration.sql +++ /dev/null @@ -1,32 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `refreeCount` on the `User` table. All the data in the column will be lost. - - You are about to drop the `Refree` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "Refree" DROP CONSTRAINT "Refree_userId_fkey"; - --- AlterTable -ALTER TABLE "User" DROP COLUMN "refreeCount", -ADD COLUMN "referralCount" INTEGER DEFAULT 0; - --- DropTable -DROP TABLE "Refree"; - --- CreateTable -CREATE TABLE "Referral" ( - "id" SERIAL NOT NULL, - "refreeAddress" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "referralId" INTEGER, - - CONSTRAINT "Referral_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Referral_refreeAddress_key" ON "Referral"("refreeAddress"); - --- AddForeignKey -ALTER TABLE "Referral" ADD CONSTRAINT "Referral_referralId_fkey" FOREIGN KEY ("referralId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20240825064700_updated_user_model/migration.sql b/prisma/migrations/20240825064700_updated_user_model/migration.sql deleted file mode 100644 index 4cfcc1ce..00000000 --- a/prisma/migrations/20240825064700_updated_user_model/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ -/* - Warnings: - - - The primary key for the `Referral` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `id` on the `Referral` table. All the data in the column will be lost. - - Made the column `referralId` on table `Referral` required. This step will fail if there are existing NULL values in that column. - -*/ --- DropForeignKey -ALTER TABLE "Referral" DROP CONSTRAINT "Referral_referralId_fkey"; - --- AlterTable -CREATE SEQUENCE referral_referralid_seq; -ALTER TABLE "Referral" DROP CONSTRAINT "Referral_pkey", -DROP COLUMN "id", -ADD COLUMN "userId" INTEGER, -ALTER COLUMN "referralId" SET NOT NULL, -ALTER COLUMN "referralId" SET DEFAULT nextval('referral_referralid_seq'), -ADD CONSTRAINT "Referral_pkey" PRIMARY KEY ("referralId"); -ALTER SEQUENCE referral_referralid_seq OWNED BY "Referral"."referralId"; - --- AddForeignKey -ALTER TABLE "Referral" ADD CONSTRAINT "Referral_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20240825141032_updated_referral_model/migration.sql b/prisma/migrations/20240825141032_updated_referral_model/migration.sql deleted file mode 100644 index 13d9a7ae..00000000 --- a/prisma/migrations/20240825141032_updated_referral_model/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - Made the column `userId` on table `Referral` required. This step will fail if there are existing NULL values in that column. - -*/ --- DropForeignKey -ALTER TABLE "Referral" DROP CONSTRAINT "Referral_userId_fkey"; - --- AlterTable -ALTER TABLE "Referral" ALTER COLUMN "userId" SET NOT NULL; - --- AddForeignKey -ALTER TABLE "Referral" ADD CONSTRAINT "Referral_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20241028130637_changes/migration.sql b/prisma/migrations/20241028130637_changes/migration.sql new file mode 100644 index 00000000..1e851fd7 --- /dev/null +++ b/prisma/migrations/20241028130637_changes/migration.sql @@ -0,0 +1,111 @@ +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "address" TEXT NOT NULL, + "isTncSigned" BOOLEAN DEFAULT false, + "message" TEXT, + "tncDocVersion" TEXT DEFAULT '1.0', + "referralCode" TEXT NOT NULL, + "referralCount" INTEGER DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Raffle" ( + "raffleId" SERIAL NOT NULL, + "isRaffleParticipant" BOOLEAN DEFAULT false, + "sharedOnX" BOOLEAN DEFAULT false, + "activeDeposits" BOOLEAN DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Raffle_pkey" PRIMARY KEY ("raffleId") +); + +-- CreateTable +CREATE TABLE "LuckyWinner" ( + "winnerId" SERIAL NOT NULL, + "updatedAt" TIMESTAMP(3) NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "raffleId" INTEGER NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "LuckyWinner_pkey" PRIMARY KEY ("winnerId") +); + +-- CreateTable +CREATE TABLE "Signatures" ( + "id" SERIAL NOT NULL, + "signature" TEXT NOT NULL, + "tncDocVersion" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Signatures_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Referral" ( + "referralId" SERIAL NOT NULL, + "refreeAddress" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Referral_pkey" PRIMARY KEY ("referralId") +); + +-- CreateTable +CREATE TABLE "og_nft_users" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "og_nft_users_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_address_key" ON "User"("address"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_referralCode_key" ON "User"("referralCode"); + +-- CreateIndex +CREATE UNIQUE INDEX "Raffle_userId_raffleId_key" ON "Raffle"("userId", "raffleId"); + +-- CreateIndex +CREATE UNIQUE INDEX "LuckyWinner_userId_winnerId_key" ON "LuckyWinner"("userId", "winnerId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Signatures_userId_tncDocVersion_key" ON "Signatures"("userId", "tncDocVersion"); + +-- CreateIndex +CREATE UNIQUE INDEX "Referral_refreeAddress_key" ON "Referral"("refreeAddress"); + +-- CreateIndex +CREATE UNIQUE INDEX "Referral_userId_refreeAddress_key" ON "Referral"("userId", "refreeAddress"); + +-- CreateIndex +CREATE UNIQUE INDEX "og_nft_users_userId_key" ON "og_nft_users"("userId"); + +-- AddForeignKey +ALTER TABLE "Raffle" ADD CONSTRAINT "Raffle_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LuckyWinner" ADD CONSTRAINT "LuckyWinner_raffleId_fkey" FOREIGN KEY ("raffleId") REFERENCES "Raffle"("raffleId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LuckyWinner" ADD CONSTRAINT "LuckyWinner_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Signatures" ADD CONSTRAINT "Signatures_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Referral" ADD CONSTRAINT "Referral_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "og_nft_users" ADD CONSTRAINT "og_nft_users_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20241029102731_added_round_id/migration.sql b/prisma/migrations/20241029102731_added_round_id/migration.sql new file mode 100644 index 00000000..cd1ffbac --- /dev/null +++ b/prisma/migrations/20241029102731_added_round_id/migration.sql @@ -0,0 +1,22 @@ +/* + Warnings: + + - The primary key for the `LuckyWinner` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `winnerId` on the `LuckyWinner` table. All the data in the column will be lost. + - A unique constraint covering the columns `[roundId]` on the table `LuckyWinner` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[userId,roundId]` on the table `LuckyWinner` will be added. If there are existing duplicate values, this will fail. + +*/ +-- DropIndex +DROP INDEX "LuckyWinner_userId_winnerId_key"; + +-- AlterTable +ALTER TABLE "LuckyWinner" DROP CONSTRAINT "LuckyWinner_pkey", +DROP COLUMN "winnerId", +ADD COLUMN "roundId" INTEGER NOT NULL DEFAULT 0; + +-- CreateIndex +CREATE UNIQUE INDEX "LuckyWinner_roundId_key" ON "LuckyWinner"("roundId"); + +-- CreateIndex +CREATE UNIQUE INDEX "LuckyWinner_userId_roundId_key" ON "LuckyWinner"("userId", "roundId"); diff --git a/prisma/migrations/20241029103119_updated_round_id_constraints/migration.sql b/prisma/migrations/20241029103119_updated_round_id_constraints/migration.sql new file mode 100644 index 00000000..087978e7 --- /dev/null +++ b/prisma/migrations/20241029103119_updated_round_id_constraints/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "LuckyWinner_roundId_key"; diff --git a/prisma/migrations/20241029103502_updated_round_id_constraints/migration.sql b/prisma/migrations/20241029103502_updated_round_id_constraints/migration.sql new file mode 100644 index 00000000..b4fbb617 --- /dev/null +++ b/prisma/migrations/20241029103502_updated_round_id_constraints/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "LuckyWinner" ALTER COLUMN "roundId" SET DEFAULT 1, +ADD CONSTRAINT "LuckyWinner_pkey" PRIMARY KEY ("roundId"); diff --git a/prisma/migrations/20241029103711_updated_round_id_constraints/migration.sql b/prisma/migrations/20241029103711_updated_round_id_constraints/migration.sql new file mode 100644 index 00000000..d186da9c --- /dev/null +++ b/prisma/migrations/20241029103711_updated_round_id_constraints/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - The primary key for the `LuckyWinner` table will be changed. If it partially fails, the table could be left without primary key constraint. + +*/ +-- AlterTable +ALTER TABLE "LuckyWinner" DROP CONSTRAINT "LuckyWinner_pkey", +ADD COLUMN "winnerId" SERIAL NOT NULL, +ADD CONSTRAINT "LuckyWinner_pkey" PRIMARY KEY ("winnerId"); diff --git a/prisma/migrations/20241029105811_updated_raffle_model/migration.sql b/prisma/migrations/20241029105811_updated_raffle_model/migration.sql new file mode 100644 index 00000000..ed8dfcf5 --- /dev/null +++ b/prisma/migrations/20241029105811_updated_raffle_model/migration.sql @@ -0,0 +1,18 @@ +/* + Warnings: + + - You are about to drop the column `roundId` on the `LuckyWinner` table. All the data in the column will be lost. + - A unique constraint covering the columns `[userId,winnerId]` on the table `LuckyWinner` will be added. If there are existing duplicate values, this will fail. + +*/ +-- DropIndex +DROP INDEX "LuckyWinner_userId_roundId_key"; + +-- AlterTable +ALTER TABLE "LuckyWinner" DROP COLUMN "roundId"; + +-- AlterTable +ALTER TABLE "Raffle" ADD COLUMN "roundId" INTEGER NOT NULL DEFAULT 1; + +-- CreateIndex +CREATE UNIQUE INDEX "LuckyWinner_userId_winnerId_key" ON "LuckyWinner"("userId", "winnerId"); diff --git a/prisma/migrations/20241029113615_updated_lucky_winner_model/migration.sql b/prisma/migrations/20241029113615_updated_lucky_winner_model/migration.sql new file mode 100644 index 00000000..d9c69c81 --- /dev/null +++ b/prisma/migrations/20241029113615_updated_lucky_winner_model/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the column `roundId` on the `Raffle` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "LuckyWinner" ADD COLUMN "roundId" SERIAL NOT NULL; + +-- AlterTable +ALTER TABLE "Raffle" DROP COLUMN "roundId"; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index 6bf90154..fbffa92c 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a8a99152..0e628ee9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -8,19 +8,51 @@ generator client { } model User { - id Int @id @default(autoincrement()) - address String @unique - isTncSigned Boolean? @default(false) + id Int @id @default(autoincrement()) + address String @unique + isTncSigned Boolean? @default(false) message String? - tncDocVersion String? @default("1.0") - referralCode String @unique + tncDocVersion String? @default("1.0") + referralCode String @unique referrals Referral[] - referralCount Int? @default(0) + referralCount Int? @default(0) + Raffles Raffle[] + og_nft_users og_nft_users? + Signatures Signatures[] + LuckyWinner LuckyWinner[] - createdAt DateTime @default(now()) - og_nft_users og_nft_users? - updatedAt DateTime @updatedAt @default(now()) - Signatures Signatures[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt +} + +model Raffle { + raffleId Int @id @default(autoincrement()) + + isRaffleParticipant Boolean? @default(false) + sharedOnX Boolean? @default(false) + activeDeposits Boolean? @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + User User @relation(fields: [userId], references: [id]) + userId Int @unique + + LuckyWinner LuckyWinner[] +} + +model LuckyWinner { + winnerId Int @id @default(autoincrement()) + roundId Int @default(autoincrement()) + + updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) + + Raffle Raffle @relation(fields: [raffleId], references: [raffleId]) + raffleId Int + + User User @relation(fields: [userId], references: [id]) + userId Int @unique } model Signatures { diff --git a/public/og_nft_eligible_users.json b/public/og_nft_eligible_users.json index 17c22937..a290965b 100644 --- a/public/og_nft_eligible_users.json +++ b/public/og_nft_eligible_users.json @@ -21,11 +21,21 @@ "0x7a900c5b496d15bbb1c3c69d090e890a4b19dbceabee72232d4f2bec67ff4c", "0x7f5d5b58f2a1c504f6a8d0e47269c903485582308b6f3415c27a561e0d1a6fa", "0x17603b7963b1e2357a57e3c16f83abacef6bd8cf59e5394c34ae72ce566da2", + "0x27391b415a803a1aa7fffbed7db19336cf4b7f9bb1d3468986eef9a26341356", "0x4bbdde9359d8bc7e513f510f9080306dbf267acb41228a4706d1b55f2fd065d", "0x4015548595f22ccf56f6f42ada31a5d8eb7cb307c4e9e550b578d44fa25bcc", + "0x19bd65c87c1cea020fafefaeb6e3aeda385a97725627d712c0523d89264c8fd", "0x50393e851e40de930abcd9569d9df55883b9f2836d4bae724f126d2258cd292", + "0xb10b74c5cf03034b84b712aaf6dfee5d231c0fa293615d902b41e7ab5c3a88", + "0x2140e267cf7e44f2f8556e75870f12632f85c3aad571a1d649828e476d6a811", + "0x45238abe57100330bc23ab1895e542778ba7ee7ce0df10ce4852a8d53f2246", + "0x6664321c527c75bdc76ba47a9620808ce810abc2aded699a59a1d81c90f3504", + "0x3cc66a2689b84c2f41fe7a2c8230ce95eb33e6edcafbb80a1141cf375b42571", + "0x720eba8edea43289347d8cc5518a1944b3eb5c9bde8f255c4946f9ff21d782d", + "0x681f8367c08ff6d5d0dbae1e56e507be26febfb370a416a76c8a7317687969f", "0x2915ca6c218df8b394237b278cc920668fd504268494e1ebcf108a660cd7136", "0x552760d9b7d629e2daf636129fb519ac17a739e1a1fa05ee928ccb1f62c26cf", + "0x5d13967477c18e3af591c71f10163fca12360c99d9f1c1c48e9c8626742dee", "0x14f59c23735b4aaaf6b6c0df567cacff9adc27f50dcb8b5270cf1237605c263", "0x6733e297fe300f78f48c7106ad550626377aa732cef360867218c08a536ea5e", "0x1ca34f742a91a588a3e770c8c8c8618a0713d7f64fda7935d42dcfcf4adffa0", @@ -35,17 +45,27 @@ "0x36177b6741a43c219602ce857c18e445920d5a6ea5f4ee3a0240e8ae319bbf5", "0x47ccae4b7dccabd0689624812f7deeb3ed283dc3349b826974ff88107d71f4c", "0x9fb60ac230ceeda227d28f138e327d2509d01531d20d9c8b2c4a7bf65afd8c", + "0x679316db27cdb5d579d0508859ce450db3c2a2483e3628f7c1fc80b52e87634", + "0x640822d69e5c3e6ecb549de81d95bae4ccee96a4b8b3fa61932d2f3ebcdce8d", + "0x122e9a7a5986d4a4eb031aee31e6df38cd6c1bd85446f066604581ba04cbfc8", "0x1f13873d0e2ff24321ca91d0530f093c25dc7b52d9316df8c2ec1a17fbfb5c1", "0x7342070d73d4ceef7e7c84420acb3026720e88fef10302fc11fd25a7ee0b715", "0x2b27457428b94b38ccad5339ebc17a211b7c482c008ac8ad22e01b30e923628", "0x67b72d3df972e5816b07ad4794af8e85c968409554281880149e96f09df1d56", + "0x5f5781997b93d118825ecfbd96e04f94b2fee90b7841f402f3e2ebcc95672ed", "0x1eb945a1b881a2d8f8d8ea5eada7ec42c999ab5e5ed225af7b62f00865bafbd", + "0xeabce6178a1c78cfa54649cc52ecdc237cbacbdd506edda0d44a3db4840f47", "0x73298a2ca8b06596d7bc85311c1c9d06458664a02a341655dee4e663600ac53", "0x297268ffc3c342f9c7fa3df6a5a6ef63ef5a5232ceaaf67168df686283effca", + "0x4bd49519bd6b640e0d4dd3f0d382aff5ef25969b0e7aaa34bf9c97fa5a3e2fd", "0x16d730875c5dd15f3c1086523683bf5463fc11572405c8bee6e1ec65bead84e", "0x4d1b676e430b55175ce9ecbe073486a15411a8605c99aff8a14804fd4088da5", "0x147b941bec50a2b497eb1bd966cf36e33ad3da7e508ebd5ea994978fa5be5a6", + "0x6fd089667ad15016fa88eb492049d1ad723f6d37c2b39e9669745318963830d", + "0x70512c3a3c5e90a3ef0bed1078ad8ec12bf1085c05f2f10f8413b7879bddfcf", "0x5a39462a82784de9f0f30c356f3fd5dfe71c7fa510bf22e8893cec254f59fc2", + "0x748f1a40e54099dce8252becc5c5affdc2e4cccbcad024046ea50a9ceb3e1bf", + "0xeec20d6fae576395ba3312d71173c704bc604c6ffd2a1f75c58c7f620518ab", "0x7364ce0a8aab411beddf7780f222b3508af4daf5c542bb258e9fe55ae5846ba", "0x3d87ee70baf292cdc23c654153cfd711ff580a076d1dccc0dfd9d3eb62df311", "0x63d87659aeb300ce268e872fd16d3d2ad5821444c438fae86f2b1fc39d26c17", @@ -55,14 +75,22 @@ "0x53f7a43286d4c5a2c5104b44ccb7b9e103ea915a96c6a1f6870a7c6c2206d99", "0x2321807e25b3ef5ddd835e23696cc13a645405baec4cd8b918323704a870cc9", "0x367c0c4603a29bc5aca8e07c6a2776d7c0d325945abb4f772f448b345ca4cf7", + "0x30339cee56c4ec12655e4eef28f7788a3b4b931fdb7a5b133e1e3a298577484", + "0x3f2b3aa69cb5123da70fa5569d760c60b71e312ae7e2b5fc93b9f3cdfb4dab2", + "0x4a2e0d92a5fbe6cce8c946e73f3e9d598268da80009a8382d6c9528d60b7422", "0x5e2ceca0361cc280ae6c67fcbc2bc8f1d052d81590ef730232f13d6ebf5fbd2", "0x3d0925e3d88cec40c818b5388fca09094bca0f3b2ee71c5d8459c79f6ead07", + "0x4e8c601e8f9542f2a66481ec03252d5ad75adaacf53a87075af3f7e51ccbf69", "0x2768d87d73919754122d5a66923d3da58a98e9e06ef2ccf27c4d0ff3b4ec2a8", - "0x3bb0ee1ace26d86a9045872166f145dcb9ab4d37da9bdf76f6fe11ab129f0c8", - "0x1af714eed6c7e26bf8f794fc75c0e2f5f25dbca13b9875a344a97e64cccaec1", - "0x6d1b40ae61ee3c2e794b9a5ff209d91c48e11618151260151b83813f3895faf", - "0x745fc3081d4e195e41c6c44fcb6a56d28d9d2fa683101cb2bc820bbeb7f91fd", - "0x58e058cc515404046b9a125531b92dfb9542b02829447381483520df7e7e39e", - "0x1f88cf149991c7768351fdf9c2bd80a56814a2b9a15e73e93c25d811b234f99", - "0x37780473b2cd3d58fa4a9b5be172da2479159df129649cb38576678a90e3ed7" + "0x64fb7f85fd9dee10c313696b0aef1f4afc888ce8422edbc2f1695ec5ed152e9", + "0xb1ddd66dfd43f359706730088685770a2dc23ba097d56837d06efe6004247e", + "0x33d81412229469eb75ad178fd5cfdf37a439a5757f0a48878912aa7204d644c", + "0x3072de7549420ea000fdea27f8d2882d6179fa6c1967d0fda54e76eeaed7fd2", + "0x46f969a97eb52b8757522cb78996fd9b1c7fab996e63e8c4d481da7e6fac332", + "0x5aed32c092b4d597e524160d749c4ac4bfe38960693b79f3c407e9fdf6ec7f4", + "0x9f60931cd5bb85b19ed67011a4d0bbed126976ec708b201f30fa94562f5633", + "0x73698c80cd58d145a9900eb43240a0f85e3a4f24025b4b56c3480075d133f6b", + "0x551533735edca74e90d4b055a4987c89fde8f65a497c02d621e306b0ab7567d", + "0x109b84c85aa005a6f5ee1789f746693e72732e0fa4d3c9a3cac2eccff2299de", + "0x12ef68c3dd74994ea548cbe29def0335602dc40a752f66beaf18d769e2ff8d0" ] diff --git a/public/raffle-deposits.svg b/public/raffle-deposits.svg new file mode 100644 index 00000000..95342c85 --- /dev/null +++ b/public/raffle-deposits.svg @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/raffle-hero.svg b/public/raffle-hero.svg new file mode 100644 index 00000000..c534feaa --- /dev/null +++ b/public/raffle-hero.svg @@ -0,0 +1,1188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/raffle-register.svg b/public/raffle-register.svg new file mode 100644 index 00000000..a755bd0f --- /dev/null +++ b/public/raffle-register.svg @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/raffle-share.svg b/public/raffle-share.svg new file mode 100644 index 00000000..bd8de8c9 --- /dev/null +++ b/public/raffle-share.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/app/api/raffle/luckyWinner/route.ts b/src/app/api/raffle/luckyWinner/route.ts new file mode 100644 index 00000000..e908b194 --- /dev/null +++ b/src/app/api/raffle/luckyWinner/route.ts @@ -0,0 +1,147 @@ +import { db } from '@/db'; +import { Raffle } from '@prisma/client'; +import { NextResponse } from 'next/server'; + +export const dynamic = 'force-dynamic'; // static by default, unless reading the request + +export async function GET(request: Request) { + const authHeader = request.headers.get('authorization'); + if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { + return new Response('Unauthorized', { + status: 401, + }); + } + + const { searchParams } = new URL(request.url); + let noOfWinners = parseInt(searchParams.get('winnersCount') || '0', 10); + console.log('No of winners requested:', noOfWinners); + + if (noOfWinners <= 0) { + return NextResponse.json({ + success: false, + message: 'Invalid number of winners requested', + }); + } + + try { + const raffleParticipants = await db.raffle.findMany({ + where: { + OR: [ + { isRaffleParticipant: true }, + { sharedOnX: true }, + { activeDeposits: true }, + ], + }, + }); + + if (raffleParticipants.length === 0) { + return NextResponse.json({ + success: false, + message: 'No raffle participants found', + }); + } + + console.log('Total raffle participants:', raffleParticipants.length); + + const totalExistingWinners = await db.luckyWinner.findMany({ + select: { + userId: true, + }, + }); + if (totalExistingWinners.length == raffleParticipants.length) { + return NextResponse.json({ + success: false, + message: 'No new participants found', + }); + } + + // index to ticket owner map + const ticketOwners: Raffle[] = []; + + let uniqueUsersCount = 0; + raffleParticipants.forEach((participant) => { + const exists = totalExistingWinners.find( + (winner) => winner.userId === participant.userId, + ); + if (exists) return; + + uniqueUsersCount++; + if (participant.isRaffleParticipant) { + ticketOwners.push(participant); + } + if (participant.sharedOnX) { + ticketOwners.push(participant); + } + if (participant.activeDeposits) { + ticketOwners.push(participant); + } + }); + + if (uniqueUsersCount < noOfWinners) { + noOfWinners = uniqueUsersCount; + } + + if (noOfWinners === 0) { + return NextResponse.json({ + success: false, + message: 'No winners to select', + }); + } + + const luckyWinners: Raffle[] = []; + + // Continue selecting winners until we reach the desired count + while (luckyWinners.length < noOfWinners) { + // Try to find a participant from each group in order + if (ticketOwners.length === 0) continue; + + // Keep searching within the current group until a valid participant is found + const randomIndex = Math.floor(Math.random() * ticketOwners.length); + const selectedParticipant = ticketOwners[randomIndex]; + + // assert selectedParticipant is not already a winner + const exists = luckyWinners.find( + (winner) => winner.userId === selectedParticipant.userId, + ); + if (exists) continue; + + luckyWinners.push(selectedParticipant); + } + + // Check if we were able to select enough winners + if (luckyWinners.length == 0) { + return NextResponse.json({ + success: false, + message: 'No winner found', + }); + } + + // Add selected users to the LuckyWinner table + const maxRoundIdInfo = await db.luckyWinner.findFirst({ + select: { roundId: true }, + orderBy: { roundId: 'desc' }, + }); + const maxRoundId = maxRoundIdInfo ? maxRoundIdInfo.roundId : 0; + const newLuckyWinners = await db.luckyWinner.createMany({ + data: luckyWinners.map((userId) => ({ + roundId: maxRoundId + 1, + raffleId: userId.raffleId, + userId: userId.userId, + })), + }); + + console.log('Lucky winners selected successfully:', newLuckyWinners); + + return NextResponse.json({ + success: true, + message: 'Lucky winners selected successfully', + luckyWinners: newLuckyWinners, + }); + } catch (error) { + console.error('Error selecting lucky winners:', error); + return NextResponse.json({ + success: false, + message: 'An error occurred while selecting lucky winners', + }); + } +} diff --git a/src/app/api/raffle/route.ts b/src/app/api/raffle/route.ts new file mode 100644 index 00000000..d4182be3 --- /dev/null +++ b/src/app/api/raffle/route.ts @@ -0,0 +1,157 @@ +import { NextResponse } from 'next/server'; + +import { db } from '@/db'; +import { getStrategies } from '@/store/strategies.atoms'; +import { standariseAddress } from '@/utils'; + +export async function POST(req: Request) { + const { address, type } = await req.json(); + + if (!address || !type) { + return NextResponse.json({ + success: false, + message: 'address not found', + user: null, + }); + } + + if (!type || !['SHARED_ON_X', 'ACTIVE_DEPOSITS', 'REGISTER'].includes(type)) { + return NextResponse.json({ + success: false, + message: 'Invalid type', + }); + } + + // standardised address + let parsedAddress = address; + try { + parsedAddress = standariseAddress(address); + } catch (e) { + throw new Error('Invalid address'); + } + + const user = await db.user.findFirst({ + where: { + address: parsedAddress, + }, + }); + + if (!user) { + return NextResponse.json({ + success: false, + message: 'User not found', + user: null, + }); + } + + if (type === 'REGISTER') { + const raffleUser = await db.raffle.findFirst({ + where: { + userId: user.id, + }, + }); + + if (raffleUser) { + return NextResponse.json({ + success: false, + message: 'User already registered', + user: raffleUser, + }); + } + + const createdUser = await db.raffle.create({ + data: { + isRaffleParticipant: true, + User: { + connect: { + address: parsedAddress, + }, + }, + }, + }); + + return NextResponse.json({ + success: true, + message: 'User registered for raffle successfully', + user: createdUser, + }); + } + + const raffleUser = await db.raffle.findFirst({ + where: { + userId: user.id, + isRaffleParticipant: true, + }, + }); + + if (!raffleUser) { + return NextResponse.json({ + success: false, + message: 'Registered user not found', + user: null, + }); + } + + if (type === 'SHARED_ON_X') { + const updatedUser = await db.raffle.update({ + where: { + raffleId: raffleUser.raffleId, + }, + data: { + sharedOnX: true, + }, + }); + + return NextResponse.json({ + success: true, + message: 'Shared on X successfully', + user: updatedUser, + }); + } + + if (type === 'ACTIVE_DEPOSITS') { + const strategies = getStrategies(); + + const values = strategies.map(async (strategy) => { + const balanceInfo = await strategy.getUserTVL(parsedAddress); + return { + id: strategy.id, + usdValue: balanceInfo.usdValue, + tokenInfo: { + name: balanceInfo.tokenInfo.name, + symbol: balanceInfo.tokenInfo.name, + logo: balanceInfo.tokenInfo.logo, + decimals: balanceInfo.tokenInfo.decimals, + displayDecimals: balanceInfo.tokenInfo.displayDecimals, + }, + amount: balanceInfo.amount.toEtherStr(), + }; + }); + + const result = await Promise.all(values); + const sum = result.reduce((acc, item) => acc + item.usdValue, 0); + + if (sum > 10) { + const createdUser = await db.raffle.update({ + where: { + raffleId: raffleUser.raffleId, + }, + data: { + activeDeposits: true, + }, + }); + + return NextResponse.json({ + success: true, + message: 'Active deposits found', + user: createdUser, + }); + } + + return NextResponse.json({ + success: false, + message: 'No active deposits found', + user: null, + }); + } +} diff --git a/src/app/api/tnc/getUser/[address]/route.ts b/src/app/api/tnc/getUser/[address]/route.ts index 8947b65d..6647c810 100644 --- a/src/app/api/tnc/getUser/[address]/route.ts +++ b/src/app/api/tnc/getUser/[address]/route.ts @@ -3,10 +3,13 @@ import { NextResponse } from 'next/server'; import { db } from '@/db'; import { standariseAddress } from '@/utils'; -export async function GET(_req: Request, context: any) { +export async function GET(req: Request, context: any) { const { params } = context; const address = params.address; + const { searchParams } = new URL(req.url); + const type = searchParams.get('type'); + if (!address) { return NextResponse.json({ success: false, @@ -33,6 +36,27 @@ export async function GET(_req: Request, context: any) { }); } + if (type && type === 'RAFFLE') { + const raffleUser = await db.raffle.findFirst({ + where: { + userId: user.id, + }, + }); + + if (!raffleUser) { + return NextResponse.json({ + success: false, + message: 'Raffle user not found', + user: null, + }); + } + + return NextResponse.json({ + success: true, + user: raffleUser, + }); + } + return NextResponse.json({ success: true, user, diff --git a/src/app/raffle/_components/active-deposits.tsx b/src/app/raffle/_components/active-deposits.tsx new file mode 100644 index 00000000..ac28e2c2 --- /dev/null +++ b/src/app/raffle/_components/active-deposits.tsx @@ -0,0 +1,114 @@ +'use client'; + +import { Spinner } from '@chakra-ui/react'; +import { useAccount } from '@starknet-react/core'; +import axios from 'axios'; +import Image from 'next/image'; +import React from 'react'; +import toast from 'react-hot-toast'; + +const ActiveDeposits = () => { + const { address } = useAccount(); + + const [loading, setLoading] = React.useState(false); + const [initialLoading, setInitialLoading] = React.useState(false); + const [isActiveDeposits, setIsActiveDeposits] = React.useState(false); + + const handleActiveDeposits = async () => { + setLoading(true); + + try { + const res = await axios.post('/api/raffle', { + address, + type: 'ACTIVE_DEPOSITS', + }); + + if (res?.data?.success) { + setIsActiveDeposits(true); + toast.success('Successfully completed!', { + position: 'bottom-right', + }); + } else if ( + !res?.data?.success && + res?.data?.message === 'No active deposits found' + ) { + toast.error('You should have atleast $10 deposited in STRKFarm', { + position: 'bottom-right', + }); + } + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setLoading(false); + } + }; + + React.useEffect(() => { + if (!address) return; + + setInitialLoading(true); + setIsActiveDeposits(false); + + (async () => { + try { + const res = await axios.get(`/api/tnc/getUser/${address}`, { + params: { type: 'RAFFLE' }, + }); + + if (res?.data?.success && res?.data?.user?.activeDeposits) { + setIsActiveDeposits(true); + } else setIsActiveDeposits(false); + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setInitialLoading(false); + } + })(); + }, [address]); + + return ( +
+
+
+ STRKFarm +

+ Deposit atleast $10 in STRKFarm +

+
+ + +
+
+ ); +}; + +export default ActiveDeposits; diff --git a/src/app/raffle/_components/raffle-timer.tsx b/src/app/raffle/_components/raffle-timer.tsx new file mode 100644 index 00000000..aeccdeb4 --- /dev/null +++ b/src/app/raffle/_components/raffle-timer.tsx @@ -0,0 +1,63 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; + +const RaffleTimer: React.FC = () => { + const [timeLeft, setTimeLeft] = useState({ + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }); + + useEffect(() => { + const endDate = new Date('2024-11-11T23:59:59'); + + const updateTimer = () => { + const now = new Date(); + const difference = endDate.getTime() - now.getTime(); + + if (difference > 0) { + setTimeLeft({ + days: Math.floor(difference / (1000 * 60 * 60 * 24)), + hours: Math.floor((difference / (1000 * 60 * 60)) % 24), + minutes: Math.floor((difference / (1000 * 60)) % 60), + seconds: Math.floor((difference / 1000) % 60), + }); + } else { + clearInterval(timer); + } + }; + + const timer = setInterval(updateTimer, 1000); + + return () => clearInterval(timer); + }, []); + + return ( +
+
+ {timeLeft.days} + + Days + +
+
+ {timeLeft.hours} + Hrs +
+
+ {timeLeft.minutes} + + Mins + +
+
+ {timeLeft.seconds} + Sec +
+
+ ); +}; + +export default RaffleTimer; diff --git a/src/app/raffle/_components/register-raffle.tsx b/src/app/raffle/_components/register-raffle.tsx new file mode 100644 index 00000000..f1b79d4d --- /dev/null +++ b/src/app/raffle/_components/register-raffle.tsx @@ -0,0 +1,108 @@ +'use client'; + +import { Spinner } from '@chakra-ui/react'; +import { useAccount } from '@starknet-react/core'; +import axios from 'axios'; +import Image from 'next/image'; +import React from 'react'; +import toast from 'react-hot-toast'; + +const RegisterRaffle: React.FC = () => { + const { address } = useAccount(); + + const [isUserRegistered, setIsUserRegistered] = React.useState(false); + const [loading, setLoading] = React.useState(false); + const [initialLoading, setInitialLoading] = React.useState(false); + + const handleRegister = async () => { + setLoading(true); + + if (isUserRegistered) return; + + try { + const res = await axios.post('/api/raffle', { + address, + type: 'REGISTER', + }); + if (res?.data?.success) { + setIsUserRegistered(true); + toast.success('Successfully completed!', { + position: 'bottom-right', + }); + } + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setLoading(false); + } + + setLoading(false); + }; + + React.useEffect(() => { + if (!address) return; + + setInitialLoading(true); + setIsUserRegistered(false); + + (async () => { + try { + const res = await axios.get(`/api/tnc/getUser/${address}`, { + params: { type: 'RAFFLE' }, + }); + + if (res?.data?.success && res?.data?.user?.isRaffleParticipant) { + setIsUserRegistered(true); + } else setIsUserRegistered(false); + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setInitialLoading(false); + } + })(); + }, [address]); + + return ( +
+
+
+ STRKFarm +

+ Register if you are coming to Devcon and get one ticket. +

+
+ + +
+
+ ); +}; + +export default RegisterRaffle; diff --git a/src/app/raffle/_components/share-on-x.tsx b/src/app/raffle/_components/share-on-x.tsx new file mode 100644 index 00000000..ce18fd45 --- /dev/null +++ b/src/app/raffle/_components/share-on-x.tsx @@ -0,0 +1,105 @@ +'use client'; + +import { Spinner } from '@chakra-ui/react'; +import { useAccount } from '@starknet-react/core'; +import axios from 'axios'; +import Image from 'next/image'; +import Link from 'next/link'; +import React from 'react'; +import toast from 'react-hot-toast'; + +const ShareOnX = () => { + const { address } = useAccount(); + + const [loading, setLoading] = React.useState(false); + const [initialLoading, setInitialLoading] = React.useState(false); + const [isSharedOnX, setIsSharedOnX] = React.useState(false); + + const handleShare = async () => { + setLoading(true); + + try { + const res = await axios.post('/api/raffle', { + address, + type: 'SHARED_ON_X', + }); + + if (res?.data?.success) { + await new Promise((resolve) => setTimeout(resolve, 8000)); + setIsSharedOnX(true); + toast.success('Successfully completed!', { + position: 'bottom-right', + }); + } + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setLoading(false); + } + }; + + React.useEffect(() => { + if (!address) return; + + setInitialLoading(true); + setIsSharedOnX(false); + + (async () => { + try { + const res = await axios.get(`/api/tnc/getUser/${address}`, { + params: { type: 'RAFFLE' }, + }); + + if (res?.data?.success && res?.data?.user?.sharedOnX) { + setIsSharedOnX(true); + } else setIsSharedOnX(false); + } catch (error) { + console.error(error); + toast.error('Something went wrong'); + } finally { + setInitialLoading(false); + } + })(); + }, [address]); + + return ( +
+
+
+ STRKFarm +

+ RT our tweet +

+
+ + {}} + > + {loading && ( + + )} + {initialLoading && 'loading...'} + {isSharedOnX && 'completed'} + {!isSharedOnX && !initialLoading && '1 ticket'} + +
+
+ ); +}; + +export default ShareOnX; diff --git a/src/app/raffle/_components/total-tickets.tsx b/src/app/raffle/_components/total-tickets.tsx new file mode 100644 index 00000000..10a20455 --- /dev/null +++ b/src/app/raffle/_components/total-tickets.tsx @@ -0,0 +1,60 @@ +'use client'; + +import { Spinner } from '@chakra-ui/react'; +import { useAccount } from '@starknet-react/core'; +import axios from 'axios'; +import React from 'react'; +import toast from 'react-hot-toast'; + +const TotalTickets: React.FC = () => { + const { address } = useAccount(); + + const [totalTickets, setTotalTickets] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + React.useEffect(() => { + if (!address) return; + + setLoading(true); + setTotalTickets(0); + + (async () => { + try { + const res = await axios.get(`/api/tnc/getUser/${address}`, { + params: { type: 'RAFFLE' }, + }); + + if (res?.data?.success && res?.data?.user?.isRaffleParticipant) { + setTotalTickets((prev) => prev + 1); + console.log('+1'); + } + if (res?.data?.success && res?.data?.user?.sharedOnX) { + setTotalTickets((prev) => prev + 1); + console.log('+1 +1'); + } + if (res?.data?.success && res?.data?.user?.activeDeposits) { + setTotalTickets((prev) => prev + 1); + console.log('+1 +1 +1'); + } + } catch (error) { + console.error(error); + toast.error('Something went wrong', { + position: 'bottom-right', + }); + } finally { + setLoading(false); + } + })(); + }, [address]); + + return ( +

+ Your tickets:{' '} + + {!loading ? totalTickets : } + +

+ ); +}; + +export default TotalTickets; diff --git a/src/app/raffle/page.tsx b/src/app/raffle/page.tsx new file mode 100644 index 00000000..0b23bf95 --- /dev/null +++ b/src/app/raffle/page.tsx @@ -0,0 +1,107 @@ +import { NextPage } from 'next'; +import Image from 'next/image'; +import React from 'react'; + +import ActiveDeposits from './_components/active-deposits'; +import RaffleTimer from './_components/raffle-timer'; +import RegisterRaffle from './_components/register-raffle'; +import ShareOnX from './_components/share-on-x'; +import TotalTickets from './_components/total-tickets'; + +const Raffle: NextPage = () => { + return ( +
+
+
+

+ Devcon raffle +

+

+ Each day, we shall select 3 winners who will receive exclusive merch + during Starkspace (Devcon, Bangkok) +

+ + +
+ + Raffle Hero Image +
+ +
+
+

+ Earn Raffle tickets for every task and increase chances to win +

+ +
+

+ Raffle end's in +

+ +
+
+
+ +
+
+

Tasks

+
+

+ Participate and + + {' '} + get Raffle tickets + +

+ + +
+ +
+ + + + + +
+
+
+ +
+
+ Rules: +
+

+ 1. 3 unique winners will be selected each day +

+

+ 2. You just have to register once and you will be part of each round + automatically +

+

+ 3. You have to register if you want to participate. This mean you or + anyone on your behalf will be available t to collect the merch.{' '} +

+

+ 4. The rewards will be in the form of exclusive merch reserved for you +

+

+ 5. Selected winners can collect their merch on 13th Nov, from The Fig + lobby, Bangkok +

+

+ 6. Winners will be announced on our socials everyday +

+
+
+ ); +}; + +export default Raffle; diff --git a/src/components/Deposit.tsx b/src/components/Deposit.tsx index ea0ce96f..f044a27c 100755 --- a/src/components/Deposit.tsx +++ b/src/components/Deposit.tsx @@ -339,15 +339,6 @@ export default function Deposit(props: DepositProps) { /> - - No additional fees by STRKFarm - - diff --git a/src/components/HarvestTime.tsx b/src/components/HarvestTime.tsx index 7c1b372f..088bbfdd 100644 --- a/src/components/HarvestTime.tsx +++ b/src/components/HarvestTime.tsx @@ -96,17 +96,19 @@ const HarvestTime: React.FC = ({ strategy, balData }) => { - - APY - - {((strategyInfo?.apy || 0) * 100).toFixed(2)}% - - + + + APY + + {((strategyInfo?.apy || 0) * 100).toFixed(2)}% + + + */} - + + + +