From 31b468204f15d70131b59425d463f5ebdf816e79 Mon Sep 17 00:00:00 2001 From: Iamfittz Date: Mon, 6 Apr 2026 12:29:59 +0300 Subject: [PATCH 1/5] ci: add CI workflow, fix README badges and remove quest references --- .github/workflows/ci.yml | 63 +++++++++++++++++++++++++++++++++++ README.md | 5 +++ SKILL.md | 11 +++--- references/contract-detect.md | 4 +-- 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d0a9d51 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + links: + name: Check Links + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Check links in README and SKILL.md + uses: lycheeverse/lychee-action@v2 + with: + args: > + --no-progress + --exclude-loopback + --exclude-mail + --timeout 15 + --retry-wait-time 5 + --max-retries 3 + README.md SKILL.md references/*.md + fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + markdown: + name: Markdown Lint + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Lint markdown files + uses: DavidAnson/markdownlint-cli2-action@v17 + with: + globs: "**/*.md" + config: | + { + "default": true, + "MD013": false, + "MD033": false, + "MD041": false + } + + secrets: + name: Secret Scan (gitleaks) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index caaeee6..8137fef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # UZPROOF Agent Skill +[![npm](https://img.shields.io/npm/v/%40uzproof%2Fverify?label=npm%3A%20%40uzproof%2Fverify)](https://www.npmjs.com/package/@uzproof/verify) +[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) + Agent Skill for verifying real on-chain usage on Solana. Works with [Claude Code](https://claude.ai/code), [Cursor](https://cursor.com), [GitHub Copilot](https://github.com/features/copilot), [Gemini CLI](https://geminicli.com), and [30+ other AI coding agents](https://agentskills.io/). ## What is UZPROOF? @@ -8,6 +11,8 @@ Agent Skill for verifying real on-chain usage on Solana. Works with [Claude Code UZPROOF is also the first Proof-of-Use attestor on the Solana Attestation Service (SAS), creating permanent on-chain records of verified usage. +**On-chain credential:** [`2chgBfvkwhnHQVVAyXKDK6CBjbCRMQ8aLWrysL5UQyyF`](https://explorer.solana.com/address/2chgBfvkwhnHQVVAyXKDK6CBjbCRMQ8aLWrysL5UQyyF) + ## Install ```bash diff --git a/SKILL.md b/SKILL.md index 531d819..0561244 100644 --- a/SKILL.md +++ b/SKILL.md @@ -142,6 +142,7 @@ See [references/attestation.md](references/attestation.md) for SAS integration d ## Action Types ### DeFi Actions + | Type | Verifies | |---|---| | `defi_swap` | Any swap on a supported DEX | @@ -164,6 +165,7 @@ See [references/attestation.md](references/attestation.md) for SAS integration d | `defi_create_lst` | LST creation | ### NFT Actions + | Type | Verifies | |---|---| | `nft_hold` | Owns NFT from collection | @@ -171,6 +173,7 @@ See [references/attestation.md](references/attestation.md) for SAS integration d | `nft_check` | General NFT ownership check | ### Utility Actions + | Type | Verifies | |---|---| | `token_balance` | Raw token balance | @@ -205,10 +208,10 @@ async function checkEligibility(wallet: string): Promise { } ``` -### Quest/Task Verification +### Task Verification ```typescript -async function verifyQuestTask(wallet: string, task: { type: string; config: object }) { +async function verifyTask(wallet: string, task: { type: string; config: object }) { const client = new UzproofClient({ apiKey: process.env.UZPROOF_API_KEY }); const result = await client.verify({ wallet, @@ -231,8 +234,8 @@ const info = await client.detectContract(userProgramId); if (info.detected) { console.log(`Detected: ${info.program.name} (${info.program.category})`); console.log(`Supported verifications: ${info.program.supportedActions.join(', ')}`); - // Use suggested quest template - const template = info.questTemplate; + // Use suggested verification template + const template = info.verificationTemplate; } ``` diff --git a/references/contract-detect.md b/references/contract-detect.md index b6e2b4a..5c96716 100644 --- a/references/contract-detect.md +++ b/references/contract-detect.md @@ -25,7 +25,7 @@ const info = await client.detectContract('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNy "category": "dex", "supportedActions": ["defi_swap", "defi_swap_buy", "defi_swap_sell", "defi_swap_volume"] }, - "questTemplate": { + "verificationTemplate": { "suggestedTitle": "Get started with Jupiter Aggregator v6", "suggestedDescription": "Complete tasks to earn XP and prove your on-chain activity with Jupiter Aggregator v6.", "suggestedTasks": [ @@ -79,7 +79,7 @@ If a program ID is not in the supported list, `detectContract()` returns: { "detected": false, "program": null, - "questTemplate": null + "verificationTemplate": null } ``` From 860bc7c1769c942b6bb8f4f9ad07fa3cd441f761 Mon Sep 17 00:00:00 2001 From: Iamfittz Date: Mon, 6 Apr 2026 13:27:58 +0300 Subject: [PATCH 2/5] fix: fix CI workflow errors --- .github/workflows/ci.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0a9d51..3694246 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,13 +14,12 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Check links in README and SKILL.md + - name: Check links in markdown files uses: lycheeverse/lychee-action@v2 with: args: > --no-progress --exclude-loopback - --exclude-mail --timeout 15 --retry-wait-time 5 --max-retries 3 @@ -36,17 +35,21 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Write markdownlint config + run: | + cat > .markdownlint.json << 'EOF' + { + "default": true, + "MD013": false, + "MD033": false, + "MD041": false + } + EOF + - name: Lint markdown files uses: DavidAnson/markdownlint-cli2-action@v17 with: globs: "**/*.md" - config: | - { - "default": true, - "MD013": false, - "MD033": false, - "MD041": false - } secrets: name: Secret Scan (gitleaks) @@ -61,3 +64,4 @@ jobs: uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} From b0645316550a9d76e24f2e32657bd4324c711a39 Mon Sep 17 00:00:00 2001 From: Iamfittz Date: Mon, 6 Apr 2026 13:31:30 +0300 Subject: [PATCH 3/5] fix: blank lines in SKILL.md, accept 403 in lychee, remove gitleaks --- .github/workflows/ci.yml | 16 +--------------- SKILL.md | 5 +++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3694246..f1c00c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ jobs: args: > --no-progress --exclude-loopback + --accept 200,403,429 --timeout 15 --retry-wait-time 5 --max-retries 3 @@ -50,18 +51,3 @@ jobs: uses: DavidAnson/markdownlint-cli2-action@v17 with: globs: "**/*.md" - - secrets: - name: Secret Scan (gitleaks) - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Run gitleaks - uses: gitleaks/gitleaks-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} diff --git a/SKILL.md b/SKILL.md index 76683f6..dcd5829 100644 --- a/SKILL.md +++ b/SKILL.md @@ -14,6 +14,7 @@ You are building with UZPROOF, the first Proof-of-Use verification layer on Sola ## Use / Do Not Use **Use when:** + - Verifying a wallet performed a specific on-chain action (swap, stake, hold, mint) - Building reward distribution that requires proof of real usage - Gating access to features based on on-chain behavior @@ -23,6 +24,7 @@ You are building with UZPROOF, the first Proof-of-Use verification layer on Sola - Fetching token metadata and live prices **Do not use when:** + - Executing transactions (use Jupiter, Drift, etc. for that) - Reading raw transaction data (use Helius for that) - Building wallets or signing transactions @@ -234,7 +236,6 @@ const info = await client.detectContract(userProgramId); if (info.detected) { console.log(`Detected: ${info.program.name} (${info.program.category})`); console.log(`Supported verifications: ${info.program.supportedActions.join(', ')}`); - // Use suggested verification template const template = info.verificationTemplate; } ``` @@ -268,7 +269,7 @@ import { SAS_PROGRAM_ID, UZPROOF_CREDENTIAL, POU_SCHEMA, ACTION_TYPES, SUPPORTED SAS_PROGRAM_ID // "22zoJMtdu4tQc2PzL74ZUT7FrwgB1Udec8DdW4yw4BdG" UZPROOF_CREDENTIAL // "2chgBfvkwhnHQVVAyXKDK6CBjbCRMQ8aLWrysL5UQyyF" -POU_SCHEMA // "8yW2BboQuhp2MMmrQLFz35V6VSqC48MF7wZ5bmzcTeTF" +POU_SCHEMA // "9FQiiMtroSHP2Ewqfh3D94GPKnDjmeLT2ftqJ3E7QyWc" ACTION_TYPES // All 24 supported action types SUPPORTED_PROTOCOLS // 14 protocol names ``` From 01d9d9b57b92d3ed4a34bdb3647dd25ea1e1b161 Mon Sep 17 00:00:00 2001 From: Iamfittz Date: Mon, 6 Apr 2026 13:35:27 +0300 Subject: [PATCH 4/5] docs: add anti-fraud reference with real signal documentation --- references/anti-fraud.md | 148 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 references/anti-fraud.md diff --git a/references/anti-fraud.md b/references/anti-fraud.md new file mode 100644 index 0000000..d3c931f --- /dev/null +++ b/references/anti-fraud.md @@ -0,0 +1,148 @@ +# Anti-Fraud Scoring + +## Overview + +Every verification request in UZPROOF runs an anti-fraud check alongside the on-chain data lookup. The check produces a **risk score (0–100)** based on suspicious signals detected on the wallet. It does not block requests — it flags them for review. + +The result is returned alongside verification data so your application can decide how to handle high-risk wallets. + +## Risk Score + +```typescript +const result = await client.verify({ + wallet: '7H4RVL...', + action: 'defi_swap', + config: { program_id: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4' } +}); + +// result.riskScore = 0–100 +// result.signals = array of detected signals +// result.verified = true/false (on-chain result, unaffected by risk score) +``` + +A score of `0` means no suspicious signals. A score of `100` means maximum risk. + +## Signals + +### 1. `no_history` — No Transaction History (severity: high, +30) + +The wallet has zero recorded transactions on-chain. + +``` +Wallet has zero transaction history +``` + +Fresh wallets with no history are a strong indicator of sybil accounts created purely to farm rewards. + +### 2. `low_tx_count` — Low Transaction Count (severity: medium, +15) + +The wallet has fewer than 5 transactions total. + +``` +Only 2 transactions (min: 5) +``` + +Legitimate DeFi users accumulate transactions naturally. Very low counts suggest a wallet created for a single purpose. + +### 3. `new_wallet` — Recently Created Wallet (severity: high, +30) + +The wallet's oldest transaction is less than 3 days ago. + +``` +Wallet is only 1.2 days old (min: 3) +``` + +New wallets are a classic sybil pattern — attackers spin up fresh addresses in bulk before a campaign launches. + +### 4. `dust_balance` — Near-Zero SOL Balance (severity: medium, +15) + +The wallet holds less than 0.01 SOL. + +``` +SOL balance: 0.0021 SOL (below 0.01 SOL threshold) +``` + +Real users need SOL for gas. Dust balances indicate a funded-just-enough-to-transact sybil wallet. + +### 5. `fast_completion` — Instant Verification (severity: high, +30) + +The wallet was verified less than 10 seconds after the verification flow started. + +``` +Verified 3s after start (min: 10s) +``` + +Automated bots complete verifications near-instantly. Humans take longer to read instructions and connect wallets. + +## Risk Score Calculation + +Scores are additive and capped at 100: + +| Severity | Score Added | +|---|---| +| `low` | +5 | +| `medium` | +15 | +| `high` | +30 | +| `critical` | +50 | + +**Example:** A wallet that is 1 day old (`new_wallet`: +30) and has 2 transactions (`low_tx_count`: +15) gets a risk score of **45**. + +## Using Risk Score in Your Application + +```typescript +const client = new UzproofClient({ apiKey: process.env.UZPROOF_API_KEY }); + +const result = await client.verify({ + wallet, + action: 'defi_swap', + config: { program_id: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4' } +}); + +if (!result.verified) { + // On-chain action not found + return { eligible: false, reason: 'action_not_verified' }; +} + +if (result.riskScore >= 60) { + // High risk — flag for manual review or block + return { eligible: false, reason: 'high_fraud_risk', score: result.riskScore }; +} + +if (result.riskScore >= 30) { + // Medium risk — allow but mark as suspicious + return { eligible: true, flagged: true, score: result.riskScore }; +} + +// Clean wallet, verified action +return { eligible: true, flagged: false }; +``` + +## Recommended Thresholds + +| Risk Score | Suggested Action | +|---|---| +| 0–29 | Allow | +| 30–59 | Allow with flag / extra review | +| 60–100 | Block or require manual review | + +Thresholds depend on your campaign's risk tolerance. Airdrops with large rewards should use stricter thresholds than loyalty programs. + +## Signal Response Format + +```typescript +// result.signals example +[ + { + signalType: 'new_wallet', + severity: 'high', + details: 'Wallet is only 1.2 days old (min: 3)', + value: 1.2 + }, + { + signalType: 'low_tx_count', + severity: 'medium', + details: 'Only 2 transactions (min: 5)', + value: 2 + } +] +``` From a291b16a0c131ae7a2f12eca170cb4b06cab40b9 Mon Sep 17 00:00:00 2001 From: Iamfittz Date: Mon, 6 Apr 2026 13:37:22 +0300 Subject: [PATCH 5/5] fix: add language to fenced code blocks in anti-fraud.md --- references/anti-fraud.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/references/anti-fraud.md b/references/anti-fraud.md index d3c931f..8f3d889 100644 --- a/references/anti-fraud.md +++ b/references/anti-fraud.md @@ -28,7 +28,7 @@ A score of `0` means no suspicious signals. A score of `100` means maximum risk. The wallet has zero recorded transactions on-chain. -``` +```text Wallet has zero transaction history ``` @@ -38,7 +38,7 @@ Fresh wallets with no history are a strong indicator of sybil accounts created p The wallet has fewer than 5 transactions total. -``` +```text Only 2 transactions (min: 5) ``` @@ -48,7 +48,7 @@ Legitimate DeFi users accumulate transactions naturally. Very low counts suggest The wallet's oldest transaction is less than 3 days ago. -``` +```text Wallet is only 1.2 days old (min: 3) ``` @@ -58,7 +58,7 @@ New wallets are a classic sybil pattern — attackers spin up fresh addresses in The wallet holds less than 0.01 SOL. -``` +```text SOL balance: 0.0021 SOL (below 0.01 SOL threshold) ``` @@ -68,7 +68,7 @@ Real users need SOL for gas. Dust balances indicate a funded-just-enough-to-tran The wallet was verified less than 10 seconds after the verification flow started. -``` +```text Verified 3s after start (min: 10s) ```