Integrate to wallets
In this integration guide, we will guide you how to support TokenScript (opens in a new tab) and EIP-5169 (opens in a new tab) as a wallet provider like JoyId (opens in a new tab) and Alphawallet (opens in a new tab).
We will use NextJS and wagmi as an example, but the idea is the same for any other tech stack.
Step 1: Add support for EIP-5169
Check if the NFT contract implements EIP-5169, if yes, then you can use the first value of scriptURI
to load TokenScript Viewer iframe.
app/[chainId]/[contract]/[tokenId]/page.tsx
export default function AppPageContent({
params,
}: {
params: {
chainId: string
contract: string
tokenId: string
}
}) {
const chainId = parseInt(params.chainId, 10)
const { address } = useAccount()
// read contract to get scriptURI content, need to check if it's a valid tokenscript url
const { scriptURI } = useGetTokenScriptURI(params.contract, chainId)
const iframeRef = useRef<HTMLIFrameElement>(null)
const dAppUrl = addQueriesToUrl(`https://viewer.tokenscript.org/`, {
chainId: params.chainId,
contract: params.contract,
tokenId: params.tokenId,
viewType: "sts-token",
chain: chainId.toString(),
tokenscriptUrl: encodeURIComponent(scriptURI),
})
useIframePostMessage(iframeRef, dAppUrl)
return (
<iframe
key={`${chainId}-${params.contract}-${params.tokenId}-${address}`}
ref={iframeRef}
src={dAppUrl}
/>
)
}
function addQueriesToUrl(
url: string,
params: { [key: string]: string }
): string {
const result = new URL(url)
Object.entries(params).forEach(([key, value]) => {
result.searchParams.append(key, value)
})
return result.toString()
}
Step 2: implement TokenScript RPC requirements
import { RefObject, useEffect } from "react"
import { useWalletClient } from "wagmi"
export const useIframePostMessage = (
iframeRef: RefObject<HTMLIFrameElement>,
targetOrigin: string
) => {
const { data: walletClient } = useWalletClient()
useEffect(() => {
function sendResponse(
messageData: MessageEvent["data"],
response: any,
error?: any
) {
const data = messageData
if (response) {
data.result = response
} else {
data.error = error
}
iframeRef.current?.contentWindow?.postMessage(data, targetOrigin)
}
const handleMessage = async (event: MessageEvent) => {
if (!walletClient) {
return
}
try {
switch (event.data.method) {
case "eth_accounts":
case "eth_requestAccounts": {
const data = await walletClient.request({
method: event.data.method,
})
sendResponse(event.data, data)
break
}
case "eth_chainId":
case "net_version":
case "eth_blockNumber":
case "eth_estimateGas":
case "eth_sendTransaction":
case "eth_getTransactionByHash":
case "eth_getTransactionReceipt":
case "eth_getTransactionCount":
case "personal_sign":
case "eth_signTypedData":
case "wallet_switchEthereumChain": {
const data = await walletClient.request({
method: event.data.method,
params: event.data.params,
})
sendResponse(event.data, data)
break
}
default:
sendResponse(event.data, null, {
code: -1,
message:
"RPC Method " + event.data.method + " is not implemented",
})
break
}
} catch (e: any) {
const innerError = e.walk()
if (innerError) e = innerError
sendResponse(event.data, null, {
code: e.data?.code ?? e.code,
message: e.message + (e.data?.message ? " " + e.data?.message : ""),
})
}
}
window.addEventListener("message", handleMessage)
return () => window.removeEventListener("message", handleMessage)
}, [iframeRef, targetOrigin, walletClient])
}
That's it, you can now ready with TokenScript and EIP-5169.