Add NFT token gating on Astar
Token gating answers one question: does this wallet currently hold at least one live token from the required collection? The owner endpoint is authoritative for current holdings, but it does not accept a collection filter, so a wallet with more than 100 NFTs must be paged until a match is found or the list ends.
curl -sS \ -H "Authorization: Bearer $ARADIA_API_TOKEN" \ "https://api.aradia.app/v1/owners/0x0000000000000000000000000000000000000002/nfts?limit=100"async function ownsCollection(owner, requiredCollection, token) { const base = `https://api.aradia.app/v1/owners/${owner}/nfts`; let params = new URLSearchParams({ limit: "100" });
while (true) { const response = await fetch(`${base}?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); if (!response.ok) throw new Error(`Aradia API error ${response.status}`); const page = await response.json(); if (page.data.some((nft) => nft.collection_address === requiredCollection && !nft.is_burned)) { return true; } if (!page.pagination.has_more) return false; params = new URLSearchParams({ limit: "100" }); for (const [key, value] of Object.entries(page.pagination.next_page_params)) { params.set(key, String(value)); } }}import requests
def owns_collection(owner, required_collection, token): url = f"https://api.aradia.app/v1/owners/{owner}/nfts" params = {"limit": 100} while True: response = requests.get(url, params=params, headers={"Authorization": f"Bearer {token}"}, timeout=30) response.raise_for_status() page = response.json() if any(nft["collection_address"] == required_collection and not nft["is_burned"] for nft in page["data"]): return True if not page["pagination"]["has_more"]: return False params = {"limit": 100, **page["pagination"]["next_page_params"]}Enforce access on the server
Section titled “Enforce access on the server”Never trust a boolean sent by the browser. Run the ownership check in your backend, associate the checked wallet with a verified wallet session, and cache a positive result only for a short period if immediate transfer revocation matters.
Check the response coverage.status before presenting the result as exhaustive. unknown means the API is not claiming complete historical coverage.
