Skip to content

Commit

Permalink
miniapp(zora-minter): initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
stephancill committed Nov 13, 2023
1 parent f855aab commit 555a7b3
Show file tree
Hide file tree
Showing 25 changed files with 2,600 additions and 113 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-lies-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mod-protocol/core": minor
---

feat(core): miniapp permissions
10 changes: 10 additions & 0 deletions .changeset/spicy-coins-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@mod-protocol/react": minor
"@mod-protocol/core": minor
"@mod-protocol/miniapp-registry": patch
"@miniapps/zora-nft-minter": patch
"web": patch
"api": patch
---

feat: add `SENDETHTRANSACTION` action
1 change: 1 addition & 0 deletions examples/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@mod-protocol/core": "^0.0.2",
"@reservoir0x/reservoir-sdk": "^1.8.4",
"@vercel/postgres-kysely": "^0.6.0",
"chatgpt": "^5.2.5",
"kysely": "^0.26.3",
Expand Down
83 changes: 83 additions & 0 deletions examples/api/src/app/api/nft-minter/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { createClient, reservoirChains } from "@reservoir0x/reservoir-sdk";
import { NextRequest, NextResponse } from "next/server";
import { createWalletClient, http } from "viem";
import * as viemChains from "viem/chains";

export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const taker = searchParams.get("taker");
const itemId = searchParams.get("itemId"); // CAIP-19 ID
const referrer = searchParams.get("referrer") || undefined;

// Extract contract, type, and chain ID from itemId
// e.g. chain://eip155:1/erc721:0xa723a8a69d9b8cf0bc93b92f9cb41532c1a27f8f/11
// e.g. chain://eip155:7777777/erc1155:0xd4fbb6ee19708983b4a2ba7e6e627b94da690a3e/1
// e.g. chain://eip155:8453/erc721:0x029B142Fe0cEb2e50e02C319647CE9A7657c2B59
// e.g. chain://eip155:1/erc721:0x87C9ffD26ADe3fDAEf35cddB8c1ff86B6355a263 (allowlist)
// e.g. chain://eip155:10/erc721:0xEc5cF8551C812A9fa2DDF3B0741AEeF72314B25d
// e.g. chain://eip155:7777777/erc1155:0x4afa7992f876225cda4d503d0d1a3125348ce35b/1
const [, , prefixAndChainId, prefixAndContractAddress, tokenId] =
itemId.split("/");

let [, chainId] = prefixAndChainId.split(":");
const [type, contractAddress] = prefixAndContractAddress.split(":");

let buyTokenPartial: { token?: string; collection?: string };
if (type === "erc721") {
buyTokenPartial = { collection: contractAddress };
} else if (type === "erc1155") {
buyTokenPartial = { token: `${contractAddress}:${tokenId}` };
}

const reservoirChain = [...Object.values(reservoirChains)].find(
(chain) => chain.id === parseInt(chainId)
);

const viemChain: viemChains.Chain = [...Object.values(viemChains)].find(
(chain) => chain.id === parseInt(chainId)
);

if (!reservoirChain) {
throw new Error("Unsupported chain");
}

// Create reservoir client with applicable chain
const reservoirClient = createClient({
chains: [{ ...reservoirChain, active: true }],
});

const wallet = createWalletClient({
account: taker as `0x${string}`,
transport: http(),
chain: viemChain,
});

const res = await reservoirClient.actions.buyToken({
items: [{ ...buyTokenPartial, quantity: 1, fillType: "mint" }],
options: {
referrer,
},
wallet,
precheck: true,
onProgress: () => void 0,
});

if (res === true) {
return NextResponse.json(res);
}

const mintTx = res.steps.find((step) => step.id === "sale").items[0];

return NextResponse.json({
...mintTx,
chainId,
explorer: viemChain.blockExplorers.default,
});
} catch (err) {
return NextResponse.json(
{ message: err.response?.data?.message || err.message },
{ status: err.status ?? 400 }
);
}
}
3 changes: 2 additions & 1 deletion examples/nextjs-shadcn/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NEXT_PUBLIC_API_URL="http://localhost:3001/api"
NEXT_PUBLIC_API_URL="http://localhost:3001/api"
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=
9 changes: 6 additions & 3 deletions examples/nextjs-shadcn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
"lint": "next lint"
},
"dependencies": {
"@mod-protocol/miniapp-registry": "^0.0.2",
"@mod-protocol/core": "^0.0.2",
"@mod-protocol/miniapp-registry": "^0.0.2",
"@mod-protocol/react": "^0.0.2",
"@mod-protocol/react-editor": "^0.0.2",
"@mod-protocol/react-ui-shadcn": "^0.0.3",
"@rainbow-me/rainbowkit": "^1.2.0",
"next": "^13.5.6",
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwindcss-animate": "^1.0.6"
"tailwindcss-animate": "^1.0.6",
"viem": "^1.19.0",
"wagmi": "^1.4.6"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",
Expand All @@ -33,4 +36,4 @@
"tsconfig": "*",
"typescript": "^5.2.2"
}
}
}
46 changes: 46 additions & 0 deletions examples/nextjs-shadcn/src/app/dummy-casts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,50 @@ export const dummyCastData: Array<{
},
],
},
{
avatar_url:
"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_144/https%3A%2F%2Flh3.googleusercontent.com%2F-S5cdhOpZtJ_Qzg9iPWELEsRTkIsZ7qGYmVlwEORgFB00WWAtZGefRnS4Bjcz5ah40WVOOWeYfU5pP9Eekikb3cLMW2mZQOMQHlWhg",
display_name: "David Furlong",
username: "df",
timestamp: "2023-08-17 09:16:52.293739",
text: "I just minted this straight from my feed",
embeds: [
{
url: "https://zora.co/collect/zora:0x787c6366341fbb8a7bfff1064009bce60796338f/61",
status: "loaded",
metadata: {
image: {
url: "https://ipfs.io/ipfs/bafkreibyyf6rd5w3l3gxksy2narahb2yj3a2b4nngkqfvwpc3hkaj3daae",
},
alt: "Hyperbrand: Opepen",
description: "a collection expressing Opepen as a hyperbrand",
title: "Hyperbrand: Opepen",
publisher: "boop",
logo: {
url: "https://i.imgur.com/Cus7QVM.png",
},
nft: {
mediaUrl:
"https://ipfs.io/ipfs/bafkreifass5p37alcfqz5vn5b5lrgpfvxq7lkvpz45ovwa354jogttwr5u",
tokenId: "61",
collection: {
chain: "zora",
contractAddress: "0x787c6366341fbb8a7bfff1064009bce60796338f",
creatorAddress: "0x5adf1c982bde935ce98a07e115ff8d09254ecb1b",
description: "a collection expressing Opepen as a hyperbrand",
id: "chain://eip155:7777777/erc1155:0x787c6366341fbb8a7bfff1064009bce60796338f",
imageUrl:
"https://ipfs.io/ipfs/bafkreibyyf6rd5w3l3gxksy2narahb2yj3a2b4nngkqfvwpc3hkaj3daae",
itemCount: 53,
mintUrl:
"https://mint.fun/zora/0x787c6366341fbb8a7bfff1064009bce60796338f",
name: "Hyperbrand: Opepen",
openSeaUrl: "https://opensea.io/collection/hyperbrand-opepen",
ownerCount: 22,
},
},
},
},
],
},
];
34 changes: 30 additions & 4 deletions examples/nextjs-shadcn/src/app/embeds.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
"use client";

import React from "react";
import { renderers } from "@mod-protocol/react-ui-shadcn/dist/renderers";
import { RenderEmbed } from "@mod-protocol/react";
import { Embed } from "@mod-protocol/core";
import {
defaultContentMiniApp,
contentMiniApps,
defaultContentMiniApp,
} from "@mod-protocol/miniapp-registry";
import { RenderEmbed } from "@mod-protocol/react";
import { renderers } from "@mod-protocol/react-ui-shadcn/dist/renderers";
import { sendTransaction, switchNetwork } from "@wagmi/core";
import { useAccount } from "wagmi";

export function Embeds(props: { embeds: Array<Embed> }) {
const { address } = useAccount();

return (
<div>
{props.embeds.map((embed, i) => (
Expand All @@ -20,6 +23,29 @@ export function Embeds(props: { embeds: Array<Embed> }) {
renderers={renderers}
defaultContentMiniApp={defaultContentMiniApp}
contentMiniApps={contentMiniApps}
user={{
wallet: {
address,
},
}}
resolvers={{
onSendEthTransactionAction: async (
{ data, chainId },
{ onSuccess, onError }
) => {
try {
await switchNetwork({ chainId: parseInt(chainId) });

const { hash } = await sendTransaction({
...data,
chainId: parseInt(chainId),
});
onSuccess(hash);
} catch (e) {
onError(e);
}
},
}}
/>
))}
</div>
Expand Down
1 change: 0 additions & 1 deletion examples/nextjs-shadcn/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ThemeProvider } from "@mod-protocol/react-ui-shadcn/dist/components/theme-provider";

import "./globals.css";

export default function RootLayout({
Expand Down
Loading

0 comments on commit 555a7b3

Please sign in to comment.