@farcaster/frame-core 0.0.0-canary-20250430150627

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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/actions/AddFrame.d.ts +36 -0
  4. package/dist/actions/AddFrame.js +57 -0
  5. package/dist/actions/ComposeCast.d.ts +32 -0
  6. package/dist/actions/ComposeCast.js +2 -0
  7. package/dist/actions/Ready.d.ts +13 -0
  8. package/dist/actions/Ready.js +6 -0
  9. package/dist/actions/SendToken.d.ts +48 -0
  10. package/dist/actions/SendToken.js +2 -0
  11. package/dist/actions/SignIn.d.ts +41 -0
  12. package/dist/actions/SignIn.js +47 -0
  13. package/dist/actions/SwapToken.d.ts +46 -0
  14. package/dist/actions/SwapToken.js +2 -0
  15. package/dist/actions/ViewProfile.d.ts +4 -0
  16. package/dist/actions/ViewProfile.js +2 -0
  17. package/dist/actions/ViewToken.d.ts +4 -0
  18. package/dist/actions/ViewToken.js +2 -0
  19. package/dist/actions/index.d.ts +8 -0
  20. package/dist/actions/index.js +44 -0
  21. package/dist/context.d.ts +72 -0
  22. package/dist/context.js +2 -0
  23. package/dist/errors.d.ts +13 -0
  24. package/dist/errors.js +12 -0
  25. package/dist/index.d.ts +7 -0
  26. package/dist/index.js +46 -0
  27. package/dist/internal/types.d.ts +8 -0
  28. package/dist/internal/types.js +2 -0
  29. package/dist/manifest.d.ts +101 -0
  30. package/dist/manifest.js +2 -0
  31. package/dist/schemas/embeds.d.ts +243 -0
  32. package/dist/schemas/embeds.js +32 -0
  33. package/dist/schemas/events.d.ts +131 -0
  34. package/dist/schemas/events.js +25 -0
  35. package/dist/schemas/index.d.ts +5 -0
  36. package/dist/schemas/index.js +21 -0
  37. package/dist/schemas/manifest.d.ts +208 -0
  38. package/dist/schemas/manifest.js +61 -0
  39. package/dist/schemas/notifications.d.ts +60 -0
  40. package/dist/schemas/notifications.js +23 -0
  41. package/dist/schemas/shared.d.ts +39 -0
  42. package/dist/schemas/shared.js +58 -0
  43. package/dist/types.d.ts +60 -0
  44. package/dist/types.js +21 -0
  45. package/dist/wallet/ethereum.d.ts +47 -0
  46. package/dist/wallet/ethereum.js +2 -0
  47. package/dist/wallet/index.d.ts +1 -0
  48. package/dist/wallet/index.js +37 -0
  49. package/esm/actions/AddFrame.d.ts +36 -0
  50. package/esm/actions/AddFrame.js +19 -0
  51. package/esm/actions/ComposeCast.d.ts +32 -0
  52. package/esm/actions/ComposeCast.js +1 -0
  53. package/esm/actions/Ready.d.ts +13 -0
  54. package/esm/actions/Ready.js +3 -0
  55. package/esm/actions/SendToken.d.ts +48 -0
  56. package/esm/actions/SendToken.js +1 -0
  57. package/esm/actions/SignIn.d.ts +41 -0
  58. package/esm/actions/SignIn.js +10 -0
  59. package/esm/actions/SwapToken.d.ts +46 -0
  60. package/esm/actions/SwapToken.js +1 -0
  61. package/esm/actions/ViewProfile.d.ts +4 -0
  62. package/esm/actions/ViewProfile.js +1 -0
  63. package/esm/actions/ViewToken.d.ts +4 -0
  64. package/esm/actions/ViewToken.js +1 -0
  65. package/esm/actions/index.d.ts +8 -0
  66. package/esm/actions/index.js +8 -0
  67. package/esm/context.d.ts +72 -0
  68. package/esm/context.js +1 -0
  69. package/esm/errors.d.ts +13 -0
  70. package/esm/errors.js +8 -0
  71. package/esm/index.d.ts +7 -0
  72. package/esm/index.js +7 -0
  73. package/esm/internal/types.d.ts +8 -0
  74. package/esm/internal/types.js +1 -0
  75. package/esm/manifest.d.ts +101 -0
  76. package/esm/manifest.js +1 -0
  77. package/esm/schemas/embeds.d.ts +243 -0
  78. package/esm/schemas/embeds.js +28 -0
  79. package/esm/schemas/events.d.ts +131 -0
  80. package/esm/schemas/events.js +22 -0
  81. package/esm/schemas/index.d.ts +5 -0
  82. package/esm/schemas/index.js +5 -0
  83. package/esm/schemas/manifest.d.ts +208 -0
  84. package/esm/schemas/manifest.js +58 -0
  85. package/esm/schemas/notifications.d.ts +60 -0
  86. package/esm/schemas/notifications.js +20 -0
  87. package/esm/schemas/shared.d.ts +39 -0
  88. package/esm/schemas/shared.js +54 -0
  89. package/esm/tsconfig.tsbuildinfo +1 -0
  90. package/esm/types.d.ts +60 -0
  91. package/esm/types.js +3 -0
  92. package/esm/wallet/ethereum.d.ts +47 -0
  93. package/esm/wallet/ethereum.js +1 -0
  94. package/esm/wallet/index.d.ts +1 -0
  95. package/esm/wallet/index.js +1 -0
  96. package/package.json +41 -0
  97. package/src/actions/AddFrame.ts +51 -0
  98. package/src/actions/ComposeCast.ts +36 -0
  99. package/src/actions/Ready.ts +15 -0
  100. package/src/actions/SendToken.ts +57 -0
  101. package/src/actions/SignIn.ts +51 -0
  102. package/src/actions/SwapToken.ts +54 -0
  103. package/src/actions/ViewProfile.ts +5 -0
  104. package/src/actions/ViewToken.ts +5 -0
  105. package/src/actions/index.ts +8 -0
  106. package/src/context.ts +90 -0
  107. package/src/errors.ts +21 -0
  108. package/src/index.ts +7 -0
  109. package/src/internal/types.ts +20 -0
  110. package/src/manifest.ts +113 -0
  111. package/src/schemas/embeds.ts +44 -0
  112. package/src/schemas/events.ts +41 -0
  113. package/src/schemas/index.ts +5 -0
  114. package/src/schemas/manifest.ts +68 -0
  115. package/src/schemas/notifications.ts +33 -0
  116. package/src/schemas/shared.ts +81 -0
  117. package/src/types.ts +95 -0
  118. package/src/wallet/ethereum.ts +65 -0
  119. package/src/wallet/index.ts +1 -0
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@farcaster/frame-core",
3
+ "version": "0.0.0-canary-20250430150627",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/farcasterxyz/frames.git",
8
+ "directory": "packages/frame-core"
9
+ },
10
+ "main": "dist/index.js",
11
+ "module": "esm/index.js",
12
+ "files": [
13
+ "dist",
14
+ "esm",
15
+ "src"
16
+ ],
17
+ "devDependencies": {
18
+ "@vitest/coverage-v8": "^2.1.8",
19
+ "typescript": "^5.7.2",
20
+ "vitest": "^2.1.9",
21
+ "@farcaster/tsconfig": "0.0.2"
22
+ },
23
+ "dependencies": {
24
+ "ox": "^0.4.4",
25
+ "zod": "^3.24.1"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "scripts": {
31
+ "clean": "rm -rf dist esm",
32
+ "prebuild": "npm run clean",
33
+ "build": "pnpm build:cjs & pnpm build:esm",
34
+ "build:cjs": "tsc -p tsconfig.node.json",
35
+ "build:esm": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "test:coverage": "vitest --coverage"
40
+ }
41
+ }
@@ -0,0 +1,51 @@
1
+ import * as Errors from '../errors'
2
+ import type { OneOf } from '../internal/types'
3
+ import type { FrameNotificationDetails } from '../schemas'
4
+
5
+ export type AddFrameResult = {
6
+ notificationDetails?: FrameNotificationDetails
7
+ }
8
+
9
+ export type AddFrame = () => Promise<AddFrameResult>
10
+
11
+ type InvalidDomainManifestJsonError = {
12
+ type: 'invalid_domain_manifest'
13
+ }
14
+
15
+ type RejectedByUserJsonError = {
16
+ type: 'rejected_by_user'
17
+ }
18
+
19
+ export type AddFrameJsonError =
20
+ | InvalidDomainManifestJsonError
21
+ | RejectedByUserJsonError
22
+
23
+ export type AddFrameRejectedReason = AddFrameJsonError['type']
24
+
25
+ export type AddFrameJsonResult = OneOf<
26
+ { result: AddFrameResult } | { error: AddFrameJsonError }
27
+ >
28
+
29
+ export type WireAddFrame = () => Promise<AddFrameJsonResult>
30
+
31
+ /**
32
+ * Thrown when the frame does not have a valid domain manifest.
33
+ */
34
+ export class InvalidDomainManifest extends Errors.BaseError {
35
+ override readonly name = 'AddFrame.InvalidDomainManifest'
36
+
37
+ constructor() {
38
+ super('Invalid domain manifest')
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Thrown when add frame action was rejected by the user.
44
+ */
45
+ export class RejectedByUser extends Errors.BaseError {
46
+ override readonly name = 'AddFrame.RejectedByUser'
47
+
48
+ constructor() {
49
+ super('Add frame rejected by user')
50
+ }
51
+ }
@@ -0,0 +1,36 @@
1
+ export type Options<close extends boolean | undefined = undefined> = {
2
+ /**
3
+ * Suggested text for the body of the cast.
4
+ *
5
+ * Mentions can be included using the human-writeable form (e.g. @farcaster).
6
+ **/
7
+ text?: string
8
+
9
+ /** Suggested embeds. Max two. */
10
+ embeds?: [] | [string] | [string, string]
11
+
12
+ /** Suggested parent. */
13
+ parent?: { type: 'cast'; hash: string }
14
+
15
+ /** Whether the app should be closed when this action is called. */
16
+ close?: close
17
+ }
18
+
19
+ export type Result<close extends boolean | undefined = undefined> =
20
+ close extends true
21
+ ? undefined
22
+ : {
23
+ cast: {
24
+ /** Cast of the created cast */
25
+ hash: string
26
+
27
+ /** Text of the created cast */
28
+ text?: string
29
+
30
+ /** Embeds of the created cast */
31
+ embeds?: [] | [string] | [string, string]
32
+
33
+ /** Parent of the created cast */
34
+ parent?: { type: 'cast'; hash: string }
35
+ }
36
+ }
@@ -0,0 +1,15 @@
1
+ export type ReadyOptions = {
2
+ /**
3
+ * Disable native gestures. Use this option if your frame uses gestures
4
+ * that conflict with native gestures.
5
+ *
6
+ * @defaultValue false
7
+ */
8
+ disableNativeGestures: boolean
9
+ }
10
+
11
+ export const DEFAULT_READY_OPTIONS = {
12
+ disableNativeGestures: false,
13
+ } satisfies ReadyOptions
14
+
15
+ export type Ready = (options?: Partial<ReadyOptions>) => void
@@ -0,0 +1,57 @@
1
+ export type SendTokenOptions = {
2
+ /**
3
+ * CAIP-19 asset ID
4
+ * For example, Base USDC:
5
+ * eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
6
+ */
7
+ token?: string
8
+
9
+ /**
10
+ * Token amount, as numeric string.
11
+ * For example, 10 USDC: 1000000
12
+ */
13
+ amount?: string
14
+
15
+ /**
16
+ * Recipient address.
17
+ */
18
+ recipientAddress?: string
19
+
20
+ /**
21
+ * Recipient fid.
22
+ */
23
+ recipientFid?: number
24
+ }
25
+
26
+ type SendTokenDetails = {
27
+ /**
28
+ * Tx identifier.
29
+ */
30
+ transaction: `0x${string}`
31
+ }
32
+
33
+ type SendTokenErrorDetails = {
34
+ /**
35
+ * Error code.
36
+ */
37
+ error: string
38
+ /**
39
+ * Error message.
40
+ */
41
+ message?: string
42
+ }
43
+
44
+ export type SendTokenErrorReason = 'rejected_by_user' | 'send_failed'
45
+
46
+ export type SendTokenResult =
47
+ | {
48
+ success: true
49
+ send: SendTokenDetails
50
+ }
51
+ | {
52
+ success: false
53
+ reason: SendTokenErrorReason
54
+ error?: SendTokenErrorDetails
55
+ }
56
+
57
+ export type SendToken = (options: SendTokenOptions) => Promise<SendTokenResult>
@@ -0,0 +1,51 @@
1
+ import * as Errors from '../errors'
2
+ import type { OneOf } from '../internal/types'
3
+
4
+ export type SignInOptions = {
5
+ /**
6
+ * A random string used to prevent replay attacks.
7
+ */
8
+ nonce: string
9
+
10
+ /**
11
+ * Start time at which the signature becomes valid.
12
+ * ISO 8601 datetime.
13
+ */
14
+ notBefore?: string
15
+
16
+ /**
17
+ * Expiration time at which the signature is no longer valid.
18
+ * ISO 8601 datetime.
19
+ */
20
+ expirationTime?: string
21
+ }
22
+
23
+ export type SignInResult = {
24
+ signature: string
25
+ message: string
26
+ }
27
+
28
+ export type SignIn = (options: SignInOptions) => Promise<SignInResult>
29
+
30
+ type RejectedByUserJsonError = {
31
+ type: 'rejected_by_user'
32
+ }
33
+
34
+ export type SignInJsonError = RejectedByUserJsonError
35
+
36
+ export type SignInJsonResult = OneOf<
37
+ { result: SignInResult } | { error: SignInJsonError }
38
+ >
39
+
40
+ export type WireSignIn = (options: SignInOptions) => Promise<SignInJsonResult>
41
+
42
+ /**
43
+ * Thrown when a sign in action was rejected.
44
+ */
45
+ export class RejectedByUser extends Errors.BaseError {
46
+ override readonly name = 'SignIn.RejectedByUser'
47
+
48
+ constructor() {
49
+ super('Sign in rejected by user')
50
+ }
51
+ }
@@ -0,0 +1,54 @@
1
+ export type SwapTokenOptions = {
2
+ /**
3
+ * CAIP-19 asset ID
4
+ * For example, Base USDC:
5
+ * eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
6
+ */
7
+ sellToken?: string
8
+
9
+ /**
10
+ * CAIP-19 token ID. For example, OP ETH:
11
+ * eip155:10/native
12
+ */
13
+ buyToken?: string
14
+
15
+ /**
16
+ * Sell token amount, as numeric string.
17
+ * For example, 10 USDC: 1000000
18
+ */
19
+ sellAmount?: string
20
+ }
21
+
22
+ type SwapTokenDetails = {
23
+ /**
24
+ * Array of tx identifiers in order of execution.
25
+ * Some swaps will have both an approval and swap tx.
26
+ */
27
+ transactions: `0x${string}`[]
28
+ }
29
+
30
+ type SwapTokenErrorDetails = {
31
+ /**
32
+ * Error code.
33
+ */
34
+ error: string
35
+ /**
36
+ * Error message.
37
+ */
38
+ message?: string
39
+ }
40
+
41
+ export type SwapErrorReason = 'rejected_by_user' | 'swap_failed'
42
+
43
+ export type SwapTokenResult =
44
+ | {
45
+ success: true
46
+ swap: SwapTokenDetails
47
+ }
48
+ | {
49
+ success: false
50
+ reason: SwapErrorReason
51
+ error?: SwapTokenErrorDetails
52
+ }
53
+
54
+ export type SwapToken = (options: SwapTokenOptions) => Promise<SwapTokenResult>
@@ -0,0 +1,5 @@
1
+ export type ViewProfileOptions = {
2
+ fid: number
3
+ }
4
+
5
+ export type ViewProfile = (options: ViewProfileOptions) => Promise<void>
@@ -0,0 +1,5 @@
1
+ export type ViewTokenOptions = {
2
+ token: string
3
+ }
4
+
5
+ export type ViewToken = (options: ViewTokenOptions) => Promise<void>
@@ -0,0 +1,8 @@
1
+ export * as AddFrame from './AddFrame'
2
+ export * as ComposeCast from './ComposeCast'
3
+ export * as Ready from './Ready'
4
+ export * as SignIn from './SignIn'
5
+ export * as SendToken from './SendToken'
6
+ export * as SwapToken from './SwapToken'
7
+ export * as ViewProfile from './ViewProfile'
8
+ export * as ViewToken from './ViewToken'
package/src/context.ts ADDED
@@ -0,0 +1,90 @@
1
+ import type { FrameNotificationDetails } from './schemas'
2
+
3
+ export type CastEmbedLocationContext = {
4
+ type: 'cast_embed'
5
+ embed: string
6
+ cast: {
7
+ fid: number
8
+ hash: string
9
+ }
10
+ }
11
+
12
+ export type NotificationLocationContext = {
13
+ type: 'notification'
14
+ notification: {
15
+ notificationId: string
16
+ title: string
17
+ body: string
18
+ }
19
+ }
20
+
21
+ export type LauncherLocationContext = {
22
+ type: 'launcher'
23
+ }
24
+
25
+ export type ChannelLocationContext = {
26
+ type: 'channel'
27
+ channel: {
28
+ /**
29
+ * Channel key identifier
30
+ */
31
+ key: string
32
+
33
+ /**
34
+ * Channel name
35
+ */
36
+ name: string
37
+
38
+ /**
39
+ * Channel profile image URL
40
+ */
41
+ imageUrl?: string
42
+ }
43
+ }
44
+
45
+ export type LocationContext =
46
+ | CastEmbedLocationContext
47
+ | NotificationLocationContext
48
+ | LauncherLocationContext
49
+ | ChannelLocationContext
50
+
51
+ export type AccountLocation = {
52
+ placeId: string
53
+
54
+ /**
55
+ * Human-readable string describing the location
56
+ */
57
+ description: string
58
+ }
59
+
60
+ export type UserContext = {
61
+ fid: number
62
+ username?: string
63
+ displayName?: string
64
+
65
+ /**
66
+ * Profile image URL
67
+ */
68
+ pfpUrl?: string
69
+ location?: AccountLocation
70
+ }
71
+
72
+ export type SafeAreaInsets = {
73
+ top: number
74
+ bottom: number
75
+ left: number
76
+ right: number
77
+ }
78
+
79
+ export type ClientContext = {
80
+ clientFid: number
81
+ added: boolean
82
+ notificationDetails?: FrameNotificationDetails
83
+ safeAreaInsets?: SafeAreaInsets
84
+ }
85
+
86
+ export type FrameContext = {
87
+ client: ClientContext
88
+ user: UserContext
89
+ location?: LocationContext
90
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,21 @@
1
+ export type GlobalErrorType<name extends string = 'Error'> = Error & {
2
+ name: name
3
+ }
4
+
5
+ export class BaseError<
6
+ cause extends Error | undefined = undefined,
7
+ > extends Error {
8
+ override name = 'BaseError'
9
+ cause: cause
10
+
11
+ constructor(message: string, options: BaseError.Options<cause> = {}) {
12
+ super(message, options.cause ? { cause: options.cause } : undefined)
13
+ this.cause = options.cause as any
14
+ }
15
+ }
16
+
17
+ export declare namespace BaseError {
18
+ type Options<cause extends Error | undefined = Error | undefined> = {
19
+ cause?: cause | undefined
20
+ }
21
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './actions'
2
+ export * from './wallet'
3
+ export * as Errors from './errors'
4
+ export * as Context from './context'
5
+ export * as Manifest from './manifest'
6
+ export * from './types'
7
+ export * from './schemas'
@@ -0,0 +1,20 @@
1
+ type Compute<type> = { [key in keyof type]: type[key] } & unknown
2
+
3
+ type KeyofUnion<type> = type extends type ? keyof type : never
4
+
5
+ export type OneOf<
6
+ union extends object,
7
+ fallback extends object | undefined = undefined,
8
+ ///
9
+ keys extends KeyofUnion<union> = KeyofUnion<union>,
10
+ > = union extends infer item
11
+ ? Compute<
12
+ item & {
13
+ [key in Exclude<keys, keyof item>]?: fallback extends object
14
+ ? key extends keyof fallback
15
+ ? fallback[key]
16
+ : undefined
17
+ : undefined
18
+ }
19
+ >
20
+ : never
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Farcaster manifest for a domain hosted at `/.well-known/farcaster.json`
3
+ */
4
+ export type Manifest = {
5
+ accountAssociation: AccountAssociation
6
+ frame: FrameConfig
7
+ }
8
+
9
+ /**
10
+ * Signed domain association linking this frame to a Farcaster account
11
+ *
12
+ * A DomainAssociation can be generated using the {@link https://warpcast.com/~/developers/domains | Warpcast
13
+ * Domains Developer} tool.
14
+ */
15
+ export type AccountAssociation = {
16
+ /**
17
+ * Base64URL encoded JFS signature
18
+ */
19
+ header: string
20
+
21
+ /**
22
+ * Base64URL encoded payload signature
23
+ */
24
+ payload: string
25
+
26
+ /**
27
+ * Base64URL encoded signature
28
+ */
29
+ signature: string
30
+ }
31
+
32
+ /**
33
+ * Frame configuration
34
+ *
35
+ * @example
36
+ * ``ts
37
+ * const frame: FrameConfig = {
38
+ * version: '1',
39
+ * name: 'Yoink!',
40
+ * homeUrl: 'https://yoink.party',
41
+ * iconUrl: 'https://yoink.party/img/icon.png',
42
+ * imageUrl: 'https://yoink.party/framesV2/opengraph-image',
43
+ * buttonTitle: '🚩 Start',
44
+ * splashImageUrl: 'https://yoink.party/img/splash.png',
45
+ * splashImageBackgroundColor: '#eeeee4',
46
+ * webhookUrl: 'https://yoink.party/webhook'
47
+ * };
48
+ * ``
49
+ */
50
+ export type FrameConfig = {
51
+ /**
52
+ * Manifest version
53
+ *
54
+ * Must be the literal '1'.
55
+ */
56
+ version: '1'
57
+
58
+ /**
59
+ * App name that will be displayed to users
60
+ *
61
+ * Max length of 32 characters.
62
+ */
63
+ name: string
64
+
65
+ /**
66
+ * Default launch URL
67
+ *
68
+ * Max length of 1024 characters.
69
+ */
70
+ homeUrl: string
71
+
72
+ /**
73
+ * Icon URL
74
+ *
75
+ * Max length of 1024 characters. Image must be 200x200px and less than 1MB.
76
+ */
77
+ iconUrl: string
78
+
79
+ /**
80
+ * Image URL
81
+ *
82
+ * Max length of 1024 characters. Image must have a 3:2 ratio.
83
+ */
84
+ imageUrl: string
85
+
86
+ /**
87
+ * Default button title to use when frame is rendered.
88
+ *
89
+ * Max length of 32 characters.
90
+ */
91
+ buttonTitle: string
92
+
93
+ /**
94
+ * Splash image URL
95
+ *
96
+ * Max length of 1024 characters. Image must be 200x200px and less than 1MB.
97
+ */
98
+ splashImageUrl?: string
99
+
100
+ /**
101
+ * Splash background color
102
+ *
103
+ * Must be a hex color code.
104
+ */
105
+ splashBackgroundColor?: string
106
+
107
+ /**
108
+ * URL to which clients will POST server events.
109
+ * Max length of 1024 characters.
110
+ * Required if the frame application uses notifications.
111
+ */
112
+ webhookUrl?: string
113
+ }
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod'
2
+ import {
3
+ aspectRatioSchema,
4
+ buttonTitleSchema,
5
+ caip19TokenSchema,
6
+ frameNameSchema,
7
+ hexColorSchema,
8
+ secureUrlSchema,
9
+ } from './shared'
10
+
11
+ export const actionLaunchFrameSchema = z.object({
12
+ type: z.literal('launch_frame'),
13
+ name: frameNameSchema,
14
+ url: secureUrlSchema.optional(),
15
+ splashImageUrl: secureUrlSchema.optional(),
16
+ splashBackgroundColor: hexColorSchema.optional(),
17
+ })
18
+
19
+ export const actionViewTokenSchema = z.object({
20
+ type: z.literal('view_token'),
21
+ token: caip19TokenSchema,
22
+ })
23
+
24
+ export const actionSchema = z.discriminatedUnion('type', [
25
+ actionLaunchFrameSchema,
26
+ actionViewTokenSchema,
27
+ ])
28
+
29
+ export const buttonSchema = z.object({
30
+ title: buttonTitleSchema,
31
+ action: actionSchema,
32
+ })
33
+
34
+ export const frameEmbedNextSchema = z.object({
35
+ version: z.literal('next'),
36
+ imageUrl: secureUrlSchema,
37
+ aspectRatio: aspectRatioSchema.optional(),
38
+ button: buttonSchema,
39
+ })
40
+
41
+ export const safeParseFrameEmbed = (rawResponse: unknown) =>
42
+ frameEmbedNextSchema.safeParse(rawResponse)
43
+
44
+ export type FrameEmbedNext = z.infer<typeof frameEmbedNextSchema>
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod'
2
+ import { notificationDetailsSchema } from './notifications'
3
+
4
+ export const eventFrameAddedSchema = z.object({
5
+ event: z.literal('frame_added'),
6
+ notificationDetails: notificationDetailsSchema.optional(),
7
+ })
8
+
9
+ export type EventFrameAdded = z.infer<typeof eventFrameAddedSchema>
10
+
11
+ export const eventFrameRemovedSchema = z.object({
12
+ event: z.literal('frame_removed'),
13
+ })
14
+
15
+ export type EventFrameRemoved = z.infer<typeof eventFrameRemovedSchema>
16
+
17
+ export const eventNotificationsEnabledSchema = z.object({
18
+ event: z.literal('notifications_enabled'),
19
+ notificationDetails: notificationDetailsSchema.required(),
20
+ })
21
+
22
+ export type EventNotificationsEnabled = z.infer<
23
+ typeof eventNotificationsEnabledSchema
24
+ >
25
+
26
+ export const notificationsDisabledSchema = z.object({
27
+ event: z.literal('notifications_disabled'),
28
+ })
29
+
30
+ export type EventNotificationsDisabled = z.infer<
31
+ typeof notificationsDisabledSchema
32
+ >
33
+
34
+ export const serverEventSchema = z.discriminatedUnion('event', [
35
+ eventFrameAddedSchema,
36
+ eventFrameRemovedSchema,
37
+ eventNotificationsEnabledSchema,
38
+ notificationsDisabledSchema,
39
+ ])
40
+
41
+ export type FrameServerEvent = z.infer<typeof serverEventSchema>
@@ -0,0 +1,5 @@
1
+ export * from './embeds'
2
+ export * from './events'
3
+ export * from './shared'
4
+ export * from './manifest'
5
+ export * from './notifications'