@farcaster/frame-core 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import { miniAppHostCapabilityList } from '../types.ts'
3
3
  import {
4
4
  buttonTitleSchema,
5
5
  createSimpleStringSchema,
6
+ domainSchema,
6
7
  encodedJsonFarcasterSignatureSchema,
7
8
  frameNameSchema,
8
9
  hexColorSchema,
@@ -25,7 +26,7 @@ const primaryCategorySchema = z.enum([
25
26
  'art-creativity',
26
27
  ])
27
28
 
28
- const chainList: [string, ...string[]] = [
29
+ const chainList = [
29
30
  'eip155:1', // Ethereum mainnet
30
31
  'eip155:8453', // Base mainnet
31
32
  'eip155:42161', // Arbitrum One
@@ -42,7 +43,12 @@ const chainList: [string, ...string[]] = [
42
43
  'eip155:10143', // Monad testnet
43
44
  'eip155:42220', // Celo
44
45
  'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // Solana
45
- ]
46
+ ] as const
47
+
48
+ function removeArrayDuplicates<T>(arr: T[]) {
49
+ const set = new Set(arr)
50
+ return Array.from(set)
51
+ }
46
52
 
47
53
  export const domainFrameConfigSchema = z
48
54
  .object({
@@ -82,14 +88,19 @@ export const domainFrameConfigSchema = z
82
88
  /** see: https://github.com/farcasterxyz/miniapps/discussions/204 */
83
89
  noindex: z.boolean().optional(),
84
90
  /** see https://github.com/farcasterxyz/miniapps/discussions/256 */
85
- requiredChains: z.array(z.enum(chainList)).max(chainList.length).optional(),
91
+ requiredChains: z
92
+ .array(z.enum(chainList))
93
+ .transform(removeArrayDuplicates)
94
+ .optional(),
86
95
  requiredCapabilities: z
87
96
  .array(z.enum(miniAppHostCapabilityList))
88
- .max(miniAppHostCapabilityList.length)
97
+ .transform(removeArrayDuplicates)
89
98
  .optional(),
90
99
  /** see https://github.com/farcasterxyz/miniapps/discussions/158 */
91
100
  /** Documentation will be added once this feature is finalized. */
92
101
  castShareUrl: secureUrlSchema.optional(),
102
+ /** Canonical domain for the frame application */
103
+ canonicalDomain: domainSchema.optional(),
93
104
  })
94
105
  .refine(
95
106
  (data) => {
@@ -58,6 +58,34 @@ export const hexColorSchema = z
58
58
  'Invalid hex color code. It should be in the format #RRGGBB or #RGB.',
59
59
  })
60
60
 
61
+ // Domain validation regex:
62
+ // - Each label (part between dots) must start and end with alphanumeric
63
+ // - Labels can contain hyphens in the middle
64
+ // - Cannot have consecutive dots
65
+ // - Must have at least one dot (TLD required)
66
+ // - TLD must be at least 2 characters and only letters
67
+ const DOMAIN_REGEX =
68
+ /^(?!.*\.\.)([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/
69
+
70
+ export const domainSchema = z
71
+ .string()
72
+ .max(1024)
73
+ .regex(DOMAIN_REGEX, {
74
+ message: 'Must be a valid domain name (e.g., example.com, sub.example.com)',
75
+ })
76
+ .refine((value) => !value.includes('://'), {
77
+ message: 'Domain must not include protocol (http://, https://, etc.)',
78
+ })
79
+ .refine((value) => !value.includes('/'), {
80
+ message: 'Domain must not include path separators',
81
+ })
82
+ .refine((value) => !value.includes('@'), {
83
+ message: 'Domain must not include @ symbol',
84
+ })
85
+ .refine((value) => !value.includes(':'), {
86
+ message: 'Domain must not include port numbers',
87
+ })
88
+
61
89
  export const aspectRatioSchema = z.union([z.literal('1:1'), z.literal('3:2')])
62
90
 
63
91
  export const encodedJsonFarcasterSignatureSchema = z.object({
package/src/types.ts CHANGED
@@ -43,7 +43,7 @@ export type SetPrimaryButton = (options: SetPrimaryButtonOptions) => void
43
43
  // Export haptics types
44
44
  export type { ImpactOccurred, NotificationOccurred, SelectionChanged }
45
45
 
46
- export const miniAppHostCapabilityList: [string, ...string[]] = [
46
+ export const miniAppHostCapabilityList = [
47
47
  'wallet.getEthereumProvider',
48
48
  'wallet.getSolanaProvider',
49
49
  'actions.ready',
@@ -62,27 +62,9 @@ export const miniAppHostCapabilityList: [string, ...string[]] = [
62
62
  'haptics.notificationOccurred',
63
63
  'haptics.selectionChanged',
64
64
  'back',
65
- ]
65
+ ] as const
66
66
 
67
- export type MiniAppHostCapability =
68
- | 'wallet.getEthereumProvider'
69
- | 'wallet.getSolanaProvider'
70
- | 'actions.ready'
71
- | 'actions.openUrl'
72
- | 'actions.close'
73
- | 'actions.setPrimaryButton'
74
- | 'actions.addMiniApp'
75
- | 'actions.signIn'
76
- | 'actions.viewCast'
77
- | 'actions.viewProfile'
78
- | 'actions.composeCast'
79
- | 'actions.viewToken'
80
- | 'actions.sendToken'
81
- | 'actions.swapToken'
82
- | 'haptics.impactOccurred'
83
- | 'haptics.notificationOccurred'
84
- | 'haptics.selectionChanged'
85
- | 'back'
67
+ export type MiniAppHostCapability = (typeof miniAppHostCapabilityList)[number]
86
68
 
87
69
  export type GetCapabilities = () => Promise<MiniAppHostCapability[]>
88
70