Skip to content

NFT gallery (Soroban CAP-46) - #600

Open
attyolu wants to merge 5 commits into
Miracle656:mainfrom
attyolu:NFT-gallery
Open

NFT gallery (Soroban CAP-46)#600
attyolu wants to merge 5 commits into
Miracle656:mainfrom
attyolu:NFT-gallery

Conversation

@attyolu

@attyolu attyolu commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

##closes #349

## Summary

Closes #349. Implements the `/nfts` gallery route in `frontend/wallet` to detect, filter, and render Soroban CAP-46 non-fungible tokens held by the connected wallet.

## Key Changes

### 1. NFT Gating & Correctness Rules (`frontend/wallet/lib/nfts.ts`)
- **Fixture Gating**: Fixture NFTs are strictly gated behind an explicit opt-in (`NEXT_PUBLIC_NFT_FIXTURES=1` or `includeFixtures: true`). They are **never** rendered in production or used as a fallback for empty results or network errors.
- **Owner Preservation**: Item owner addresses are never mutated or rewritten to the connected wallet address.
- **Indexer Endpoint**: Configured `NEXT_PUBLIC_WRAITH_URL` (or `NEXT_PUBLIC_INDEXER_URL`) as the base URL, defaulting to `https://wraith-0jo1.onrender.com`.

### 2. Gallery UI & Distinct States (`frontend/wallet/app/nfts/page.tsx`)
- **Real CAP-46 Render**: Displays real on-chain CAP-46 NFTs held by the wallet.
- **Empty State**: Renders a dedicated empty state banner when the wallet holds 0 CAP-46 tokens.
- **Distinct Error State**: Renders an error card displaying failure details and a working **Retry Fetching** button when indexer API requests fail.
- **Dev Controls**: Added quick test toggles for verifying empty and error UI states.

### 3. Environment Variables & Documentation (`.env.example`)
- Documented `NEXT_PUBLIC_WRAITH_URL` and `NEXT_PUBLIC_NFT_FIXTURES` in `frontend/wallet/.env.example` and root `.env.example`.

### 4. Unit Test Suite (`frontend/wallet/lib/__tests__/nfts.test.ts`)
- Added tests for fixture gating, error throwing on fetch failure, owner non-mutation, CAP-46 transfer filtering, and empty state returns.

---

## Acceptance Criteria Verification

- [x] **Renders real CAP-46 NFTs held by the connected wallet**: Queries Wraith indexer `/transfers/address/:address` and filters CAP-46 contracts.
- [x] **Fixture NFTs gated**: Gated behind `NEXT_PUBLIC_NFT_FIXTURES=1` / `includeFixtures: true`. Never rendered as a fallback.
- [x] **Wallet holds no NFTs → real empty state**: Returns `[]` and displays empty state UI.
- [x] **Fetch fails → distinct error state with retry**: Throws error on HTTP failure and renders distinct error card with Retry button.
- [x] **Indexer base URL comes from env var**: Configured `NEXT_PUBLIC_WRAITH_URL`, documented in `.env.example`.
- [x] **No fabricated holdings / owner rewriting**: Owner property preserved as true on-chain owner or fixture owner.

---

## Test Plan

Run Jest unit tests in `frontend/wallet`:
```bash
npm test frontend/wallet/lib/__tests__/nfts.test.ts
PASS lib/__tests__/nfts.test.ts
  Soroban CAP-46 NFT Module
    FIXTURE_NFTS
      ✓ contains at least one fixture NFT (2 ms)
      ✓ each fixture has required CAP-46 fields (name, image, attributes, standard) (2 ms)
    truncateAddress
      ✓ truncates a long Soroban contract address correctly
      ✓ returns short addresses unchanged (1 ms)
    formatTokenId
      ✓ formats numeric token IDs with leading hash
      ✓ handles string token IDs correctly
    fetchWalletNFTs
      ✓ throws error when indexer fetch fails and fixtures are not enabled (10 ms)
      ✓ returns fixture NFTs when includeFixtures is explicitly true
      ✓ never overwrites fixture owner with connected wallet address
      ✓ filters CAP-46 transfers when Wraith responds with token transfers
      ✓ returns empty list if includeFixtures is false and no on-chain NFTs exist (Empty State test) (1 ms)

Test Suites: 1 passed, 1 total
Tests:       11 passed, 11 total


## Summary
<!-- What does this PR change and why? -->

## Related issue
<!-- Closes #123 -->

## Type of change
- [ ] Bug fix
- [ ] New feature
- [ ] Refactor
- [ ] Docs
- [ ] Tests
- [ ] CI / tooling

## Component
- [ ] Wallet frontend
- [ ] SDK
- [ ] Contracts
- [ ] Agent

## Checklist
- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] `cargo test` passes (contracts)
- [ ] `npm run typecheck` passes (wallet / sdk / agent)
- [ ] `npm run build` passes (wallet / agent)
- [ ] I added or updated tests where relevant
- [ ] I updated docs / README where relevant

## Screenshots / test output
<!-- For UI changes, include before/after screenshots. For tx flows, include tx hashes. -->

@attyolu
attyolu requested a review from Miracle656 as a code owner July 30, 2026 22:19
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the miracle656's projects Team on Vercel.

A member of the Team first needs to authorize it.

@attyolu

attyolu commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I’ve fixed the in-repo code issues that were causing the mobile typecheck and wallet build failures:

removed the duplicate merge-conflict style blocks in the mobile app
cleaned up the duplicate style declaration / theme token issue in the mobile landing screen
I also verified the relevant checks locally:

mobile typecheck passes
wallet production build passes
NFT regression tests pass
The remaining GitHub checks are external to the code fix:

the Vercel checks are failing because the project has not been authorized for deployment in GitHub, so those jobs cannot complete until repo/Vercel access is granted
the Playwright wallet E2E check is a CI environment check and still needs to be re-run in the GitHub Actions environment with the required browser setup/secrets
In other words, the code-level issues in this branch have been resolved, and the remaining red checks are authorization/environment blockers rather than repository compile failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NFT gallery (Soroban CAP-46)

1 participant