Skip to content

[T2.4a] Build lib/airdrop/siwe-verify.ts (full EIP-4361 validation) #1240

Description

@realproject7

Epic: #1229 · Spec: §3.1, §6.3 · Type: CODE · Estimate: 0.3 day · Depends on: T2.1

Scope

(0) Install siwe npm package (RE1 round-23 — not yet in package.json)

npm install siwe@^2
  • Verify siwe appears in package.json dependencies + package-lock.json updated
  • Spec uses EIP-4361 + ENS resolution from siwe@2.x (compatible with viem@2.x / wagmi@2.x / next@16 confirmed by main-app risk audit)
  • Lockfile change committed

(1) Build lib/airdrop/siwe-verify.ts

Create the lib using the installed siwe package. This is the auth foundation for ALL signed airdrop endpoints (activation + referral mutation).

```ts
export async function verifySiweRequest(
message: string,
signature: string
): Promise<
| { ok: true; address: string }
| { ok: false; error: string }

```

Validates the FULL EIP-4361 envelope:

  • Signature recovers to claimed address
  • Domain matches SIWE_DOMAIN (plotlink.xyz)
  • URI matches SIWE_URI (https://plotlink.xyz/airdrop)
  • Chain ID matches SIWE_CHAIN_ID (8453)
  • Statement matches SIWE_STATEMENT (PlotLink Buy-Back Sprint activation)
  • expirationTime has not passed
  • issuedAt is within SIGNATURE_FRESHNESS_MIN (10 min) of server time

Uses SiweMessage(message).verify({ signature, domain, ... }) per the siwe package API.

Replaces v1's lib/airdrop/verify-wallet.ts (verifyWalletOwnership) for ALL signed v5 endpoints (activation 5 + referral 2). v1 file is NOT modified — kept for legacy/deprecated endpoint compat until post-launch cleanup PR.

Acceptance

  • Valid signature within 10 min freshness → { ok: true, address }
  • Signature older than 10 min → { ok: false, error: 'expired' }
  • Wrong domain / URI / chainId / statement → { ok: false, error: '...' }
  • Bad signature → { ok: false, error: 'invalid_signature' }
  • Unit tests cover all rejection paths — including tests that exercise the siwe package (new SiweMessage(...).verify(...))
  • siwe in package.json dependencies + lockfile committed
  • npm run typecheck passes (siwe types resolve)
  • No DB writes (pure verification lib)

Dependencies

T2.1 (config provides SIWE_DOMAIN/SIWE_URI/etc.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    airdropPLOT 10x Airdrop Campaign

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions