Skip to content

Commit

Permalink
Port the Explorer from Create React App to Next 13 (w/ App Router)
Browse files Browse the repository at this point in the history
  • Loading branch information
steveluscher committed May 8, 2023
1 parent fa28f1a commit 5577645
Show file tree
Hide file tree
Showing 706 changed files with 39,016 additions and 95,987 deletions.
11 changes: 11 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": ["next/core-web-vitals", "@solana/eslint-config-solana"],
"plugins": ["testing-library"],
"overrides": [
// Only uses Testing Library lint rules in test files
{
"files": ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
"extends": ["plugin:testing-library/react"]
}
]
}
7 changes: 4 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
---
name: Bug report
about: Create a report to help us improve
title: "[Bug]"
title: '[Bug]'
labels: bug
assignees: ngundotra

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Example Links**
- [Please provide at least 1 link here](https://explorer.solana.com)

- [Please provide at least 1 link here](https://explorer.solana.com)

**Expected behavior**
A clear and concise description of what you expected to happen.
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
Build-And-Test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x]

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install package manager
uses: pnpm/action-setup@v2
with:
version: 8.2.0

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Build
run: pnpm build

- name: Test
run: pnpm test:ci
29 changes: 21 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies

/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build
/wasm/target

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.eslintcache
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

#comment
# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# Sentry Auth Token
.sentryclirc

# Speedy Web Compiler
.swc/
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto-install-peers=true
6 changes: 0 additions & 6 deletions .prettierrc.json

This file was deleted.

4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"typescript.tsdk": "node_modules/.pnpm/[email protected]/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
41 changes: 8 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,17 @@

# Solana Explorer

This was recently moved from `solana-labs/explorer`.

## Development

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

In the project directory, you can run:

### `npm start`

Runs the app in the development mode.<br />
Open [https://localhost:3000](https://localhost:3000) to view it in the browser.

The page will reload if you make edits.<br />
You will also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.<br />
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.<br />
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.<br />
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
- `pnpm dev` \
Runs the app in the development mode. \
Open [https://localhost:3000](https://localhost:3000) to view it in the browser. \
\
The page will reload if you make edits. \
You will also see any lint errors in the console.

To learn React, check out the [React documentation](https://reactjs.org/).
- `pnpm test` \
Launches the test runner in the interactive watch mode.<br />

# Disclaimer

Expand Down
31 changes: 31 additions & 0 deletions app/address/[address]/anchor-account/page-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

import { AnchorAccountCard } from '@components/account/AnchorAccountCard';
import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer';
import { LoadingCard } from '@components/common/LoadingCard';
import { Suspense } from 'react';
import React from 'react';

type Props = Readonly<{
params: {
address: string;
};
}>;

function AnchorAccountCardRenderer({
account,
onNotFound,
}: React.ComponentProps<React.ComponentProps<typeof ParsedAccountRenderer>['renderComponent']>) {
if (!account) {
return onNotFound();
}
return (
<Suspense fallback={<LoadingCard message="Decoding account data using anchor interface" />}>
<AnchorAccountCard account={account} />
</Suspense>
);
}

export default function AnchorAccountPageClient({ params: { address } }: Props) {
return <ParsedAccountRenderer address={address} renderComponent={AnchorAccountCardRenderer} />;
}
20 changes: 20 additions & 0 deletions app/address/[address]/anchor-account/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Metadata } from 'next/types';

import AnchorAccountPageClient from './page-client';

type Props = Readonly<{
params: {
address: string;
};
}>;

export async function generateMetadata({ params: { address } }: Props): Promise<Metadata> {
return {
description: `Contents of the Anchor Account at address ${address} on Solana`,
title: `Anchor Account Data | ${address} | Solana`,
};
}

export default function AnchorAccountPage(props: Props) {
return <AnchorAccountPageClient {...props} />;
}
25 changes: 25 additions & 0 deletions app/address/[address]/anchor-program/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AnchorProgramCard } from '@components/account/AnchorProgramCard';
import { LoadingCard } from '@components/common/LoadingCard';
import { Metadata } from 'next/types';
import { Suspense } from 'react';

type Props = Readonly<{
params: {
address: string;
};
}>;

export async function generateMetadata({ params: { address } }: Props): Promise<Metadata> {
return {
description: `The Interface Definition Language (IDL) file for the Anchor program at address ${address} on Solana`,
title: `Anchor Program IDL | ${address} | Solana`,
};
}

export default function AnchorProgramIDLPage({ params: { address } }: Props) {
return (
<Suspense fallback={<LoadingCard message="Loading anchor program IDL" />}>
<AnchorProgramCard programId={address} />
</Suspense>
);
}
26 changes: 26 additions & 0 deletions app/address/[address]/attributes/page-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import { MetaplexNFTAttributesCard } from '@components/account/MetaplexNFTAttributesCard';
import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer';
import React from 'react';

type Props = Readonly<{
params: {
address: string;
};
}>;

function MetaplexNFTAttributesCardRenderer({
account,
onNotFound,
}: React.ComponentProps<React.ComponentProps<typeof ParsedAccountRenderer>['renderComponent']>) {
const parsedData = account?.data?.parsed;
if (!parsedData || parsedData.program !== 'spl-token' || parsedData.parsed.type !== 'mint' || !parsedData.nftData) {
return onNotFound();
}
return <MetaplexNFTAttributesCard nftData={parsedData.nftData} />;
}

export default function MetaplexNFTAttributesPageClient({ params: { address } }: Props) {
return <ParsedAccountRenderer address={address} renderComponent={MetaplexNFTAttributesCardRenderer} />;
}
20 changes: 20 additions & 0 deletions app/address/[address]/attributes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Metadata } from 'next/types';

import NFTAttributesPageClient from './page-client';

type Props = Readonly<{
params: {
address: string;
};
}>;

export async function generateMetadata({ params: { address } }: Props): Promise<Metadata> {
return {
description: `Attributes of the Metaplex NFT with address ${address} on Solana`,
title: `Metaplex NFT Attributes | ${address} | Solana`,
};
}

export default function MetaplexNFTAttributesPage(props: Props) {
return <NFTAttributesPageClient {...props} />;
}
26 changes: 26 additions & 0 deletions app/address/[address]/blockhashes/page-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import { BlockhashesCard } from '@components/account/BlockhashesCard';
import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer';
import React from 'react';

type Props = Readonly<{
params: {
address: string;
};
}>;

function BlockhashesCardRenderer({
account,
onNotFound,
}: React.ComponentProps<React.ComponentProps<typeof ParsedAccountRenderer>['renderComponent']>) {
const parsedData = account?.data?.parsed;
if (!parsedData || parsedData.program !== 'sysvar' || parsedData.parsed.type !== 'recentBlockhashes') {
return onNotFound();
}
return <BlockhashesCard blockhashes={parsedData.parsed.info} />;
}

export default function RecentBlockhashesPageClient({ params: { address } }: Props) {
return <ParsedAccountRenderer address={address} renderComponent={BlockhashesCardRenderer} />;
}
16 changes: 16 additions & 0 deletions app/address/[address]/blockhashes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import RecentBlockhashesPageClient from './page-client';

type Props = Readonly<{
params: {
address: string;
};
}>;

export const metadata = {
description: `Recent blockhashes on Solana`,
title: `Recent Blockhashes | Solana`,
};

export default function RecentBlockhashesPage(props: Props) {
return <RecentBlockhashesPageClient {...props} />;
}
19 changes: 19 additions & 0 deletions app/address/[address]/domains/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DomainsCard } from '@components/account/DomainsCard';
import { Metadata } from 'next/types';

type Props = Readonly<{
params: {
address: string;
};
}>;

export async function generateMetadata({ params: { address } }: Props): Promise<Metadata> {
return {
description: `Domain names owned by the address ${address} on Solana`,
title: `Domains | ${address} | Solana`,
};
}

export default function OwnedDomainsPage({ params: { address } }: Props) {
return <DomainsCard address={address} />;
}
Loading

0 comments on commit 5577645

Please sign in to comment.