Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Addition of IPFS in TurboEth #169

Open
wants to merge 12 commits into
base: integrations
Choose a base branch
from
114 changes: 114 additions & 0 deletions app/(general)/integration/ipfs/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
'use client'
import { ReactNode } from 'react'

import { motion } from 'framer-motion'
import Image from 'next/image'
import Balancer from 'react-wrap-balancer'

import { IsDarkTheme } from '@/components/shared/is-dark-theme'
import { IsLightTheme } from '@/components/shared/is-light-theme'
import { LinkComponent } from '@/components/shared/link-component'
import { FADE_DOWN_ANIMATION_VARIANTS } from '@/config/design'
import { turboIntegrations } from '@/data/turbo-integrations'

import { SideBar } from './sidebar'
import { PageHeader, PageHeaderCTA, PageHeaderDescription, PageHeaderHeading } from '@/components/layout/page-header'
import { buttonVariants } from '@/components/ui/button'
import { cn } from "@/lib/utils"
import Link from 'next/link'
import { LuBook } from 'react-icons/lu'
import { PageSection } from '@/components/layout/page-section'
import { LightDarkImage } from '@/components/shared/light-dark-image'
import { FormOpenAIPrompt } from '@/integrations/openai/components/form-openai-prompt'

const integrationData = turboIntegrations.ipfs

export default function LayoutIntegration({ children }: { children: ReactNode }) {
return (
<>
{/* <div className="flex-center w-full flex-col items-center justify-center text-center">
<motion.div
animate="show"
className="max-w-3xl px-5 text-center xl:px-0"
initial="hidden"
viewport={{ once: true }}
whileInView="show"
variants={{
hidden: {},
show: {
transition: {
staggerChildren: 0.15,
},
},
}}>
<IsLightTheme>
<Image alt="Starter logo" className="mx-auto" height={100} src={integrationData.imgDark} width={100} />
</IsLightTheme>
<IsDarkTheme>
<Image alt="Starter logo" className="mx-auto" height={100} src={integrationData.imgLight} width={100} />
</IsDarkTheme>
<motion.h1
className="text-gradient-sand my-8 text-center text-4xl font-bold tracking-[-0.02em] drop-shadow-sm md:text-8xl md:leading-[6rem]"
variants={FADE_DOWN_ANIMATION_VARIANTS}>
{integrationData.name}
</motion.h1>
<motion.p className="my-4 text-xl" variants={FADE_DOWN_ANIMATION_VARIANTS}>
<Balancer>{integrationData.description}</Balancer>
</motion.p>
<PageHeaderCTA>
<Link
href={turboIntegrations.ipfs.url}
target="_blank"
rel="noreferrer noopener"
className={cn(buttonVariants({ variant: "outline" }))}
>
<LuBook className="mr-2 h-4 w-4" />
Documentation
</Link>
</PageHeaderCTA>
</motion.div>
<motion.div className="container my-4 w-full text-xl" variants={FADE_DOWN_ANIMATION_VARIANTS}>
<section className="mt-10 flex flex-col overflow-hidden rounded-xl bg-neutral-200 dark:bg-neutral-900 sm:flex-row">
<SideBar />
<div className="flex-center min-h-[600px] flex-1 flex-col items-center justify-center p-10 text-center">{children}</div>
</section>
</motion.div>
</div> */}
<div className="container relative mt-20">
<PageHeader className="pb-8">
<LightDarkImage
LightImage={turboIntegrations.ipfs.imgDark}
DarkImage={turboIntegrations.ipfs.imgLight}
alt="OpenAI Logo"
width={100}
height={100}
/>
<PageHeaderHeading>IPFS</PageHeaderHeading>
<PageHeaderDescription>
{turboIntegrations.ipfs.description}
</PageHeaderDescription>
<PageHeaderCTA>
<Link
href={turboIntegrations.ipfs.url}
target="_blank"
rel="noreferrer noopener"
className={cn(buttonVariants({ variant: "outline" }))}
>
<LuBook className="mr-2 h-4 w-4" />
Documentation
</Link>
</PageHeaderCTA>
</PageHeader>
<PageSection>
<motion.div className="container my-4 w-full text-xl" variants={FADE_DOWN_ANIMATION_VARIANTS}>
<section className="mt-10 flex flex-col overflow-hidden rounded-xl bg-neutral-200 dark:bg-neutral-900 sm:flex-row">
<SideBar />
<div className="flex-center min-h-[600px] flex-1 flex-col items-center justify-center p-10 text-center">{children}</div>
</section>
</motion.div>
</PageSection>

</div>
</>
)
}
7 changes: 7 additions & 0 deletions app/(general)/integration/ipfs/node/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use client'

import UploadedList from '@/integrations/ipfs/components/uploaded-list'

export default function IpfsNodePage() {
return <UploadedList />
}
9 changes: 9 additions & 0 deletions app/(general)/integration/ipfs/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IntegrationOgImage } from '@/components/ui/social/og-image-integrations'

export const runtime = 'edge'
export const size = {
width: 1200,
height: 630,
}

export default IntegrationOgImage('starter')
11 changes: 11 additions & 0 deletions app/(general)/integration/ipfs/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Ipfs } from '@/integrations/ipfs'

export default function PageIntegration() {
return (
<section className="w-full lg:mt-10">
<div className="container mx-auto mt-10 max-w-screen-xl gap-6 text-center">
<Ipfs />
</div>
</section>
)
}
67 changes: 67 additions & 0 deletions app/(general)/integration/ipfs/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { LinkComponent } from '@/components/shared/link-component'
import { turboIntegrations } from '@/data/turbo-integrations'
import { ArweaveAccountPreview } from '@/integrations/arweave/components/arweave-account/sidebar-preview'

export const SideBar = () => {
const ipfsBaseUrl = turboIntegrations.ipfs.href
return (
<aside aria-label="Sidebar" className="w-full sm:w-64">
<div className="overflow-y-auto bg-neutral-50 px-3 py-4 text-left dark:bg-neutral-800 sm:h-full">
<ArweaveAccountPreview />
<ul className="space-y-2 font-medium">
<li>
<LinkComponent
className="group flex items-center rounded-lg p-2 text-neutral-900 hover:bg-neutral-100 dark:text-white dark:hover:bg-neutral-700"
href={`${ipfsBaseUrl}/node`}>
<svg
aria-hidden="true"
className="h-5 w-5 text-neutral-500 transition duration-75 group-hover:text-neutral-900 dark:text-neutral-400 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 22 21"
xmlns="http://www.w3.org/2000/svg">
<path d="M16.975 11H10V4.025a1 1 0 0 0-1.066-.998 8.5 8.5 0 1 0 9.039 9.039.999.999 0 0 0-1-1.066h.002Z" />
<path d="M12.5 0c-.157 0-.311.01-.565.027A1 1 0 0 0 11 1.02V10h8.975a1 1 0 0 0 1-.935c.013-.188.028-.374.028-.565A8.51 8.51 0 0 0 12.5 0Z" />
</svg>
<span className="ml-3">Uploaded List</span>
</LinkComponent>
</li>
<li>
<LinkComponent
className="group flex items-center rounded-lg p-2 text-neutral-900 hover:bg-neutral-100 dark:text-white dark:hover:bg-neutral-700"
href={`${ipfsBaseUrl}/status`}>
<svg
aria-hidden="true"
className="h-5 w-5 shrink-0 text-neutral-500 transition duration-75 group-hover:text-neutral-900 dark:text-neutral-400 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 18 18"
xmlns="http://www.w3.org/2000/svg">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z" />
</svg>
<span className="ml-3 flex-1 whitespace-nowrap">Status</span>
</LinkComponent>
</li>

<li>
<LinkComponent
className="group flex items-center rounded-lg p-2 text-neutral-900 hover:bg-neutral-100 dark:text-white dark:hover:bg-neutral-700"
href={`${ipfsBaseUrl}/upload/`}>
<svg
aria-hidden="true"
className="h-5 w-5 shrink-0 text-neutral-500 transition duration-75 group-hover:text-neutral-900 dark:text-neutral-400 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
{' '}
<path d="M0 0h24v24H0z" fill="none" />{' '}
<path d="M15 4H5v16h14V8h-4V4zM3 2.992C3 2.444 3.447 2 3.999 2H16l5 5v13.993A1 1 0 0 1 20.007 22H3.993A1 1 0 0 1 3 21.008V2.992zM13 12v4h-2v-4H8l4-4 4 4h-3z" />{' '}
={' '}
</svg>

<span className="ml-3 flex-1 whitespace-nowrap">New Upload</span>
</LinkComponent>
</li>
</ul>
</div>
</aside>
)
}
6 changes: 6 additions & 0 deletions app/(general)/integration/ipfs/status/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client'

import IpfsStatus from '@/integrations/ipfs/components/status'
export default function IpfsStatusPage() {
return <IpfsStatus />
}
9 changes: 9 additions & 0 deletions app/(general)/integration/ipfs/twitter-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Image from './opengraph-image'

export const runtime = 'edge'
export const size = {
width: 1200,
height: 630,
}

export default Image
6 changes: 6 additions & 0 deletions app/(general)/integration/ipfs/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client'

import FormUploadFiles from '@/integrations/ipfs/components/form-upload-files'
export default function IpfsUpload() {
return <FormUploadFiles />
}
1 change: 1 addition & 0 deletions app/api/ipfs/get-api-key/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { GET } from '@/integrations/ipfs/api/get-api-key'
1 change: 1 addition & 0 deletions app/api/ipfs/list/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { GET } from '@/integrations/ipfs/api/list'
17 changes: 17 additions & 0 deletions components/shared/example-demos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,23 @@ const demos = [
</div>
),
},
{
title: turboIntegrations.ipfs.name,
description: turboIntegrations.ipfs.description,
href: turboIntegrations.ipfs.href,
demo: (
<div className="flex items-center justify-center space-x-20">
<LightDarkImage
LightImage={turboIntegrations.ipfs.imgDark}
DarkImage={turboIntegrations.ipfs.imgLight}
alt="Starter logo"
height={100}
width={100}
/>

</div>
),
},
]

interface ExampleDemosProps extends MotionProps {
Expand Down
10 changes: 10 additions & 0 deletions data/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,15 @@ export const integrations = {
imgLight: "/integrations/moralis.png",
imgDark: "/integrations/moralis.png",
},
ipfs: {
name: "IPFS",
href: "/integration/ipfs/upload",
url: "https://ipfs.io/",
description:
"IPFS (InterPlanetary File System) is a protocol and network designed to create a content-addressable, peer-to-peer method of storing and sharing hypermedia in a distributed file system.",
imgLight: "/integrations/ipfs-logo.svg",
imgDark: "/integrations/ipfs-logo.svg",
},

},
}
9 changes: 9 additions & 0 deletions data/turbo-integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,13 @@ export const turboIntegrations = {
imgLight: "/logo-gradient.png",
imgDark: "/logo-dark.png",
},
ipfs: {
name: 'IPFS',
href: '/integration/ipfs',
url: 'https://ipfs.io',
description:
'IPFS (InterPlanetary File System) is a peer-to-peer hypermedia protocol designed to make the web faster, safer, and more open. It enables the creation of distributed applications and the permanent, decentralized storage and sharing of data.',
imgLight: '/integrations/ipfs-logo.svg',
imgDark: '/integrations/ipfs-logo.svg',
},
}
2 changes: 2 additions & 0 deletions env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const env = createEnv({
ETHERSCAN_API_KEY_ARBITRUM: z.string().min(1).optional(),
ETHERSCAN_API_KEY_POLYGON: z.string().min(1).optional(),
MORALIS_API_KEY: z.string().min(1).optional(),
WEB3_STORAGE_KEY: z.string().min(1).optional(),
},
client: {
NEXT_PUBLIC_USE_PUBLIC_PROVIDER: z.enum(["true", "false"]).default("true"),
Expand All @@ -42,6 +43,7 @@ export const env = createEnv({
ETHERSCAN_API_KEY_ARBITRUM: process.env.ETHERSCAN_API_KEY_ARBITRUM,
ETHERSCAN_API_KEY_POLYGON: process.env.ETHERSCAN_API_KEY_POLYGON,
MORALIS_API_KEY: process.env.MORALIS_API_KEY,
WEB3_STORAGE_KEY: process.env.WEB3_STORAGE_KEY,
NEXT_PUBLIC_USE_PUBLIC_PROVIDER:
process.env.NEXT_PUBLIC_USE_PUBLIC_PROVIDER,
NEXT_PUBLIC_ALCHEMY_API_KEY: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY,
Expand Down
4 changes: 4 additions & 0 deletions integrations/ipfs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ipfs Integration in TurboETH

This document describes how to integrate Ipfs with TurboETH.

12 changes: 12 additions & 0 deletions integrations/ipfs/api/get-api-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { env } from '@/env.mjs'

export function GET(req: Request) {
const web3StorageKey = env.WEB3_STORAGE_KEY

return new Response(JSON.stringify({ web3StorageKey }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
})
}
12 changes: 12 additions & 0 deletions integrations/ipfs/api/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ipfsGetUploadList } from '../routes/get-upload-list'

export async function GET(req: Request) {
try {
const data = await ipfsGetUploadList()

return new Response(JSON.stringify(data), { status: 200, headers: { 'Content-Type': 'application/json' } })
} catch (e) {
const errorMessage = e instanceof Error ? e.message : String(e)
return new Response(errorMessage, { status: 500 })
}
}
Loading