Skip to content

Commit

Permalink
Feat/examples testnet (#11)
Browse files Browse the repository at this point in the history
* feat: examples

* chore: revert devnet

* fix: build issues
  • Loading branch information
crypblizz8 authored Nov 7, 2024
1 parent aaf8c90 commit b3fb733
Show file tree
Hide file tree
Showing 13 changed files with 999 additions and 73 deletions.
6 changes: 5 additions & 1 deletion examples/nextjs/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"extends": ["next/core-web-vitals", "next/typescript"]
"extends": ["next/core-web-vitals", "next/typescript"],
"rules": {
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-empty-object-type": "off"
}
}
1 change: 1 addition & 0 deletions examples/nextjs/app/components/ClientWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ReactNode } from "react";

import { NillionProvider } from "@nillion/client-react-hooks";

// To switch from devnet to testnet(photon), change the network in the NillionProvider
export const ClientWrapper: React.FC<{ children: ReactNode }> = ({
children,
}) => {
Expand Down
56 changes: 56 additions & 0 deletions examples/nextjs/app/components/InstructionsTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"use client";

import { useState } from 'react';
import KeplrWalletConnector from './KeplrWallet';
import { Login } from './Login';
import { TestNetContent } from './TestNetContent';
import { WelcomeContent } from './WelcomeContent';

const InstructionsTab = () => {
const [activeTab, setActiveTab] = useState('devnet');

return (
<div className="min-w-4xl mx-auto p-6">
<div className="flex space-x-1 border-b border-gray-200 mb-6">
<button
onClick={() => setActiveTab('devnet')}
className={`px-4 py-2 text-sm font-medium rounded-t-lg ${
activeTab === 'devnet'
? 'bg-gray-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
Devnet
</button>
<button
onClick={() => setActiveTab('testnet')}
className={`px-4 py-2 text-sm font-medium rounded-t-lg ${
activeTab === 'testnet'
? 'bg-gray-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
Testnet
</button>
</div>

<div className="mt-4 ">
{activeTab === 'devnet' ? (
<div className="space-y-6">
<h2 className={`text-2xl font-bold dark:text-white text-gray-800 mb-4`}>Devnet Instructions</h2>
<WelcomeContent />
<Login />
</div>
) : (
<div className="space-y-6">
<h2 className={`text-2xl font-bold dark:text-white text-gray-800 mb-4`}>Testnet Instructions</h2>
<TestNetContent />
<KeplrWalletConnector />
</div>
)}
</div>
</div>
);
};

export default InstructionsTab;
165 changes: 165 additions & 0 deletions examples/nextjs/app/components/KeplrWallet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"use client";

import { useState } from "react";
import { useNillionAuth, UserCredentials } from "@nillion/client-react-hooks";
import { config } from "../config/Chain";
import Image from "next/image";
import { Window as KeplrWindow } from "@keplr-wallet/types";

declare global {
interface Window extends KeplrWindow {}
}

const SEED = "example-secret-seed";

const KeplrWalletConnector = () => {
const { authenticated, login, logout } = useNillionAuth();
const [walletAddress, setWalletAddress] = useState("");
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);

const checkKeplr = async () => {
try {
const keplr = window.keplr;
if (!keplr) {
throw new Error("Please install Keplr extension");
}
} catch (err:unknown) {
if (err instanceof Error) {
setError(err.message);
} else {
setError("An unknown error occurred");
}
}
};

const addDevnetChain = async () => {
try {
await checkKeplr();

const chainId = "nillion-chain-testnet-1";
const keplr = window.keplr;
if (!keplr) {
throw new Error("Keplr not found");
}

try {
await keplr.getKey(chainId);
console.log("Chain already exists in Keplr!");
} catch {
console.log("Adding new chain to Keplr...");
await keplr.experimentalSuggestChain(config);
}
await keplr.enable(chainId);
} catch (error:unknown) {
console.error("Error:", error);
if (error instanceof Error && error.message.includes("chain not supported")) {
console.log("This chain needs to be manually added with chainInfo configuration");
}
throw error;
}
};

const handleLogin = async () => {
try {
setIsLoading(true);
await checkKeplr();

const chainId = "nillion-chain-testnet-1";
await addDevnetChain();

const keplr = window.keplr;
if (!keplr) {
throw new Error("Keplr not found");
}

const offlineSigner = keplr.getOfflineSigner(chainId);
const accounts = await offlineSigner.getAccounts();

if (!accounts || accounts.length === 0) {
throw new Error("No accounts found");
}

const address = accounts[0].address;
setWalletAddress(address);
const credentials: UserCredentials = {
userSeed: SEED,
};
await login(credentials);
console.log("Successfully logged in with address:", address);
} catch (err: unknown) {
console.error("Login error:", err);
if (err instanceof Error) {
setError(err.message);
} else {
setError("An unknown error occurred");
}
setWalletAddress("");
} finally {
setIsLoading(false);
}
};

const handleLogout = async () => {
try {
setIsLoading(true);
await logout();
setWalletAddress("");
setError("");
} catch (err: unknown) {
console.error("Logout error:", err);
if (err instanceof Error) {
setError(err.message);
} else {
setError("An unknown error occurred");
}
} finally {
setIsLoading(false);
}
};
return (
<div>
{error && (
<div className="mb-4 p-4 bg-red-100 text-red-700 rounded">{error}</div>
)}
<div className="flex flex-row">
<button
onClick={addDevnetChain}
className="px-4 py-2 border dark:bg-gray-100 border-gray-300 rounded text-white rounded hover:bg-gray-200 transition-colors mr-2 flex items-center"
>
<Image
src="/nillion_n.png"
alt="Nillion Icon"
width={24}
height={24}
/>
</button>

{isLoading ? (
<button
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
disabled
>
Connecting...
</button>
) : authenticated ? (
<button
onClick={handleLogout}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
>
{walletAddress?.substring(0, 11) + "..." + walletAddress?.substring(walletAddress.length - 3)}
</button>
) : (
<button
onClick={handleLogin}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
>
Connect Keplr Wallet
</button>
)}
</div>

</div>
);
};
export default KeplrWalletConnector;
27 changes: 27 additions & 0 deletions examples/nextjs/app/components/TestNetContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const TestNetContent = () => {
return (
<div className="min-w-4xl">
<ol className="list-inside list-decimal text-sm text-center sm:text-left mt-4">
<li className="mb-2">
Ensure you are logged out of the devnet / not running nillion-devnet
</li>
<li className="mb-2">
Change your network in
<code className="bg-gray-200 text-gray-800 dark:bg-gray-700 dark:text-gray-200 rounded-md p-1 mx-1">
ClientWrapper.tsx
</code>
to &quot;photon&quot;
</li>
<li className="mb-2">
Ensure you have a Keplr Wallet
</li>
<li className="mb-2">
Add the Nillion Testnet chain
</li>
<li className="mb-2">
Connect to Keplr Wallet
</li>
</ol>
</div>
);
};
36 changes: 9 additions & 27 deletions examples/nextjs/app/components/WelcomeContent.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
import Image from "next/image";

export const WelcomeContent = () => {
return (
<>
<Image
src="/logo.svg"
alt="Next.js logo"
width={180}
height={38}
priority
className="hidden dark:block"
/>
<Image
src="/dark_logo.svg"
alt="Next.js logo"
width={180}
height={38}
priority
className="block dark:hidden"
/>
<div className="max-w-4xl">
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)] mt-4">
<li className="mb-2">
Follow along the quickstart guide {" "}
Expand All @@ -31,6 +13,13 @@ export const WelcomeContent = () => {
here
</a>
</li>
<li className="mb-2">
Make sure you are running
<code className="bg-gray-200 text-gray-800 dark:bg-gray-700 dark:text-gray-200 rounded-md p-1 mx-1">
nillion-devnet
</code>
in a separate terminal.
</li>
<li className="mb-2">
Reach out to us on {" "}
<a
Expand All @@ -43,14 +32,7 @@ export const WelcomeContent = () => {
</a>
{""} if you get stuck
</li>
<li>
Make sure you are running
<code className="bg-gray-200 text-gray-800 dark:bg-gray-700 dark:text-gray-200 rounded-md p-1 mx-1">
nillion-devnet
</code>
in a separate terminal.
</li>
</ol>
</>
</div>
);
};
55 changes: 55 additions & 0 deletions examples/nextjs/app/config/Chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export const config = {
rpc: "https://testnet-nillion-rpc.lavenderfive.com",
rest: "https://testnet-nillion-api.lavenderfive.com",
nodeProvider: {
name: "Lavender.Five",
email: "[email protected]",
website: "https://www.lavenderfive.com/",
},
chainId: "nillion-chain-testnet-1",
chainName: "Nillion Testnet",
chainSymbolImageUrl:
"https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/nillion-chain-testnet/nil.png",
stakeCurrency: {
coinDenom: "NIL",
coinMinimalDenom: "unil",
coinDecimals: 6,
coinImageUrl:
"https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/nillion-chain-testnet/nil.png",
},
bip44: {
coinType: 118,
},
bech32Config: {
bech32PrefixAccAddr: "nillion",
bech32PrefixAccPub: "nillionpub",
bech32PrefixValAddr: "nillionvaloper",
bech32PrefixValPub: "nillionvaloperpub",
bech32PrefixConsAddr: "nillionvalcons",
bech32PrefixConsPub: "nillionvalconspub",
},
currencies: [
{
coinDenom: "NIL",
coinMinimalDenom: "unil",
coinDecimals: 6,
coinImageUrl:
"https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/nillion-chain-testnet/nil.png",
},
],
feeCurrencies: [
{
coinDenom: "NIL",
coinMinimalDenom: "unil",
coinDecimals: 6,
coinImageUrl:
"https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/nillion-chain-testnet/nil.png",
gasPriceStep: {
low: 0.001,
average: 0.001,
high: 0.01,
},
},
],
features: [],
};
Binary file modified examples/nextjs/app/favicon.ico
Binary file not shown.
Loading

0 comments on commit b3fb733

Please sign in to comment.