Skip to content

Commit

Permalink
feat: parse targets
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Feb 8, 2024
1 parent 08d5ea2 commit 69aa0f3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 10 deletions.
21 changes: 20 additions & 1 deletion src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@ import {

const html = `
<meta property="fc:frame" content="vNext">
<meta property="fc:frame:button:1" content="foo">
<meta property="fc:frame:button:2" content="bar">
<meta property="fc:frame:button:2:action" content="link">
<meta property="fc:frame:button:2:target" content="https://example.com">
<meta property="fc:frame:button:3" content="baz">
<meta property="fc:frame:button:3:action" content="post_redirect">
<meta property="fc:frame:button:3:target" content="https://example.com/redirect">
<meta property="fc:frame:button:4" content="mint">
<meta property="fc:frame:button:4:action" content="mint">
<meta property="fc:frame:button:4:target" content="eip155:7777777:0x060f3edd18c47f59bd23d063bbeb9aa4a8fec6df">
<meta property="fc:frame:image" content="http://example.com/image">
<meta property="fc:frame:post_url" content="http://localhost:3001">
<meta property="og:image" content="https://example.com/og">
Expand Down Expand Up @@ -54,13 +65,21 @@ describe('parseFrameButtons', () => {
{
title: 'bar',
index: 2,
type: 'post',
target: 'https://example.com',
type: 'link',
},
{
title: 'baz',
index: 3,
target: 'https://example.com/redirect',
type: 'post_redirect',
},
{
title: 'mint',
index: 4,
target: 'eip155:7777777:0x060f3edd18c47f59bd23d063bbeb9aa4a8fec6df',
type: 'mint',
},
])
})
})
Expand Down
26 changes: 19 additions & 7 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,9 @@ export function parseFrameButtons(metaTags: readonly HTMLMetaElement[]) {
let currentButtonIndex = 0
let buttonsAreMissing = false
let buttonsAreOutOfOrder = false
const buttonMap = new Map<number, Omit<FrameButton, 'type'>>()
const buttonMap = new Map<number, Omit<FrameButton, 'target' | 'type'>>()
const buttonActionMap = new Map<number, FrameButton['type']>()
const buttonTargetMap = new Map<number, FrameButton['target']>()
const invalidButtons: FrameButton['index'][] = []

for (const metaTag of metaTags) {
Expand All @@ -483,10 +484,13 @@ export function parseFrameButtons(metaTags: readonly HTMLMetaElement[]) {
string | undefined,
]
const index = parseInt(matchArray[1], 10) as FrameButton['index']
const type = matchArray[2] as FrameButton['type'] | undefined
const type = matchArray[2]

const content = metaTag.getAttribute('content') ?? ''
if (type) buttonActionMap.set(index, content as FrameButton['type'])
if (type === 'action')
buttonActionMap.set(index, content as FrameButton['type'])
else if (type === 'target')
buttonTargetMap.set(index, content as FrameButton['target'])
else {
if (currentButtonIndex >= index) buttonsAreOutOfOrder = true
if (currentButtonIndex + 1 === index) currentButtonIndex = index
Expand All @@ -499,11 +503,15 @@ export function parseFrameButtons(metaTags: readonly HTMLMetaElement[]) {
}
}

// TODO: Validate `fc:frame:button:$idx:action="link"` has corresponding `fc:frame:button:$idx:target`
const buttons = [] as FrameButton[]
const buttons: FrameButton[] = []
for (const [index, button] of buttonMap) {
const type = buttonActionMap.get(index) ?? 'post'
buttons.push({ ...button, type })
const target = buttonTargetMap.get(index) as FrameButton['target']
buttons.push({
...button,
...(target ? { target } : {}),
type,
} as FrameButton)
}

return buttons.toSorted((a, b) => a.index - b.index)
Expand All @@ -515,11 +523,15 @@ export function validateFrameButtons(buttons: readonly FrameButton[]) {
for (let i = 0; i < buttons.length; i++) {
const button = buttons[i]
const previousButton = buttons[i - 1]

const isOutOfOrder = button.index < previousButton?.index ?? 0
const isButtonMissing = button.index !== i + 1
if (isOutOfOrder || isButtonMissing) buttonsAreOutOfOrder = true

// TODO: `invalidButtons`
// link must have target in format
// mint must have target in format
}
// TODO: `invalidButtons`
return { buttonsAreOutOfOrder, invalidButtons }
}

Expand Down
14 changes: 12 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,18 @@ export type FrameDebug = Pretty<
export type FrameButton = {
index: 1 | 2 | 3 | 4
title: string
type: 'link' | 'mint' | 'post' | 'post_redirect'
}
} & (
| { type: 'link'; target: `http://${string}` | `https://${string}` }
| {
type: 'mint'
// TODO: tighten type
target: `eip155:${string}`
}
| {
type: 'post' | 'post_redirect'
target?: `http://${string}` | `https://${string}` | undefined
}
)

export type FrameInput = {
text: string
Expand Down

0 comments on commit 69aa0f3

Please sign in to comment.