diff --git a/README.md b/README.md index 94bf5ed..b77b25b 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,20 @@ This repository contains a simple web interface and API for creating, viewing, a Visit [inscribe.news](https://inscribe.news) to see it in action! -## API Endpoints +Visit the [inscribe.news documentation](https://docs.inscribe.news) to learn more about the standard! -The API fetches info, content, or news from an inscription ID, grabbing the data from the [Hiro Ordinals API](https://github.com/hirosystems/ordinals-api) with either [ordapi.xyz](https://ordapi.xyz) or [ordinals.com](https://ordinals.com) as a fallback, then saving it in KV for future requests. +## API -- `/api/info/INSCRIPTION_ID` - returns inscription data (all) -- `/api/content/INSCRIPTION_ID` - returns inscription content (all) -- `/api/news/INSCRIPTION_ID` - returns html from news inscription body (news only) -- `/api/data/INSCRIPTION_ID` - returns inscription data and content (news only) -- `/api/data/ord-news` - returns all known news inscriptions in KV -- `/api/data/ord-list` - returns all known inscriptions in KV +The API fetches info, content, or news from an inscription ID or inscription number, and will: + +- first try to return the data from Cloudflare KV, if indexed +- fetch and store the data from the [Hiro Ordinals API](https://github.com/hirosystems/ordinals-api) for future reads + +The available endpoints are [listed in the documentation](https://docs.inscribe.news/api). ## Development -This repository can be cloned and hosted with an active Cloudflare account, using [Cloudflare Pages](https://pages.cloudflare.com/). +This repository can be cloned and hosted with an active Cloudflare account using [Cloudflare Pages](https://pages.cloudflare.com/). To develop the site locally, run: @@ -30,13 +30,17 @@ npx wrangler pages dev dist/ To develop the site locally with KV enabled: ``` -npx wrangler pages dev --kv ORD_LIST --kv ORD_NEWS --kv ORD_DATA --local ./public ./dist +npx wrangler pages dev --kv ORD_LIST_V2 --kv ORD_NEWS_V2 --local ./public ./dist ``` ### Cloudflare Configuration In order to setup the same environment, a few Cloudflare settings need to be enabled on the dashboard for this Pages project. +#### Link to GitHub + +Clone this repository and set it up within the Cloudflare Dashboard using Cloudflare Pages. + #### Builds & Deployments - Build command: npm run build @@ -57,12 +61,10 @@ Preview: Create KV namespaces: -- ord-list -- ord-news -- ord-data -- ord-list-preview -- ord-news-preview -- ord-data-preview +- ord-list-v2 +- ord-news-v2 +- ord-list-preview-v2 +- ord-news-preview-v2 #### Functions @@ -71,10 +73,8 @@ Usage model: Unbound KV namespace bindings: - Production: - - ORD_LIST = ord-list - - ORD_NEWS = ord-news - - ORD_DATA = ord-data + - ORD_LIST_V2 = ord-list-v2 + - ORD_NEWS_V2 = ord-news-v2 - Preview: - - ORD_LIST = ord-list-preview - - ORD_NEWS = ord-news-preview - - ORD_DATA = ord-data-preview + - ORD_LIST_V2 = ord-list-preview-v2 + - ORD_NEWS_V2 = ord-news-preview-v2 diff --git a/functions/api/[[catchall]].ts b/functions/api/[[catchall]].ts index 414839b..b6dae3c 100644 --- a/functions/api/[[catchall]].ts +++ b/functions/api/[[catchall]].ts @@ -4,11 +4,13 @@ export async function onRequest({ request }): Promise { const url = new URL(request.url); const path = url.pathname; return createResponse( - `Welcome to the Ordinal News Indexer and API! Supported routes below:\n\n - /api/info/INSCRIPTION_ID - returns inscription data (all)\n - /api/content/INSCRIPTION_ID - returns inscription content (all)\n - /api/news/INSCRIPTION_ID - returns html from news inscription body (news only)\n - /api/data/INSCRIPTION_ID - returns inscription data and content (news only)\n + `Welcome to the Ordinal News Indexer and API!\n\n + More information can be found in the docs: https://docs.inscribe.news/api\n\n + Supported routes below, where ID = inscription ID or number:\n\n + /api/info/ID - returns inscription data (all)\n + /api/content/ID - returns inscription content (all)\n + /api/news/ID - returns html from news inscription body (news only)\n + /api/data/ID - returns inscription data and content (news only)\n /api/data/ord-news - returns all known news inscriptions in KV\n /api/data/ord-list - returns all known inscriptions in KV\n\n current path: ${path}` diff --git a/lib/api-helpers.ts b/lib/api-helpers.ts index 35fe110..1331d4a 100644 --- a/lib/api-helpers.ts +++ b/lib/api-helpers.ts @@ -71,20 +71,10 @@ export async function getInscription( }; } } catch (err) { + // TODO: throw err? console.log(`getInscription: unable to retrieve from V2 KV key\n${id}\n${String(err)}`); } - // check for data in V1 key, store if found - try { - const kvData = await env.ORD_LIST.getWithMetadata(id, { type: 'arrayBuffer' }); - if (kvData.metadata !== null && kvData.value !== null) { - metadata = kvData.metadata as InscriptionMeta; - content = new Response(kvData.value as ArrayBuffer); - } - } catch (err) { - console.log(`getInscription: unable to retrieve from V1 KV key\n${id}\n${String(err)}`); - } - // check that data was returned, fetch from Hiro API if not // works with inscription ID or inscription number if (metadata === undefined || Object.keys(metadata).length === 0 || content === undefined) { diff --git a/lib/api-types.ts b/lib/api-types.ts index 617625a..1ba39ec 100644 --- a/lib/api-types.ts +++ b/lib/api-types.ts @@ -2,8 +2,6 @@ import { KVNamespace } from '@cloudflare/workers-types'; // KV binding export interface Env { - ORD_LIST: KVNamespace; - ORD_NEWS: KVNamespace; ORD_LIST_V2: KVNamespace; ORD_NEWS_V2: KVNamespace; } diff --git a/src/components/bitcoin-icon.tsx b/src/components/bitcoin-icon.tsx new file mode 100644 index 0000000..b027662 --- /dev/null +++ b/src/components/bitcoin-icon.tsx @@ -0,0 +1,23 @@ +import { Icon } from '@chakra-ui/react'; + +// credit for the bitcoin icon +// https://commons.wikimedia.org/wiki/File:Bitcoin_logo.svg#/media/File:Bitcoin.svg +export default function BitcoinIcon({ color = 'currentColor' }) { + return ( + + + + + + + ); +} diff --git a/src/routes/post-news.tsx b/src/routes/post-news.tsx index 6e1aeff..44916c5 100644 --- a/src/routes/post-news.tsx +++ b/src/routes/post-news.tsx @@ -9,7 +9,6 @@ import { FormControl, FormLabel, Heading, - Icon, Input, Link as ChakraLink, Modal, @@ -29,26 +28,7 @@ import { } from '@chakra-ui/react'; import { Link } from 'react-router-dom'; import copy from 'copy-to-clipboard'; - -// credit for the bitcoin icon -// https://commons.wikimedia.org/wiki/File:Bitcoin_logo.svg#/media/File:Bitcoin.svg -const BitcoinIcon = () => ( - - - - - - -); +import BitcoinIcon from '../components/bitcoin-icon'; // credit for the form template goes to: // https://chakra-templates.dev/templates/forms/authentication/simpleSignupCard diff --git a/src/routes/recent-news.tsx b/src/routes/recent-news.tsx index 0c3b2d8..56641c6 100644 --- a/src/routes/recent-news.tsx +++ b/src/routes/recent-news.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Box, Divider, Heading, HStack, Text, VStack, Wrap, WrapItem } from '@chakra-ui/react'; +import { Box, Divider, Heading, HStack, Text, VStack } from '@chakra-ui/react'; import { KVNamespaceListKey, KVNamespaceListResult } from '@cloudflare/workers-types'; import { InscriptionMeta, OrdinalNews } from '../../lib/api-types'; import { Link } from 'react-router-dom'; @@ -10,7 +10,6 @@ async function getRecentNews() { const result = await fetch(new URL(`/api/data/ord-news`, apiUrl).toString()); if (result.ok) { const infoData: KVNamespaceListResult = await result.json(); - console.log(`getRecentNews: found ${infoData.keys.length} news items from API`); return infoData; } console.log(`getRecentNews: ${result.status} ${result.statusText}`); @@ -52,8 +51,6 @@ function NewsItem(props: InscriptionMeta & OrdinalNews) { {new Date(timestamp).toLocaleString()} - News # 005 - Inscription # {number.toLocaleString()} {author ? author : 'anonymous'} @@ -63,6 +60,11 @@ function NewsItem(props: InscriptionMeta & OrdinalNews) { ); } +/* + +News # 005 +*/ + export default function RecentNews() { const [loading, setLoading] = useState(true); const [newsList, setNewsList] = useState(undefined); diff --git a/src/routes/view-news.tsx b/src/routes/view-news.tsx index f81df92..8c3438f 100644 --- a/src/routes/view-news.tsx +++ b/src/routes/view-news.tsx @@ -58,7 +58,6 @@ export default function ViewNews() { setData(data); // extract news values as InscriptionMeta const { p, op, title, url, body, author, authorAddress, signature } = data; - // TODO: fix for SNS names coming up in view-news if (p === 'ons' && title) { setNews({ p, @@ -159,6 +158,13 @@ export default function ViewNews() { maxW="100%" pt={3} > + + {new Date(data.timestamp).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + })} + {news.author && Author: {news.author}} {news.url && (