Skip to content

fix: show collection creator and info when ODA fails#846

Open
preschian wants to merge 1 commit intomainfrom
fix/collection-creator-when-oda-fails
Open

fix: show collection creator and info when ODA fails#846
preschian wants to merge 1 commit intomainfrom
fix/collection-creator-when-oda-fails

Conversation

@preschian
Copy link
Member

@preschian preschian commented Mar 11, 2026

Fixes #844

Summary

When the ODA collection API errors (e.g. issue #844), the collection and gallery detail pages should still show collection creator and collection information by falling back to other sources.

Changes

Collection page ([chain]/collection/[collection_id])

  • Catch ODA fetch failure so the page still loads with drops data; collection is null when ODA fails.
  • Use chainSpec for route validate instead of @kodadot1/static CHAINS.

Gallery detail (useToken + GalleryDetails)

  • useToken: If ODA collection has no owner, fall back to genart (/api/genart/list by collection) for creator; if still missing, query on-chain Nfts.Collection for owner so collectionCreator is set.
  • GalleryDetails: Always show the collection info block (link + name or "Collection #id"); when creator is unknown, show fallback "–" instead of endless skeleton.

Collection page header (CollectionHeader)

  • When creator and collection.owner are both missing, fetch collection owner from chain (api.query.Nfts.Collection) in onMounted so creator + Subscan button still appear.
  • Narrow chain prop type to AssetHubChain so api.query.Nfts is type-safe (relay chains have no Nfts pallet).

- Collection page: catch ODA fetch so page still loads with drops; use chainSpec for route validate
- useToken: fallback to genart then on-chain Nfts.Collection for collection creator when ODA fails
- GalleryDetails: always show collection info block and creator (fallback to – when unknown)
- CollectionHeader: fetch collection owner from chain when ODA/drops fail; narrow chain prop to AssetHubChain

Made-with: Cursor
@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
koda Ready Ready Preview, Comment Mar 11, 2026 10:29am

@railway-app
Copy link

railway-app bot commented Mar 11, 2026

🚅 Deployed to the app-pr-846 environment in chaotic-art-preview

Service Status Web Updated (UTC)
app 😴 Sleeping (View Logs) Web Mar 15, 2026 at 6:20 pm

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

The PR adds fallback mechanisms to resolve collection owners and creators by querying blockchain data when direct props are unavailable. Template rendering improvements use optional chaining for safer null handling, and collection fetching now includes error recovery with graceful degradation.

Changes

Cohort / File(s) Summary
Owner & Creator Resolution with Chain Fallbacks
app/components/collection/CollectionHeader.vue, app/composables/useToken.ts
Added onMounted hook to fetch collection owner from blockchain via SDK when prop-based owner is missing. Updated chain type to AssetHubChain. In useToken, introduced sequential fallbacks: first attempt API fetch, then fallback to on-chain query for missing collectionCreator.
Collection Data Safety & Error Handling
app/components/gallery/GalleryDetails.vue, app/pages/[chain]/collection/[collection_id].vue
Converted collection info rendering to always-render with optional chaining (?.) for defensive property access. Updated page-level collection fetch with error catch, defaulting to null on failure. Replaced CHAINS validation with chainSpec for consistency.

Sequence Diagram(s)

sequenceDiagram
    participant CH as CollectionHeader
    participant LC as Lifecycle
    participant SDK as App SDK
    participant BC as Blockchain<br/>(AssetHubChain)
    
    CH->>LC: onMounted triggered
    activate LC
    alt ownerFromProps exists
        LC->>CH: use ownerFromProps
    else ownerFromProps missing
        LC->>SDK: query Collection.getValue(collectionId)
        activate SDK
        SDK->>BC: fetch collection metadata
        activate BC
        BC-->>SDK: owner data
        deactivate BC
        SDK-->>LC: owner resolved
        deactivate SDK
        LC->>CH: store in ownerFromChain
    end
    deactivate LC
    CH->>CH: ownerAddress = ownerFromProps || ownerFromChain
Loading
sequenceDiagram
    participant UT as useToken<br/>Composable
    participant API as /api/genart/list
    participant SDK as App SDK
    participant BC as Blockchain
    
    UT->>UT: collectionCreator missing?
    alt creator missing
        UT->>API: fetch genart list
        activate API
        API-->>UT: data or error
        deactivate API
        
        alt creator found in API response
            UT->>UT: use first creator
        else creator still missing
            UT->>SDK: Nfts.Collection.getValue
            activate SDK
            SDK->>BC: query on-chain
            activate BC
            BC-->>SDK: owner field
            deactivate BC
            SDK-->>UT: owner data
            deactivate SDK
            UT->>UT: use owner as creator
        end
    else creator exists
        UT->>UT: use existing creator
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

Poem

🐰 A rabbit hops through fallback chains,
When owners hide, the chain explains,
With optional dots, we safely land,
No null shall break what we have planned,
Safe queries bloom, both fast and grand!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding fallback logic to display collection creator and information when ODA API fails, which aligns with the primary objectives across all modified files.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/collection-creator-when-oda-fails

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

Deploying app with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2e6e098
Status: ✅  Deploy successful!
Preview URL: https://7a16b266.app-bzd.pages.dev
Branch Preview URL: https://fix-collection-creator-when.app-bzd.pages.dev

View logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/composables/useToken.ts (1)

81-96: Consider extracting owner resolution into a shared utility.

This fallback logic (genart → on-chain) is duplicated in CollectionHeader.vue (lines 45-64). Both implementations:

  1. Check genart API for creator
  2. Fall back to api.query.Nfts.Collection.getValue() for on-chain owner
♻️ Suggested extraction

Create a shared utility in ~/composables/useCollectionOwner.ts:

export async function resolveCollectionOwner(
  chain: AssetHubChain,
  collectionId: string | number,
  $sdk: ReturnType<typeof useNuxtApp>['$sdk'],
): Promise<string | null> {
  // Try genart first
  const [genartOk, _, genartRes] = await t($fetch<{ data: Array<{ creator?: string }> }>('/api/genart/list', {
    query: { collection: collectionId.toString() },
  }))
  if (genartOk && genartRes?.data?.[0]?.creator) {
    return genartRes.data[0].creator
  }

  // Fall back to on-chain
  const { api } = $sdk(chain)
  const collection = await api.query.Nfts.Collection.getValue(Number(collectionId)).catch(() => null)
  return collection?.owner?.toString() ?? null
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/composables/useToken.ts` around lines 81 - 96, Extract the duplicated
genart → on-chain owner resolution into a shared composable (e.g., create
resolveCollectionOwner in useCollectionOwner.ts) and replace the logic in
useToken.ts (the block that queries /api/genart/list and
api.query.Nfts.Collection.getValue) with a call to that utility; the utility
should accept (chain, collectionId, $sdk), try the genart fetch first and return
genartRes.data[0].creator if present, otherwise call
$sdk(chain).api.query.Nfts.Collection.getValue(...) and return
collection.owner?.toString() or null, and update CollectionHeader.vue to use the
same function to remove duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/pages/`[chain]/collection/[collection_id].vue:
- Around line 173-177: The page meta validate function currently allows any
chain in chainSpec but the page code casts route.params.chain to AssetHubChain
and renders CollectionHeader which requires the Nfts pallet; change the
validation used in definePageMeta.validate to call and return
isAssetHubChain(route.params.chain) (the same predicate used in the studio page)
so only AssetHubChain values are accepted, ensuring the cast to AssetHubChain
and the CollectionHeader usage are safe; update any imports to include
isAssetHubChain where validate is defined.

---

Nitpick comments:
In `@app/composables/useToken.ts`:
- Around line 81-96: Extract the duplicated genart → on-chain owner resolution
into a shared composable (e.g., create resolveCollectionOwner in
useCollectionOwner.ts) and replace the logic in useToken.ts (the block that
queries /api/genart/list and api.query.Nfts.Collection.getValue) with a call to
that utility; the utility should accept (chain, collectionId, $sdk), try the
genart fetch first and return genartRes.data[0].creator if present, otherwise
call $sdk(chain).api.query.Nfts.Collection.getValue(...) and return
collection.owner?.toString() or null, and update CollectionHeader.vue to use the
same function to remove duplication.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fbe964af-a4dd-4aab-8bc8-e8cd9b7fc5f1

📥 Commits

Reviewing files that changed from the base of the PR and between ea80b42 and 2e6e098.

📒 Files selected for processing (4)
  • app/components/collection/CollectionHeader.vue
  • app/components/gallery/GalleryDetails.vue
  • app/composables/useToken.ts
  • app/pages/[chain]/collection/[collection_id].vue

@preschian preschian requested a review from hassnian March 11, 2026 10:32
@preschian
Copy link
Member Author

@hassnian This PR only fixes the frontend part, because the collection (831) metadata was invalid

Screenshot 2026-03-11 at 17 31 08

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.

Collection not loading from oda

2 participants