diff --git a/package-lock.json b/package-lock.json index 2f257482..f55683a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@headlessui/react": "^1.4.3", "@heroicons/react": "^1.0.5", "@ipld/car": "^5.2.5", + "@open-frames/proxy-client": "0.3.3", "@rainbow-me/rainbowkit": "^2.0.1", "@tanstack/react-query": "^5.24.1", "@wagmi/connectors": "^4.1.14", @@ -23,7 +24,7 @@ "@xmtp/content-type-remote-attachment": "^1.1.4", "@xmtp/content-type-reply": "^1.1.5", "@xmtp/experimental-content-type-screen-effect": "^1.0.2", - "@xmtp/frames-client": "0.4.2", + "@xmtp/frames-client": "0.5.4", "@xmtp/react-sdk": "^5.1.0", "buffer": "^6.0.3", "date-fns": "^2.29.3", @@ -53,7 +54,6 @@ "zustand": "^4.3.2" }, "devDependencies": { - "@open-frames/proxy-client": "0.2.0", "@tailwindcss/forms": "^0.5.7", "@types/lodash": "^4.14.202", "@types/node": "^20.11.24", @@ -4087,17 +4087,17 @@ } }, "node_modules/@open-frames/proxy-client": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@open-frames/proxy-client/-/proxy-client-0.2.0.tgz", - "integrity": "sha512-elfy9da998KR65tQDt+Z/nvNnFeXHhYAxlIjI3lftJbg5Vt6zwAtoWvV3r10B9nTcaA4/MWipZezD5pGV5tazg==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@open-frames/proxy-client/-/proxy-client-0.3.3.tgz", + "integrity": "sha512-D1yLfP05w1hWQEEvppXvPhShOMZ1CB6slT93xCASkP1WOKP6IMTvt3k+5VVS68C2SThRPfqZNWW10W8Sns7xvg==", "dependencies": { - "@open-frames/proxy-types": "0.1.0" + "@open-frames/proxy-types": "0.2.3" } }, "node_modules/@open-frames/proxy-types": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@open-frames/proxy-types/-/proxy-types-0.1.0.tgz", - "integrity": "sha512-fFcUmUmnGn3JkiBL3az6sqcs62pOnKPWc3tKar6LV9VciHaRXC059kCxpLh2mcYVfpZ0HgRILBtttEupIrAPDw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@open-frames/proxy-types/-/proxy-types-0.2.3.tgz", + "integrity": "sha512-/dC64ORHJGXP7fLO4gvo1h4rPGCaQ4pf+oO6FaKiF/aXcN0uF2Sq446wysl7pZNQdFI2gQtQhbm+PUuRa84l3A==", "engines": { "node": ">=18" }, @@ -8537,13 +8537,13 @@ } }, "node_modules/@xmtp/frames-client": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@xmtp/frames-client/-/frames-client-0.4.2.tgz", - "integrity": "sha512-47fy35WGJ/QDzPKjuCCc45GLvLrDb92Jh5sDXY6B/HmWrssb8dZtrV5kw77kKsdGVhnqTQTRUM3WjMC6l83T0w==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@xmtp/frames-client/-/frames-client-0.5.4.tgz", + "integrity": "sha512-efoMlZCXK2zx9kD0DPcztzoc/kCnNAFfthf4S34CLPjDFAUz0w10d1h3lf6GVZ7DVnEp5xw8Fhq2XqkSkk+ttA==", "dependencies": { - "@noble/hashes": "^1.3.3", - "@open-frames/proxy-client": "^0.2.0", - "@xmtp/proto": "3.44.0", + "@noble/hashes": "^1.4.0", + "@open-frames/proxy-client": "^0.3.3", + "@xmtp/proto": "3.62.1", "long": "^5.2.3" }, "peerDependencies": { @@ -8551,9 +8551,9 @@ } }, "node_modules/@xmtp/frames-client/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "engines": { "node": ">= 16" }, @@ -8562,9 +8562,9 @@ } }, "node_modules/@xmtp/proto": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/@xmtp/proto/-/proto-3.44.0.tgz", - "integrity": "sha512-5M23JsxONb/qluZF6QMjoXHT67xDRR7pWwHTd1tfw59jS+jXTxm/+v8/UeSOoK47PBSJhDD5I90bAeA5NrLRig==", + "version": "3.62.1", + "resolved": "https://registry.npmjs.org/@xmtp/proto/-/proto-3.62.1.tgz", + "integrity": "sha512-7LZz60EOKKfO5gqwaTaX7vaIRxZO9H3cQ+7SWI9XCQM9UGHdSvJKfQDPnJ4Z0E0GIJGLDoyQ44P2bvXCxC8SNA==", "dependencies": { "long": "^5.2.0", "protobufjs": "^7.0.0", diff --git a/package.json b/package.json index c10fbf70..f525bf19 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@headlessui/react": "^1.4.3", "@heroicons/react": "^1.0.5", "@ipld/car": "^5.2.5", + "@open-frames/proxy-client": "0.3.3", "@rainbow-me/rainbowkit": "^2.0.1", "@tanstack/react-query": "^5.24.1", "@wagmi/connectors": "^4.1.14", @@ -43,7 +44,7 @@ "@xmtp/content-type-remote-attachment": "^1.1.4", "@xmtp/content-type-reply": "^1.1.5", "@xmtp/experimental-content-type-screen-effect": "^1.0.2", - "@xmtp/frames-client": "0.4.2", + "@xmtp/frames-client": "0.5.4", "@xmtp/react-sdk": "^5.1.0", "buffer": "^6.0.3", "date-fns": "^2.29.3", @@ -73,7 +74,6 @@ "zustand": "^4.3.2" }, "devDependencies": { - "@open-frames/proxy-client": "0.2.0", "@tailwindcss/forms": "^0.5.7", "@types/lodash": "^4.14.202", "@types/node": "^20.11.24", diff --git a/src/component-library/components/Frame/Frame.tsx b/src/component-library/components/Frame/Frame.tsx index 8816a83c..ae819a00 100644 --- a/src/component-library/components/Frame/Frame.tsx +++ b/src/component-library/components/Frame/Frame.tsx @@ -1,5 +1,8 @@ import { ArrowCircleRightIcon } from "@heroicons/react/outline"; -import type { FrameButton } from "../../../helpers/frameInfo"; +import type { + OpenFrameButton, + OpenFrameResult, +} from "@open-frames/proxy-client"; import { classNames } from "../../../helpers"; import { ButtonLoader } from "../Loaders/ButtonLoader"; @@ -7,10 +10,10 @@ type FrameProps = { image: string; title: string; textInput?: string; - buttons: FrameButton[]; + buttons: OpenFrameResult["buttons"]; handleClick: ( buttonNumber: number, - action?: FrameButton["action"], + action?: OpenFrameButton["action"], ) => Promise; onTextInputChange: (value: string) => void; frameButtonUpdating: number; @@ -77,23 +80,33 @@ const FrameButtonContainer = ({ ); }; +type ButtonsContainerProps = Pick< + FrameProps, + "frameButtonUpdating" | "handleClick" +> & { + buttons: NonNullable; +}; + const ButtonsContainer = ({ frameButtonUpdating, buttons, handleClick, -}: Pick) => { - if (buttons.length < 1 || buttons.length > 4) { +}: ButtonsContainerProps) => { + if (Object.keys(buttons).length < 1 || Object.keys(buttons).length > 4) { return null; } // If there is only one button make it full-width - const gridColumns = buttons.length === 1 ? "grid-cols-1" : "grid-cols-2"; + const gridColumns = + Object.keys(buttons).length === 1 ? "grid-cols-1" : "grid-cols-2"; return (
- {buttons.map((button, index) => { + {Object.keys(buttons).map((key, index) => { + const button = buttons[key]; + const buttonIndex = parseInt(key, 10); const clickHandler = () => { - void handleClick(button.buttonIndex, button.action); + void handleClick(buttonIndex, button.action); }; - const isFullWidth = buttons.length === 3 && index === 2; + const isFullWidth = Object.keys(buttons).length === 3 && index === 2; return ( 0} clickHandler={clickHandler} /> @@ -139,7 +152,7 @@ export const Frame = ({ /> )}
- {interactionsEnabled && buttons.length ? ( + {interactionsEnabled && buttons ? ( { if (!frameMetadata || !client || !frameMetadata?.frameInfo?.buttons) { return; @@ -54,7 +51,8 @@ export const FullMessageController = ({ setFrameButtonUpdating(buttonIndex); const framesClient = new FramesClient(client); - const postUrl = button.target || frameInfo.postUrl || frameUrl; + const postUrl = + button.target || button.postUrl || frameInfo.postUrl || frameUrl; const payload = await framesClient.signFrameAction({ frameUrl, inputText: textInputValue || undefined, @@ -135,7 +133,7 @@ export const FullMessageController = ({ { - const button = buttonMap[key]; - return { - ...button, - buttonIndex: parseInt(key, 10), - }; - }); -} - export function isXmtpFrame(metadata: GetMetadataResponse): boolean { const minXmtpVersion = metadata.frameInfo?.acceptedClients?.xmtp; diff --git a/src/helpers/openFrames.ts b/src/helpers/openFrames.ts index e274d354..17a0150c 100644 --- a/src/helpers/openFrames.ts +++ b/src/helpers/openFrames.ts @@ -1,10 +1,9 @@ -import { OpenFramesProxy, type FramesApiResponse } from "@xmtp/frames-client"; +import { OpenFramesProxy } from "@xmtp/frames-client"; const proxy = new OpenFramesProxy(); const BUTTON_INDEX_REGEX = /fc:frame:button:(\d)(?:$|:).*/; -export const readMetadata = async (url: string): Promise => - proxy.readMetadata(url); +export const readMetadata = async (url: string) => proxy.readMetadata(url); export const mediaUrl = (url: string): string => proxy.mediaUrl(url);