Skip to content

Commit

Permalink
Merge pull request #260 from framesjs/feat/debugger-mint-tx
Browse files Browse the repository at this point in the history
feat: mint tx via reservoir api
  • Loading branch information
stephancill authored Mar 28, 2024
2 parents 3875369 + 306673d commit 92987b2
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/gorgeous-crabs-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@frames.js/debugger": patch
---

feat: mint tx via reservoir api
130 changes: 130 additions & 0 deletions packages/debugger/app/mint/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { createClient, reservoirChains } from "@reservoir0x/reservoir-sdk";
import { TransactionTargetResponse, getTokenFromUrl } from "frames.js";
import { NextRequest, NextResponse } from "next/server";
import {
createPublicClient,
createWalletClient,
hexToBigInt,
http,
parseAbi,
} 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 target = searchParams.get("target"); // CAIP-10 ID
const referrer = searchParams.get("referrer") || undefined;

if (!taker || !target) {
throw new Error("Missing required parameters");
}

// Extract contract, type, and chain ID from itemId
const {
address: contractAddress,
chainId,
tokenId,
} = getTokenFromUrl(target);

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

const viemChain = Object.values(viemChains).find(
(chain) => chain.id === chainId
);

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

const publicClient = createPublicClient({
chain: viemChain,
transport: http(),
});

const ERC1155_ERC165 = "0xd9b67a26";
const ERC721_ERC165 = "0x80ac58cd";

async function supportsInterface(
interfaceId: `0x${string}`
): Promise<boolean> {
return await publicClient
.readContract({
address: contractAddress as `0x${string}`,
abi: parseAbi([
"function supportsInterface(bytes4 interfaceID) external view returns (bool)",
]),
functionName: "supportsInterface",
args: [interfaceId],
})
.catch((err) => {
console.error(err);
return false;
});
}

// Get token type
const [isERC721, isERC1155] = await Promise.all([
supportsInterface(ERC721_ERC165),
supportsInterface(ERC1155_ERC165),
]);

let buyTokenPartial: { token?: string; collection?: string };
if (isERC721) {
buyTokenPartial = { collection: contractAddress };
} else if (isERC1155) {
buyTokenPartial = { token: `${contractAddress}:${tokenId}` };
} else {
buyTokenPartial = { collection: contractAddress };
}

// 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];

const txResponse: TransactionTargetResponse = {
chainId: `eip155:${viemChain.id}`,
method: "eth_sendTransaction",
params: {
...mintTx!.data,
value: hexToBigInt(mintTx?.data.value).toString(),
},
};

return NextResponse.json({
data: txResponse,
explorer: viemChain.blockExplorers?.default,
});
} catch (err: any) {
return NextResponse.json(
{ message: err.response?.data?.message || err.message },
{ status: err.status ?? 400 }
);
}
}
31 changes: 31 additions & 0 deletions packages/debugger/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,37 @@ export default function App({
signerState,
extraButtonRequestPayload: { mockData: mockHubContext },
onTransaction,
onMint(t) {
if (!confirm(`Mint ${t.target}?`)) {
return;
}

if (!account.address) {
openConnectModal?.();
return;
}

const searchParams = new URLSearchParams({
target: t.target,
taker: account.address,
});

fetch(`/mint?${searchParams.toString()}`)
.then(async (res) => {
if (!res.ok) {
const json = await res.json();
throw new Error(json.message);
}
return await res.json();
})
.then((json) => {
onTransaction({ ...t, transactionData: json.data });
})
.catch((e) => {
alert(e);
console.error(e);
});
},
});

return (
Expand Down
21 changes: 11 additions & 10 deletions packages/debugger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"url": "https://github.com/framesjs/frames.js/tree/main/packages/debugger"
},
"dependencies": {
"@farcaster/core": "^0.14.7",
"@frames.js/render": "^0.0.2",
"@noble/ed25519": "^2.0.0",
"@radix-ui/react-accordion": "^1.1.2",
Expand All @@ -25,6 +26,9 @@
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@rainbow-me/rainbowkit": "^2.0.2",
"@reservoir0x/reservoir-sdk": "^2.0.11",
"@tanstack/react-query": "^5.22.2",
"@types/node": "^18.17.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
Expand All @@ -35,25 +39,22 @@
"clsx": "^2.1.0",
"eslint": "^8.56.0",
"eslint-config-next": "^14.1.0",
"frames.js": "^0.11.0",
"is-port-reachable": "^4.0.0",
"lucide-react": "^0.344.0",
"next": "^14.1.3",
"open": "^10.0.3",
"postcss": "^8",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^2.2.1",
"tailwindcss": "^3.3.0",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.3.3",
"yargs": "^17.7.2",
"@farcaster/core": "^0.14.7",
"@rainbow-me/rainbowkit": "^2.0.2",
"@tanstack/react-query": "^5.22.2",
"frames.js": "^0.11.0",
"next": "^14.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"viem": "^2.7.12",
"wagmi": "^2.5.7"
"wagmi": "^2.5.7",
"yargs": "^17.7.2"
},
"engines": {
"node": ">=18.17.0"
Expand All @@ -79,4 +80,4 @@
"root": true,
"extends": "next"
}
}
}
26 changes: 26 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,13 @@
dependencies:
web-streams-polyfill "^3.1.1"

"@reservoir0x/reservoir-sdk@^2.0.11":
version "2.0.11"
resolved "https://registry.yarnpkg.com/@reservoir0x/reservoir-sdk/-/reservoir-sdk-2.0.11.tgz#400310406d7137119364f124630b61f1973ff57f"
integrity sha512-ha9UrNKyFNB0OSZ82NROA74gKYPo50syOcqI3DeBbSkTR0auioKykmf3kn9WWcrgbZ2km5EONtJ6uwhXFzxfiw==
dependencies:
axios "^1.6.7"

"@resvg/[email protected]":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@resvg/resvg-wasm/-/resvg-wasm-2.4.0.tgz#e01164b9a267c822e1ff797daa2fb91b663ea6f0"
Expand Down Expand Up @@ -4926,6 +4933,15 @@ axe-core@=4.7.0:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf"
integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==

axios@^1.6.7:
version "1.6.8"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

axobject-query@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a"
Expand Down Expand Up @@ -7488,6 +7504,11 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==

follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==

for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
Expand Down Expand Up @@ -11984,6 +12005,11 @@ [email protected]:
resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600"
integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==

proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==

pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
Expand Down

0 comments on commit 92987b2

Please sign in to comment.