Skip to main content
guide12 min read

Contributing Guide

How to add new wallets and contribute to the comparison

Summary: How to add new wallets and contribute to the comparison

Share:

Keep the tables accurate and sourced. Tables are the source of truth.

Software Wallets (EVM)

Hardware Wallets (Cold Storage)

Crypto Cards

Ramps (On/Off-Ramp Providers)


Score Sync Workflow

Scores and recommendation cells are generated from the visible table columns. Do not hand-edit the score cells unless you are also changing the underlying data.

Run this after any change to the comparison tables:

bun scripts/sync_table_scores.js --write
cd frontend
bun test

What this does:

  1. Recomputes Score and recommendation cells for software wallets, hardware wallets, cards, and ramps.
  2. Sorts rows by computed score.
  3. Refreshes the generated snapshot blocks near the top of the matching *_DETAILS.md files.
  4. Fails the frontend smoke test if the markdown tables drift from the generated output.

Current methodology version: 2026-04-visible-columns-v3 (SCORING_METHODOLOGY_VERSION in frontend/src/lib/scoring.js).

How the Rec mark is set

The Rec mark is a rank band, not a fixed score cutoff. assignRecommendationBands in frontend/src/lib/scoring.js sets it per table every time the sync script or the site build runs:

  1. Inactive rows are 🔴 Avoid, whatever their score.
  2. Software wallets only: a row with Core not full, or Developer Safety & Control of 10 or less, is ⚪ Not for dev.
  3. The remaining rows (N of them) are sorted by score, lowest first. The bottom floor(N × 0.25) are 🔴 Avoid, the rows up to floor(N × 0.5) are 🟡 Situational, and the rest are 🟢 Recommended. Rows with equal scores keep their table order, so the cutoffs are rounded down and ties are not split by any other rule.
  4. A row with status "launching" cannot be 🟢. It is capped at 🟡.

So the same score can land in different bands in different tables, and in the same table after other rows change. Never write a Rec by hand.

Adding a New Software Wallet

Prerequisites

Before adding a wallet, verify:

  1. ✅ It's an EVM-compatible wallet (Ethereum, Polygon, Arbitrum, etc.)
  2. ✅ It has been publicly released (not alpha/private beta)
  3. ✅ It has a GitHub repo OR is a well-known proprietary wallet

Step 1: Gather Required Data

ColumnHow to Verify
ScoreGenerated from the visible columns after sync
GitHubFind the main wallet repo (not SDK/packages)
ActiveCheck last commit date on default branch
ChainsCount from official docs or registry files
DevicesCheck app stores + Chrome Web Store
TestnetsCheck if custom RPC/chains can be added
LicenseRead LICENSE file in repo root
AuditsSearch repo for /audits folder or security page
FundingResearch company backing, funding rounds
Tx SimTest wallet or check WalletBeat
ScamTest wallet or check WalletBeat
Account TypeEOA, Safe, EIP-4337, or EIP-7702
HW WalletsCheck settings for Ledger/Trezor support
EIP-4337Check if smart account creation is supported
Best ForYour assessment of ideal use case
RecGenerated from the computed score and activity status

Step 2: Fill The Scoring Inputs

Software wallet scores are generated from the visible columns in frontend/src/lib/scoring.js. The current categories are:

Core Readiness
Release Discipline
Developer Safety & Control
Ecosystem & Accounts
Transparency & Access
Maintenance & Assurance

If you want to change the formula, update the scoring code first, then rerun the sync script.

Step 3: Add to Main Table

Add your row to data/tables/SOFTWARE_WALLETS.md. Ordering does not need to be perfect before sync because the score script will sort rows automatically.

| **WalletName** | XX | [repo](https://github.com/org/repo) | ✅ | 50+ | 📱🌐 | ✅ | ✅ MIT | ✅ 2024 | 🟢 Company | ✅ | ✅ | EOA | ✅ Multiple | ❌ | Use Case | 🟢 |

Step 4: Update Other Sections

If applicable, also update:

  • Scoring table (if in top 10)
  • Security Audits table (if audited)
  • Account Type Support table
  • Hardware Wallet Support table
  • ENS & Address Resolution table
  • Browser Integration table
  • Monetization table
  • Privacy & Data Collection table

Adding a New Hardware Wallet

Prerequisites

Before adding a hardware wallet, verify:

  1. ✅ It's an actual hardware device (not software/mobile wallet)
  2. ✅ It's commercially available (not crowdfunding/prototype)
  3. ✅ It stores private keys on device (true cold storage)

Step 1: Gather Required Data

ColumnHow to Verify
ScoreGenerated from the visible columns after sync (see hardware wallet scoring)
Air-GapCheck if device requires USB/BT connection during signing
Open SourceFind firmware repo on GitHub; verify it's actual firmware, not just SDK
Secure ElementCheck official specs for SE chip (e.g., ATECC608, Optiga)
DisplayScreen type, size, touch capability
ChainsCount from official supported assets list
PriceCheck official store (not Amazon/resellers)
ConnectivityUSB, Bluetooth, QR, NFC, MicroSD, WiFi
CompanyResearch company background, funding, location

Hardware Wallet Scoring

Hardware scores are generated by computeHardwareScore in frontend/src/lib/scoring.js from the visible columns. Do not calculate them by hand. The categories and their maximum points (100 in total):

Security Architecture        34
Transparency & Maintenance   28
Usability & Value            32
Company Track Record          6

The Founded and Funding columns feed Company Track Record, and the Price column feeds Usability & Value. The Rec mark follows the rank bands. If you want to change the formula, update the scoring code first, then rerun the sync script.

Step 2: Add to Main Table

Add your row to data/tables/HARDWARE_WALLETS.md in score order:

| [**WalletName**](https://example.com/) | 0 | [firmware](https://github.com/org/repo) | ✅/❌ | ✅/⚠️/❌ | ✅/❌ SE Type | Display | ~$XXX | Conn | ✅/⚠️/❌/🔒 | YYYY | 🟢/🟡/🔴 Source | 🔴 |

Notes:

  • Founded and Funding are now required hardware scoring inputs.
  • Keep placeholder score/recommendation (0 / 🔴) and run bun scripts/sync_table_scores.js --write.

Step 3: Update Other Sections

If applicable, also update:

  • Scoring breakdown table
  • GitHub Metrics table (if open source)
  • Security Features table
  • Funding section
  • Known Quirks section
  • Software integration tables
  • Changelog — Add entry to CHANGELOG.md

Step 4: Run Verification

cd scripts
./refresh-hardware-wallet-data.sh --markdown

Adding a New Ramp Provider

Prerequisites

Before adding a ramp provider, verify:

  1. ✅ It's a legitimate on-ramp and/or off-ramp service (not just a wallet feature)
  2. ✅ It's publicly available (not private/enterprise-only without public docs)
  3. ✅ It has developer documentation or API/SDK available

Step 1: Gather Required Data

ColumnHow to Verify
ScoreGenerated from the visible columns after sync (see ramp scoring)
TypeBoth, On-Ramp only, or Off-Ramp only
On-Ramp✅ if supports fiat → crypto, ❌ otherwise
Off-Ramp✅ if supports crypto → fiat, ❌ otherwise
CoverageCheck official docs for supported countries/regions
Fee ModelCheck pricing page or API docs
Min FeeCheck pricing page (use ~ prefix if approximate)
Dev UXCheck developer docs (SDK, Widget, API)
Status✅ Active, ⚠️ Verify (needs verification), 🚧 Launching
Best ForYour assessment of ideal use case
RecGenerated by the rank bands (see How the Rec mark is set)
URLOfficial website URL

Ramp Scoring

Ramp scores are generated by computeRampScore in frontend/src/lib/scoring.js from the visible columns. Do not calculate them by hand. The categories and their maximum points (100 in total):

Coverage                 25
Product Breadth          15
Developer UX             18
Pricing Shape            25
Operational Confidence   15
Company Track Record      2

Operational Confidence comes from the Status column: 15 for active, 9 for verify, 5 for launching, 0 otherwise. Pricing Shape adds the Fee Model and Min Fee points. The Rec mark follows the rank bands. Inactive and launching rows are handled by the band rules.

Step 2: Add to Main Table

Add your row to data/tables/RAMPS.md in score order (highest first):

| [**ProviderName**](https://provider.com/) | XX 🟢 | Both | ✅ | ✅ | ~160+ Countries | Medium | ~$5.00 | Excellent (React SDK) | ✅ | Developers |

Important: Use markdown link format [**Name**](url) for provider name to enable clickable links.

Step 3: Update Other Sections

If applicable, also update:

  • Provider-Specific Notes section
  • Fee Analysis section
  • Developer Experience section
  • Changelog — Add entry to CHANGELOG.md

Step 4: Frontend Integration

When adding a new comparison type (like ramps), you must update:

4a. Type Definitions (frontend/src/types/wallets.ts)

  • Add interface (e.g., Ramp) with all required fields including url: string | null
  • Add to WalletData union type

4b. Data Parsing (frontend/src/lib/wallet-data.ts)

  • Add parsing function (e.g., parseRamps())
  • Extract name and URL from markdown links: [**Name**](url)
  • Add to getAllWalletData() return object
  • Export parsing function

4c. Filtering (frontend/src/lib/wallet-filtering.ts)

  • Add filtering function (e.g., filterRamps())
  • Map status types correctly if different from filter types
  • Export filtering function
  • Add to wallet-data.ts exports

4d. Components

  • WalletTable.tsx: Add item component (e.g., RampItem) for table/grid views
  • ComparisonTool.tsx: Add comparison component (e.g., RampComparison)
  • WalletFilters.tsx: Add filter options if needed
  • ExploreContent.tsx: Add tab, state management, filtering

4e. Pages

  • explore/page.tsx: Call parsing function, pass to ExploreContent
  • docs/[slug]/page.tsx: Add to isTablePage check
  • sitemap.ts: Add to isComparisonTable check

4f. Navigation (See Rule #127)

  • Navigation.tsx: Add to burger menu
  • Footer.tsx: Add to Comparisons section
  • InternalLinks.tsx: Add card to FeaturedCategoryLinks
  • page.tsx: Add to hero section, stats section, Top Developer Picks

4g. SEO (frontend/src/lib/seo.ts)

  • Add OG image mappings for table and details pages
  • Add keyword detection for new type (e.g., ramp-specific keywords)
  • Update ItemList schema to handle new type correctly

4h. OG Images (frontend/scripts/generate-og-images.js)

  • Add data to WALLET_DATA object
  • Create generator function for table image
  • Create generator function for details image
  • Add to main() function
  • Run bun run generate-og and commit PNGs
  • Update CI workflow to check for new images

4i. Markdown Config (frontend/src/lib/markdown.ts)

  • Add file to DOCUMENT_CONFIG
  • Add to relatedMap for table/details navigation

Step 5: Verification

cd frontend
bun run type-check  # Verify TypeScript
bun run lint        # Verify linting
bun run build       # Verify build
bun run generate-og # Regenerate OG images

Adding a New Crypto Card

See existing data/tables/CRYPTO_CARDS.md for card-specific guidelines. Follow similar pattern to software/hardware wallets.


Updating Existing Data

Activity Status Updates

For Software Wallets:

cd scripts
./refresh-github-data.sh --markdown

For Hardware Wallets:

cd scripts
./refresh-hardware-wallet-data.sh --markdown

If a wallet's status changes, update:

  1. Main table Active column (or strikethrough if abandoned)
  2. GitHub Metrics table
  3. Recalculate score if needed
  4. Add changelog entry to CHANGELOG.md

Audit Updates

When a wallet publishes a new audit:

  1. Update Audits column in main table
  2. Update Security Audits section
  3. Recalculate score if applicable
  4. Add changelog entry to CHANGELOG.md

Verification Standards

What Requires Verification

ClaimVerification Method
LicenseRead LICENSE file in repo
ActivityCheck last commit via GitHub API
Chain countOfficial docs or registry file
AuditLink to audit report
FundingPress releases, Crunchbase, etc.
Ramp coverageOfficial docs or API documentation
Ramp feesPricing page or API docs

What Doesn't Require Verification

  • Feature claims from official docs (trust but verify when possible)
  • WalletBeat data (already verified)
  • GitHub stars/issues (automated)

Pull Request Template

Use this template for your PR:

## New [Wallet/Card/Ramp]: [Name]

### Data Sources
- GitHub: [link] (if applicable)
- Official docs: [link]
- WalletBeat: [link if available]

### Verification
- [x] GitHub repo verified (if applicable)
- [x] Last commit date checked: YYYY-MM-DD (if applicable)
- [x] License verified: [LICENSE] (if applicable)
- [x] Chain count verified: [N] chains (if applicable)
- [x] Score calculated: XX/100

### Score Breakdown
- [Component 1]: XX/pts
- [Component 2]: XX/pts
- **Total: XX/100**

### Changes
- Added row to main comparison table
- Added to [list other sections updated]
- Updated [CHANGELOG.md](./CHANGELOG.md)
- Updated frontend (if new comparison type)

Renaming Files or Changing URLs

⚠️ IMPORTANT: Changing file names or URL slugs requires updates across the whole codebase. Follow this checklist to avoid breaking links and SEO.

When to Rename

Only rename files/URLs if:

  • URLs are too long or unclear (e.g., wallet-comparison-unified-table → software-wallets)
  • File names don't match the URL pattern
  • You're consolidating multiple files into a clearer structure

File Naming Convention

Comparison pages follow this pattern:

  • Table view: CATEGORY.md → /docs/category (e.g., data/tables/SOFTWARE_WALLETS.md → /docs/software-wallets)
  • Details view: CATEGORY_DETAILS.md renders inside the category page at /docs/category/#details (e.g., data/tables/SOFTWARE_WALLETS_DETAILS.md → /docs/software-wallets/#details)

Slug generation formula: filename.replace('.md', '').toLowerCase().replace(/_/g, '-')

Rename Checklist

When renaming files or changing URL patterns, you MUST update:

1. File System

  • Rename markdown files
  • Verify files exist in correct location

2. Frontend Configuration (frontend/src/lib/markdown.ts)

  • Update DOCUMENT_CONFIG with new file names
  • Verify slug generation matches expected URLs
  • Update relatedMap in getRelatedDocument() function
  • Update getWalletStats() function if it references specific slugs

3. SEO & Metadata (frontend/src/lib/seo.ts)

  • Update getOgImagePath() mapping for new slugs
  • Verify OG image paths are correct
  • Check that image files exist in public/ directory
  • Add keyword detection if needed

4. Frontend Components

  • Update Navigation.tsx nav items
  • Update Footer.tsx links
  • Update InternalLinks.tsx (FeaturedCategoryLinks)
  • Update page.tsx (homepage links and structured data)
  • Update any page-specific links (e.g., companies/page.tsx)

5. Page Logic (frontend/src/app/docs/[slug]/page.tsx)

  • Update table/details detection logic
  • Verify isTablePage and isDetailsPage detection
  • Update RelatedDocuments component logic if needed
  • Update ItemList schema to handle new type correctly

6. Sitemap (frontend/src/app/sitemap.ts)

  • Update isComparisonTable detection logic
  • Verify priority logic still works correctly

7. Data Parsers (frontend/src/lib/wallet-data.ts)

  • Update file paths in parsing functions
  • Update any comments referencing old file names

8. Scripts

  • Update scripts/generate-og-images.js file references and comments
  • Update scripts/smoke-test-wallet-data.js file paths
  • Verify any other scripts that reference file names

9. Documentation

  • Update frontend/README.md file mapping table
  • Update README.md (root) file references
  • Update internal markdown links in comparison files
  • Update CONTRIBUTING.md if it references specific files

10. Verification

  • Run verification script to check file existence
  • Verify slug generation produces expected URLs
  • Test related document mapping (table ↔ details)
  • Check for any remaining old references: rg -n "old-name" frontend/
  • Verify no broken internal links in markdown files
  • Run bun run type-check, bun run lint, bun run build

SEO Considerations

When changing URLs, be aware:

  1. Broken External Links: Old URLs will 404 unless you add redirects

    • Consider adding Next.js redirects in next.config.js if URLs are public-facing
    • Update any social media posts or external documentation
  2. OG Images: Social media caches OG images

    • Increment ogImageVersion in layout.tsx when regenerating images
    • Verify OG image paths match new slugs
  3. Sitemap: Search engines need updated sitemap

    • Sitemap auto-generates from getAllDocuments(), so it updates automatically
    • Verify sitemap priorities are correct for new naming pattern
  4. Structured Data: Schema.org markup includes URLs

    • Verify structured data URLs in page.tsx match new slugs
    • Check breadcrumb and article schema URLs

Example: Complete Rename Workflow

# 1. Rename files
mv OLD_NAME.md NEW_NAME.md
mv OLD_NAME_DETAILS.md NEW_NAME_DETAILS.md

# 2. Update frontend config
# Edit frontend/src/lib/markdown.ts: DOCUMENT_CONFIG

# 3. Update all references
# Edit: seo.ts, Navigation.tsx, Footer.tsx, etc.

# 4. Verify
cd frontend
bun run type-check
bun run lint
bun run build

Testing After Rename

  1. Build check: cd frontend && bun run build
  2. Type check: cd frontend && bun run type-check
  3. Lint check: cd frontend && bun run lint
  4. Smoke test: cd frontend && bun run test
  5. Manual verification: Check that all URLs load correctly

Adding a New Comparison Type

See docs/ADDING_A_CATEGORY.md for the checklist. For card re-verification passes see docs/CARD_RESWEEP_RUNBOOK.md.


Questions?

Open an issue if you're unsure about:

  • How to classify a wallet's license
  • What activity status to assign
  • How to score a particular feature
  • How to rename files without breaking links
  • How to add a new comparison type

We're happy to help!