From ca5872c518507666cbf2ea6bd24b68143ec802f3 Mon Sep 17 00:00:00 2001 From: Sebastian Anioke Date: Wed, 26 Aug 2026 05:32:41 +0100 Subject: [PATCH 1/2] ci: redirect PRs targeting main to dev --- .github/workflows/pr-target-check.yml | 56 ++++++++++++--------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/.github/workflows/pr-target-check.yml b/.github/workflows/pr-target-check.yml index 3ac6108c..18af621f 100644 --- a/.github/workflows/pr-target-check.yml +++ b/.github/workflows/pr-target-check.yml @@ -1,35 +1,29 @@ -name: PR Target Check +name: Redirect PRs to dev on: - pull_request_target: - branches: - - main + pull_request_target: + branches: + - main jobs: - warn-wrong-target: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: Comment and close PR targeting main - uses: actions/github-script@v7 - with: - script: | - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: `👋 Hey @${context.payload.pull_request.user.login}, thanks for your contribution!\n\n` + - `This PR is targeting \`main\` directly. We use \`main\` for stable releases only — ` + - `all contributions should be opened against the \`dev\` branch instead.\n\n` + - `**Please close this PR and reopen it with \`dev\` as the base branch.** ` + - `If you're unsure how to do that, you can change the base branch using the *Edit* button at the top of this PR page.\n\n` + - `Closing this PR automatically. See you in \`dev\`! 🚀` - }); - - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number, - state: 'closed' - }); + close-and-redirect: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Close PR and redirect to dev + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: "👋 Thanks for your contribution! We don't accept pull requests directly to `main`. Please re-open your PR targeting the `dev` branch instead. See our contributing guide for details." + }); + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + state: 'closed' + }); From fe7dc3a13fe70cab70bb129912ceb509471de50d Mon Sep 17 00:00:00 2001 From: meloball Date: Thu, 27 Aug 2026 13:59:20 +0100 Subject: [PATCH 2/2] fix: all issues fixed --- .gitignore | 5 +- src/components/common/AirdropPanel.tsx | 136 ++++++++++++++++++ src/components/common/AuctionPhaseBanner.tsx | 42 ++++++ src/components/common/GlobalPauseBanner.tsx | 34 +++++ src/hooks/useGlobalPause.ts | 41 ++++++ src/utils/__tests__/airdropValidation.test.ts | 83 +++++++++++ src/utils/airdropValidation.ts | 63 ++++++++ 7 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 src/components/common/AirdropPanel.tsx create mode 100644 src/components/common/AuctionPhaseBanner.tsx create mode 100644 src/components/common/GlobalPauseBanner.tsx create mode 100644 src/hooks/useGlobalPause.ts create mode 100644 src/utils/__tests__/airdropValidation.test.ts create mode 100644 src/utils/airdropValidation.ts diff --git a/.gitignore b/.gitignore index d4f78a58..022aac77 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ dist-ssr *.sln *.sw? issue.md -pr.md \ No newline at end of file +pr.md + +# MiMoCode +.mimocode/ \ No newline at end of file diff --git a/src/components/common/AirdropPanel.tsx b/src/components/common/AirdropPanel.tsx new file mode 100644 index 00000000..4abc7047 --- /dev/null +++ b/src/components/common/AirdropPanel.tsx @@ -0,0 +1,136 @@ +import { useMemo, useState } from 'react'; +import { Button } from '@/components/ui/button'; +import showToast from '@/utils/toast.util'; +import { + parseAirdropInput, + validateAirdropRecipients, + type AirdropRecipient, +} from '@/utils/airdropValidation'; + +const MAX_RECIPIENTS = 50; + +const AirdropPanel: React.FC = () => { + const [rawInput, setRawInput] = useState(''); + const [submitted, setSubmitted] = useState(false); + + const recipients: AirdropRecipient[] = useMemo( + () => parseAirdropInput(rawInput), + [rawInput] + ); + + const errors = useMemo( + () => validateAirdropRecipients(recipients), + [recipients] + ); + + const hasLimitError = errors.some(e => e.rowIndex === -1); + const rowErrors = errors.filter(e => e.rowIndex >= 0); + const rowErrorMap = new Map(rowErrors.map(e => [e.rowIndex, e.message])); + const totalKeys = recipients.reduce((sum, r) => sum + r.quantity, 0); + const canSubmit = + recipients.length > 0 && + recipients.length <= MAX_RECIPIENTS && + rowErrors.length === 0; + + const handleSubmit = () => { + if (!canSubmit) return; + setSubmitted(true); + showToast.transactionSuccess( + 'Airdrop submitted', + `${totalKeys} keys distributed to ${recipients.length} recipients.` + ); + }; + + const handleFileUpload = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + const reader = new FileReader(); + reader.onload = () => { + setRawInput(String(reader.result ?? '')); + }; + reader.readAsText(file); + }; + + return ( +
+

+ Airdrop Keys +

+

+ Paste wallet:quantity pairs (one per line) or upload a CSV. Up to{' '} + {MAX_RECIPIENTS} recipients. +

+ +