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: add template #1 - quickstart #4

Merged
merged 15 commits into from
Aug 7, 2024
4 changes: 3 additions & 1 deletion .env.local.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# See https://www.coinbase.com/developer-platform/products/base-node
NEXT_PUBLIC_CDP_API_KEY="GET_FROM_COINBASE_DEVELOPER_PLATFORM"
ENVIRONMENT=localhost
ENVIRONMENT=localhost
# See https://cloud.walletconnect.com/
WALLET_CONNECTOR_PROJECT_ID="GET_FROM_WALLET_CONNECT"
6 changes: 5 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
env: {
WALLET_CONNECTOR_PROJECT_ID: process.env.WALLET_CONNECTOR_PROJECT_ID,
},
};

module.exports = nextConfig;
21 changes: 21 additions & 0 deletions src/app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,25 @@ ul {
#__next {
position: relative;
z-index: 0;
}

.ockConnectWallet_Container span {
color: #030712;
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's start introducing CSS variables

}

/* i believe this is necessary because
of a div added by rainbowkit provider */
body > div {
Copy link
Contributor

Choose a reason for hiding this comment

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

I can see junior developer tripping on this.

Can we do this in a more simple way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmmm i couldn't really think of anything better because it is a hidden div without a classname. do you have an idea?

Copy link
Contributor

Choose a reason for hiding this comment

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

so are you trying to target what in particular? the first div after the body ?

height: 100%;
max-width: 100vw;
box-sizing: border-box;
padding: 0 10px;
}

a {
text-decoration: none;
}

.templateSection > div {
max-width: 100%;;
}
1 change: 1 addition & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NEXT_PUBLIC_URL } from '../config';

import './global.css';
import '@coinbase/onchainkit/styles.css';
import '@rainbow-me/rainbowkit/styles.css';

export const viewport = {
width: 'device-width',
Expand Down
47 changes: 34 additions & 13 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
'use client';
import WalletComponents from '../components/WalletComponents';
import Footer from 'src/components/Footer';
import TransactionWrapper from 'src/components/TransactionWrapper';
import WalletWrapper from 'src/components/WalletWrapper';
import { useAccount } from 'wagmi';
import LoginButton from '../components/LoginButton';
import SignupButton from '../components/SignupButton';

export default function Page() {
const { address } = useAccount();

return (
<div className="flex w-96 flex-col md:w-[600px]">
<section className="mb-6 flex w-full flex-col border-sky-800 border-b pb-6">
<aside className="mb-6 flex">
<h2 className="text-2xl">Onchain App Template</h2>
</aside>
<div className="flex h-full w-96 max-w-full flex-col md:w-[1008px]">
<section className="mt-6 mb-6 flex w-full flex-col md:flex-row">
<div className="flex w-full flex-col items-center justify-between gap-2 md:flex-row md:gap-0">
<h2 className="text-3xl">Onchainkit</h2>
<div className="flex gap-3">
<SignupButton />
{!address && <LoginButton />}
</div>
</div>
</section>
<section className="mb-6 flex w-full flex-col border-sky-800 border-b pb-6">
<aside className="mb-6 flex">
<h2 className="text-xl">Identity</h2>
</aside>
<main className="flex h-10 items-center space-x-4">
<WalletComponents />
</main>
<section className="templateSection flex w-full grow flex-col items-center justify-center gap-4 rounded-xl md:bg-gray-100">
<div className="flex h-[450px] w-[450px] max-w-full items-center justify-center rounded-xl bg-[#030712]">
<div className="rounded-xl bg-[#F3F4F6] px-4 py-[11px]">
<p className="font-normal text-indigo-600 text-xl not-italic tracking-[-1.2px]">
npm install @coinbase/onchainkit
</p>
</div>
</div>
{address ? (
<TransactionWrapper address={address} />
) : (
<WalletWrapper
className="w-[450px] max-w-full"
text="Sign in to collect"
/>
)}
</section>
<Footer />
</div>
);
}
31 changes: 31 additions & 0 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

const docLinks = [
{ href: 'https://onchainkit.xyz', title: 'Docs' },
{ href: 'https://github.com/coinbase/onchainkit', title: 'Github' },
{ href: 'https://discord.gg/8gW3h6w5', title: 'Discord' },
{
href: 'https://www.figma.com/community/file/1370194397345450683/onchainkit',
title: 'Figma',
},
{ href: 'https://x.com/Onchainkit', title: 'X' },
];

export default function Footer() {
return (
<section className="mt-12 mb-6 flex w-full flex-col justify-between gap-2 md:flex-row ">
<aside className="flex items-center justify-center md:justify-start">
<h3 className="mr-2 text-m">Built with love by the OnchainKit team</h3>
</aside>
<ul className="flex justify-center gap-6 md:justify-start">
{docLinks.map(({ href, title }) => (
<li className="flex" key={href}>
<a href={href} target="_blank" rel="noreferrer" title={title}>
<p>{title}</p>
</a>
</li>
))}
</ul>
</section>
);
}
6 changes: 6 additions & 0 deletions src/components/LoginButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client';
import WalletWrapper from './WalletWrapper';

export default function LoginButton() {
return <WalletWrapper text="Log in" />;
}
5 changes: 4 additions & 1 deletion src/components/OnchainProviders.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';
import { OnchainKitProvider } from '@coinbase/onchainkit';
import { RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { ReactNode } from 'react';
import { base } from 'viem/chains';
Expand All @@ -16,7 +17,9 @@ function OnchainProviders({ children }: Props) {
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<OnchainKitProvider apiKey={NEXT_PUBLIC_CDP_API_KEY} chain={base}>
{children}
<RainbowKitProvider modalSize="compact">
{children}
</RainbowKitProvider>
</OnchainKitProvider>
</QueryClientProvider>
</WagmiProvider>
Expand Down
12 changes: 12 additions & 0 deletions src/components/SignupButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';
import WalletWrapper from './WalletWrapper';

export default function SignupButton() {
return (
<WalletWrapper
className="ockConnectWallet_Container bg-slate-200 text-[#030712] hover:bg-slate-300"
text="Sign up"
withWalletAggregator={true}
/>
);
}
49 changes: 49 additions & 0 deletions src/components/TransactionWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';
import {
Transaction,
TransactionButton,
TransactionStatus,
TransactionStatusAction,
TransactionStatusLabel,
} from '@coinbase/onchainkit/transaction';
import { clickContractAbi, clickContractAddress } from 'src/constants';
import type { Address, ContractFunctionParameters } from 'viem';

type TransactionWrapperParams = {
address: Address;
};

export default function TransactionWrapper({
address,
}: TransactionWrapperParams) {
const contracts = [
{
address: clickContractAddress,
abi: clickContractAbi,
functionName: 'click',
args: [],
},
{
address: clickContractAddress,
abi: clickContractAbi,
functionName: 'click',
args: [],
},
] as ContractFunctionParameters[];

return (
<div className="flex w-[450px]">
<Transaction
address={address}
contracts={contracts}
className="w-[450px]"
>
<TransactionButton className="mt-0 mr-auto ml-auto w-[450px] text-[white]" />
<TransactionStatus>
<TransactionStatusLabel />
<TransactionStatusAction />
</TransactionStatus>
</Transaction>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { render } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import WalletComponents from './WalletComponents';
import WalletWrapper from './WalletWrapper';

describe('WalletComponents', () => {
describe('WalletWrapper', () => {
it('should renders', () => {
render(<WalletComponents />);
render(<WalletWrapper />);
expect(true).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,24 @@ import {
WalletDropdownLink,
} from '@coinbase/onchainkit/wallet';

export default function WalletComponents() {
type WalletWrapperParams = {
text?: string;
className?: string;
withWalletAggregator?: boolean;
};
export default function WalletWrapper({
className,
text,
withWalletAggregator = false,
}: WalletWrapperParams) {
return (
<>
<Wallet>
<ConnectWallet>
<ConnectWallet
withWalletAggregator={withWalletAggregator}
text={text}
className={className}
>
<Avatar className="h-6 w-6" />
<Name />
</ConnectWallet>
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const NEXT_PUBLIC_URL =
: 'https://onchain-app-template.vercel.app';
// Add your API KEY from the Coinbase Developer Portal
export const NEXT_PUBLIC_CDP_API_KEY = process.env.NEXT_PUBLIC_CDP_API_KEY;
export const WALLET_CONNECTOR_PROJECT_ID =
process.env.WALLET_CONNECTOR_PROJECT_ID;
11 changes: 11 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const clickContractAddress =
'0x67c97D1FB8184F038592b2109F854dfb09C77C75';
export const clickContractAbi = [
{
type: 'function',
name: 'click',
inputs: [],
outputs: [],
stateMutability: 'nonpayable',
},
];
18 changes: 18 additions & 0 deletions src/svg/BaseSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function BaseSvg() {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<title>Base SVG</title>
<circle cx="10" cy="10" r="10" fill="#0052FF" />
<path
d="M10.0437 16.9488C13.9196 16.9488 17.0616 13.8123 17.0616 9.94315C17.0616 6.07404 13.9196 2.9375 10.0437 2.9375C6.36653 2.9375 3.34989 5.76073 3.05029 9.35427H12.3263V10.532H3.05029C3.34989 14.1256 6.36653 16.9488 10.0437 16.9488Z"
fill="white"
/>
</svg>
);
}
34 changes: 26 additions & 8 deletions src/wagmi.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
'use client';
import { connectorsForWallets } from '@rainbow-me/rainbowkit';
import {
coinbaseWallet,
metaMaskWallet,
rainbowWallet,
} from '@rainbow-me/rainbowkit/wallets';
import { http, createConfig } from 'wagmi';
import { baseSepolia } from 'wagmi/chains';
import { coinbaseWallet } from 'wagmi/connectors';
import { WALLET_CONNECTOR_PROJECT_ID } from './config';

const connectors = connectorsForWallets(
[
{
groupName: 'Recommended Wallet',
wallets: [coinbaseWallet],
},
{
groupName: 'Other Wallets',
wallets: [rainbowWallet, metaMaskWallet],
},
],
{
appName: 'onchainkit',
projectId: WALLET_CONNECTOR_PROJECT_ID || '',
},
);

export const wagmiConfig = createConfig({
chains: [baseSepolia],
// turn off injected provider discovery
multiInjectedProviderDiscovery: false,
connectors: [
coinbaseWallet({
appName: 'anOnchainAppIn100Components',
preference: 'all',
version: '4',
}),
],
connectors,
ssr: true,
transports: {
[baseSepolia.id]: http(),
Expand Down
Loading