├── .gitignore
├── .husky
└── pre-commit
├── .prettierrc.yml
├── README.md
├── docs
├── .vitepress
│ ├── config.mts
│ └── theme
│ │ ├── custom.css
│ │ └── index.js
├── assets
│ ├── actions
│ │ ├── frame_type.png
│ │ └── message_type.png
│ ├── architecture.png
│ ├── contracts.png
│ ├── frame_app.png
│ ├── frame_og.png
│ ├── frame_poll.png
│ ├── gcp_compute_engine_api.png
│ ├── gcp_hubble_running.png
│ ├── gcp_project_id.png
│ ├── gcp_terraform_apply.png
│ ├── gcp_terraform_plan.png
│ ├── gcp_vm_overview.png
│ ├── google_cloud_shell.png
│ ├── high-level.png
│ ├── hub.png
│ ├── registry-contracts.png
│ └── usernames.png
├── auth-kit
│ ├── auth-kit-provider.md
│ ├── client
│ │ ├── app
│ │ │ ├── client.md
│ │ │ ├── create-channel.md
│ │ │ ├── status.md
│ │ │ ├── verify-sign-in-message.md
│ │ │ └── watch-status.md
│ │ ├── introduction.md
│ │ └── wallet
│ │ │ ├── authenticate.md
│ │ │ ├── build-sign-in-message.md
│ │ │ ├── client.md
│ │ │ └── parse-sign-in-uri.md
│ ├── examples.md
│ ├── hooks
│ │ ├── use-profile.md
│ │ ├── use-sign-in-message.md
│ │ └── use-sign-in.md
│ ├── index.md
│ ├── installation.md
│ ├── service-providers.md
│ └── sign-in-button.md
├── developers
│ ├── frames
│ │ ├── advanced.md
│ │ ├── best-practices.md
│ │ ├── frog_frame_preview.png
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ ├── resources.md
│ │ ├── safari_frame.gif
│ │ └── spec.md
│ ├── guides
│ │ ├── accounts
│ │ │ ├── change-custody.md
│ │ │ ├── change-fname.md
│ │ │ ├── change-recovery.md
│ │ │ ├── create-account-key.md
│ │ │ ├── create-account.md
│ │ │ ├── find-by-name.md
│ │ │ └── register-ens.md
│ │ ├── advanced
│ │ │ ├── decode-key-metadata.md
│ │ │ └── query-signups.md
│ │ ├── apps
│ │ │ ├── feed.md
│ │ │ └── replicate.md
│ │ ├── basics
│ │ │ └── hello-world.md
│ │ ├── querying
│ │ │ ├── fetch-casts.md
│ │ │ ├── fetch-channel-casts.md
│ │ │ ├── fetch-profile.md
│ │ │ └── setting-up.md
│ │ └── writing
│ │ │ ├── casts.md
│ │ │ ├── messages.md
│ │ │ ├── submit-messages.md
│ │ │ └── verify-address.md
│ ├── index.md
│ ├── resources.md
│ ├── siwf
│ │ ├── index.md
│ │ └── siwf_demo.avifs
│ └── utilities.md
├── examples
│ └── contracts
│ │ ├── clients.ts
│ │ ├── metadata.ts
│ │ └── signer.ts
├── hubble
│ ├── hubble.md
│ ├── install.md
│ ├── migrating.md
│ ├── monitoring.md
│ ├── networks.md
│ ├── troubleshooting.md
│ ├── tutorials.md
│ └── tutorials
│ │ └── gcp.md
├── index.md
├── learn
│ ├── architecture
│ │ ├── contracts.md
│ │ ├── ens-names.md
│ │ ├── hubs.md
│ │ └── overview.md
│ ├── contributing
│ │ ├── fips.md
│ │ ├── governance.md
│ │ └── overview.md
│ ├── index.md
│ └── what-is-farcaster
│ │ ├── accounts.md
│ │ ├── apps.md
│ │ ├── channels.md
│ │ ├── messages.md
│ │ └── usernames.md
├── public
│ ├── icon.png
│ └── og-image.png
└── reference
│ ├── actions
│ └── spec.md
│ ├── contracts
│ ├── deployments.md
│ ├── faq.md
│ ├── index.md
│ └── reference
│ │ ├── bundler.md
│ │ ├── id-gateway.md
│ │ ├── id-registry.md
│ │ ├── key-gateway.md
│ │ ├── key-registry.md
│ │ ├── signed-key-request-validator.md
│ │ └── storage-registry.md
│ ├── fname
│ └── api.md
│ ├── frames-redirect.md
│ ├── hubble
│ ├── architecture.md
│ ├── datatypes
│ │ ├── events.md
│ │ └── messages.md
│ ├── grpcapi
│ │ ├── casts.md
│ │ ├── events.md
│ │ ├── fids.md
│ │ ├── grpcapi.md
│ │ ├── links.md
│ │ ├── message.md
│ │ ├── onchain.md
│ │ ├── reactions.md
│ │ ├── storagelimits.md
│ │ ├── sync.md
│ │ ├── userdata.md
│ │ ├── usernameproof.md
│ │ └── verification.md
│ └── httpapi
│ │ ├── casts.md
│ │ ├── events.md
│ │ ├── fids.md
│ │ ├── httpapi.md
│ │ ├── info.md
│ │ ├── links.md
│ │ ├── message.md
│ │ ├── onchain.md
│ │ ├── reactions.md
│ │ ├── storagelimits.md
│ │ ├── userdata.md
│ │ ├── usernameproof.md
│ │ └── verification.md
│ ├── index.md
│ ├── replicator
│ └── schema.md
│ ├── third-party
│ └── neynar
│ │ └── index.md
│ └── warpcast
│ ├── api.md
│ ├── cast-composer-intents.md
│ ├── direct-casts.md
│ ├── embeds.md
│ ├── signer-requests.md
│ ├── signers.md
│ └── videos.md
├── package.json
├── vercel.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # node-waf configuration
29 | .lock-wscript
30 |
31 | # Compiled binary addons (https://nodejs.org/api/addons.html)
32 | build/Release
33 |
34 | # Dependency directories
35 | node_modules/
36 | jspm_packages/
37 |
38 | # TypeScript v1 declaration files
39 | typings/
40 |
41 | # TypeScript cache
42 | *.tsbuildinfo
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 | .env.test
62 |
63 | # parcel-bundler cache (https://parceljs.org/)
64 | .cache
65 |
66 |
67 | # Vitepress configuration files
68 | docs/.vitepress/dist
69 | docs/.vitepress/cache
70 |
71 | .DS_Store
72 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | yarn lint-staged
5 |
--------------------------------------------------------------------------------
/.prettierrc.yml:
--------------------------------------------------------------------------------
1 | semi: true
2 | trailingComma: 'es5'
3 | singleQuote: true
4 | printWidth: 80
5 | tabWidth: 2
6 | useTabs: false
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # docs.farcaster.xyz
2 |
3 | Documentation for the Farcaster Protocol
4 |
5 | ### Getting Started
6 |
7 | 1. Run `yarn`
8 | 2. Run `yarn docs:dev`
9 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/custom.css:
--------------------------------------------------------------------------------
1 | /* .vitepress/theme/custom.css */
2 |
3 |
4 | /**
5 | * Colors: Palette
6 | *
7 | * The primitive colors used for accent colors. These colors are referenced
8 | * by functional colors such as "Text", "Background", or "Brand".
9 | *
10 | * Each color have exact same color scale system with 3 levels of solid
11 | * colors with different brightness, and 1 soft color.
12 | *
13 | * - `XXX-1`: The most solid color used mainly for colored text. It must
14 | * satisfy the contrast ratio against when used on top of `XXX-soft`.
15 | *
16 | * - `XXX-2`: The color used mainly for hover state of the button.
17 | *
18 | * - `XXX-3`: The color for solid background, such as bg color of the button.
19 | * It must satisfy the contrast ratio with pure white (#ffffff) text on
20 | * top of it.
21 | *
22 | * - `XXX-soft`: The color used for subtle background such as custom container
23 | * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
24 | * on top of it.
25 | *
26 | * The soft color must be semi transparent alpha channel. This is crucial
27 | * because it allows adding multiple "soft" colors on top of each other
28 | * to create a accent, such as when having inline code block inside
29 | * custom containers.
30 | * -------------------------------------------------------------------------- */
31 |
32 | :root {
33 | --vp-c-purple-1: #8a63d2;
34 | --vp-c-purple-2: #6944BA;
35 | --vp-c-purple-3: #7C65C1;
36 | --vp-c-purple-soft: rgba(138, 99, 210, 0.2);
37 | }
38 |
39 |
40 | /**
41 | * Colors: Function
42 | *
43 | * - `default`: The color used purely for subtle indication without any
44 | * special meanings attached to it such as bg color for menu hover state.
45 | *
46 | * - `brand`: Used for primary brand colors, such as link text, button with
47 | * brand theme, etc.
48 | *
49 | * - `tip`: Used to indicate useful information. The default theme uses the
50 | * brand color for this by default.
51 | *
52 | * - `warning`: Used to indicate warning to the users. Used in custom
53 | * container, badges, etc.
54 | *
55 | * - `danger`: Used to show error, or dangerous message to the users. Used
56 | * in custom container, badges, etc.
57 | *
58 | * To understand the scaling system, refer to "Colors: Palette" section.
59 | * -------------------------------------------------------------------------- */
60 |
61 | :root {
62 | --vp-c-brand-1: var(--vp-c-purple-1);
63 | --vp-c-brand-2: var(--vp-c-purple-2);
64 | --vp-c-brand-3: var(--vp-c-purple-3);
65 | --vp-c-brand-soft: var(--vp-c-purple-soft);
66 |
67 | }
68 |
69 | :root {
70 | --vp-c-green: #8a63d2;
71 | --vp-c-green-light: #9c83d5;
72 | --vp-c-green-lighter: #c2b2e5;
73 | --vp-c-green-dark: #6950a3;
74 | --vp-c-green-darker: #5d468e;
75 | --vp-c-green-dimm-1: rgba(138, 99, 210, 0.05);
76 | --vp-c-green-dimm-2: rgba(138, 99, 210, 0.2);
77 | --vp-c-green-dimm-3: rgba(138, 99, 210, 0.5);
78 | }
79 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.js:
--------------------------------------------------------------------------------
1 | // .vitepress/theme/index.js
2 | import DefaultTheme from 'vitepress/theme'
3 | import './custom.css'
4 |
5 | export default DefaultTheme
--------------------------------------------------------------------------------
/docs/assets/actions/frame_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/actions/frame_type.png
--------------------------------------------------------------------------------
/docs/assets/actions/message_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/actions/message_type.png
--------------------------------------------------------------------------------
/docs/assets/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/architecture.png
--------------------------------------------------------------------------------
/docs/assets/contracts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/contracts.png
--------------------------------------------------------------------------------
/docs/assets/frame_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/frame_app.png
--------------------------------------------------------------------------------
/docs/assets/frame_og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/frame_og.png
--------------------------------------------------------------------------------
/docs/assets/frame_poll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/frame_poll.png
--------------------------------------------------------------------------------
/docs/assets/gcp_compute_engine_api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_compute_engine_api.png
--------------------------------------------------------------------------------
/docs/assets/gcp_hubble_running.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_hubble_running.png
--------------------------------------------------------------------------------
/docs/assets/gcp_project_id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_project_id.png
--------------------------------------------------------------------------------
/docs/assets/gcp_terraform_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_terraform_apply.png
--------------------------------------------------------------------------------
/docs/assets/gcp_terraform_plan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_terraform_plan.png
--------------------------------------------------------------------------------
/docs/assets/gcp_vm_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/gcp_vm_overview.png
--------------------------------------------------------------------------------
/docs/assets/google_cloud_shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/google_cloud_shell.png
--------------------------------------------------------------------------------
/docs/assets/high-level.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/high-level.png
--------------------------------------------------------------------------------
/docs/assets/hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/hub.png
--------------------------------------------------------------------------------
/docs/assets/registry-contracts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/registry-contracts.png
--------------------------------------------------------------------------------
/docs/assets/usernames.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/assets/usernames.png
--------------------------------------------------------------------------------
/docs/auth-kit/auth-kit-provider.md:
--------------------------------------------------------------------------------
1 | # `AuthKitProvider`
2 |
3 | Wrap your application in an `AuthKitProvider` to use Farcaster Auth. This provider component stores configuration information about your app and makes it available to auth-kit components and hooks.
4 |
5 | **Note:** You must create an `AuthKitProvider` to use Farcaster Connect. Don't forget to create one at the top level of your application.
6 |
7 | ```tsx
8 | const config = {
9 | domain: 'example.com',
10 | siweUri: 'https://example.com/login',
11 | rpcUrl: process.env.OP_MAINNET_RPC_URL,
12 | relay: 'https://relay.farcaster.xyz',
13 | };
14 |
15 | const App = () => {
16 | return (
17 | {/* Your App */}
18 | );
19 | };
20 | ```
21 |
22 | # Props
23 |
24 | | Prop | Type | Required | Description |
25 | | -------- | --------------- | -------- | --------------------------------------------------------- |
26 | | `config` | `AuthKitConfig` | No | Configuration object. See the options in the table below. |
27 |
28 | `config` object options:
29 |
30 | | Parameter | Type | Required | Description | Default |
31 | | --------- | -------- | -------- | ---------------------------------- | ----------------------------- |
32 | | `domain` | `string` | No | The domain of your application. | `window.location.host` |
33 | | `siweUri` | `string` | No | The login URL of your application. | `window.location.href` |
34 | | `relay` | `string` | No | Farcaster Auth relay server URL | `https://relay.farcaster.xyz` |
35 | | `rpcUrl` | `string` | No | Optimism RPC server URL | `https://mainnet.optimism.io` |
36 | | `version` | `string` | No | Farcaster Auth version | `v1` |
37 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/app/client.md:
--------------------------------------------------------------------------------
1 | # App Client
2 |
3 | If you're building a [connected app](https://docs.farcaster.xyz/learn/what-is-farcaster/apps#connected-apps) and want users to sign in with Farcaster, use an `AppClient`.
4 |
5 | You can use an `AppClient` to create a Farcaster Auth relay channel, generate a deep link to request a signature from the user's Farcaster wallet app, and verify the returned signature.
6 |
7 | ```ts
8 | import { createAppClient, viemConnector } from '@farcaster/auth-client';
9 |
10 | const appClient = createAppClient({
11 | relay: 'https://relay.farcaster.xyz',
12 | ethereum: viemConnector(),
13 | });
14 | ```
15 |
16 | ## Parameters
17 |
18 | | Parameter | Type | Description | Required |
19 | | ---------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
20 | | `ethereum` | `EthereumConnector` |
An Ethereum connector, used to query the Farcaster contracts and verify smart contract wallet signatures. `@farcaster/auth-client` currently provides only the `viem` connector type.
To use a custom RPC, pass an RPC URL to the viem connector.
| Yes |
21 | | `relay` | `string` | Relay server URL. Defaults to the public relay at `https://relay.farcaster.xyz` | No |
22 | | `version` | `string` | Farcaster Auth version. Defaults to `"v1"` | No |
23 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/app/create-channel.md:
--------------------------------------------------------------------------------
1 | # `createChannel`
2 |
3 | Create a Farcaster Auth relay channel.
4 |
5 | Returns a secret token identifying the channel, and a URI to display to the end user as a link or QR code.
6 |
7 | ```ts
8 | const channel = await appClient.createChannel({
9 | siweUri: 'https://example.com/login',
10 | domain: 'example.com',
11 | });
12 | ```
13 |
14 | ## Parameters
15 |
16 | | Parameter | Type | Description | Required | Example |
17 | | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------- |
18 | | `siweUri` | `string` | Login URL for your application. | Yes | `https://example.com/login` |
19 | | `domain` | `string` | Domain of your application. | Yes | `example.com` |
20 | | `nonce` | `string` | A custom nonce. Must be at least 8 alphanumeric characters. | No | `ESsxs6MaFio7OvqWb` |
21 | | `notBefore` | `string` | Start time at which the signature becomes valid. ISO 8601 datetime. | No | `2023-12-20T23:21:24.917Z` |
22 | | `expirationTime` | `string` | Expiration time at which the signature is no longer valid. ISO 8601 datetime. | No | `2023-12-20T23:21:24.917Z` |
23 | | `requestId` | `string` | A system specific ID your app can use to refer to the sign in request. | No | `8d0494d9-e0cf-402b-ab0a-394ac7fe07a0` |
24 | | `acceptAuthAddress` | `boolean` | Whether your application accepts signatures from an [auth address](https://github.com/farcasterxyz/protocol/discussions/225). | No | `true` |
25 |
26 | ## Returns
27 |
28 | ```ts
29 | {
30 | response: Response;
31 | data: {
32 | channelToken: string;
33 | url: string;
34 | nonce: string;
35 | }
36 | isError: boolean;
37 | error: Error;
38 | }
39 | ```
40 |
41 | | Parameter | Description |
42 | | ------------------- | --------------------------------------------------------------------------------------- |
43 | | `response` | HTTP response from the Connect relay server. |
44 | | `data.channelToken` | Connect relay channel token. |
45 | | `data.url` | Sign in With Farcaster URL to present to the user. Links to the Farcaster client in v1. |
46 | | `data.nonce` | Random nonce included in the Sign in With Farcaster message. |
47 | | `isError` | True when an error has occurred. |
48 | | `error` | `Error` instance. |
49 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/app/verify-sign-in-message.md:
--------------------------------------------------------------------------------
1 | # `verifySignInMessage`
2 |
3 | Verify a Sign In With Farcaster message. Your app should call this function and check that it succeeds after reading the message and signature provided by the user's Farcaster wallet over the Connect channel.
4 |
5 | Returns the parsed Sign in With Farcaster message, the user's fid, and whether the verification succeeded.
6 |
7 | ```ts
8 | const { data, success, fid } = await appClient.verifySignInMessage({
9 | nonce: 'abcd1234',
10 | domain: 'example.com',
11 | message: 'example.com wants you to sign in with your Ethereum account…',
12 | signature: '0x9335c3055d47780411a3fdabad293c68c84ea350a11794cd11fd51b…',
13 | acceptAuthAddress: true,
14 | });
15 | ```
16 |
17 | ## Parameters
18 |
19 | | Parameter | Type | Description | Required |
20 | | ------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
21 | | `domain` | `string` | Domain of your application. Must match the domain in the provided SIWF message. | Yes |
22 | | `nonce` | `string` | A custom nonce. Must match the nonce in the provided SIWF message. | Yes |
23 | | `message` | `string` or `SiweMessage` | The Sign in With Farcaster message to verify. This may be either a string or a parsed `SiweMessage`. Your app should read this value from the Connect channel once the request is completed. | Yes |
24 | | `signature` | `Hex` | Signature provided by the user's Farcaster wallet. Your app should read this from the Connect channel once the request is completed. | Yes |
25 | | `acceptAuthAddress` | `boolean` | Pass `true` to accept an [auth address](https://github.com/farcasterxyz/protocol/discussions/225) signature in addition to a custody address signature. | No |
26 |
27 | ## Returns
28 |
29 | ```ts
30 | {
31 | data: SiweMessage,
32 | success: boolean,
33 | fid: number
34 | isError: boolean
35 | error: Error
36 | }
37 | ```
38 |
39 | | Parameter | Description |
40 | | --------- | ----------------------------------------------- |
41 | | `data` | Parsed SIWF message, as a `SiweMessage` object. |
42 | | `success` | True if the provided signature is valid. |
43 | | `fid` | FID of the user. |
44 | | `isError` | True when an error has occurred. |
45 | | `error` | `Error` instance. |
46 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/introduction.md:
--------------------------------------------------------------------------------
1 | # Auth client
2 |
3 | [](https://www.npmjs.com/package/@farcaster/auth-client)
4 |
5 | The `@farcaster/auth-client` library provides a framework agnostic client for Farcaster Auth. If you're not using React, want greater customizability, or want to interact with the Farcaster Auth relay directly, you can use the Auth client library to build your own Sign in With Farcaster flow.
6 |
7 | ## Getting Started
8 |
9 | ### Installation
10 |
11 | Install the Auth client and its peer dependency [viem](https://viem.sh/).
12 |
13 | ```sh
14 | npm install @farcaster/auth-client viem
15 | ```
16 |
17 | **Note:** This is a low level client library. If you're using React, take a look at [auth-kit](../) instead.
18 |
19 | ### Create a client
20 |
21 | Set up a client with a relay server URL and Ethereum connector.
22 |
23 | ```tsx
24 | import { createAppClient, viemConnector } from '@farcaster/auth-client';
25 |
26 | const appClient = createAppClient({
27 | relay: 'https://relay.farcaster.xyz',
28 | ethereum: viemConnector(),
29 | });
30 | ```
31 |
32 | Depending on the type of app you're building, you may use an `AppClient` or a `WalletClient`. If you're building a connected app and logging in users, use an _app client_. If you're building a Farcaster wallet app, use a _wallet client_.
33 |
34 | ### Consume actions
35 |
36 | Now that your client is set up, you can use it to interact with Farcaster Auth actions.
37 |
38 | ```tsx
39 | const { data: { channelToken } } = await appClient.createChannel({
40 | siweUri: "https://example.com/login",
41 | domain: "example.com";
42 | });
43 |
44 | const status = await appClient.watchStatus({
45 | channelToken,
46 | });
47 | ```
48 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/wallet/authenticate.md:
--------------------------------------------------------------------------------
1 | # `authenticate`
2 |
3 | Submit a Sign In With Farcaster message, user signature, and profile data to the Connect relay server.
4 |
5 | ```ts
6 | const params = await walletClient.authenticate({
7 | message: 'example.com wants you to sign in with your Ethereum account…',
8 | signature: '0x9335c3055d47780411a3fdabad293c68c84ea350a11794cdc811fd5…',
9 | authMethod: 'authAddress',
10 | fid: 1,
11 | username: 'alice',
12 | bio: "I'm a little teapot who didn't fill out my bio",
13 | displayName: 'Alice Teapot',
14 | pfpUrl: 'https://images.example.com/profile.png',
15 | });
16 | ```
17 |
18 | ## Parameters
19 |
20 | | Parameter | Type | Description | Required |
21 | | -------------- | -------- | -------------------------------------------------------------------------------------------------------------- | -------- |
22 | | `authKey` | `string` | Farcaster Auth API key. Farcaster Auth v1 restricts calls to `/authenticate` to the official Farcaster client. | Yes |
23 | | `channelToken` | `string` | Farcaster Auth channel token. | Yes |
24 | | `message` | `string` | The Sign in With Farcaster message produced by your wallet app and signed by the user. | Yes |
25 | | `signature` | `Hex` | SIWE signature created by the wallet user's account. | Yes |
26 | | `authMethod` | `string` | Method used to sign the SIWF message. Either `"custody"` or `"authAddress"`. | Yes |
27 | | `fid` | `number` | Wallet user's fid. | Yes |
28 | | `username` | `string` | Wallet user's Farcaster username. | Yes |
29 | | `bio` | `string` | Wallet user's bio. | Yes |
30 | | `displayName` | `string` | Wallet user's display name. | Yes |
31 | | `pfpUrl` | `string` | Wallet user's profile photo URL. | Yes |
32 |
33 | ## Returns
34 |
35 | ```ts
36 | {
37 | response: Response
38 | data: {
39 | state: 'completed'
40 | nonce: string
41 | message?: string
42 | signature?: `Hex`
43 | fid?: number
44 | username?: string
45 | bio?: string
46 | displayName?: string
47 | pfpUrl?: string
48 | }
49 | isError: boolean
50 | error: Error
51 | }
52 | ```
53 |
54 | | Parameter | Description |
55 | | ------------------ | ----------------------------------------------------------------- |
56 | | `response` | HTTP response from the Connect relay server. |
57 | | `data.state` | Status of the sign in request, either `"pending"` or `"complete"` |
58 | | `data.nonce` | Random nonce used in the SIWE message. |
59 | | `data.message` | The generated SIWE message. |
60 | | `data.signature` | Hex signature produced by the user's Farcaster client app wallet. |
61 | | `data.fid` | User's Farcaster ID. |
62 | | `data.username` | User's Farcaster username. |
63 | | `data.bio` | User's Farcaster bio. |
64 | | `data.displayName` | User's Farcaster display name. |
65 | | `data.pfpUrl` | User's Farcaster profile picture URL. |
66 | | `isError` | True when an error has occurred. |
67 | | `error` | `Error` instance. |
68 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/wallet/build-sign-in-message.md:
--------------------------------------------------------------------------------
1 | # `buildSignInMessage`
2 |
3 | Build a Sign In With Farcaster message to present to the end user for signing.
4 |
5 | Adds required Sign In With Farcaster message attributes to any provided parameters. You should parse most of these parameters from a provided protocol URI. Your wallet app must provide the user's custody address and fid.
6 |
7 | Returns a `SiweMessage` object and the message as a string.
8 |
9 | ```ts
10 | const { siweMessage, message } = walletClient.buildSignInMessage({
11 | address: '0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231',
12 | fid: 1,
13 | uri: 'https://example.com/login',
14 | domain: 'example.com',
15 | nonce: 'ESsxs6MaFio7OvqWb',
16 | });
17 | ```
18 |
19 | ## Parameters
20 |
21 | | Parameter | Type | Description | Required |
22 | | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
23 | | `address` | `Hex` | Wallet user's custody address. This address must be the same account that signs the generated Sign In With Farcaster message. Your wallet app should provide the custody address of the authenticated user. | Yes |
24 | | `fid` | `string` | Wallet user's fid. Your wallet app should provide the fid of the authenticated user. | Yes |
25 | | `uri` | `string` | Login URL of the relying connected app. Parse this from the provided Sign In With Farcaster URI. | Yes |
26 | | `domain` | `string` | Domain of the relying connected app. Parse this from the provided Sign In With Farcaster URI. | Yes |
27 | | `nonce` | `string` | Random nonce to include in the Sign In With Farcaster message. Must be at least 8 alphanumeric characters. Parse this from the provided Sign In With Farcaster URI. | Yes |
28 | | `notBefore` | `string` | Start time at which the SIWE signature becomes valid. ISO 8601 datetime. Parse this from the provided Sign In With Farcaster URI. | No |
29 | | `expirationTime` | `string` | Expiration time after which the SIWE signature becomes valid. ISO 8601 datetime. Parse this from the provided Sign In With Farcaster URI. | No |
30 | | `requestId` | `string` | A system specific ID provided by the relying app. Parse this from the provided Sign In With Farcaster URI. | No |
31 |
32 | ## Returns
33 |
34 | ```ts
35 | {
36 | siweMessage: SiweMessage;
37 | message: string;
38 | isError: boolean;
39 | error: Error;
40 | }
41 | ```
42 |
43 | | Parameter | Description |
44 | | ------------- | ------------------------------------------------- |
45 | | `siweMessage` | Constructed Sign In With Ethereum message object. |
46 | | `message` | SIWE message serialized as a string. |
47 | | `isError` | True when an error has occurred. |
48 | | `error` | `Error` instance. |
49 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/wallet/client.md:
--------------------------------------------------------------------------------
1 | # Wallet Client
2 |
3 | If you're building a [wallet app](https://docs.farcaster.xyz/learn/what-is-farcaster/apps#wallet-apps) and receiving signature requests, use a `WalletClient`.
4 |
5 | You can use a `WalletClient` to parse an incoming Sign In With Farcaster request URL, build a Sign In With Farcaster message to present to the user, and submit the signed message to a Farcaster Auth relay channel.
6 |
7 | ```ts
8 | import { createWalletClient, viemConnector } from '@farcaster/auth-client';
9 |
10 | const walletClient = createWalletClient({
11 | relay: 'https://relay.farcaster.xyz',
12 | ethereum: viemConnector(),
13 | });
14 | ```
15 |
16 | ## Parameters
17 |
18 | | Parameter | Type | Description | Required |
19 | | ---------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
20 | | `ethereum` | `EthereumConnector` |
An Ethereum connector, used to query the Farcaster contracts and verify smart contract wallet signatures. `@farcaster/auth-client` currently provides only the `viem` connector type.
To use a custom RPC, pass an RPC URL to the viem connector.
| Yes |
21 | | `relay` | `string` | Relay server URL. Defaults to the public relay at `https://relay.farcaster.xyz` | No |
22 | | `version` | `string` | Farcaster Auth version. Defaults to `"v1"` | No |
23 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/wallet/parse-sign-in-uri.md:
--------------------------------------------------------------------------------
1 | # `parseSignInURI`
2 |
3 | Parse the Sign In With Farcaster URI provided by a connected app user.
4 |
5 | Returns the parsed parameters. Your app should use these to construct a Sign In With Farcaster message.
6 |
7 | Returns an error if URI is invalid.
8 |
9 | ```ts
10 | const params = walletClient.parseSignInURI({
11 | uri: 'farcaster://connect?channelToken=23W59BKK&nonce=ESsxs6MaFio7OvqWb&siweUri=https%3A%2F%2Fexample.com%2Flogin&domain=example.com',
12 | });
13 | ```
14 |
15 | ## Parameters
16 |
17 | | Parameter | Type | Description | Required |
18 | | --------- | -------- | --------------------------- | -------- |
19 | | `uri` | `string` | Sign In With Farcaster URI. | Yes |
20 |
21 | ## Returns
22 |
23 | ```ts
24 | {
25 | channelToken: string
26 | params: {
27 | domain: string
28 | uri: string
29 | nonce: string
30 | notBefore?: string
31 | expirationTime?: string
32 | requestId?: string
33 | }
34 | isError: boolean
35 | error: Error
36 | }
37 | ```
38 |
39 | | Parameter | Description |
40 | | ----------------------- | ----------------------------------------------------------------- |
41 | | `channelToken` | Connect relay channel token. |
42 | | `params.uri` | Login URI of the relying connected app. |
43 | | `params.domain` | Domain of the relying app. |
44 | | `params.nonce` | Random nonce provided by the relying app. |
45 | | `params.notBefore` | Time at which this message becomes valid. |
46 | | `params.expirationTime` | Time at which this message expires. |
47 | | `params.requestId` | A system specific identifier provided by the relying application. |
48 | | `isError` | True when an error has occurred. |
49 | | `error` | `Error` instance. |
50 |
--------------------------------------------------------------------------------
/docs/auth-kit/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ## Client Side
4 |
5 | A frontend-only app that lets users Sign in with Farcaster and shows them their profile picture and username.
6 |
7 |
8 |
9 | [Try Demo](https://farcaster-auth-kit-vite-demo.replit.app/) | [View Source](https://github.com/farcasterxyz/connect-monorepo/tree/main/examples/frontend-only)
10 |
11 | ## Server Side
12 |
13 | A Next.js app that lets users Sign in with Farcaster and handles sessions server-side.
14 |
15 |
16 |
17 | [Try Demo](https://farcaster-auth-kit-next-auth-demo.replit.app/) | [View Source](https://github.com/farcasterxyz/connect-monorepo/tree/main/examples/with-next-auth)
18 |
--------------------------------------------------------------------------------
/docs/auth-kit/hooks/use-profile.md:
--------------------------------------------------------------------------------
1 | # `useProfile`
2 |
3 | Hook for reading information about the authenticated user.
4 |
5 | You can use this hook to read the authenticated user's profile information from other components inside your app.
6 |
7 | ```tsx
8 | import { useProfile } from '@farcaster/auth-kit';
9 |
10 | function App() {
11 | const {
12 | isAuthenticated,
13 | profile: { username, fid, bio, displayName, pfpUrl },
14 | } = useProfile();
15 |
16 | return (
17 |
18 | {isAuthenticated ? (
19 |
20 | Hello, {username}! Your fid is: {fid}
21 |
22 | ) : (
23 |
You're not signed in.
24 | )}
25 |
26 | );
27 | }
28 | ```
29 |
30 | ## Returns
31 |
32 | ```ts
33 | {
34 | isAuthenticated: boolean;
35 | profile?: {
36 | fid?: number;
37 | username?: string;
38 | bio?: string;
39 | displayName?: string;
40 | pfpUrl?: string;
41 | custody?: Hex;
42 | verifications?: Hex[];
43 | },
44 | };
45 | ```
46 |
47 | | Parameter | Description |
48 | | ----------------------- | ---------------------------------- |
49 | | `isAuthenticated` | True when the user is logged in. |
50 | | `profile.fid` | User's Farcaster ID. |
51 | | `profile.username` | User's username. |
52 | | `profile.bio` | User's bio text. |
53 | | `profile.displayName` | User's display name. |
54 | | `profile.pfpUrl` | User's profile picture URL. |
55 | | `profile.custody` | User's FID custody address. |
56 | | `profile.verifications` | List of user's verified addresses. |
57 |
--------------------------------------------------------------------------------
/docs/auth-kit/hooks/use-sign-in-message.md:
--------------------------------------------------------------------------------
1 | # `useSignInMessage`
2 |
3 | Hook for reading the Sign in With Farcaster message and signature used to authenticate the user.
4 |
5 | If you're providing the message and signature to a backend API, you may want to use this hook.
6 |
7 | ```tsx
8 | import { useSignInMessage } from '@farcaster/auth-kit';
9 |
10 | function App() {
11 | const { message, signature } = useSignInMessage();
12 |
13 | return (
14 |
15 |
You signed: {message}
16 |
Your signature: {signature}
17 |
18 | );
19 | }
20 | ```
21 |
22 | ## Returns
23 |
24 | ```ts
25 | {
26 | message: string;
27 | signature: Hex;
28 | }
29 | ```
30 |
31 | | Parameter | Description |
32 | | ----------- | -------------------------------------------------- |
33 | | `message` | SIWE message signed by the user. |
34 | | `signature` | Signature produced by the user's Farcaster wallet. |
35 |
--------------------------------------------------------------------------------
/docs/auth-kit/index.md:
--------------------------------------------------------------------------------
1 | # AuthKit
2 |
3 | [](https://www.npmjs.com/package/@farcaster/auth-kit)
4 |
5 | AuthKit is a React library that lets users log in to your app with a Farcaster account.
6 |
7 |
8 |
9 | Click "Sign in With Farcaster" above to try it out on web or click [here](https://sign-in-with-farcaster-demo.replit.app/) for mobile.
10 |
11 | ### How does it work?
12 |
13 | It uses the [Sign In With Farcaster](#sign-in-with-farcaster-siwf) standard under the hood, which is conceptually like "Sign in with Google". When integrated, AuthKit will:
14 |
15 | 1. Show a "Sign in with Farcaster" button to the user.
16 | 2. Wait for the user to click, scan a QR code and approve the request in Warpcast.
17 | 3. Receive and verify a signature from Warpcast.
18 | 4. Show the logged in user's profile picture and username.
19 |
--------------------------------------------------------------------------------
/docs/auth-kit/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | Install auth-kit and its peer dependency [viem](https://viem.sh/).
4 |
5 | ```sh
6 | npm install @farcaster/auth-kit viem
7 | ```
8 |
9 | **Note:** auth-kit is a [React](https://react.dev/) library. If you're using a different framework, take a look at the [client library](./client/introduction.md) instead.
10 |
11 | ### 1. Import the libraries
12 |
13 | Import auth-kit and CSS styles.
14 |
15 | ```tsx
16 | import '@farcaster/auth-kit/styles.css';
17 | import { AuthKitProvider } from '@farcaster/auth-kit';
18 | import { SignInButton } from '@farcaster/auth-kit';
19 | ```
20 |
21 | ### 2. Configure your provider
22 |
23 | Configure a provider with an Optimism RPC URL, your app's domain and login URL, and wrap your application in it.
24 |
25 | ```tsx
26 | const config = {
27 | rpcUrl: 'https://mainnet.optimism.io',
28 | domain: 'example.com',
29 | siweUri: 'https://example.com/login',
30 | };
31 |
32 | const App = () => {
33 | return (
34 | {/* Your App */}
35 | );
36 | };
37 | ```
38 |
39 | ### 3. Add a connect button
40 |
41 | Render the `SignInButton` component. When the user clicks this button, they will be prompted to complete sign in using their Farcaster wallet application.
42 |
43 | ```tsx
44 | export const Login = () => {
45 | return ;
46 | };
47 | ```
48 |
49 | ### 4. Read user profile
50 |
51 | Optionally, fetch details about the logged in user anywhere in your app with `useProfile`.
52 |
53 | ```tsx
54 | import { useProfile } from '@farcaster/auth-kit';
55 |
56 | export const UserProfile = () => {
57 | const {
58 | isAuthenticated,
59 | profile: { username, fid },
60 | } = useProfile();
61 | return (
62 |
63 | {isAuthenticated ? (
64 |
65 | Hello, {username}! Your fid is: {fid}
66 |
67 | ) : (
68 |
You're not signed in.
69 | )}
70 |
71 | );
72 | };
73 | ```
74 |
--------------------------------------------------------------------------------
/docs/auth-kit/service-providers.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | In addition to the core AuthKit implementation, "Sign in With Farcaster" can be implemented through multiple service providers and combined with additional functionality and login methods.
4 |
5 | # Providers
6 |
7 | Below is a list of providers that currently support "Sign in With Farcaster" functionality as part of their product suite.
8 |
9 | - [Dynamic](https://docs.dynamic.xyz/guides/integrations/sign-in-with-farcaster)
10 | - [Neynar](https://docs.neynar.com/docs/how-to-let-users-connect-farcaster-accounts-with-write-access-for-free-using-sign-in-with-neynar-siwn)
11 | - [Privy](https://docs.privy.io/guide/react/recipes/misc/farcaster)
12 | - [Web3auth](https://web3auth.io/docs/guides/farcaster-sfa-web)
13 | - [ThirdWeb](https://github.com/thirdweb-example/thirdweb-siwf)
14 |
--------------------------------------------------------------------------------
/docs/auth-kit/sign-in-button.md:
--------------------------------------------------------------------------------
1 | # `SignInButton`
2 |
3 | The main component. Renders a "Sign in With Farcaster" button that prompts the user to scan a QR code with their phone in a web browser or redirects to a mobile device. You can use the `onSuccess` callback prop or the `useProfile` hook to access the user's authentication status and profile information.
4 |
5 | **Note:** Make sure you've wrapped your application in an [`AuthKitProvider`](./auth-kit-provider.md) to use the `SignInButton` component.
6 |
7 | ```tsx
8 | import { SignInButton } from '@farcaster/auth-kit';
9 |
10 | export const Login = () => {
11 | return (
12 |
14 | console.log(`Hello, ${username}! Your fid is ${fid}.`)
15 | }
16 | />
17 | );
18 | };
19 | ```
20 |
21 | ## Props
22 |
23 | | Prop | Type | Description | Default |
24 | | ------------------ | ---------- | ----------------------------------------------------------------------------------- | --------------------- |
25 | | `timeout` | `number` | Return an error after polling for this long. | `300_000` (5 minutes) |
26 | | `interval` | `number` | Poll the relay server for updates at this interval. | `1500` (1.5 seconds) |
27 | | `nonce` | `string` | A random nonce to include in the Sign In With Farcaster message. | None |
28 | | `notBefore` | `string` | Time when the message becomes valid. ISO 8601 datetime string. | None |
29 | | `expirationTime` | `string` | Time when the message expires. ISO 8601 datetime string. | None |
30 | | `requestId` | `string` | An optional system-specific ID to include in the message. | None |
31 | | `onSuccess` | `function` | Callback invoked when sign in is complete and the user is authenticated. | None |
32 | | `onStatusResponse` | `function` | Callback invoked when the component receives a status update from the relay server. | None |
33 | | `onError` | `function` | Error callback function. | None |
34 | | `onSignOut` | `function` | Callback invoked when the user signs out. | None |
35 | | `hideSignOut` | `function` | Hide the Sign out button. | `false` |
36 | | `debug` | `boolean` | Render a debug panel displaying internal auth-kit state. | `false` |
37 |
38 | ## Examples
39 |
40 | ### Custom nonce
41 |
42 | ```tsx
43 | import { SignInButton } from '@farcaster/auth-kit';
44 |
45 | export const Login = ({ nonce }: { nonce: string }) => {
46 | return (
47 |
50 | console.log(`Hello, ${username}! Your fid is ${fid}.`)
51 | }
52 | />
53 | );
54 | };
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/developers/frames/advanced.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Frames Advanced Topics
3 | ---
4 |
5 | # Advanced Topics
6 |
7 | Advanced topics for building sophisticated Farcaster Frames.
8 |
9 | #### Making the initial Frame image dynamic
10 |
11 | When a Frame is shared in a cast the metadata for it will generally be scraped
12 | and cached so that it can be rendered into users feeds without additional
13 | loading. This means whatever URL is set on the initial frame will always be
14 | rendered.
15 |
16 | In order to make the initial image dynamic you'll need to:
17 |
18 | - serve a dynamic image at a static URL
19 | - set an appropriate cache header
20 |
21 | An example, imagine you want to build a frame where the initial frame shows the
22 | current price of ETH. For the initial frame you'd set a static image url
23 | like `https://example.xyz/eth-price.png`. When a GET request is made to this endpoint:
24 |
25 | - the server fetches the latest ETH price from a cache
26 | - renders an image using a tool like [Vercel OG](https://vercel.com/docs/functions/og-image-generation) and returns it
27 | - sets the following header: `Cache-Control: public, immutable, no-transform, max-age=60`
28 |
29 | We recommend setting a non-zero `max-age` so that the image can get cached and
30 | served from CDNs, otherwise users will see a gray image in their feed while the
31 | dynamic image is generated and loads. The exact time depends on your
32 | application but opt for the longest time that still keeps the image reasonably
33 | fresh.
34 |
35 | #### Avoid caching error images when generating dynamic images at static URLs
36 |
37 | If you have a static URL that generates a dynamic image and you use a fallback
38 | image for cases when you're unable to generate the image, you should set
39 | `max-age=0` in the `Cache-Control` header so it does not get cached.
40 |
41 | As an example, let's say you generate a dynamic image at `/img/eth-price` that
42 | shows a 24hr chart for the price of ETH. Normally you want this image to be
43 | cached for 5 minutes. However, if the ETH price data is unavailable and you
44 | render a fallback image you don't want the request cached so that you can try
45 | again in subsequent requests.
46 |
47 | #### Data persistence
48 |
49 | [Vercel KV](https://vercel.com/docs/storage/vercel-kv) and [Cloudflare Workers
50 | KV](https://developers.cloudflare.com/kv/) are convenient options for adding a
51 | simple persistence layer to your Frame server.
52 |
--------------------------------------------------------------------------------
/docs/developers/frames/best-practices.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Frame Best Practices
3 | ---
4 |
5 | # Frame Best Practices
6 |
7 | Learn best practices for building great Frame experiences.
8 |
9 | ::: info
10 | These best practices assume a prior knowledge of Frames. If you're looking for
11 | general information about building Frames check out these resources:
12 |
13 | - [Getting Started](./getting-started)
14 | - [Frames Specification](./spec)
15 | - guides from [frames.js](https://framesjs.org/guides/create-frame) or [frog](https://frog.fm/concepts/overview)
16 | :::
17 |
18 | ## UI / UX
19 |
20 | #### Follow the Frame Interface Guidelines (FIG)
21 |
22 | The [FIG](https://github.com/paradigmxyz/Fig) provides comprehensive guidance that can help you design a great
23 | experience for frames. It covers everything from [foundational
24 | topics](https://github.com/paradigmxyz/Fig?tab=readme-ov-file#foundations) like
25 | layout and typography to [best practices when working with
26 | transactions.](https://github.com/paradigmxyz/Fig?tab=readme-ov-file#patterns)
27 |
28 | #### Optimize performance
29 |
30 | Make your frame respond to the user as fast as possible. Review and implement
31 | the [performance best practices](#performance).
32 |
33 | #### Use reusable styles and components
34 |
35 | Building a set of reusable styles and components can help you move fast and build
36 | consistent interfaces.
37 |
38 | [FrogUI](https://frog.fm/ui) is an extension of the Frog Framework that provides a theme-able
39 | set of primitive components.
40 |
41 | ## Performance Best Practices
42 |
43 | ::: tip
44 | Don't worry about these recommendations if you're just getting started or working on a prototype.
45 |
46 | Remember, premature optimization is the root of all evil!
47 | :::
48 |
49 | #### Use cached images
50 |
51 | Where possible, serve images at stable URLs with appropriate cache headers as
52 | this can drastically reduce render time.
53 |
54 | #### Respond to requests as quickly as possible
55 |
56 | Don't perform long-running computations like interacting with an LLM while the
57 | user is waiting for the next Frame to load. See [perform long-running computations in the background](#long-running).
58 |
59 | #### Perform long-running computations in the background {#long-running}
60 |
61 | If your Frame needs to perform a long-running computation like interacting with
62 | an LLM or sending an onchain transaction, it should be done in the "background"
63 | by immediately respond with a frame that tells the user an action is being
64 | taken and let's the user refresh to check the status.
65 |
66 | #### Use a local copy of Farcaster data {#local-farcaster-data}
67 |
68 | If your frame needs to access Farcaster data, consider [using Shuttle to
69 | replicate it to Postgres](/developers/guides/apps/replicate.md) so it can be fetched
70 | locally.
71 |
72 | ::: warning Advanced
73 | Maintaining a replicated database is a non-trivial amount of work. Consider
74 | fetching data from a provider like Neynar, Pinata, or Airstack unless you're
75 | willing to pay this cost.
76 | :::
77 |
78 | #### Skip Frame message signature verification when appropriate {#skip-verification}
79 |
80 | You may not need to verify the frame message if the data in the message does
81 | result in any sensitive data being updated or exposed.
82 |
83 | For example, if your frame returns public analytics data about a user's cast
84 | history, relying on the untrusted data is likely sufficient.
85 |
86 | ::: info Note
87 | For multi-step frames it might be the case that some interactions require
88 | verification while others don't.
89 | :::
90 |
91 | ::: warning Exercise caution
92 | If your frame relies on the message to allow the user to take a privileged
93 | action or expose sensitive data you must verify the message.
94 | :::
95 |
96 | #### Minimize latency from external dependencies like hubs
97 |
98 | This is a generalization of tactics like [skipping
99 | verification](#skip-verification) and [using a local copy of the Farcaster
100 | data](#local-farcaster-data).
101 |
102 | Find all the external dependencies for your frame server. For each of these
103 | external dependencies ask the following:
104 |
105 | - Can it be removed?
106 | - Can the data be cached?
107 | - Can it be co-located with my frame server?
108 |
--------------------------------------------------------------------------------
/docs/developers/frames/frog_frame_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/developers/frames/frog_frame_preview.png
--------------------------------------------------------------------------------
/docs/developers/frames/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started with Frames
3 | ---
4 |
5 | # Getting Started
6 |
7 | ::: info Not ready to build?
8 | If you'd prefer to learn more about Frames before building one, jump ahead to the [Frames Specification](./spec).
9 | :::
10 |
11 | Let's use Frog to go from 0 to 1 in less than a minute. At the end of this we'll have:
12 |
13 | - a type-safe frame server with a basic frame
14 | - a tool for interacting with and debugging our Frame locally
15 | - our server deployed on the public internet
16 |
17 | ### Bootstrap via CLI
18 |
19 | To get started, scaffold a new project:
20 |
21 | ::: code-group
22 |
23 | ```ts [npm]
24 | npm init frog -t vercel
25 | ```
26 |
27 | ```ts [yarn]
28 | yarn create frog -t vercel
29 | ```
30 |
31 | ```ts [bun]
32 | bunx create-frog -t vercel
33 | ```
34 |
35 | ```ts [pnpm]
36 | pnpm create frog -t vercel
37 | ```
38 |
39 | Complete the prompts and follow the instructions:
40 |
41 | ```
42 | bun install // install dependencies
43 | bun run dev // start dev server
44 | ```
45 |
46 | ::: info
47 | This guide uses Frog + Vercel but frames can be built and deployed in any
48 | number of ways. You can check out popular alternatives like [frame.js](https://framesjs.org/)
49 | on the [Frame Developer Resources](./resources) page.
50 | :::
51 |
52 | ### Open the preview
53 |
54 | Now that you have a frame server running, navigate to
55 | `http://localhost:5174/api/dev` to interact with your frame in the
56 | [Devtools](https://frog.fm/concepts/devtools) preview.
57 |
58 | You should see a frame that says "Welcome!" and has three buttons: apples,
59 | oranges, and bananas. Click on any of the buttons and the frame will update
60 | with a message echoing your choice.
61 |
62 | 
63 |
64 | ### Deploy the frame
65 |
66 | ::: info
67 | This project was scaffolded for deployment with Vercel since it's a popular and
68 | easy option. If you'd like to deploy your Frame another way check out the [Frog
69 | Platforms documentation](https://frog.fm/platforms/bun).
70 | :::
71 |
72 | To distribute your frame your server will need to be hosted somewhere on the
73 | internet. Feel free to skip this step and come back later.
74 |
75 | ::: code-group
76 |
77 | ```ts [npm]
78 | npm run deploy
79 | ```
80 |
81 | ```ts [yarn]
82 | yarn run deploy
83 | ```
84 |
85 | .
86 |
87 | ```ts [bun]
88 | bunx run deploy
89 | ```
90 |
91 | ```ts [pnpm]
92 | pnpm run deploy
93 | ```
94 |
95 | Complete the prompts. Once your frame is deployed you can test it end-to-end
96 | using the [Farcaster Client Frame Validator](https://farcaster.xyz/~/developers/frames-legacy).
97 |
98 | ::: info
99 | Make sure to plug the full frame URL in. For Vercel projects this default frame
100 | url is located at `https:///api`.
101 | :::
102 |
103 | ## Next steps
104 |
105 | Here are some next steps now that you have your first Frames project scaffolded
106 | and deployed:
107 |
108 | - Read through the [Frog Concepts
109 | documentation](https://frog.fm/concepts/overview) to learn how to build a
110 | sophisticated, [multi-step frame](https://frog.fm/concepts/routing).
111 | - Try [scaffolding a project with
112 | frames.js](https://framesjs.org/guides/create-frame) and check out their
113 | extensive [guides](https://framesjs.org/guides/create-frame) and
114 | [examples](https://framesjs.org/examples/basic).
115 | - Discover more resources for [building and learning about frames](./resources).
116 | - Read over our [best practices](./best-practices) for building a great Frame experience.
117 |
--------------------------------------------------------------------------------
/docs/developers/frames/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Frames Introduction
3 | ---
4 |
5 | # Frames Introduction
6 |
7 | ::: info Mini Apps are evolving!
8 |
9 |
10 | We recently released a new [Mini Apps standard](https://miniapps.farcaster.xyz/){target="_self"} to enable even better in-feed experiences. **Frames v1 have been deprecated and will be supported only until end of March 2025.** We strongly recommend using Mini Apps for all new projects.
11 | :::
12 |
13 | Frames are a way to build interactive apps that run directly in a Farcaster social feed.
14 |
15 | They can be used to create rich in-feed experiences for web applications:
16 |
17 | - NFTS shared from [Zora](https://zora.co/) and [Highlight](https://highlight.xyz/) can be minted in-feed
18 | - Newsletters shared from [Paragraph](https://paragraph.xyz/) can be read inline and subscribed to in-feed
19 | - Markets shared from [Polymarket](https://polymarket.com/) let users place bets in-feed
20 |
21 | Or standalone experiences like polls and games:
22 |
23 | - Spot and mint wild animals on a live-feed of a watering hole in the Namib Desert with [Safaricaster](https://warpcast.com/mattkim/0x3d165bb8)
24 | - Make an onchain payment to another user with [Paybot](https://app.paycaster.co)
25 | - RSVP to an [Eventcaster](https://warpcast.com/toadyhawk.eth/0xcb4aefe8) event
26 | - [Yoink](https://warpcast.com/horsefacts.eth/0x70019199) the flag in this simple yet viral social game
27 | - Generate a [Waifu NFT](https://warpcast.com/horsefacts.eth/0xbc7d33ca) based on your Farcaster profile
28 |
29 | ### Farcaster 101
30 |
31 | A 5 minute non-technical primer on Frames:
32 |
33 |
34 |
35 | ## Next Steps
36 |
37 | 1. [Build your first mini app](https://miniapps.farcaster.xyz/docs/getting-started){target="\_self"}
38 | 2. Read through the [formal Mini Apps Specification](https://miniapps.farcaster.xyz/docs/specification){target="\_self"}
39 | 3. Join the Farcaster developer community in the [/fc-devs](https://warpcast.com/~/channel/fc-devs) channel on Farcaster.
40 |
--------------------------------------------------------------------------------
/docs/developers/frames/resources.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Frame Resources
3 | ---
4 |
5 | # Frame Resources
6 |
7 | An opinionated collection of popular resources for building Frames.
8 |
9 | #### Learning
10 |
11 | - [/fc-devs](https://farcaster.xyz/~/channel/fc-devs) - Farcaster developer channel
12 | - [Frames Specification](./spec) - official Frames specification
13 | - [dTech Zero to Hero Getting Started Guides](https://dtech.vision/farcaster/frames/)
14 | - [Frames.js Guide](https://framesjs.org/guides/create-frame) - guides from Frames.js
15 | - [Frog Guides](https://frog.fm/getting-started) - guides from Frog
16 | - [Frame Interface Guidelines (FIG)](https://github.com/paradigmxyz/Fig) - guidance and best practices for building frames
17 | - [Pinata Tutorials](https://docs.pinata.cloud/farcaster/frames#frame-tutorials) - tutorials for building frames that leverage IPFS
18 | - [Frames.js Examples](https://framesjs.org/examples/basic) - a collection of 20+ examples that cover basic and advanced topics
19 |
20 | #### Frameworks
21 |
22 | - [frog](https://frog.fm) - minimal & lightweight framework Farcaster Frames
23 | - [FrogUI](https://frog.fm/ui) - type-safe layout and styling primitives
24 | - [frames.js](https://framesjs.org/) - build, debug, and render Frames
25 | - [onchainkit](https://github.com/coinbase/onchainkit) - A React toolkit to create frames
26 | - [simplest frame](https://github.com/depatchedmode/simplest-frame) - zero-cost, zero-framework Frame template
27 | - [framebuilder](https://framebuilder.xyz) - No-Code Farcaster Frames Builder
28 |
29 | #### Developer tools
30 |
31 | - [Farcaster Client Frame Validator](https://farcaster.xyz/~/developers/frames-legacy) - a debugger for testing frames in the Farcaster client
32 | - [Neynar](https://docs.neynar.com/docs/how-to-build-farcaster-frames-with-neynar) - infrastructure and tools for frame servers
33 | - [Neynar Frame Studio](https://neynar.com/nfs) - build no-code Frames
34 | - [Pinata](https://docs.pinata.cloud/farcaster/frames) - Frame analytics, hub APIs, and more
35 | - [Airstack Frames SDK](https://github.com/Airstack-xyz/airstack-frames-sdk) - integrate onchain data into Frames
36 | - [Vercel OG](https://vercel.com/docs/functions/og-image-generation) - use satori and resvg-js to generate PNG images from HTML and CSS
37 |
38 |
39 |
40 | A more extensive list of resources can be found at [awesome-frames](https://github.com/davidfurlong/awesome-frames).
41 |
--------------------------------------------------------------------------------
/docs/developers/frames/safari_frame.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/developers/frames/safari_frame.gif
--------------------------------------------------------------------------------
/docs/developers/guides/accounts/change-custody.md:
--------------------------------------------------------------------------------
1 | # Change custody address
2 |
3 | Accounts are owned by custody address which is an Ethereum address on OP Mainnet.
4 |
5 | A user may want to change this address for security reasons or to transfer ownership of the entire account.
6 |
7 | ### Requirements
8 |
9 | - An ETH wallet that owns the account on OP Mainnet, with some ETH.
10 | - An Ethereum provider URL for OP Mainnet (e.g. via [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/) or [QuickNode](https://www.quicknode.com/)).
11 |
12 | ### Change Custody Address
13 |
14 | Call the `transfer` function on the Id Registry contract. The receiving address must provide an EIP-712 signature accepting the transfer.
15 |
16 | ::: code-group
17 |
18 | ```ts [@farcaster/hub-web]
19 | import { ViemWalletEip712Signer } from '@farcaster/hub-web';
20 | import { walletClient, account } from './clients.ts';
21 | import { readNonce, getDeadline } from './helpers.ts';
22 |
23 | const nonce = await readNonce();
24 | const deadline = getDeadline();
25 |
26 | const eip712Signer = new ViemWalletEip712Signer(walletClient);
27 | const signature = await eip712signer.signTransfer({
28 | fid: 1n,
29 | to: account,
30 | nonce,
31 | deadline,
32 | });
33 |
34 | const { request: transferRequest } = await publicClient.simulateContract({
35 | ...IdContract,
36 | functionName: 'transfer',
37 | args: [account, deadline, signature], // to, deadline, signature
38 | });
39 |
40 | await walletClient.writeContract(transferRequest);
41 | ```
42 |
43 | ```ts [Viem]
44 | import {
45 | ID_REGISTRY_EIP_712_TYPES,
46 | idRegistryABI,
47 | ID_GATEWAY_ADDRESS,
48 | } from '@farcaster/hub-web';
49 | import { walletClient, account } from './clients.ts';
50 | import { readNonce, getDeadline } from './helpers.ts';
51 |
52 | const nonce = await readNonce();
53 | const deadline = getDeadline();
54 | const IdContract = {
55 | abi: idRegistryABI,
56 | address: ID_GATEWAY_ADDRESS,
57 | chain: optimism,
58 | };
59 |
60 | const signature = await walletClient.signTypedData({
61 | account,
62 | ...ID_REGISTRY_EIP_712_TYPES,
63 | primaryType: 'Transfer',
64 | message: {
65 | fid: 1n,
66 | to: account,
67 | nonce,
68 | deadline,
69 | },
70 | });
71 | ```
72 |
73 | ```ts [helpers.ts]
74 | import { ID_REGISTRY_ADDRESS, idRegistryABI } from '@farcaster/hub-web';
75 | import { publicClient, account } from './clients.ts';
76 |
77 | export const getDeadline = () => {
78 | const now = Math.floor(Date.now() / 1000);
79 | const oneHour = 60 * 60;
80 | return now + oneHour;
81 | };
82 |
83 | export const readNonce = async () => {
84 | return await publicClient.readContract({
85 | address: ID_REGISTRY_ADDRESS,
86 | abi: idRegistryABI,
87 | functionName: 'nonces',
88 | args: [account],
89 | });
90 | };
91 | ```
92 |
93 | <<< @/examples/contracts/clients.ts
94 |
95 | :::
96 |
97 | ::: warning
98 | Transferring a FID does not reset its recovery address. To transfer a FID and update its recovery address,
99 | call [`transferAndChangeRecovery`](/reference/contracts/reference/id-registry#transferandchangerecovery).
100 | :::
101 |
102 | See the [Id Registry](/reference/contracts/reference/id-registry#transfer) section for more
103 | details.
104 |
--------------------------------------------------------------------------------
/docs/developers/guides/accounts/change-fname.md:
--------------------------------------------------------------------------------
1 | # Change Farcaster name
2 |
3 | A user can change their offchain ENS name or Fname without affecting their account's history. This can be done at most once in 28 days.
4 |
5 | ::: warning
6 |
7 | - Fnames may be revoked if you violate the [usage policy](/learn/architecture/ens-names#offchain-ens-names-fnames).
8 | - Apps may lower your reputation if you change Fnames often.
9 | :::
10 |
11 | ### Requirements
12 |
13 | - An ETH wallet that owns the account on OP Mainnet. No ETH is required.
14 |
15 | ### Change username
16 |
17 | To transfer an Fname, e.g. `Hubble`, make a POST request to `/transfers` with the following body:
18 |
19 | ```yaml
20 | {
21 | "name": "hubble", // Name to transfer
22 | "from": 123, // FID to transfer from
23 | "to": 321, // FID to transfer to
24 | "fid": 123, // FID making the request (must match from)
25 | "owner": "0x...", // Custody address of FID making the request
26 | "timestamp": 1641234567, // Current timestamp in seconds
27 | "signature": "0x..." // EIP-712 signature signed by the custody address of the FID
28 | }
29 | ```
30 |
31 | To generate the EIP-712 signature, use the following code:
32 |
33 | ```js
34 | import { makeUserNameProofClaim, EIP712Signer } from '@farcaster/hub-nodejs';
35 |
36 | const accountKey: EIP712Signer = undefined; // Account Key for the custody address (use appropriate subclass from hub-nodejs for ethers or viem)
37 |
38 | const claim = makeUserNameProofClaim({
39 | name: 'hubble',
40 | owner: '0x...',
41 | timestamp: Math.floor(Date.now() / 1000),
42 | });
43 | const signature = (
44 | await accountKey.signUserNameProofClaim(claim)
45 | )._unsafeUnwrap();
46 | ```
47 |
48 | Example request via curl:
49 |
50 | ```bash
51 | curl -X POST https://fnames.farcaster.xyz/transfers \
52 | -H "Content-Type: application/json" \
53 | -d \
54 | '{"name": "hubble", "owner": "0x...", "signature": "0x...", "from": 123, "to": 321, "timestamp": 1641234567, fid: 123}'
55 | ```
56 |
57 | See [here](/reference/fname/api.md) for more details on the Fname registry API.
58 |
--------------------------------------------------------------------------------
/docs/developers/guides/accounts/change-recovery.md:
--------------------------------------------------------------------------------
1 | # Change recovery address
2 |
3 | Accounts can configure a recovery address to protect against the loss of the custody address. The recovery address will change the custody address of the account.
4 |
5 | ### Requirements
6 |
7 | - An ETH wallet that has an FID on OP Mainnet, with some ETH for gas costs.
8 | - An ETH RPC URL for OP Mainnet (e.g. via [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/) or [QuickNode](https://www.quicknode.com/)).
9 |
10 | ### Change Address
11 |
12 | Call the `changeRecovery` function on the Id Registry contract.
13 |
14 | ::: code-group
15 |
16 | ```ts [@farcaster/hub-web]
17 | import { walletClient, account, IdContract } from './clients.ts';
18 |
19 | const newRecoveryAddress = '0x...';
20 |
21 | const { request: transferRequest } = await walletClient.simulateContract({
22 | ...IdContract,
23 | functionName: 'changeRecovery',
24 | args: [newRecoveryAddress], // New recovery address
25 | });
26 |
27 | await walletClient.writeContract(transferRequest);
28 | ```
29 |
30 | ```ts [clients.ts]
31 | import {
32 | ID_REGISTRY_EIP_712_TYPES,
33 | idRegistryABI,
34 | ID_GATEWAY_ADDRESS,
35 | } from '@farcaster/hub-web';
36 | import { walletClient, account } from './clients.ts';
37 |
38 | const IdContract = {
39 | abi: idRegistryABI,
40 | address: ID_GATEWAY_ADDRESS,
41 | chain: optimism,
42 | };
43 |
44 | import { createWalletClient, createPublicClient, custom, http } from 'viem';
45 | import { privateKeyToAccount } from 'viem/accounts';
46 | import { optimism } from 'viem/chains';
47 |
48 | export const publicClient = createPublicClient({
49 | chain: optimism,
50 | transport: http(),
51 | });
52 |
53 | export const walletClient = createWalletClient({
54 | chain: optimism,
55 | transport: custom(window.ethereum),
56 | });
57 |
58 | // JSON-RPC Account
59 | export const [account] = await walletClient.getAddresses();
60 |
61 | // Local Account
62 | export const account = privateKeyToAccount('0x...');
63 | ```
64 |
65 | :::
66 |
67 | See the [Id Registry](/reference/contracts/reference/id-registry#transfer) section for more
68 | details.
69 |
--------------------------------------------------------------------------------
/docs/developers/guides/accounts/find-by-name.md:
--------------------------------------------------------------------------------
1 | # Find account by username
2 |
3 | If you have a user's name and want to find their account, you'll need to use one of these methods depending on what type of username they have.
4 |
5 | ## Offchain ENS Names (Fnames)
6 |
7 | If the user has an offchain ENS name like `@alice`, you'll need to call the [Fname Registry](/reference/fname/api#get-current-fname-or-fid).
8 |
9 | ```bash
10 | curl https://fnames.farcaster.xyz/transfers/current?name=farcaster | jq
11 | {
12 | "transfers": [
13 | {
14 | "id": 1,
15 | "timestamp": 1628882891,
16 | "username": "farcaster",
17 | "owner": "0x8773442740c17c9d0f0b87022c722f9a136206ed",
18 | "from": 0,
19 | "to": 1,
20 | "user_signature": "0xa6fdd2a69deab5633636f32a30a54b21b27dff123e6481532746eadca18cd84048488a98ca4aaf90f4d29b7e181c4540b360ba0721b928e50ffcd495734ef8471b",
21 | "server_signature": "0xb7181760f14eda0028e0b647ff15f45235526ced3b4ae07fcce06141b73d32960d3253776e62f761363fb8137087192047763f4af838950a96f3885f3c2289c41b"
22 | }
23 | ]
24 | }
25 | ```
26 |
27 | This returns the most recent transfer associated with the name if it is registered. Note that the creation of an Fname is a transfer from the zero address to the custody address. The `to` field indicates the current FID that owns the name.
28 |
29 | ## Onchain ENS Names
30 |
31 | If the user has an onchain ENS name like `@alice.eth`, the easiest way to do it is with the Hubble [replicator](../apps/replicate.md). It indexes onchain and offchain data and lets you easily find what you're looking for.
32 |
33 | Once you have it set up, query the `fnames` table in the replicator database for the account's FID:
34 |
35 | ```sql
36 | SELECT username, fid
37 | FROM fnames
38 | WHERE username = 'farcaster.eth'
39 | order by updated_at desc
40 | limit 1;
41 | ```
42 |
43 | See [here](/reference/replicator/schema#fnames) for more details on the replicator table schema.
44 |
--------------------------------------------------------------------------------
/docs/developers/guides/accounts/register-ens.md:
--------------------------------------------------------------------------------
1 | # Register ENS Name
2 |
3 | A user can set their farcaster username to an ENS name they own.
4 |
5 | ### Requirements
6 |
7 | - An ETH wallet that owns the account on OP Mainnet. No ETH is required.
8 | - A valid ENS name that resolves to the custody address of the Farcaster account, or a verified eth address in the
9 | Farcaster account.
10 |
11 | ### Register ENS Name
12 |
13 | First, ensure the ENS name resolves to the custody address of the farcaster account. Or the resolved address is a
14 | verified eth address in the Farcaster account. See [here](/developers/guides/writing/verify-address.md) for how to
15 | verify an ETH address.
16 |
17 | Then, generate an EIP-712 signature for the ENS name proof claim and submit the message. For more details on how to
18 | create messages, see [this guide](/developers/guides/writing/messages.md).
19 |
20 | ```js
21 | import {
22 | makeUserNameProofClaim,
23 | EIP712Signer,
24 | makeUsernameProof,
25 | FarcasterNetwork,
26 | makeUserDataAdd,
27 | UserNameType,
28 | UserDataType,
29 | } from '@farcaster/hub-nodejs';
30 |
31 | const accountKey: EIP712Signer = undefined; // Account Key for the custody/verified address (use appropriate subclass from hub-nodejs for ethers or viem)
32 | const accountEd25519Key = undefined; // Private key for the farcaster account signer
33 |
34 | const claim = makeUserNameProofClaim({
35 | name: 'farcaster.eth', // ENS name to register
36 | owner: '0x...', // Must be the public key of accountKey, and name must resolve to this address
37 | timestamp: Math.floor(Date.now() / 1000),
38 | });
39 | const signature = (
40 | await accountKey.signUserNameProofClaim(claim)
41 | )._unsafeUnwrap();
42 |
43 | const dataOptions = {
44 | fid: 123, // FID make the request
45 | network: FarcasterNetwork.MAINNET,
46 | };
47 | const signer = new NobleEd25519Signer(accountEd25519Key);
48 | const usernameProofMessage = makeUsernameProof(
49 | {
50 | name: claim.name,
51 | owner: claim.owner,
52 | timestamp: claim.timestamp,
53 | fid: dataOptions.fid,
54 | signature: signature,
55 | type: UserNameType.USERNAME_TYPE_ENS_L1,
56 | },
57 | dataOptions,
58 | signer
59 | );
60 |
61 | // Submit the message to the node. Note that this only registers the name proof to the account, it does not change the username yet.
62 | // await client.submitMessage(usernameProofMessage);
63 |
64 | // Once it's accepted, you can set the username to the ENS name
65 |
66 | const usernameMessage = makeUserData(
67 | {
68 | type: UserDataType.USERNAME,
69 | value: claim.name,
70 | },
71 | dataOptions,
72 | signer
73 | );
74 |
75 | // Submit the username message to the node
76 | // await client.submitMessage(usernameMessage);
77 | ```
78 |
--------------------------------------------------------------------------------
/docs/developers/guides/advanced/decode-key-metadata.md:
--------------------------------------------------------------------------------
1 | # Decode key metadata
2 |
3 | When users add a new key to the Key Registry, the contract emits [encoded metadata](/reference/contracts/reference/signed-key-request-validator#signedkeyrequestmetadata-struct) in an event. You can use this metadata to determine who requested the key.
4 |
5 | To decode key metadata, you can use Viem's `decodeAbiParameters` function:
6 |
7 | ::: code-group
8 |
9 | ```ts [Viem]
10 | import { decodeAbiParameters } from 'viem';
11 |
12 | const encodedMetadata =
13 | '0x' +
14 | '0000000000000000000000000000000000000000000000000000000000000020' +
15 | '00000000000000000000000000000000000000000000000000000000000023C0' +
16 | '00000000000000000000000002EF790DD7993A35FD847C053EDDAE940D055596' +
17 | '0000000000000000000000000000000000000000000000000000000000000080' +
18 | '00000000000000000000000000000000000000000000000000000000657C8AF5' +
19 | '0000000000000000000000000000000000000000000000000000000000000041' +
20 | 'F18569F4364BB2455DB27A4E8464A83AD8555416B1AAB21FF26E8501168F471F' +
21 | '7EC17BB096EA4438E5BF82CE01224B2F67EF9042737B7B101C41A1A05CB469DC' +
22 | '1B00000000000000000000000000000000000000000000000000000000000000';
23 |
24 | const decoded = decodeAbiParameters(
25 | [
26 | {
27 | components: [
28 | {
29 | name: 'requestFid',
30 | type: 'uint256',
31 | },
32 | {
33 | name: 'requestSigner',
34 | type: 'address',
35 | },
36 | {
37 | name: 'signature',
38 | type: 'bytes',
39 | },
40 | {
41 | name: 'deadline',
42 | type: 'uint256',
43 | },
44 | ],
45 | type: 'tuple',
46 | },
47 | ],
48 | encodedMetadata
49 | );
50 |
51 | console.log(decoded);
52 | /*
53 | [
54 | {
55 | requestFid: 9152n,
56 | requestSigner: '0x02ef790Dd7993A35fD847C053EDdAE940D055596',
57 | signature: '0xF185...69F4',
58 | deadline: 1702660853n
59 | }
60 | ]
61 | */
62 | ```
63 |
64 | :::
65 |
66 | See the [Signed Key Request Validator](/reference/contracts/reference/signed-key-request-validator#signedkeyrequestmetadata-struct) reference for more
67 | details.
68 |
--------------------------------------------------------------------------------
/docs/developers/guides/advanced/query-signups.md:
--------------------------------------------------------------------------------
1 | # Counting signups by day
2 |
3 | ::: info Pre-requisites
4 |
5 | - Read access to a replicator database
6 |
7 | :::
8 |
9 | To count the number of signups by day, we can use the `chain_events` table to query the number
10 | of [`ID_REGISTER`](/reference/hubble/datatypes/events#onchaineventtype) events
11 | and group by day.
12 |
13 | ```sql
14 | SELECT DATE_TRUNC('day', created_at) AS day, COUNT(*) AS count
15 | FROM chain_events
16 | WHERE type = 3 -- ID_REGISTER (see event types reference page)
17 | GROUP BY day
18 | ORDER BY day desc;
19 | ```
20 |
21 | For more information on the schema, see the [replicator schema](/reference/replicator/schema).
22 |
--------------------------------------------------------------------------------
/docs/developers/guides/apps/replicate.md:
--------------------------------------------------------------------------------
1 | # Replicate Hubble data to Postgres
2 |
3 | ::: info Pre-requisites
4 |
5 | - Hubble instance running locally (for better performance) or remotely
6 |
7 | :::
8 |
9 | While some applications can be written by directly querying Hubble, most serious applications need to access the data
10 | in a more structured way.
11 |
12 | [Shuttle](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/shuttle) is a package
13 | that can be used to mirror Hubble's data to a Postgres DB for convenient access to the underlying data.
14 |
15 | Check out the documentation for more information.
16 |
--------------------------------------------------------------------------------
/docs/developers/guides/querying/fetch-casts.md:
--------------------------------------------------------------------------------
1 | # Get account messages
2 |
3 | ::: info Pre-requisites
4 |
5 | - Read only access to a hubble instance
6 |
7 | :::
8 |
9 | See [hubble installation](/hubble/install) for more information on how to set up a local hubble instance.
10 |
11 | To query all the casts for a particular FID, you can use the castsByFid HTTP endpoint:
12 |
13 | ```bash
14 | # Default http port is 2281
15 | $ curl http://localhost:2281/v1/castsByFid\?fid\=1 | jq ".messages[].data.castAddBody.text | select( . != null)"
16 | "testing"
17 | "test"
18 | "another test"
19 | "another testy test"
20 | ```
21 |
22 | This returns all the cast related messages for the fid. There are similar endpoints for reactions and follows. See
23 | the [http api reference](/reference/hubble/httpapi/httpapi) for more details.
24 |
25 | If you have the hubble installed from source, you can use the built in `console`. This will use the grpc APIs
26 |
27 | ```bash
28 | # Ensure you are in the hubble sub directory
29 | $ cd apps/hubble
30 | # Remove `--insecure` if the host is using TLS
31 | $ yarn console --insecure -s localhost:2283
32 | > res = await rpcClient.getCastsByFid({fid: 1})
33 | Ok {
34 | value: {
35 | messages: [ [Object], [Object], [Object], [Object] ],
36 | nextPageToken:
37 | }
38 | }
39 | > res.value.messages.map( m => m.data.castAddBody.text)
40 | [ 'testing', 'test', 'another test', 'another testy test' ]
41 | ```
42 |
43 | For more details on the GRPC API, see the [grpc api reference](/reference/hubble/grpcapi/grpcapi).
44 |
--------------------------------------------------------------------------------
/docs/developers/guides/querying/fetch-channel-casts.md:
--------------------------------------------------------------------------------
1 | # Fetch casts from a channel
2 |
3 | ::: info Pre-requisites
4 |
5 | - Read access to a hubble instance
6 |
7 | :::
8 |
9 | To fetch casts from a channel, Hubble provides a `getCastsByParent` api call.
10 |
11 | For example, to query all casts to the `ethereum` channel:
12 |
13 | ```bash
14 | $ curl http://localhost:2281/v1/castsByParent\?fid\=1\&url\="https://ethereum.org" | jq " .messages | limit(10;.[]) | .data.castAddBody.text"
15 | "cue "
16 | "Commandeering this channel for the one true Ethereum, Ethereum classic."
17 | "Pretty amazing that even during a bear market, the 30 day average burn gives us deflationary ETH. \n\nSource: Ultrasound.Money"
18 | "So, Ethereum is frequently called the Base Layer or L1 when talking about scalability.\n\nBut how can you call the whole Ethereum + Ethereum L2s + L3s that commit to Ethereum L2s?\n\nWe’re building a unified multi-chain explorer for that, but we don’t know how to call it: https://ethereum.routescan.io"
19 | "This, we're already doing.\n\nBut we call it, the Full-Index Ecosystem Explorer."
20 | ". By subdomains do you mean more specific namespaces, e.g. Farcaster fnames being name.farcaster.eth?\n\nMy guess is if the root .eth namespace is available it will command higher status and value.\n\nhttps://x.com/0xfoobar/status/1687209523239604230"
21 | "what are the best examples of DAOs with independent core working groups/multisigs?"
22 | "Anyone here use Rabby?\n\nhttps://x.com/0xfoobar/status/1687474090150416385"
23 | "Who needs stablecoins when we have ETH"
24 | "782,672 active + pending validators! 🤯 \n\n(also... I haven't proposed a block for a few months)"
25 | ```
26 |
27 | Using the GRPC API:
28 |
29 | ```bash
30 | > res = await rpcClient.getCastsByParent({parentUrl: "https://ethereum.org"})
31 | > res.value.messages.slice(0, 10).map( m => m.data.castAddBody.text)
32 | [
33 | 'cue ',
34 | 'Commandeering this channel for the one true Ethereum, Ethereum classic.',
35 | 'Pretty amazing that even during a bear market, the 30 day average burn gives us deflationary ETH. \n' +
36 | '\n' +
37 | 'Source: Ultrasound.Money',
38 | 'So, Ethereum is frequently called the Base Layer or L1 when talking about scalability.\n' +
39 | '\n' +
40 | 'But how can you call the whole Ethereum + Ethereum L2s + L3s that commit to Ethereum L2s?\n' +
41 | '\n' +
42 | 'We’re building a unified multi-chain explorer for that, but we don’t know how to call it: https://ethereum.routescan.io',
43 | "This, we're already doing.\n" +
44 | '\n' +
45 | 'But we call it, the Full-Index Ecosystem Explorer.',
46 | '. By subdomains do you mean more specific namespaces, e.g. Farcaster fnames being name.farcaster.eth?\n' +
47 | '\n' +
48 | 'My guess is if the root .eth namespace is available it will command higher status and value.\n' +
49 | '\n' +
50 | 'https://x.com/0xfoobar/status/1687209523239604230',
51 | 'what are the best examples of DAOs with independent core working groups/multisigs?',
52 | 'Anyone here use Rabby?\n' +
53 | '\n' +
54 | 'https://x.com/0xfoobar/status/1687474090150416385',
55 | 'Who needs stablecoins when we have ETH',
56 | '782,672 active + pending validators! 🤯 \n' +
57 | '\n' +
58 | "(also... I haven't proposed a block for a few months)"
59 | ]
60 | ```
61 |
--------------------------------------------------------------------------------
/docs/developers/guides/querying/fetch-profile.md:
--------------------------------------------------------------------------------
1 | # Get account profile
2 |
3 | ::: info Pre-requisites
4 |
5 | - Read only access to a hubble instance
6 |
7 | :::
8 |
9 | To fetch profile details, use the
10 |
11 | ```bash
12 | $ curl http://localhost:2281/v1/userDataByFid\?fid\=1 | jq ".messages[].data.userDataBody"
13 | {
14 | "type": "USER_DATA_TYPE_PFP",
15 | "value": "https://i.imgur.com/I2rEbPF.png"
16 | }
17 | {
18 | "type": "USER_DATA_TYPE_BIO",
19 | "value": "A sufficiently decentralized social network. farcaster.xyz"
20 | }
21 | {
22 | "type": "USER_DATA_TYPE_DISPLAY",
23 | "value": "Farcaster"
24 | }
25 | {
26 | "type": "USER_DATA_TYPE_USERNAME",
27 | "value": "farcaster"
28 | }
29 | ```
30 |
31 | See the [http api reference](/reference/hubble/httpapi/userdata) for more details.
32 |
33 | If you have the hubble installed from source, you can use the built in `console`. This will use the grpc APIs
34 |
35 | ```bash
36 | # Ensure you are in the hubble sub directory
37 | $ cd apps/hubble
38 | # Remove `--insecure` if the host is using TLS
39 | $ yarn console --insecure -s localhost:2283
40 | > res = await rpcClient.getUserDataByFid({fid: 1})
41 | Ok {
42 | value: {
43 | messages: [ [Object], [Object], [Object], [Object] ],
44 | nextPageToken:
45 | }
46 | }
47 | > res.value.messages.map(m => m.data.userDataBody)
48 | [
49 | { type: 1, value: 'https://i.imgur.com/I2rEbPF.png' },
50 | {
51 | type: 3,
52 | value: 'A sufficiently decentralized social network. farcaster.xyz'
53 | },
54 | { type: 2, value: 'Farcaster' },
55 | { type: 6, value: 'farcaster' }
56 | ]
57 | ```
58 |
59 | For more details on the GRPC API, see the [grpc api reference](/reference/hubble/grpcapi/grpcapi).
60 |
--------------------------------------------------------------------------------
/docs/developers/guides/querying/setting-up.md:
--------------------------------------------------------------------------------
1 | # Connecting to Hubble
2 |
3 | ::: info Pre-requisites
4 |
5 | - Read only access to a hubble instance
6 |
7 | :::
8 |
9 | See [hubble installation](/hubble/install) for more information on how to set up a local hubble instance.
10 |
11 | Once the hub is running, verify that you can query it by querying the http api:
12 |
13 | ```bash
14 | # Default http port is 2281
15 | $ curl http://localhost:2281/v1/castsByFid\?fid\=1 | jq ".messages[1]"
16 | {
17 | "data": {
18 | "type": "MESSAGE_TYPE_CAST_ADD",
19 | "fid": 1,
20 | "timestamp": 62108253,
21 | "network": "FARCASTER_NETWORK_MAINNET",
22 | "castAddBody": {
23 | "embedsDeprecated": [],
24 | "mentions": [],
25 | "parentCastId": {
26 | "fid": 3,
27 | "hash": "0x2d8c167ac383d51328c0ffd785ccdbaf54be45e7"
28 | },
29 | "text": "test",
30 | "mentionsPositions": [],
31 | "embeds": []
32 | }
33 | },
34 | "hash": "0x0e38d339e175e4df88c553102ea7f4db43d39f1b",
35 | "hashScheme": "HASH_SCHEME_BLAKE3",
36 | "signature": "dVsNn061CoMhQbleRlPTOL8a/rn9wNCIJnwcXzJnHLXK9RyceVGVPkmxtP7vAnpb+2UYhUwncnHgDHaex/lqBw==",
37 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
38 | "signer": "0xb85cf7feef230f30925b101223fd3e3dc4e1120bacd677f5ad3523288f8f7102"
39 | }
40 | ```
41 |
42 | For more details on the HTTP API, see the [http api reference](/reference/hubble/httpapi/httpapi).
43 |
44 | Or, if you have the hubble installed from source, you can use the built in `console`. This will use the grpc APIs
45 |
46 | ```bash
47 | # Ensure you are in the hubble sub directory
48 | $ cd apps/hubble
49 | # Remove `--insecure` if the host is using TLS
50 | $ yarn console --insecure -s localhost:2283
51 | > res = await rpcClient.getCastsByFid({fid: 1})
52 | Ok {
53 | value: {
54 | messages: [ [Object], [Object], [Object], [Object] ],
55 | nextPageToken:
56 | }
57 | }
58 | ```
59 |
60 | For more details on the GRPC API, see the [grpc api reference](/reference/hubble/grpcapi/grpcapi).
61 |
--------------------------------------------------------------------------------
/docs/developers/guides/writing/casts.md:
--------------------------------------------------------------------------------
1 | # Create casts
2 |
3 | Creating simple casts is covered in the [messages](./messages.md) tutorial. This tutorial covers advanced topics like mentions, embeds, emojis, replies and channels.
4 |
5 | ## Setup
6 |
7 | - See the setup instructions in [creating messages](./messages.md)
8 |
9 | ## Mentions
10 |
11 | Users can be tagged in a cast with an @username mention (e.g. "Hello @bob!") which causes clients to send notifications.
12 |
13 | A mention is not included in the text of the cast. The target fid and the position of the mention in the text are specified in the `mentions` and `mentionPositions` array, and are populated into the cast by clients at render-time.
14 |
15 | ```typescript
16 | /**
17 | * "@dwr and @v are big fans of @farcaster"
18 | */
19 | const castWithMentions = await makeCastAdd(
20 | {
21 | text: ' and are big fans of ',
22 | embeds: [],
23 | embedsDeprecated: [],
24 | mentions: [3, 2, 1],
25 | mentionsPositions: [0, 5, 22], // The position in bytes (not characters)
26 | },
27 | dataOptions,
28 | ed25519Signer
29 | );
30 | ```
31 |
32 | ## Embeds
33 |
34 | URLs can be embedded in the cast which instructs clients to render a preview.
35 |
36 | A cast can have up to 2 embeds which can each be up to 256 bytes long. No other validation is performed on embeds.
37 |
38 | ```typescript
39 | /**
40 | * A cast with a mention and an attachment
41 | *
42 | * "Hey @dwr, check this out!"
43 | */
44 | const castWithMentionsAndAttachment = await makeCastAdd(
45 | {
46 | text: 'Hey, check this out!',
47 | embeds: [{ url: 'https://farcaster.xyz' }],
48 | embedsDeprecated: [],
49 | mentions: [3],
50 | mentionsPositions: [4],
51 | },
52 | dataOptions,
53 | ed25519Signer
54 | );
55 | ```
56 |
57 | ## Emoji
58 |
59 | Emojis can be included directly in the text of a cast and be rendered by clients.
60 |
61 | Since an emoji character often takes up multiple bytes but renders as a single character, it has an impact on how mention positions and cast length should be calculated.
62 |
63 | ```typescript
64 | /**
65 | * A cast with emojis and mentions
66 | *
67 | * "🤓@farcaster can mention immediately after emoji"
68 | */
69 | const castWithEmojiAndMentions = await makeCastAdd(
70 | {
71 | text: '🤓 can mention immediately after emoji',
72 | embeds: [],
73 | embedsDeprecated: [],
74 | mentions: [1],
75 | mentionsPositions: [4],
76 | },
77 | dataOptions,
78 | ed25519Signer
79 | );
80 | ```
81 |
82 | ## Reply
83 |
84 | A cast can be a reply to another cast, URL or NFT. A reply to another cast is treated as a thread, while a reply to a URL or NFT can be treated as a comment or a [channel](#channels).
85 |
86 | The optional parentUrl property can be set to a URL or to an fid-hash value of the cast being replied to, as shown in th example below. See [FIP-2](https://github.com/farcasterxyz/protocol/discussions/71) for more details on reply types.
87 |
88 | ```typescript
89 | /**
90 | * A cast that replies to a URL
91 | *
92 | * "I think this is a great protocol 🚀"
93 | */
94 | const castReplyingToAUrl = await makeCastAdd(
95 | {
96 | text: 'I think this is a great protocol 🚀',
97 | embeds: [],
98 | embedsDeprecated: [],
99 | mentions: [],
100 | mentionsPositions: [],
101 | parentUrl: 'https://www.farcaster.xyz/',
102 | },
103 | dataOptions,
104 | ed25519Signer
105 | );
106 | ```
107 |
108 | ## Channels
109 |
110 | A cast can be sent into a channel, which instructs clients that it is related to a specific topic. Clients may choose to use this metadata in different ways, like grouping channel casts together or recommending them to certain users.
111 |
112 | A channel is simply a `parentURL` that is either a URL or NFT, which all clients recognize as a channel by loose consensus. There is no protocol level agreement on the list of channels yet, but the `casts` table in the replicator database can be used to get a list of commonly used channels.
113 |
114 | ```sql
115 | /* Query for a list of channels */
116 | select parent_url,
117 | count(*) as count
118 | from casts
119 | where parent_url is not null
120 | group by parent_url
121 | order by count desc;
122 | ```
123 |
124 | ```typescript
125 | // Cast into the Farcaster channel
126 | const channelCast = await makeCastAdd(
127 | {
128 | text: 'I love farcaster',
129 | embeds: [],
130 | embedsDeprecated: [],
131 | mentions: [],
132 | mentionsPositions: [],
133 | parentUrl: 'https://www.farcaster.xyz/', // This is illustrative, and is not an actual channel URL
134 | },
135 | dataOptions,
136 | ed25519Signer
137 | );
138 | ```
139 |
--------------------------------------------------------------------------------
/docs/developers/guides/writing/submit-messages.md:
--------------------------------------------------------------------------------
1 | # Submit data to the hub
2 |
3 | ::: info Pre-requisites
4 |
5 | - Write access to a hubble instance
6 | - Private key of an account key registered to an fid
7 | - Local typescript development environment
8 |
9 | :::
10 |
11 | To see a full example of how to submit different kinds of messages to the hub,
12 | see [here](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs/examples/write-data)
13 |
--------------------------------------------------------------------------------
/docs/developers/guides/writing/verify-address.md:
--------------------------------------------------------------------------------
1 | # Create an address verification
2 |
3 | ::: info Pre-requisites
4 |
5 | - Write access to a hubble instance
6 | - Private key of an account key registered to an fid
7 | - An Ethereum provider URL for OP Mainnet (e.g. via [Alchemy](https://www.alchemy.com/),[Infura](https://www.infura.io/) or [QuickNode](https://www.quicknode.com/)).
8 |
9 | :::
10 |
11 | To create a [Verification](https://docs.farcaster.xyz/reference/hubble/datatypes/messages.html#_6-verification) proving ownership of an external Ethereum address, you can use an `Eip712Signer` to sign a verification message, and the `makeVerificationAddEthAddress` function to construct a message to send to a Hub.
12 |
13 | First, set up clients and account keys:
14 |
15 | ```ts
16 | import {
17 | NobleEd25519Signer,
18 | ViemLocalEip712Signer,
19 | FarcasterNetwork,
20 | makeVerificationAddEthAddress,
21 | } from '@farcaster/hub-nodejs';
22 | import { createPublicClient, http } from 'viem';
23 | import { privateKeyToAccount } from 'viem/accounts';
24 | import { optimism } from 'viem/chains';
25 |
26 | const publicClient = createPublicClient({
27 | chain: optimism,
28 | transport: http(),
29 | });
30 |
31 | const alice = privateKeyToAccount('0xab..12');
32 | const eip712Signer = new ViemLocalEip712Signer(alice);
33 |
34 | const ed25519Signer = new NobleEd25519Signer('0xcd..34');
35 | ```
36 |
37 | Then create a verification signature using an `Eip712Signer`. You'll need to query the latest blockhash on OP mainnet and include it in the signed message.
38 |
39 | ```ts
40 | const latestBlock = await publicClient.getBlock();
41 |
42 | const fid = 1n;
43 | const network = FarcasterNetwork.MAINNET;
44 | const address = alice.address;
45 | const blockHash = latestBlock.blockhash;
46 |
47 | const ethSignature = eip712Signer.signVerificationEthAddressClaim({
48 | fid,
49 | address,
50 | network,
51 | blockHash,
52 | });
53 | ```
54 |
55 | Finally, use `makeVerificationAddEthAddress` to construct a [`Verification`](https://docs.farcaster.xyz/reference/hubble/datatypes/messages.html#_6-verification) message you can send to a Hub.
56 |
57 | ```ts
58 | if (ethSignature.isOk()) {
59 | const message = await makeVerificationAddEthAddress(
60 | {
61 | address,
62 | blockHash,
63 | ethSignature,
64 | },
65 | { fid, network },
66 | ed25519Signer
67 | );
68 | }
69 | ```
70 |
71 | ### Full code example
72 |
73 | ::: code-group
74 |
75 | ```ts [@farcaster/hub-nodejs]
76 | import {
77 | NobleEd25519Signer,
78 | ViemLocalEip712Signer,
79 | FarcasterNetwork,
80 | makeVerificationAddEthAddress,
81 | } from '@farcaster/hub-nodejs';
82 | import { createPublicClient, http } from 'viem';
83 | import { privateKeyToAccount } from 'viem/accounts';
84 | import { optimism } from 'viem/chains';
85 |
86 | const publicClient = createPublicClient({
87 | chain: optimism,
88 | transport: http(),
89 | });
90 |
91 | const alice = privateKeyToAccount('0xab..12');
92 | const eip712Signer = new ViemLocalEip712Signer(alice);
93 |
94 | const ed25519Signer = new NobleEd25519Signer('0xcd..34');
95 |
96 | const latestBlock = await publicClient.getBlock();
97 |
98 | const fid = 1n;
99 | const network = FarcasterNetwork.MAINNET;
100 | const address = alice.address;
101 | const blockHash = latestBlock.blockhash;
102 |
103 | const ethSignature = eip712Signer.signVerificationEthAddressClaim({
104 | fid,
105 | address,
106 | network,
107 | blockHash,
108 | });
109 |
110 | if (ethSignature.isOk()) {
111 | const message = await makeVerificationAddEthAddress(
112 | {
113 | address,
114 | blockHash,
115 | ethSignature,
116 | },
117 | { fid, network },
118 | ed25519Signer
119 | );
120 | }
121 | ```
122 |
123 | :::
124 |
--------------------------------------------------------------------------------
/docs/developers/index.md:
--------------------------------------------------------------------------------
1 | :::tip Join the conversation
2 | Ask questions and hang out with other Farcaster developers in the [/fc-devs](https://warpcast.com/~/channel/fc-devs) channel on Farcaster.
3 | :::
4 |
5 | ## Create mini apps
6 |
7 | Learn how to build mini apps (previously called Frames) that run inside a Farcaster feed.
8 |
9 |
10 | - [Introduction](https://miniapps.farcaster.xyz/){target="_self"}- understand what a mini app is and how it works
11 |
12 | - [Getting Started](https://miniapps.farcaster.xyz/docs/getting-started){target="_self"}- Build your first mini app
13 |
14 | ## Sign in with Farcaster
15 |
16 | Make it easy for users to sign in to your app with their Farcaster account.
17 |
18 | - [Examples](/auth-kit/examples.md) - see Sign in with Farcaster (SIWF) in action
19 | - [AuthKit](/auth-kit/installation.md) - a React toolkit to integrate SIWF
20 | - [FIP-11](https://github.com/farcasterxyz/protocol/discussions/110) - the formal standard for SIWF
21 |
22 | ## Analyze Farcaster data
23 |
24 | Sync the Farcaster network to a local machine so you can run queries on the data.
25 |
26 | - [Run a hub](/hubble/install.md) - get realtime access to Farcaster data on your machine
27 | - [Write your first hub query](./guides/querying/fetch-casts.md) - get an account's casts from a hub
28 | - [Set up the replicator](./guides/apps/replicate.md) - sync a hub to a postgres database to run advanced queries
29 |
30 | ## Write to Farcaster
31 |
32 | - [Hello World](/developers/guides/basics/hello-world) - programmatically create an account and publish a cast
33 |
--------------------------------------------------------------------------------
/docs/developers/resources.md:
--------------------------------------------------------------------------------
1 | # Resources
2 |
3 | An opinionated list of the best libraries and tools for Farcaster developers. A more comprehensive list of resources can be found in a16z's [awesome-farcaster](https://github.com/a16z/awesome-farcaster) repo.
4 |
5 | Resources may be added via pull request. They must be purpose built for Farcaster only, actively maintained and adhere to the ethos and specification of the protocol.
6 |
7 | :::warning
8 | Resources are often from third parties and are not reviewed. Use them at your own risk.
9 | :::
10 |
11 | ## Libraries
12 |
13 | ### Mini Apps
14 |
15 |
16 | - [@farcaster/mini-app](https://miniapps.farcaster.xyz/docs/getting-started){target="_self"}- CLI tool for building mini apps.
17 | - [@neynar/create-farcaster-mini-app](https://www.npmjs.com/package/@neynar/create-farcaster-mini-app) - A Mini App quickstart npx script from Neynar.
18 |
19 | ### Legacy Frames
20 |
21 | - [@frame-js/frames](https://framesjs.org/) - next.js template for building and debugging frames.
22 | - [@coinbase/onchainkit](https://github.com/coinbase/onchainkit) - react toolkit to create frames.
23 | - [@frog](https://frog.fm) - framework for frames.
24 |
25 | ### Apps
26 |
27 | - [farcaster kit](https://www.farcasterkit.com/) - react hooks for building Farcaster apps.
28 |
29 | ### Hubs
30 |
31 | - [@farcaster/hub-nodejs](https://www.npmjs.com/package/@farcaster/hub-nodejs) - lightweight, fast Typescript interface for Farcaster Hubs.
32 |
33 | ### Onchain
34 |
35 | - [farcaster-solidity](https://github.com/pavlovdog/farcaster-solidity/) - libraries for verifying and parsing Farcaster messages onchain
36 |
37 | ## Dashboards
38 |
39 | - [Farcaster Hub Map](https://farcaster.spindl.xyz/) - geographical map of Farcaster hubs
40 | - [Dune: Farcaster](https://dune.com/pixelhack/farcaster) - @pixelhack's dashboard for network stats
41 | - [Dune: Farcaster User Onchain Activities](https://dune.com/yesyes/farcaster-users-onchain-activities) - dashboard of farcaster user's onchain activity
42 |
43 | ## Learning
44 |
45 | - [dTech Farcaster Tutorials](https://dtech.vision/farcaster)
46 |
47 | ## Open Source Examples
48 |
49 | - [quikcast](https://github.com/farcasterxyz/quikcast) - an end-to-end connected app implementation for Farcaster
50 | - [fc-polls](https://github.com/farcasterxyz/fc-polls) - a simple polling app built using frames
51 |
52 | ## Services
53 |
54 | - [Neynar](https://neynar.com/) - infrastructure and services for building farcaster apps.
55 | - [dTech](https://dtech.vision) - Farcaster Development and Consulting Agency
56 |
--------------------------------------------------------------------------------
/docs/developers/siwf/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Sign In with Farcaster
3 | ---
4 |
5 | # Introduction
6 |
7 | Sign In with Farcaster (SIWF) is a way for users to sign into any app using their
8 | Farcaster identity.
9 |
10 | When a user signs into your application with Farcaster you'll be able to use
11 | public social data like their social graph and profile information to provide
12 | a streamlined onboarding experience and social-powered features.
13 |
14 | ### How does it work?
15 |
16 | 1. Show a "Sign in with Farcaster" button to the user.
17 | 2. Wait for the user to click, scan a QR code and approve the request in Warpcast.
18 | 3. Receive and verify a signature from Warpcast.
19 | 4. Show the logged in user's profile picture and username.
20 |
21 | 
22 |
23 | ## Next Steps
24 |
25 | - Integrate SIWF to your app today with [AuthKit](/auth-kit/).
26 | - Read about the underlying standard in [FIP-11: Sign In With
27 | Farcaster](https://github.com/farcasterxyz/protocol/discussions/110).
28 |
--------------------------------------------------------------------------------
/docs/developers/siwf/siwf_demo.avifs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/developers/siwf/siwf_demo.avifs
--------------------------------------------------------------------------------
/docs/developers/utilities.md:
--------------------------------------------------------------------------------
1 | # Links
2 |
3 | - https://github.com/a16z/awesome-farcaster
4 |
--------------------------------------------------------------------------------
/docs/examples/contracts/clients.ts:
--------------------------------------------------------------------------------
1 | import { createWalletClient, createPublicClient, custom, http } from 'viem';
2 | import { privateKeyToAccount } from 'viem/accounts';
3 | import { optimism } from 'viem/chains';
4 |
5 | export const publicClient = createPublicClient({
6 | chain: optimism,
7 | transport: http(),
8 | });
9 |
10 | export const walletClient = createWalletClient({
11 | chain: optimism,
12 | transport: custom(window.ethereum),
13 | });
14 |
15 | // JSON-RPC Account
16 | export const [account] = await walletClient.getAddresses();
17 |
18 | // Local Account
19 | export const account = privateKeyToAccount('0x...');
20 |
--------------------------------------------------------------------------------
/docs/examples/contracts/metadata.ts:
--------------------------------------------------------------------------------
1 | import { ViemLocalEip712Signer } from '@farcaster/hub-web';
2 | import { privateKeyToAccount } from 'viem/accounts';
3 | import { getDeadline } from './helpers.ts';
4 | import { getPublicKey } from './signer.ts';
5 |
6 | // App account
7 | export const appAccount = privateKeyToAccount('0x...');
8 |
9 | const deadline = getDeadline();
10 | const publicKey = await getPublicKey();
11 |
12 | export const getMetadata = async () => {
13 | const eip712signer = new ViemLocalEip712Signer(appAccount);
14 | const metadata = await eip712signer.getSignedKeyRequestMetadata({
15 | requestFid: 9152n, // App fid
16 | key: publicKey,
17 | deadline,
18 | });
19 | if (metadata.isOk()) {
20 | return metadata.value;
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/docs/examples/contracts/signer.ts:
--------------------------------------------------------------------------------
1 | import * as ed from '@noble/ed25519';
2 | import { NobleEd25519Signer } from '@farcaster/hub-web';
3 |
4 | const privateKeyBytes = ed.utils.randomPrivateKey();
5 | export const accountKey = new NobleEd25519Signer(privateKeyBytes);
6 |
7 | export const getPublicKey = async () => {
8 | const accountKeyResult = await accountKey.getSignerKey();
9 | if (accountKeyResult.isOk()) {
10 | return accountKeyResult.value;
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/docs/hubble/hubble.md:
--------------------------------------------------------------------------------
1 | # Hubble
2 |
3 | [Hubble](https://github.com/farcasterxyz/hub-monorepo) is an implementation of the [Farcaster Hub Protocol](https://github.com/farcasterxyz/protocol), written
4 | in [TypeScript](https://www.typescriptlang.org/) and [Rust](https://www.rust-lang.org/).
5 |
6 | Hubble creates a private instance of Farcaster on your machine. It peers with other instances and downloads a copy of
7 | the entire network. Messages uploaded to your Hubble instance will be broadcast to the network.
8 |
9 | We recommend running Hubble if you are building an app, need access to the latest data or want to help decentralize the
10 | network.
11 |
12 | ## Hosted Instances
13 |
14 | Hubble instances can also be hosted for you by other service providers.
15 |
16 | - [Hubs x Neynar](https://hubs.neynar.com/)
17 | - [Hubs x Pinata](https://pinata.cloud/pinata-hub)
18 |
19 | ## Public Instances
20 |
21 | The Farcaster team runs an instance of Hubble for use by the public. This isn't guaranteed to be stable, and is
22 | read-only for now.
23 |
24 | ```bash
25 | url: hoyt.farcaster.xyz
26 | httpapi_port: 2281
27 | gossipsub_port: 2282
28 | grpc_port: 2283
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/hubble/migrating.md:
--------------------------------------------------------------------------------
1 | # Migrating to snapchain
2 |
3 | [Snapchain](https://github.com/farcasterxyz/snapchain) is a more scalable implementation of the Farcaster protocol. In order to interact with snapchain, you can operate your own read node.
4 |
5 | ## Running a node
6 |
7 | ```bash
8 | mkdir snapchain
9 | wget https://raw.githubusercontent.com/farcasterxyz/snapchain/refs/heads/main/docker-compose.mainnet.yml -O docker-compose.yml
10 | docker compose up # -d to run in the background
11 | ```
12 |
13 | Note, the default http port is `3381`, the default gossip port is `3382` and the default grpc port is `3383`. You may need to open these ports.
14 |
15 | ## Reading from snapchain
16 |
17 | Read APIs are fully backwards compatible with hubs so no migration is required. Refer to [existing docs](https://docs.farcaster.xyz/developers/guides/querying/fetch-casts) for reading data via the client library.
18 |
19 | Via http once you have a node running
20 |
21 | ```bash
22 | curl http://locaalhost:3381/v1/info
23 | ```
24 |
25 | Via grpc
26 |
27 | ```bash
28 | git clone git@github.com:farcasterxyz/snapchain.git
29 | cd snapchain
30 | grpcurl -plaintext -proto src/proto/rpc.proto -import-path src/proto localhost:3383 HubService/GetInfo
31 | ```
32 |
33 | If you are using Shuttle, it will work the same as before. Just need to point it to the snapchain node.
34 |
35 | ## Writing to snapchain
36 |
37 | The write APIs are also backwards compatible with hubs, with some caveats (see below).
38 |
39 | In order to write to snapchain, you should run a node and submit directly to it. Refer to [existing docs](https://docs.farcaster.xyz/developers/guides/writing/submit-messages) for writing dia via the client library. Note, you **MUST** use version `0.16` or later of the `hub-nodejs` library.
40 |
41 | ### Gotchas
42 |
43 | - If you're not using the builders from the `hub-nodejs` library, you should make sure to populate `dataBytes` instead of `data` in every message, like so:
44 |
45 | ```ts
46 | if (message.dataBytes === undefined) {
47 | message.dataBytes = protobufs.MessageData.encode(message.data).finish();
48 | message.data = undefined;
49 | }
50 | ```
51 |
52 | - Some of the error messages returned from `submitMessage` are different in Snapchain than in Hubs.
53 | - Snapchain submits are best-effort. It's possible that `submitMessage` succeeds but the message is not included into a block. Follow [this issue](https://github.com/farcasterxyz/snapchain/issues/353) on the plan for providing feedback to clients when a message accepted into the mempool is not able to be included in a block.
54 |
55 | ## Testnet
56 |
57 | There is a testnet for snapchain, you can run a node against it by using this docker compose file:
58 |
59 | ```bash
60 | mkdir snap_test
61 | wget https://raw.githubusercontent.com/farcasterxyz/snapchain/refs/heads/main/docker-compose.testnet.yml -O docker-compose.yml
62 | docker compose up # -d to run in the background
63 | ```
64 |
65 | Note, testnet is unstable and will be reset from time to time.
66 |
--------------------------------------------------------------------------------
/docs/hubble/monitoring.md:
--------------------------------------------------------------------------------
1 | # Monitoring Hubble
2 |
3 | Hubble ships with a default Grafana configuration to monitor sync and perf.
4 |
5 | If you used the install script, open localhost:3000 in a browser to see your dashboard. If you used docker manually or installed from source, you may need to set this up yourself.
6 |
7 | If you've set hubble up on a remote server, set up an ssh tunnel with `ssh -L 3000:localhost:3000 xyz@1.1.1.1` and then open localhost:3000 in a browser to see your dashboards.
8 |
9 | ## Setting up monitoring
10 |
11 | 1. Start grafana and statsd
12 |
13 | ```bash
14 | docker compose up statsd grafana
15 | ```
16 |
17 | 2. Enable monitoring on your Hub by setting this in your `.env`
18 |
19 | ```bash
20 | STATSD_METRICS_SERVER=statsd:8125
21 | ```
22 |
23 | If you are running hubble from source, you can pass this in as a command line argument
24 |
25 | ```bash
26 | yarn start --statsd-metrics-server 127.0.0.1:8125
27 | ```
28 |
29 | 3. Restart your hub
30 |
31 | 4. Open Grafana in a browser at `127.0.0.1:3000`. The default username/password is `admin`/`admin`. You will need to change your password on first login
32 |
33 | 5. Go to `Settings -> Datasource -> Add new data source` and select `Graphite`. Set the URL to `http://statsd:80` and click `Save & Test` to make sure it is working
34 |
35 | 6. Go to `Settings -> Dashboard -> Add New -> Import`, and in the `Import from Panel JSON`, paste the contents of the [Default Grafana Dashboard](https://github.com/farcasterxyz/hub-monorepo/blob/main/apps/hubble/grafana/grafana-dashboard.json)
36 |
--------------------------------------------------------------------------------
/docs/hubble/networks.md:
--------------------------------------------------------------------------------
1 | # Networks
2 |
3 | A Farcaster account must choose which network it posts its messages to. Any account registered in the [contracts](../learn/architecture/contracts.md) can post to any network. But messages posted in one network are not visible in any other network.
4 |
5 | There are two main networks:
6 |
7 | - **Testnet** - the latest beta release intended for developers
8 | - **Mainnet** - the stable version that everyone uses
9 |
10 | When [installing your hub](./install.md), you'll need to choose a network to connect to.
11 |
12 | ## Testnet
13 |
14 | Testnet is a sandbox environment for developers to test new features. Dummy messages are broadcast every 10 seconds to simulate activity.
15 |
16 | Set the following variables in your .env file in `apps/hubble`:
17 |
18 | ```sh
19 | FC_NETWORK_ID=2
20 | BOOTSTRAP_NODE=/dns/testnet1.farcaster.xyz/tcp/2282
21 | ```
22 |
23 | If running from source code, add these arguments to the `yarn start` command
24 |
25 | ```sh
26 | yarn start ... \
27 | -n 2 \
28 | -b /dns/testnet1.farcaster.xyz/tcp/2282
29 | ```
30 |
31 | ## Mainnet
32 |
33 | Mainnet is the production environment that everyone uses.
34 |
35 | Set the following variables in your .env file in `apps/hubble`:
36 |
37 | ```sh
38 | FC_NETWORK_ID=1
39 | BOOTSTRAP_NODE=/dns/hoyt.farcaster.xyz/tcp/2282
40 | ```
41 |
42 | If running from source code, add these arguments to the `yarn start` command
43 |
44 | ```sh
45 | yarn start ... \
46 | -n 1 \
47 | -b /dns/hoyt.farcaster.xyz/tcp/2282
48 | ```
49 |
--------------------------------------------------------------------------------
/docs/hubble/troubleshooting.md:
--------------------------------------------------------------------------------
1 | # Hubble troubleshooting
2 |
3 | ## Fetch Hubble logs
4 |
5 | From the hubble folder, fetch logs with the following command:
6 |
7 | ```bash
8 | $ ./hubble.sh logs
9 | ```
10 |
11 | Or you can use docker-compose directly:
12 |
13 | ```bash
14 | # sudo is required if you used the hubble script to install the hub
15 | # You may need to use `docker-compose` instead of `docker compose` depending on your docker setup
16 | $ sudo docker compose logs -f hubble
17 | ```
18 |
19 | ## Restart Hubble
20 |
21 | From the hubble folder, spin up and down the instance with the following commands
22 |
23 | ```bash
24 | $ ./hubble.sh down
25 | $ ./hubble.sh up
26 | ```
27 |
28 | ## Reset the db
29 |
30 | The best way to reset the db is to delete the `.rocks` directory entirely, which forces the hub to fetch the latest
31 | snapshot and re-sync from there.
32 |
33 | ```bash
34 | $ ./hubble.sh down # Ensure the hub is not running
35 | $ rm -rf .rocks # make sure you are in the hub directory
36 | ```
37 |
38 | ## No peers or incoming gossip connections
39 |
40 | If you're not seeing any peers or incoming gossip connections, it's likely that network issues are preventing the hub
41 | with communicating with other hubs.
42 |
43 | Check your firewall and NAT settings to ensure that ports 2282 (gossip) and 2283 (rpc, for sync) are accessible.
44 |
45 | You could also try bootstrapping the hub with a non-default peer by adding the following line to your `.env` file:
46 |
47 | ```dotenv
48 | BOOTSTRAP_NODE=/dns/hoyt.farcaster.xyz/tcp/2282
49 | ```
50 |
51 | ## Is my hub in sync?
52 |
53 | Use the [grafana dashboard](/hubble/monitoring) to monitor your hub. The Status tab will show the message sync
54 | percent of your hub compared to its peers. If this is less than 100%, try restarting the hub and waiting a while. If
55 | this persists, file an issue on the [hub repo](https://github.com/farcasterxyz/hub-monorepo/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=bug%20%28hubble%29%3A).
56 |
57 | ## Managing your Peer ID
58 |
59 | Hubble has a key pair that it uses to sign peer-to-peer messages, which is stored in the `.hub` directory as a `...._id.protobuf` file. The name of the file contains the public key or Peer ID, while the contents contain the private key.
60 |
--------------------------------------------------------------------------------
/docs/hubble/tutorials.md:
--------------------------------------------------------------------------------
1 | # Tutorials
2 |
3 | Guides to set up a Hubble instance using various cloud providers.
4 |
5 | - [AWS EC2](https://warpcast.notion.site/Set-up-Hubble-on-EC2-Public-23b4e81d8f604ca9bf8b68f4bb086042)
6 | - [Digital Ocean](https://warpcast.notion.site/Set-up-Hubble-on-DigitalOcean-Public-e38173c487874c91828665e73eac94c1)
7 | - [Google Cloud Platform (GCP)](tutorials/gcp.md)
8 |
--------------------------------------------------------------------------------
/docs/hubble/tutorials/gcp.md:
--------------------------------------------------------------------------------
1 | # Run a Hubble on GCP
2 |
3 | ## Intro
4 |
5 | This is a step-by-step guide to setting up Hubble on GCP.
6 | It usually takes less than 30 minutes to complete the whole process.
7 |
8 | ### Requirements
9 |
10 | - [GCP](https://console.cloud.google.com/) account
11 | - [Alchemy](https://www.alchemy.com/) account
12 |
13 | ### Costs
14 |
15 | - GCP setup recommended in this tutorial may cost up to $70/month
16 | - Alchemy usage should stay within the free tier
17 |
18 | ## Create GCP VM
19 |
20 | Open **Google Cloud Shell** and execute the following commands:
21 |
22 |
Click on Google Cloud Shell Icon
23 |
24 | Execute the below commands in the cloud shell:
25 |
26 |
112 |
113 | It will take a few minutes before the VM is created. Time to enjoy your :coffee:
114 |
115 |
116 |
117 | Now you should be able to connect to your VM by clicking on the **SSH** button.
118 |
119 | \
120 | Now Install Docker as described here [https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)
121 |
122 | Now follow the steps as described on [Install page](../install.md) \
123 | \
124 | Your Hubble is up and running when you see below :white_check_mark:
125 |
126 |
127 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Farcaster Docs
6 | tagline: Permissionlessly build and distribute social apps
7 | actions:
8 | - theme: brand
9 | text: Build a mini app
10 | link: https://miniapps.farcaster.xyz/docs/getting-started
11 | target: _self
12 | - theme: alt
13 | text: Explore Sign In with Farcaster
14 | link: /developers/siwf/
15 | - theme: alt
16 | text: Learn about the protocol
17 | link: /learn/
18 | ---
19 |
20 | ### Build a Mini App
21 |
22 | Learn how to build Mini Apps (previously known as Frames v2) that run inside a Farcaster feed.
23 |
24 |
25 | - [Introduction to Mini Apps](https://miniapps.farcaster.xyz/){target="_self"}- Understand what a mini app is and how it works.
26 |
27 | - [Build your first Mini App](https://miniapps.farcaster.xyz/docs/getting-started){target="_self"}- Make mini apps that run inside Farcaster.
28 |
29 | ### Explore Sign In with Farcaster
30 |
31 | Allow users to Sign In with Farcaster and leverage social data in your app.
32 |
33 | - [Introduction](/developers/siwf/) - Learn about Sign In with Farcaster.
34 | - [Add SIWF using AuthKit](/auth-kit/installation) - a React toolkit to add SIWF to your app.
35 | - [Examples](/auth-kit/examples) - see Sign In with Farcaster in action.
36 |
37 | ### Analyze Farcaster data
38 |
39 | Sync the Farcaster network to a local machine so you can run queries on the data.
40 |
41 | - [Write your first hub query](/developers/guides/querying/fetch-casts.md) - get an account's casts from a hub.
42 | - [Set up the replicator](/developers/guides/apps/replicate.md) - sync a hub to a postgres database to run advanced queries.
43 | - [Run a hub](/hubble/install.md) - get realtime access to Farcaster data on your machine.
44 |
--------------------------------------------------------------------------------
/docs/learn/architecture/contracts.md:
--------------------------------------------------------------------------------
1 | # Contracts
2 |
3 | A Farcaster account is managed and secured onchain using the Farcaster contracts. This section provides a high level overview and avoids some implementation details. For the full picture, see the [contracts repository](https://github.com/farcasterxyz/contracts/).
4 |
5 |
6 |
7 | There are three main contracts deployed on OP Mainnet:
8 |
9 | - **Id Registry** - creates new accounts
10 | - **Storage Registry** - rents storage to accounts
11 | - **Key Registry** - adds and removes app keys from accounts
12 |
13 |
14 |
15 | 
16 |
17 | The contracts are deployed at the following addresses:
18 |
19 | | Contract | Address |
20 | | --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
21 | | IdRegistry | [0x00000000fc6c5f01fc30151999387bb99a9f489b](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b) |
22 | | StorageRegistry | [0x00000000fcce7f938e7ae6d3c335bd6a1a7c593d](https://optimistic.etherscan.io/address/0x00000000fcce7f938e7ae6d3c335bd6a1a7c593d) |
23 | | KeyRegistry | [0x00000000fc1237824fb747abde0ff18990e59b7e](https://optimistic.etherscan.io/address/0x00000000fc1237824fb747abde0ff18990e59b7e) |
24 |
25 | ### Id Registry
26 |
27 | The IdRegistry lets users register, transfer and recover Farcaster accounts. An account is identified by a unique number (the fid) which is assigned to an Ethereum address on registration. An Ethereum address may only own one account at a time, though it may transfer it freely to other accounts. It may also specify a recovery address which can transfer the account at any time.
28 |
29 | ### Storage Registry
30 |
31 | The Storage Registry lets accounts rent [storage](../what-is-farcaster/messages.md#storage) by making a payment in ETH. The storage prices are set by admins in USD and converted to ETH using a Chainlink oracle. The price increases or decreases based on supply and demand.
32 |
33 | ### Key Registry
34 |
35 | The Key Registry lets accounts issue keys to apps, so that they can publish messages on their behalf. Keys can be added or removed at any time. To add a key, an account must submit the public key of an EdDSA key pair along with a requestor signature. The requestor can be the account itself or an app that wants to operate on its behalf.
36 |
--------------------------------------------------------------------------------
/docs/learn/architecture/ens-names.md:
--------------------------------------------------------------------------------
1 | # ENS Names
2 |
3 | Farcaster uses ENS names as human readable identifiers for accounts. Two kinds of ENS names are supported:
4 |
5 | - **Offchain ENS names**: free and controlled by farcaster. (e.g. @alice)
6 | - **Onchain ENS names**: costs money and is controlled by your wallet. (e.g. @alice.eth)
7 |
8 | ENS names can only be used on Farcaster if they are <= 16 characters and contain only lowercase letters, numbers, and hyphens.
9 |
10 | 
11 |
12 | ## Onchain ENS Names
13 |
14 | Users can use onchain ENS names like `@alice.eth` on Farcaster.
15 |
16 | Onchain ENS names are issued by ENS, end in .eth and must be registered on the Ethereum L1 blockchain. Anyone can register an ENS name by using the [ENS app](https://app.ens.domains/).
17 |
18 | Users must pay a fee to register an onchain ENS name, but once registered, it is controlled by the user and cannot be revoked.
19 |
20 | ## Offchain ENS Names (Fnames)
21 |
22 | Users can use offchain ENS names like `@alice` on Farcaster.
23 |
24 | Offchain ENS names, also called Farcaster Names or Fnames, are compliant with ENS but registered offchain. Fnames are free but are subject to a usage policy to prevent squatting and impersonation. They are also subject to the following requirements:
25 |
26 | 1. An account can only have one Fname at a time.
27 | 2. An account can change its Fname once every 28 days.
28 |
29 | ### Usage Policy
30 |
31 | Registering an Fname is free but subject to the following policy:
32 |
33 | 1. Names connected to public figures or entities may be reclaimed (e.g. @google).
34 | 2. Names that haven't been used for 60+ days may be reclaimed.
35 | 3. Names that are registered for the sole purpose of resale may be reclaimed.
36 |
37 | Decisions are made by the Farcaster team and often require human judgment. Users who want a name that is fully under their control should use an onchain ENS name.
38 |
39 | ### Registry
40 |
41 | Fnames are issued as offchain names under the subdomain `fcast.id`.
42 |
43 | Bob can register the offchain ENS name `bob.fcast.id` and use it on any Farcaster app with the shorthand `@bob`. The name can be registered by making a signed request to the Fname Registry server. See the [FName API reference](/reference/fname/api) for more details on how to query and create Fnames.
44 |
45 | To learn more about how Fnames work, see [ENSIP-16](https://docs.ens.domains/ens-improvement-proposals/ensip-16-offchain-metadata)
46 | and [ERC-3668](https://eips.ethereum.org/EIPS/eip-3668).
47 |
--------------------------------------------------------------------------------
/docs/learn/architecture/hubs.md:
--------------------------------------------------------------------------------
1 | # Hubs
2 |
3 | Hubs are a distributed network of servers that store and validate Farcaster data.
4 |
5 | A computer can run software to become a Farcaster Hub. It will download onchain Farcaster data from Ethereum and offchain Farcaster data from other Hubs. Each Hub stores a copy of all Farcaster data, which can be accessed over an API.
6 |
7 | Hubs let you read and write data to Farcaster, and anyone building a Farcaster app will need to talk to one. Anyone can run a Hub on their laptop or on a cloud server. A full guide to setting up and running a Hub is available [here](https://www.thehubble.xyz).
8 |
9 | ## Design
10 |
11 | A Hub starts by syncing data from Farcaster contracts on the Optimism blockchain. It becomes aware of every user's account and their account keys.
12 |
13 | The lifecycle of a Farcaster message looks like this:
14 |
15 | 1. Alice creates a new "Hello World!" message.
16 | 2. Alice (or her app) signs the message with an account key.
17 | 3. Alice (or her app) uploads the message to a Hub.
18 | 4. The Hub checks the message's validity.
19 | 5. The Hub sends the message to peer hubs over gossip.
20 |
21 | 
22 |
23 | ### Validation
24 |
25 | Alice's message is validated by checking that it has a valid signature from one of her account keys. The Hub also ensures that the message obeys the requirements of the message type. For example, a public message or "cast" must be less than 320 bytes. Message type requirements are specified in detail in the [protocol spec](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md).
26 |
27 | ### Storage
28 |
29 | Alice's message is then checked for conflicts before being stored in the Hub. Conflicts can occur for many reasons:
30 |
31 | 1. The Hub already has a copy of the message.
32 | 2. The Hub has a later message from Alice deleting this message.
33 | 3. Alice has only paid rent for 5000 casts, and this is her 5001st cast.
34 |
35 | Conflicts are resolved deterministically and asynchronously using CRDTs (Conflict-free Replicated Data Types). For example, if Alice has no space to store messages, her oldest message will be removed.
36 |
37 | ### Replication
38 |
39 | Hubs sync using a two-phase process: gossip and diff sync. When a Hub receives and stores a message, it immediately gossips it to its peers. Gossip is performed using libp2p's gossipsub protocol and is lossy. Hubs then periodically select a random peer and perform a diff sync to find dropped messages. The diff sync process compares merkle tries of message hashes to efficiently find dropped messages.
40 |
41 | ### Consistency
42 |
43 | Hubs are said to have strong eventual consistency. If a Hub is disconnected, it can be written to it and will recover safely when it comes online. This is unlike blockchains where a node that is disconnected cannot confirm transactions. The downside is that messages may arrive out of order. For example, Bob's reply to Alice might appear before her "Hello World!" message.
44 |
45 | ### Peer Scoring
46 |
47 | Hubs monitor peers and score their behavior. If a peer doesn't accept valid messages, falls behind, or gossips too much it may be ignored by its peers.
48 |
49 | ### Implementations
50 |
51 | - [Hubble](https://www.thehubble.xyz) - a Hub implementation in TypeScript and Rust
52 |
53 | ## FAQ
54 |
55 | **1. Why should I run a Hub?**
56 |
57 | You may need a Hub if you are building an app that wants to read or write Farcaster data.
58 |
59 | **2. Are there rewards for running a Hub?**
60 |
61 | Farcaster does not provide rewards for Hubs and does not plan to.
62 |
--------------------------------------------------------------------------------
/docs/learn/architecture/overview.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | Farcaster has a hybrid architecture that stores identity onchain and data offchain.
4 |
5 | 
6 |
7 | ## Onchain
8 |
9 | Farcaster's onchain systems are implemented as [contracts on OP Mainnet](./contracts.md). Actions are performed onchain only when security and consistency are critical. Use of onchain actions is kept at a minimum to reduce costs and improve performance.
10 |
11 | Only a handful of actions are performed onchain, including:
12 |
13 | - Creating an [account](../what-is-farcaster/accounts.md).
14 | - Paying rent to [store data](../what-is-farcaster/messages.md#storage).
15 | - Adding account keys for [connected apps](../what-is-farcaster/apps.md#connected-apps).
16 |
17 | ## Offchain
18 |
19 | Farcaster's offchain system is a peer-to-peer network of servers called [Hubs](./hubs.md) which store user data. The majority of user actions are performed offchain. These include:
20 |
21 | - Posting a new public message.
22 | - Following another user.
23 | - Reacting to a post.
24 | - Updating your profile picture.
25 |
26 | Actions are performed offchain when performance and cost are critical. Use of offchain actions is typically preferred when consistency isn't a strict requirement. Offchain systems achieve security by relying on signatures from onchain systems.
27 |
--------------------------------------------------------------------------------
/docs/learn/contributing/fips.md:
--------------------------------------------------------------------------------
1 | # FIPs
2 |
3 | An FIP, or Farcaster Improvement Proposal, is a process for building consensus around protocol changes. FIP's are
4 | inspired by [Ethereum's EIPs](https://eips.ethereum.org/EIPS/eip-1)
5 | and [Python's PEPs](https://peps.python.org/pep-0001/). Anyone can write an FIP to propose a change to:
6 |
7 | 1. A process, like the protocol's release schedule
8 | 2. A standard, like URIs for onchain assets
9 | 3. An implementation, like adding a new protocol feature
10 |
11 | Read more about FIP's
12 | in [FIP-0: A proposal for making proposals](https://github.com/farcasterxyz/protocol/discussions/82). A list of
13 | finalized proposals can be found below. Proposals are made and ratified on
14 | the [discussions board](https://github.com/farcasterxyz/protocol/discussions/categories/fip-stage-4-finalized).
15 |
16 | | FIP | Title | Authors |
17 | | --- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
18 | | 0 | [A proposal for making proposals](https://github.com/farcasterxyz/protocol/discussions/82) | @v |
19 | | 1 | [Canonical URIs](https://github.com/farcasterxyz/protocol/discussions/72) | @pfh, @v |
20 | | 2 | [Flexible targets for messages](https://github.com/farcasterxyz/protocol/discussions/71) | @pfh |
21 | | 3 | [Links](https://github.com/farcasterxyz/protocol/discussions/85) | @cassie, @v |
22 | | 4 | [ENS Usernames](https://github.com/farcasterxyz/protocol/discussions/90) | @horsefacts, @sanjay, @sds, @v |
23 | | 5 | [Instant Recovery](https://github.com/farcasterxyz/protocol/discussions/100) | @v |
24 | | 6 | [Flexible Storage](https://github.com/farcasterxyz/protocol/discussions/98) | @cassie, @horsefacts, @v |
25 | | 7 | [Onchain Signers](https://github.com/farcasterxyz/protocol/discussions/103) | @horsefacts, @sanjay, @v |
26 | | 8 | [Verifications for Contract Wallets](https://github.com/farcasterxyz/protocol/discussions/109) | @horsefacts, @sanjay, @eulerlagrange.eth |
27 | | 9 | [Globally Unique Verifications](https://github.com/farcasterxyz/protocol/discussions/114) | @sanjay, @v |
28 | | 10 | [Gateways](https://github.com/farcasterxyz/protocol/discussions/133) | @horsefacts, @sanjay, @v |
29 | | 11 | [Sign in with Farcaster](https://github.com/farcasterxyz/protocol/discussions/110) | @deodad, @horsefacts, @sanjay, @v |
30 | | 12 | [Pricing schedule for flexible storage](https://github.com/farcasterxyz/protocol/discussions/126) | @v |
31 | | 13 | [Canonical serialization for hashing messages](https://github.com/farcasterxyz/protocol/discussions/87) | @sanjay, @adityapk |
32 |
--------------------------------------------------------------------------------
/docs/learn/contributing/governance.md:
--------------------------------------------------------------------------------
1 | # Governance
2 |
3 | Farcaster embraces [rough consensus and running code](https://en.wikipedia.org/wiki/Rough_consensus) as its governance model. Changes happen when someone makes a proposal, gets buy-in and ships running code. Depending on the change, different groups need to be convinced:
4 |
5 | 1. **Protocol devs**, who choose to merge changes into hubs and contracts.
6 | 2. **Hub runners**, who choose to deploy those changes to their hubs.
7 | 3. **App devs**, who choose the hubs they read from.
8 | 4. **Users**, who choose the apps they want to use.
9 |
10 | Consensus emerges from people accepting new code or rejecting it. Farcaster will not have a binding voting process,
11 | official roles or veto power for anyone. Having too much structure ossifies systems, encourages politicking and slows
12 | progress. Rough consensus biases to action, encourages diversity of viewpoints, and maximizes decentralization, which is
13 | essential for a long-lived protocol. Most changes happen through the [FIP](./fips.md) process.
14 |
--------------------------------------------------------------------------------
/docs/learn/contributing/overview.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Farcaster welcomes contributions of all sizes from the community. The protocol owes thanks to over 100 contributors who
4 | have helped us so far.
5 |
6 | To get involved, try looking up open issues in one of the repos below or join a dev call.
7 |
8 | ## Repositories
9 |
10 | | Repository | Description |
11 | | ---------------------------------------------------------------- | -------------------------------------------- |
12 | | [Protocol](https://github.com/farcasterxyz/protocol) | Specification of the protocol |
13 | | [Contracts](https://github.com/farcasterxyz/contracts) | The canonical Farcaster contracts |
14 | | [Hubble](https://github.com/farcasterxyz/hub-monorepo) | A Farcaster Hub written in Rust + Typescript |
15 | | [FName Registry](https://github.com/farcasterxyz/fname-registry) | The canonical server to register fnames |
16 | | [Docs](https://github.com/farcasterxyz/docs) | Documentation for all the above (this site) |
17 |
18 | ## Documentation
19 |
20 | This site serves as the central hub for documentation on the protocol. If you have feedback, please open an issue or
21 | create a pull request at [farcasterxyz/docs](https://github.com/farcasterxyz/docs)
22 |
23 | ## Dev Calls
24 |
25 | We host a bi-weekly developer call to discuss upcoming changes to the protocol. The call is open to anyone and is a
26 | great way to get involved.
27 |
28 | - [Calendar Invite](https://calendar.google.com/calendar/u/0?cid=NjA5ZWM4Y2IwMmZiMWM2ZDYyMTkzNWM1YWNkZTRlNWExN2YxOWQ2NDU3NTA3MjQwMTk3YmJlZGFjYTQ3MjZlOEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) -
29 | Calendar invite to join upcoming calls.
30 | - [Recordings](https://www.youtube.com/watch?v=lmGXWP5m1_Y&list=PL0eq1PLf6eUeZnPtyKMS6uN9I5iRIlnvq) - watch recordings
31 | of previous calls.
32 |
--------------------------------------------------------------------------------
/docs/learn/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | Farcaster is a [sufficiently decentralized](https://www.varunsrinivasan.com/2022/01/11/sufficient-decentralization-for-social-networks) social network built on Ethereum.
4 |
5 | It is a public social network similar to X and Reddit. Users can create profiles, post "casts" and follow others. They own their accounts and relationships with other users and are free to move between different apps.
6 |
7 | :::tip Join Farcaster
8 | If you're not on Farcaster, get started by [creating your account](https://www.farcaster.xyz/) with the official Farcaster client.
9 | :::
10 |
11 | ## Learn
12 |
13 | If you want to learn more, get started by diving into these concepts:
14 |
15 | - [Farcaster 101](https://www.youtube.com/playlist?list=PL0eq1PLf6eUdm35v_840EGLXkVJDhxhcF) - a walkthrough of the Farcaster protocol in short, 5 minute videos.
16 | - [Core Concepts](/learn/what-is-farcaster/accounts) - learn about the building blocks of Farcaster, starting with accounts.
17 | - [Architecture](/learn/architecture/overview) - a breakdown of Farcaster's onchain and offchain systems.
18 |
19 | ## Tutorials
20 |
21 | - [Build your first mini app](/developers/frames/getting-started) - Make mini-apps that run inside Farcaster.
22 | - [Sign in with Farcaster](/auth-kit/installation) - Let users login to your app with their Farcaster account.
23 | - [Write your first app](/developers/index) - Publish a "Hello World" message to Farcaster.
24 |
25 | Find more how-tos, guide and tutorials like this in the [developers](/developers/) section.
26 |
27 | ## Documentation
28 |
29 | - [Farcaster Spec](https://github.com/farcasterxyz/protocol) - Specifications for Farcaster, including its contracts and hubs.
30 | - [Mini Apps Spec](/developers/frames/spec) - Specifications for writing and rendering mini apps in Farcaster apps.
31 | - [APIs](/reference/) - Docs for API's and ABI's for onchain and offchain systems.
32 |
33 | ## Contributing
34 |
35 | To learn about how to contribute to the protocol, including this documentation site, check out
36 | the [Contributing](/learn/contributing/overview) section.
37 |
--------------------------------------------------------------------------------
/docs/learn/what-is-farcaster/accounts.md:
--------------------------------------------------------------------------------
1 | # Accounts
2 |
3 | A Farcaster account lets you set up a username, profile picture and publish short text messages known as casts. Any Ethereum address can register a Farcaster account by making an onchain transaction.
4 |
5 | ## Creating an account
6 |
7 | A Farcaster account is created by calling the IdGateway contract. It will assign a new Farcaster ID or fid to your Ethereum address.
8 |
9 | You'll need to get a username, rent storage and add a key before you can use your account. These steps require many signatures and onchain transactions and can be tedious with a regular Ethereum wallet.
10 |
11 | We recommend starting with the [official client](https://www.farcaster.xyz/), developed by the Farcaster team which will handle the entire flow for you. It also uses a separate Ethereum account to sign transactions, so you can keep your main Ethereum account secure.
12 |
13 | ## Adding account keys
14 |
15 | Accounts can issue keys which let apps write messages on their behalf. Users will typically issue a key to each Farcaster app they use.
16 |
17 | Keys are managed by the KeyRegistry contract. To add a key, you'll need to submit the public key of an EdDSA key pair along with a requestor signature. The requestor can be the account itself or an app that wants to operate on its behalf.
18 |
19 | ## Recovering an account
20 |
21 | Users often set up separate wallets for their social apps and it's easy to lose access. Farcaster lets any account specify a recovery address which can be used to recover the account. It can be configured when creating the account or anytime after.
22 |
23 | Users can set the recovery address to trusted services like the official Farcaster client or they can manage it themselves using a regular Ethereum wallet.
24 |
25 | ## Resources
26 |
27 | ### Specifications
28 |
29 | - [Contract Specifications](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#1-smart-contracts) - The onchain contracts that manage Farcaster accounts, account keys and recovery addresses.
30 |
31 | ### APIs
32 |
33 | - [IdRegistry](../../reference/contracts/reference/id-registry) - Lookup account data onchain.
34 | - [IdGateway](../../reference/contracts/reference/id-gateway) - Create accounts onchain.
35 | - [KeyRegistry](../../reference/contracts/reference/key-registry) - Lookup account key data onchain.
36 | - [KeyGateway](../../reference/contracts/reference/key-gateway) - Create account keys onchain.
37 | - [Get Farcaster Ids](../../reference/hubble/httpapi/fids) - Fetch a list of all registered account fids from a hub.
38 | - [Get account keys](../../reference/hubble/httpapi/onchain#onchainsignersbyfid) - Fetch the account keys (signers) for an account from a hub.
39 |
40 | ### Tutorials
41 |
42 | - [Create an account](../../developers/guides/accounts/create-account.md) - Create a new account on Farcaster.
43 | - [Create an account key](../../developers/guides/accounts/create-account-key.md) - Create a new account key for your account.
44 | - [Find account by username](../../developers/guides/accounts/find-by-name.md) - Find an account by its username.
45 | - [Change custody address](../../developers/guides/accounts/change-custody.md) - Change the address that owns your account.
46 | - [Change recovery address](../../developers/guides/accounts/change-recovery.md) - Change the address that recovers your account.
47 | - [Find account key requestor](../../developers/guides/advanced/decode-key-metadata.md) - Find the app that the user granted an account key to.
48 | - [Query signups from replicator](../../developers/guides/advanced/query-signups.md) - Query the number of signups from the replicator.
49 |
--------------------------------------------------------------------------------
/docs/learn/what-is-farcaster/apps.md:
--------------------------------------------------------------------------------
1 | # Apps
2 |
3 | Using Farcaster requires an Ethereum wallet to register your account and UI to browse the network. If you are new, we recommend starting with the official Farcaster client on [iOS](https://apps.apple.com/us/app/warpcast/id1600555445) or [Android](https://play.google.com/store/apps/details?id=com.farcaster.mobile&hl=en_US&gl=US)
4 |
5 | There are two kinds of apps:
6 |
7 | 1. **Wallet App** - allows signing up, adding connected apps, posting and browsing messages.
8 | 2. **Connected App** - allows posting and browsing messages only.
9 |
10 | ## Wallet Apps
11 |
12 | Users must install a wallet app to get started with Farcaster. They can take onchain and offchain actions like signing up, adding connected apps, posting messages and users.
13 |
14 | A wallet app controls the Ethereum address that owns the account. It has control over the account and can take any action on your behalf, so only use a wallet app that you trust.
15 |
16 | ### Farcaster client
17 |
18 | The Farcaster client is a wallet app developed by the Farcaster team. It has a web and mobile app, though signing up is only available on mobile.
19 |
20 | - Download: [iOS](https://apps.apple.com/us/app/warpcast/id1600555445), [Android](https://play.google.com/store/apps/details?id=com.farcaster.mobile&hl=en_US&gl=US)
21 |
22 | ## Connected Apps
23 |
24 | Connected apps can only be added once a user signs up with a wallet app. They can take offchain actions on Farcaster like writing casts, following accounts and browsing.
25 |
26 | A connected app controls an app key granted by the wallet app. Users can add many connected apps to their account and remove them at any time. A malicious connected app cannot take control of your account and any actions it takes can be reversed by your wallet app.
27 |
28 | Some popular connected apps include:
29 |
30 | - [Supercast](https://supercast.xyz/)
31 | - [Yup](https://yup.io/)
32 | - [Farcord](https://farcord.com/)
33 |
34 | **Connected apps are not reviewed by Farcaster, use them at your own risk**
35 |
36 | ## Resources
37 |
38 | ### Tools
39 |
40 | - [Hubble](../../hubble/hubble.md) - a farcaster hub for reading and writing messages.
41 | - [Replicator](https://github.com/farcasterxyz/hub-monorepo/tree/main/apps/replicator) - a tool to sync a hub to a postgres database.
42 |
43 | ### Tutorials
44 |
45 | - [Set up hubble](../..//hubble/install#install-via-script) - run a farcaster hub.
46 | - [Set up replicator](../../developers/guides/apps/replicate) - sync a hub to postgres for easy querying.
47 | - [Schema for replication](../../reference/replicator/schema) - schema for a replicator's postgres tables.
48 |
49 | ### Services
50 |
51 | - [Neynar](https://neynar.com/) - infrastructure and services for building farcaster apps.
52 |
--------------------------------------------------------------------------------
/docs/learn/what-is-farcaster/channels.md:
--------------------------------------------------------------------------------
1 | # Channels
2 |
3 | A channel is a public space for your community to have conversations around a topic.
4 |
5 | Creating a channel starts a new feed for your community. People can join, cast and find other interesting people. It sparks conversations that wouldn’t otherwise happen on the home feed.
6 |
7 | :::warning Experimental Feature
8 | Channels are being prototyped in the Farcaster client and not fully supported by the Farcaster protocol. They may be ported to the protocol in the future if the feature is deemed successful or they may be removed entirely.
9 | :::
10 |
11 | ## Hosting Channels
12 |
13 | Anyone can create a channel host by paying a fee in the Farcaster client and choosing a channel name. The name must be under 16 characters and can only contain lowercase alphabets and numbers. A channel's creator is called a host and may invite other co-hosts to operate the channel. Hosts have special privileges like:
14 |
15 | 1. Defining “channel norms" which everyone must agree to when joining.
16 | 2. Pinning or hiding casts in a channel.
17 | 3. Blocking other users from casting in their channel.
18 | 4. Setting a channel picture, description and other metadata.
19 |
20 | Channel metadata is not part of the protocol and stored in the Farcaster client while channels are in the experimental stage.
21 |
22 | ## Casting in Channels
23 |
24 | Anyone can post into a channel by using the Farcaster client and selecting the channel when creating the cast. The client automatically sets the cast's `parentUrl` to `https://farcaster.xyz/~/channel/`. A cast is considered "in a channel" if it's parentUrl is the channel URI or another cast which is "in a channel".
25 |
26 | Channel casts are part of the protocol and stored on hubs. Using a replicator, you can fetch all casts in a channel by filtering the `parentUrl` field for the channel's FIP-2 URL.
27 |
28 | ## Following Channels
29 |
30 | Anyone can follow a channel just like a user. A user will see casts from a followed channel in their home feed when using the Farcaster client.
31 |
32 | Channel follows are not part of the protocol and are stored in the Farcaster client while channels are in the experimental stage.
33 |
34 | ## Cast Visibility
35 |
36 | If a user casts in a channel, Farcaster will:
37 |
38 | 1. Always send the casts to the home feeds of any user who follows the channel.
39 | 2. Usually send the casts to the home feeds of any user who follows the author.
40 |
41 | The determination for (2) is made based on the user's preferences, channel contents and other social graph data. This algorithm is still being fine tuned and will be documented once it is stable.
42 |
43 | ## Usage Policy
44 |
45 | The Farcaster client may remove your channel and will NOT refund your warps if:
46 |
47 | 1. Your profile or channel impersonates someone.
48 | 2. You squat a channel without using it.
49 | 3. You violate the Farcaster client's terms and conditions or app store rules.
50 |
51 | ## FAQ
52 |
53 | **Why are channel hosts allowed to hide and ban? Isn’t this censorship?**
54 |
55 | Channels are not free-for-all public spaces, they are owned and moderated by their creators. You are always free to start your own channel at any time with its own rules.
56 |
57 | **Why is there a fee for creating channels?**
58 |
59 | The fee discourages people from squatting short names and not using the channels.
60 |
61 | **What's the benefit of creating a channel?**
62 |
63 | Starting a channel also helps grow your audience:
64 |
65 | 1. The Farcaster client will send your followers a notification about your channel.
66 | 2. Your channel will be promoted to users who follow similar channels.
67 | 3. Users who follow your channel will see channel casts in their home feed.
68 |
69 | ## Resources
70 |
71 | ### APIs
72 |
73 | - [Farcaster Client Channel APIs](../../reference/warpcast/api.md) - fetch a list of all known channels
74 |
--------------------------------------------------------------------------------
/docs/learn/what-is-farcaster/usernames.md:
--------------------------------------------------------------------------------
1 | # Usernames
2 |
3 | A Farcaster account needs a username so it can be found and mentioned by other users. Farcaster uses the [Ethereum Name Service](https://ens.domains/) to manage usernames.
4 |
5 | ENS usernames are owned by Ethereum addresses, just like Farcaster accounts. The difference is that an address can own multiple ENS names, so the Farcaster account must specify the name it wishes to use. ENS names can only be used on Farcaster if they are <= 16 characters and contain only lowercase letters, numbers and hyphens.
6 |
7 | ## Changing usernames
8 |
9 | A Farcaster account can change between different usernames at any time. Changing names does not affect your history or your followers.
10 |
11 | It's safe to change your name a few times a year. But changing your name more often may cause users or apps to lose trust in your account. If you want to change a public indicator, consider changing your display name instead.
12 |
13 | ## Offchain vs Onchain Names
14 |
15 | An account can choose between two kinds of usernames:
16 |
17 | - **Offchain ENS Names**: free and controlled by farcaster. (e.g. @alice)
18 | - **Onchain ENS Names**: costs money and controlled by your wallet. (e.g. @alice.eth)
19 |
20 | Choose an offchain ENS name if you want to get started quickly and don't have an onchain ENS name. An account can always upgrade to an onchain name later. It's recommended to use an app like the official Farcaster client to set this up for you.
21 |
22 | 
23 |
24 | ### Offchain ENS Names
25 |
26 | - Offchain ENS names, also called fnames, are free and issued by Farcaster.
27 | - Any Ethereum account can get one unique fname by calling the [Fname Registry](/learn/architecture/ens-names).
28 | - Fnames are free but they can be revoked by Farcaster at any time.
29 |
30 | ### Onchain ENS fnames
31 |
32 | - Onchain ENS names, also called .eth names, are onchain and issued by ENS.
33 | - Any Ethereum account can get an ENS by calling the [ENS Registry](https://docs.ens.domains/dapp-developer-guide/the-ens-registry).
34 | - Names are not free but they cannot be revoked by Farcaster.
35 |
36 | ## Resources
37 |
38 | ### Specifications
39 |
40 | - [Farcaster Name](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#5-fname-specifications) - An ENSIP-10 offchain ENS name usable within Farcaster.
41 | - [UserData: Username](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#23-user-data) - Sets a valid Username Proof as the current username.
42 | - [Username Proof](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#17-username-proof) - Proves ownership of an onchain or offchain username.
43 | - [Verifications](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#25-verifications) - Proves ownership of an address, required for onchain Username Proofs.
44 |
45 | ### APIs
46 |
47 | - [UserData API](../../reference/hubble/httpapi/userdata) - Fetch the UserData for a user's current username.
48 | - [Username Proofs API](../../reference/hubble/httpapi/usernameproof) - Fetch a user's Username Proofs from a hub.
49 | - [Verification Proofs API](../../reference/hubble/httpapi/verification) - Fetch a user's Verifications from a hub.
50 | - [Fname Registry API](../../reference/fname/api.md) - Register and track fname ownership programmatically.
51 |
52 | ### Tutorials
53 |
54 | - [Get UserData](../../developers/guides/querying/fetch-profile.md) - Get UserData messages from an account.
55 | - [Create UserData](../../developers/guides/writing/messages#user-data) - Create a UserData message to select a valid username.
56 | - [Verify an Address](../../developers/guides/writing/verify-address.md) - Verify ownership of an Ethereum account.
57 | - [Find account by username](../../developers/guides/accounts/find-by-name.md) - Find an account by its username.
58 | - [Change farcaster name](../../developers/guides/accounts/change-fname.md) - Change a farcaster username.
59 |
--------------------------------------------------------------------------------
/docs/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/public/icon.png
--------------------------------------------------------------------------------
/docs/public/og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/farcasterxyz/docs/d30952ac28b95c3b93b94c8f6a8d515e856fce8a/docs/public/og-image.png
--------------------------------------------------------------------------------
/docs/reference/contracts/deployments.md:
--------------------------------------------------------------------------------
1 | # Deployments
2 |
3 | ## Addresses
4 |
5 | All Farcaster contracts are deployed on Optimism mainnet. There is no testnet deployment.
6 |
7 | | Contract | Optimism Address | Etherscan Link |
8 | | ---------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------ |
9 | | Id Registry | `0x00000000fc6c5f01fc30151999387bb99a9f489b` | [link](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b) |
10 | | Key Registry | `0x00000000Fc1237824fb747aBDE0FF18990E59b7e` | [link](https://optimistic.etherscan.io/address/0x00000000Fc1237824fb747aBDE0FF18990E59b7e) |
11 | | Storage Registry | `0x00000000fcCe7f938e7aE6D3c335bD6a1a7c593D` | [link](https://optimistic.etherscan.io/address/0x00000000fcCe7f938e7aE6D3c335bD6a1a7c593D) |
12 | | IdGateway | `0x00000000fc25870c6ed6b6c7e41fb078b7656f69` | [link](https://optimistic.etherscan.io/address/0x00000000fc25870c6ed6b6c7e41fb078b7656f69) |
13 | | KeyGateway | `0x00000000fc56947c7e7183f8ca4b62398caadf0b` | [link](https://optimistic.etherscan.io/address/0x00000000fc56947c7e7183f8ca4b62398caadf0b) |
14 | | Bundler | `0x00000000fc04c910a0b5fea33b03e0447ad0b0aa` | [link](https://optimistic.etherscan.io/address/0x00000000fc04c910a0b5fea33b03e0447ad0b0aa) |
15 |
16 | ## ABIs
17 |
18 | The ABIs for the contracts are available via etherscan links above, or from the [`@farcaster/core`](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/core/src/eth/contracts/abis) package.
19 |
--------------------------------------------------------------------------------
/docs/reference/contracts/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | ## Signatures
4 |
5 | ### How do I generate an EIP-712 signature?
6 |
7 | See the contract reference docs for documentation on each EIP-712 signature, including Typescript [code examples](/reference/contracts/reference/id-gateway#register-signature).
8 |
9 | If you're using Typescript/JS, the [`@farcaster/hub-web`](https://www.npmjs.com/package/@farcaster/hub-web) package includes tools for generating and working with EIP-712 signatures. To ensure you're using the correct addresses and typehashes, we recommend importing the ABIs and EIP-712 types from the [contracts module](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/core/src/eth/contracts) or using the provided [`Eip712Signer`](https://github.com/farcasterxyz/hub-monorepo/blob/main/packages/core/src/signers/eip712Signer.ts) helper.
10 |
11 | See the "Working with EIP-712 signatures" [example app](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs/examples/contract-signatures) in the hub monorepo for a reference that demonstrates each signature and contract call.
12 |
13 | ### How can I debug an invalid EIP-712 signature?
14 |
15 | To help debug EIP-712 signing, every contract that uses EIP-712 signatures exposes its [domain separator](https://optimistic.etherscan.io/address/0x00000000fc25870c6ed6b6c7e41fb078b7656f69#readContract#F3) and typehashes as [constants](https://optimistic.etherscan.io/address/0x00000000fc25870c6ed6b6c7e41fb078b7656f69#readContract#F1) along with a [hashTypedDataV4](https://optimistic.etherscan.io/address/0x00000000fc25870c6ed6b6c7e41fb078b7656f69#readContract#F6) helper view. If you're constructing signatures in Solidity or another low level language, you can use these to help debug.
16 |
17 | ## Reference
18 |
19 | ### Where is the full contract source code?
20 |
21 | The contracts repo is on Github [here](https://github.com/farcasterxyz/contracts).
22 |
23 | ### Where do I get contract ABIs?
24 |
25 | Find contract ABIs and deployment addresses [here](/reference/contracts/deployments#abis).
26 |
27 | ### Where can I find audit reports?
28 |
29 | Past audit reports are linked from the [contracts repo](https://github.com/farcasterxyz/contracts/blob/1aceebe916de446f69b98ba1745a42f071785730/README.md#audits).
30 |
31 | ### Are the Farcaster contracts deployed to a testnet?
32 |
33 | No. Consider using [network forking](https://book.getfoundry.sh/tutorials/forking-mainnet-with-cast-anvil) to test or develop against the OP mainnet contracts.
34 |
35 | ## Data
36 |
37 | ### How do I find a user’s custody address?
38 |
39 | Call the [`custodyOf`](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b#readContract#F5) function on the [IdRegistry](/reference/contracts/reference/id-registry.md).
40 |
41 | ### How do I find a user’s recovery address?
42 |
43 | Call the [`recoveryOf`](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b#readContract#F23) function on the [IdRegistry](/reference/contracts/reference/id-registry.md).
44 |
45 | ### How do I find an account’s fid?
46 |
47 | Call the [`idOf`](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b#readContract#F14) function on the [IdRegistry](/reference/contracts/reference/id-registry.md).
48 |
49 | ### How do I look up the account keys for my fid?
50 |
51 | Call the [`keysOf`](https://optimistic.etherscan.io/address/0x00000000fc1237824fb747abde0ff18990e59b7e#readContract#F16) function on the [KeyRegistry](/reference/contracts/reference/key-registry.md).
52 |
53 | ## Other
54 |
55 | ### What is an app fid? How do I get one?
56 |
57 | **What is an FID?**
58 |
59 | An FID (Farcaster ID) is a unique identifier used to distinguish applications and users. With an FID, apps and users can be identified and differentiated.
60 |
61 | **Why is an FID necessary?**
62 |
63 | To create or post anything on the Farcaster platform, an FID is essential for identifying your app or user.
64 |
65 | **How do I get one?**
66 |
67 | You can register an app fid directly through the [Bundler](/reference/contracts/reference/bundler.md) or [IdGateway](/reference/contracts/reference/id-gateway.md), or use a Farcaster client to register an account for your app. Since you'll need to sign [key request metadata](/reference/contracts/reference/signed-key-request-validator.md) from the wallet that owns your app fid, keep the private key secure.
68 |
--------------------------------------------------------------------------------
/docs/reference/contracts/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | Farcaster contracts are deployed on Optimism, an Ethereum layer 2 network. There are three core contracts:
4 | Id Registry, Key Registry, and Storage Registry. Write access to the ID and Key registry is gated through the Gateway
5 | contracts. There is also a Bundler helper contract to make it easy to register an fid, add a key and rent storage in one
6 | transaction.
7 |
8 | 
9 |
10 | ## Id Registry
11 |
12 | The Id Registry contract is used to keep track of Farcaster IDs. It maps an fid to an owning Ethereum
13 | address. The owner can also designate a "recovery address" which can be used to recover the fid if the owner loses
14 | access to the registering address. Registering an fid for the first time must be done through
15 | the [ID Gateway](#idgateway).
16 |
17 | ## Key Registry
18 |
19 | The Key Registry associates a Farcaster id to zero or more ed2559 public keys. Only messages signed by a key registered
20 | here are considered valid by the hubs. Registered keys can be revoked by the owner of the fid, but revoked keys can not
21 | be added to that fid again. The same key may be registered to multiple fids. Adding a key must be done through the
22 | [Key Gateway](#keygateway).
23 |
24 | ## Storage Registry
25 |
26 | The Storage Registry allows an fid to rent one or more "units" of storage on the farcaster network. The current cost of
27 | storage is 7$ USD per unit, for one year. This fee must be paid in ETH. The storage registry uses an ETH price oracle to
28 | determine the current cost in ETH and exposes functions to query this price. Overpayments are refunded to the caller.
29 |
30 | ## IdGateway
31 |
32 | The ID Gateway handles additional logic required for first time registration of an fid. To prevent spam, the
33 | gateway also requires renting 1 unit of storage.
34 |
35 | ## KeyGateway
36 |
37 | Similarly, the Key Gateway exists for the Key Registry. Adding a key to a fid must be done via the gateway.
38 |
39 | ## Bundler
40 |
41 | The Bundler makes first time sign up easier by allowing a user to register an fid, add a key and rent storage in one
42 | function call.
43 |
44 | ## Source code
45 |
46 | The contracts source repo can be found [here](https://github.com/farcasterxyz/contracts), including more low level
47 | documentation [here](https://github.com/farcasterxyz/contracts/blob/main/docs/docs.md).
48 |
--------------------------------------------------------------------------------
/docs/reference/contracts/reference/storage-registry.md:
--------------------------------------------------------------------------------
1 | ---
2 | outline: [2, 3]
3 | ---
4 |
5 | # Storage Registry
6 |
7 | The Storage Registry allows Farcaster accounts to rent one or more "units" of storage on the network.
8 |
9 | If you want to rent storage for a Farcaster account, use the Storage Registry.
10 |
11 | ## Read
12 |
13 | ### unitPrice
14 |
15 | Get the price in wei (`uint256`) to register 1 unit of storage.
16 |
17 | ### price
18 |
19 | Get the price in wei (`uint256`) to register a specific number of storage units.
20 |
21 | | Param Name | type | Description |
22 | | ---------- | --------- | ----------------------------------- |
23 | | units | `uint256` | The number of storage units to rent |
24 |
25 | ## Write
26 |
27 | ### rent
28 |
29 | Rent a specific number of storage units for a given fid. Excess ether will be returned to the caller. Rented units are valid for 1 year from the time of registration.
30 |
31 | | Param Name | type | Description |
32 | | ----------- | --------- | -------------------------------------- |
33 | | `msg.value` | `wei` | Payment amount |
34 | | fid | `uint256` | The fid to credit the storage units to |
35 | | units | `uint256` | The number of units of storage to rent |
36 |
37 | ### batchRent
38 |
39 | Rent storage for multiple fids in one transaction. The caller must send enough ether to cover the total cost of all units. Like single-unit rental, extra ether is returned and units are valid for 1 year.
40 |
41 | | Param Name | type | Description |
42 | | ----------- | ----------- | ----------------------------------------------------------------------- |
43 | | `msg.value` | `wei` | Total payment amount |
44 | | fids | `uint256[]` | Array of fids |
45 | | units | `uint256[]` | Array of unit quantities, corresponding to each fid in the `fids` array |
46 |
47 | ## Errors
48 |
49 | | Error | Selector | Description |
50 | | ----------------- | ---------- | ---------------------------------------------------------------------------------------- |
51 | | InvalidPayment | `3c6b4b28` | The caller didn't provide enough ether to pay for the number of storage units requested. |
52 | | InvalidBatchInput | `0a514b99` | The caller provided mismatched arrays of `fids` and `units`. |
53 |
54 | ## Source
55 |
56 | [`StorageRegistry.sol`](https://github.com/farcasterxyz/contracts/blob/1aceebe916de446f69b98ba1745a42f071785730/src/validators/StorageRegistry.sol)
57 |
--------------------------------------------------------------------------------
/docs/reference/fname/api.md:
--------------------------------------------------------------------------------
1 | # FName Registry Server API Reference
2 |
3 | The [Fname registry](https://github.com/farcasterxyz/fname-registry) server is hosted at https://fnames.farcaster.xyz
4 |
5 | It's a simple HTTP service that's responsible for issuing and tracking fnames. All Fname changes are recorded as a
6 | transfer.
7 | Registering an fname is a transfer from FID 0 to the user's fid. Transferring an fname is a transfer from the user's fid
8 | to another fid. Unregistering an fname is a transfer from the user's fid to fid 0.
9 |
10 | ::: warning Registering an fname
11 |
12 | Note, when registering a new fname, calling this api is not sufficient. This only reserves the name to your fid. You
13 | must also submit a [UserDataAdd](/reference/hubble/datatypes/messages#_2-userdata) message to the hub
14 | to set this name as your username.
15 |
16 | :::
17 |
18 | ### Get Transfer History
19 |
20 | To get a history of all transfers, make a GET request to `/transfers`
21 |
22 | ```bash
23 | curl https://fnames.farcaster.xyz/transfers | jq
24 | ```
25 |
26 | It also accepts the following query parameters:
27 |
28 | - `from_id` - The transfer id to start from for pagination
29 | - `name` - The fname to filter by
30 | - `fid` - The fid (either from or to) to filter by
31 | - `from_ts` - The timestamp (in seconds) to start from for pagination
32 |
33 | ### Get current fname or fid
34 |
35 | To get the most recent transfer event for an fid or fname, make a GET request to `/transfers/current`
36 |
37 | e.g. To determine the fid of `@farcaster`, make the following call and use the value from the `to` field in the return
38 | value
39 |
40 | ```bash
41 | curl https://fnames.farcaster.xyz/transfers?name=farcaster | jq
42 | ```
43 |
44 | To determine the fname of fid `1`, make the following call and use the value from the `username` field in the return
45 | value
46 |
47 | ```bash
48 | curl https://fnames.farcaster.xyz/transfers?fid=1 | jq
49 | ```
50 |
51 | Both will return the same transfers object:
52 |
53 | ```json
54 | {
55 | "transfers": [
56 | {
57 | "id": 1,
58 | "timestamp": 1628882891,
59 | "username": "farcaster",
60 | "owner": "0x8773442740c17c9d0f0b87022c722f9a136206ed",
61 | "from": 0,
62 | "to": 1,
63 | "user_signature": "0xa6fdd2a69deab5633636f32a30a54b21b27dff123e6481532746eadca18cd84048488a98ca4aaf90f4d29b7e181c4540b360ba0721b928e50ffcd495734ef8471b",
64 | "server_signature": "0xb7181760f14eda0028e0b647ff15f45235526ced3b4ae07fcce06141b73d32960d3253776e62f761363fb8137087192047763f4af838950a96f3885f3c2289c41b"
65 | }
66 | ]
67 | }
68 | ```
69 |
70 | ### Register or transfer an fname
71 |
72 | To register a new fid, e.g. `hubble`, first make sure the fname is not already registered.
73 |
74 | Then make a POST request to `/transfers` with the following body:
75 |
76 | ```yaml
77 | {
78 | "name": "hubble", // Name to register
79 | "from": 0, // Fid to transfer from (0 for a new registration)
80 | "to": 123, // Fid to transfer to (0 to unregister)
81 | "fid": 123, // Fid making the request (must match from or to)
82 | "owner": "0x...", // Custody address of fid making the request
83 | "timestamp": 1641234567, // Current timestamp in seconds
84 | "signature": "0x..." // EIP-712 signature signed by the custody address of the fid
85 | }
86 | ```
87 |
88 | To generate the EIP-712 signature, use the following code:
89 |
90 | ```js
91 | import { makeUserNameProofClaim, EIP712Signer } from '@farcaster/hub-nodejs';
92 |
93 | const accountKey: EIP712Signer = undefined; // Account key for the custody address (use appropriate subclass from hub-nodejs for ethers or viem)
94 |
95 | const claim = makeUserNameProofClaim({
96 | name: 'hubble',
97 | owner: '0x...',
98 | timestamp: Math.floor(Date.now() / 1000),
99 | });
100 | const signature = (
101 | await accountKey.signUserNameProofClaim(claim)
102 | )._unsafeUnwrap();
103 | ```
104 |
105 | This is the exact same kind of signature used in the ENS UsernameProofs provided to hubs to prove ownership of an ENS
106 | name.
107 |
108 | e.g.
109 |
110 | ```bash
111 | curl -X POST https://fnames.farcaster.xyz/transfers \
112 | -H "Content-Type: application/json" \
113 | -d \
114 | '{"name": "hubble", "owner": "0x...", "signature": "0x...", "from": 0, "to": 1000, "timestamp": 1641234567, fid: 1000}'
115 | ```
116 |
117 | Once a name is registered, it still needs a [UserData](/reference/hubble/datatypes/messages#_2-userdata) message
118 | to be sent to the hub in order to actually
119 | set the username for the user. See examples in
120 | the [hub-nodejs](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs/examples/hello-world) repo.
121 |
--------------------------------------------------------------------------------
/docs/reference/frames-redirect.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Frames v2 have been rebranded to Mini Apps
3 | ---
4 |
5 | # Frames v2 have been rebranded to Mini Apps
6 |
7 |
8 | As of early 2025, Frames v2 have been rebranded to Mini Apps. All Frames documentation and resources have been migrated to the [Mini Apps](https://miniapps.farcaster.xyz/){target="_self"} ecosystem.
9 |
10 | Frames v2 have been deprecated and will be supported only until the end of March 2025. We strongly recommend using Mini Apps for all new projects.
11 |
12 |
13 | [Go to Mini Apps Documentation →](https://miniapps.farcaster.xyz/){target="_self"}
14 |
--------------------------------------------------------------------------------
/docs/reference/hubble/architecture.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | A Hub is a single-process daemon that receives data from clients, other hubs and farcaster contracts. It has four main
4 | components:
5 |
6 | - Storage Engine - checks message validity, persists them to disk and emits events.
7 | - P2P Engine - establishes a gossipsub network to exchange messages with hubs.
8 | - Sync Engine - handles edge cases when gossip fails to deliver messages.
9 | - RPC Servers - provides APIs to read and write data to the hub
10 |
11 | ### Storage Engine
12 |
13 | Messages received by Hubble are forwarded to the Storage engine which forwards them to the appropriate CRDT Set. Once
14 | validated by the CRDT Set, messages are persisted to [RocksDB](https://github.com/facebook/rocksdb) and events are
15 | emitted to listeners.
16 |
17 | CRDT sets are implemented to meet the specification in the Farcaster protocol. The engine also tracks state of the
18 | Farcaster contracts, which are necessary for validating the Signer CRDT Set.
19 |
20 | ### P2P Engine
21 |
22 | Hubble connects to other peers over a GossipSub network established using [LibP2P](https://github.com/libp2p/libp2p).
23 | Messages merged into the Storage Engine are immediately gossiped to all of is peers.
24 |
25 | Hubble will only peer with trusted peers and employs a simple network topology during beta. It peers only with known
26 | instances which must be configured at startup. In later releases, the network topology will be modified to operate
27 | closer to a trustless mesh.
28 |
29 | ### Sync Engine
30 |
31 | Hubble periodically performs a [diff sync](https://github.com/farcasterxyz/protocol#41-synchronization) with other peers
32 | to discover messages that may have been dropped during gossip. This is performed using gRPC APIs exposed by each Hub
33 | instance.
34 |
35 | ### RPC Servers
36 |
37 | Hubble exposes a gRPC and HTTP API for reading and writing data to the hub. The primary way to write data to the
38 | farcaster network is to call `submitMessage` on a hub. The hub will validate the message, and if it conforms to the
39 | protocol, will store the message in the appropriate CRDT set and gossip it to other peers. The hub also exposes other
40 | APIs to read the state of its sets.
41 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/casts.md:
--------------------------------------------------------------------------------
1 | # Casts API
2 |
3 | Used to retrieve valid casts or tombstones for deleted casts
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ----------------------- | ------------ | ---------------- | -------------------------------------------------------------- |
9 | | GetCast | CastId | Message | Returns a specific Cast |
10 | | GetCastsByFid | FidRequest | MessagesResponse | Returns CastAdds for an Fid in reverse chron order |
11 | | GetCastsByParent | CastId | MessagesResponse | Returns CastAdd replies to a given Cast in reverse chron order |
12 | | GetCastsByMention | FidRequest | MessagesResponse | Returns CastAdds that mention an Fid in reverse chron order |
13 | | GetAllCastMessagesByFid | FidRequest | MessagesResponse | Returns Casts for an Fid in reverse chron order |
14 |
15 | ## CastsByParentRequest
16 |
17 | | Field | Type | Label | Description |
18 | | -------------- | ----------------- | -------- | ----------- |
19 | | parent_cast_id | [CastId](#CastId) | | |
20 | | parent_url | [string](#string) | | |
21 | | page_size | [uint32](#uint32) | optional | |
22 | | page_token | [bytes](#bytes) | optional | |
23 | | reverse | [bool](#bool) | optional | |
24 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/events.md:
--------------------------------------------------------------------------------
1 | # Events API
2 |
3 | Used to subscribe to real-time event updates from the Farcaster Hub
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ----------- | ---------------- | --------------- | -------------------------------- |
9 | | Subscribe | SubscribeRequest | stream HubEvent | Streams new Events as they occur |
10 | | GetEvent | EventRequest | HubEvent | Streams new Events as they occur |
11 |
12 | ## SubscribeRequest
13 |
14 | | Field | Type | Label | Description |
15 | | ----------- | -------------- | -------- | -------------------------------- |
16 | | event_types | [EventType](#) | repeated | Types of events to subscribe to |
17 | | from_id | uint64 | optional | Event ID to start streaming from |
18 |
19 | ## EventRequest
20 |
21 | | Field | Type | Label | Description |
22 | | ----- | ----------------- | ----- | ----------- |
23 | | id | [uint64](#uint64) | | |
24 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/fids.md:
--------------------------------------------------------------------------------
1 | # Fids API
2 |
3 | Used to retrieve a list of all fids
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ----------- | ------------ | ------------- | ------------------------------------ |
9 | | GetFids | FidsRequest | FidsResponse | Returns a paginated list of all fids |
10 |
11 | ## FidsRequest
12 |
13 | | Field | Type | Label | Description |
14 | | ---------- | ----------------- | -------- | ----------- |
15 | | page_size | [uint32](#uint32) | optional | |
16 | | page_token | [bytes](#bytes) | optional | |
17 | | reverse | [bool](#bool) | optional | |
18 |
19 | ## Fids Response
20 |
21 | | Field | Type | Label | Description |
22 | | --------------- | --------------- | -------- | ------------- |
23 | | fids | [uint64](#) | repeated | Array of fids |
24 | | next_page_token | [bytes](#bytes) | optional | |
25 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/grpcapi.md:
--------------------------------------------------------------------------------
1 | # GRPC API
2 |
3 | Hubble serves a gRPC API on port 2283 by default.
4 |
5 | ## Using the API
6 |
7 | We recommend using a library
8 | like [hub-nodejs](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs) to interact with Hubble's
9 | gRPC APIs. Please refer
10 | to its [documentation](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs/docs) for how to use
11 | it.
12 |
13 | ## Other languages
14 |
15 | The protobufs for the gRPC API are available within
16 | the [hub-monorepo](https://github.com/farcasterxyz/hub-monorepo/tree/main/protobufs). They can be used to generate
17 | bindings for other clients built using other languages. Note that by default, hubs rely on the
18 | javascript [ts-proto](https://www.npmjs.com/package/ts-proto) library's serialization byte order to verify messages
19 | hashes. If you are using a different client, you may need to use the `data_bytes` field with the raw serialized bytes
20 | when calling `SubmitMessage` in order for the message to be considered valid. Refer to
21 | the [SubmitMessage HTTP API docs](/reference/hubble/httpapi/message#using-with-rust-go-or-other-programing-languages)
22 | for more details.
23 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/links.md:
--------------------------------------------------------------------------------
1 | # Links API
2 |
3 | A Link represents a relationship between two users (e.g. follow)
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ----------------------- | -------------------- | ---------------- | ---------------------------------------------------------- |
9 | | GetLink | LinkRequest | Message | Returns a specific Link |
10 | | GetLinksByFid | LinksByFidRequest | MessagesResponse | Returns Links made by an fid in reverse chron order |
11 | | GetLinksByTarget | LinksByTargetRequest | MessagesResponse | Returns LinkAdds for a given target in reverse chron order |
12 | | GetAllLinkMessagesByFid | FidRequest | MessagesResponse | Returns Links made by an fid in reverse chron order |
13 |
14 | ## Link Request
15 |
16 | | Field | Type | Label | Description |
17 | | ---------- | ----------- | ----- | ----------------------------------------------- |
18 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Link |
19 | | link_type | [string](#) | | Type of the Link being requested |
20 | | target_fid | [uint64](#) | | Fid of the target |
21 |
22 | ## LinksByFid Request
23 |
24 | | Field | Type | Label | Description |
25 | | ---------- | ----------- | ----- | ----------------------------------------------- |
26 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Link |
27 | | link_type | string | | Type of the Link being requested |
28 | | page_size | uint32 | | (optional) Type of the Link being requested |
29 | | page_token | bytes | | (optional)Type of the Link being requested |
30 | | reverse | boolean | | (optional) Ordering of the response |
31 |
32 | ## LinksByTarget Request
33 |
34 | | Field | Type | Label | Description |
35 | | ---------- | ----------- | ----- | ----------------------------------------------- |
36 | | target_fid | [uint64](#) | | Farcaster ID of the user who generated the Link |
37 | | link_type | string | | (optional) Type of the Link being requested |
38 | | page_size | uint32 | | (optional) Type of the Link being requested |
39 | | page_token | bytes | | (optional)Type of the Link being requested |
40 | | reverse | boolean | | (optional) Ordering of the response |
41 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/message.md:
--------------------------------------------------------------------------------
1 | # Message API
2 |
3 | Used to validate and send a message to the Farcaster Hub. Valid messages are accepted and gossiped to other hubs in the
4 | network.
5 |
6 | ## API
7 |
8 | | Method Name | Request Type | Response Type | Description |
9 | | --------------- | ------------ | ------------------ | ------------------------------------------------------------ |
10 | | SubmitMessage | Message | Message | Submits a Message to the Hub |
11 | | ValidateMessage | Message | ValidationResponse | Validates a Message on the Hub without merging and gossiping |
12 |
13 | ## ValidationResponse
14 |
15 | | Field | Type | Label | Description |
16 | | ------- | ------- | ----- | --------------------------------------------- |
17 | | valid | boolean | | Whether the message is valid or not |
18 | | message | Message | | The message being validated (same as request) |
19 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/onchain.md:
--------------------------------------------------------------------------------
1 | # OnChainEvents API
2 |
3 | Used to retrieve on chain events (id registry, keys, storage rent)
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ---------------------------------- | ------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------- |
9 | | GetOnChainSigner | SignerRequest | OnChainEvent | Returns the onchain event for an active signer for an Fid |
10 | | GetOnChainSignersByFid | FidRequest | OnChainEventResponse | Returns all active account keys (signers) add events for an Fid |
11 | | GetIdRegistryOnChainEvent | FidRequest | OnChainEvent | Returns the most recent register/transfer on chain event for an fid |
12 | | GetIdRegistryOnChainEventByAddress | IdRegistryEventByAddressRequest | OnChainEvent | Returns the registration/transfer event by address if it exists (allows looking up fid by address) |
13 | | GetOnChainEvents | OnChainEventRequest | OnChainEventResponse | Returns all on chain events filtered by type for an Fid (includes inactive keys and expired rent events) |
14 |
15 | ## Signer Request
16 |
17 | | Field | Type | Label | Description |
18 | | ------ | ----------- | ----- | ------------------------------------------------- |
19 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Signer |
20 | | signer | [bytes](#) | | Public Key of the Signer |
21 |
22 | ## Fid Request
23 |
24 | | Field | Type | Label | Description |
25 | | ---------- | ----------- | ----- | ------------------------------------------- |
26 | | fid | [uint64](#) | | Farcaster ID of the user |
27 | | page_size | uint32 | | (optional) Type of the Link being requested |
28 | | page_token | bytes | | (optional)Type of the Link being requested |
29 | | reverse | boolean | | (optional) Ordering of the response |
30 |
31 | #### IdRegistryEventByAddressRequest
32 |
33 | | Field | Type | Label | Description |
34 | | ------- | --------------- | ----- | ----------- |
35 | | address | [bytes](#bytes) | | |
36 |
37 | #### OnChainEventResponse
38 |
39 | | Field | Type | Label | Description |
40 | | --------------- | ----------------------------- | -------- | ----------- |
41 | | events | [OnChainEvent](#onchainevent) | repeated | |
42 | | next_page_token | [bytes](#bytes) | optional | |
43 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/reactions.md:
--------------------------------------------------------------------------------
1 | # Reactions API
2 |
3 | ## API
4 |
5 | | Method Name | Request Type | Response Type | Description |
6 | | --------------------------- | ------------------------ | ---------------- | ------------------------------------------------------------ |
7 | | GetReaction | ReactionRequest | Message | Returns a specific Reaction |
8 | | GetReactionsByFid | ReactionsByFidRequest | MessagesResponse | Returns Reactions made by an Fid in reverse chron order |
9 | | GetReactionsByCast | ReactionsByCastRequest | MessagesResponse | Returns ReactionAdds for a given Cast in reverse chron order |
10 | | GetReactionsByTarget | ReactionsByTargetRequest | MessagesResponse | Returns ReactionAdds for a given Cast in reverse chron order |
11 | | GetAllReactionMessagesByFid | FidRequest | MessagesResponse | Returns Reactions made by an Fid in reverse chron order |
12 |
13 | ## Reaction Request
14 |
15 | Used to retrieve valid or revoked reactions
16 |
17 | | Field | Type | Label | Description |
18 | | -------------- | ----------------- | ----- | --------------------------------------------------------------------- |
19 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Reaction |
20 | | reaction_type | [ReactionType](#) | | Type of the Reaction being requested |
21 | | target_cast_id | [CastId](#) | | (optional) Identifier of the Cast whose reactions are being requested |
22 | | target_url | [string](#) | | (optional) Identifier of the Url whose reactions are being requested |
23 |
24 | ## ReactionsByFid Request
25 |
26 | | Field | Type | Label | Description |
27 | | ------------- | ----------------- | ----- | --------------------------------------------------- |
28 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Reaction |
29 | | reaction_type | [ReactionType](#) | | Type of the Reaction being requested |
30 | | page_size | uint32 | | (optional) Type of the Link being requested |
31 | | page_token | bytes | | (optional)Type of the Link being requested |
32 | | reverse | boolean | | (optional) Ordering of the response |
33 |
34 | ## ReactionsByCast Request
35 |
36 | | Field | Type | Label | Description |
37 | | ------------- | ----------------- | ----- | ---------------------------------------------------------- |
38 | | cast_id | [CastId](#) | | Identifier of the Cast whose reactions are being requested |
39 | | reaction_type | [ReactionType](#) | | Type of the Reaction being requested |
40 | | page_size | uint32 | | (optional) Type of the Link being requested |
41 | | page_token | bytes | | (optional)Type of the Link being requested |
42 | | reverse | boolean | | (optional) Ordering of the response |
43 |
44 | ## ReactionsByTargetRequest
45 |
46 | | Field | Type | Label | Description |
47 | | -------------- | ----------------------------- | -------- | ----------- |
48 | | target_cast_id | [CastId](#CastId) | | |
49 | | target_url | [string](#string) | | |
50 | | reaction_type | [ReactionType](#ReactionType) | optional | |
51 | | page_size | [uint32](#uint32) | optional | |
52 | | page_token | [bytes](#bytes) | optional | |
53 | | reverse | [bool](#bool) | optional | |
54 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/storagelimits.md:
--------------------------------------------------------------------------------
1 | # Storage API
2 |
3 | Get an FID's storage limits.
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ---------------------------- | ------------ | --------------------- | -------------------------------------------------------- |
9 | | GetCurrentStorageLimitsByFid | FidRequest | StorageLimitsResponse | Returns current storage limits for all stores for an Fid |
10 |
11 | #### StorageLimitsResponse
12 |
13 | | Field | Type | Label | Description |
14 | | ------ | ----------------- | -------- | ----------------------------- |
15 | | limits | [StorageLimit](#) | repeated | Storage limits per store type |
16 |
17 | #### StorageLimit
18 |
19 | | Field | Type | Label | Description |
20 | | ---------- | -------------- | ----- | ------------------------------------------------------ |
21 | | store_type | [StoreType](#) | | The specific type being managed by the store |
22 | | limit | [uint64](#) | | The limit of the store type, scaled by the user's rent |
23 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/userdata.md:
--------------------------------------------------------------------------------
1 | # UserData API
2 |
3 | Used to retrieve the current metadata associated with a user
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | --------------------------- | --------------- | ---------------- | -------------------------------------- |
9 | | GetUserData | UserDataRequest | Message | Returns a specific UserData for an Fid |
10 | | GetUserDataByFid | FidRequest | MessagesResponse | Returns all UserData for an Fid |
11 | | GetAllUserDataMessagesByFid | FidRequest | MessagesResponse | Returns all UserData for an Fid |
12 |
13 | ## UserData Request
14 |
15 | | Field | Type | Label | Description |
16 | | -------------- | ----------------- | ----- | --------------------------------------------------- |
17 | | fid | [uint64](#) | | Farcaster ID of the user who generated the UserData |
18 | | user_data_type | [UserDataType](#) | | Type of UserData being requested |
19 |
20 | ## Messages Response
21 |
22 | | Field | Type | Label | Description |
23 | | --------------- | --------------- | -------- | ----------------- |
24 | | messages | [Message](#) | repeated | Farcaster Message |
25 | | next_page_token | [bytes](#bytes) | optional | |
26 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/usernameproof.md:
--------------------------------------------------------------------------------
1 | # Username Proofs API
2 |
3 | ## API
4 |
5 | | Method Name | Request Type | Response Type | Description |
6 | | ---------------------- | --------------------------------------------- | ------------------------------------------------- | -------------- |
7 | | GetUsernameProof | [UsernameProofRequest](#UsernameProofRequest) | [UserNameProof](#UserNameProof) | Username Proof |
8 | | GetUserNameProofsByFid | [FidRequest](#FidRequest) | [UsernameProofsResponse](#UsernameProofsResponse) | |
9 |
10 | ## UsernameProofRequest
11 |
12 | | Field | Type | Label | Description |
13 | | ----- | --------------- | ----- | ----------- |
14 | | name | [bytes](#bytes) | | |
15 |
16 | ## UsernameProofsResponse
17 |
18 | | Field | Type | Label | Description |
19 | | ------ | ------------------------------- | -------- | ----------- |
20 | | proofs | [UserNameProof](#UserNameProof) | repeated | |
21 |
22 | ## UserNameProof
23 |
24 | | Field | Type | Label | Description |
25 | | --------- | ----------------------------- | ----- | ----------- |
26 | | timestamp | [uint64](#uint64) | | |
27 | | name | [bytes](#bytes) | | |
28 | | owner | [bytes](#bytes) | | |
29 | | signature | [bytes](#bytes) | | |
30 | | fid | [uint64](#uint64) | | |
31 | | type | [UserNameType](#UserNameType) | | |
32 |
33 | ## UserNameProof
34 |
35 | | Field | Type | Label | Description |
36 | | --------- | ----------------------------- | ----- | ----------- |
37 | | timestamp | [uint64](#uint64) | | |
38 | | name | [bytes](#bytes) | | |
39 | | owner | [bytes](#bytes) | | |
40 | | signature | [bytes](#bytes) | | |
41 | | fid | [uint64](#uint64) | | |
42 | | type | [UserNameType](#UserNameType) | | |
43 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/verification.md:
--------------------------------------------------------------------------------
1 | # Verifications API
2 |
3 | Used to retrieve valid or revoked proof of ownership of an Ethereum Address.
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ------------------------------- | ------------------- | ---------------- | ------------------------------------------------- |
9 | | GetVerification | VerificationRequest | Message | Returns a VerificationAdd for an Ethereum Address |
10 | | GetVerificationsByFid | FidRequest | MessagesResponse | Returns all VerificationAdds made by an Fid |
11 | | GetAllVerificationMessagesByFid | FidRequest | MessagesResponse | Returns all Verifications made by an Fid |
12 |
13 | ## Verification Request
14 |
15 | | Field | Type | Label | Description |
16 | | ------- | ----------- | ----- | ------------------------------------------------------- |
17 | | fid | [uint64](#) | | Farcaster ID of the user who generated the Verification |
18 | | address | [bytes](#) | | Ethereum Address being verified |
19 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/events.md:
--------------------------------------------------------------------------------
1 | # Events API
2 |
3 | The events API returns events as they are merged into the Hub, which can be used to listen to Hub activity.
4 |
5 | ## eventById
6 |
7 | Get an event by its Id
8 |
9 | **Query Parameters**
10 | | Parameter | Description | Example |
11 | | --------- | ----------- | ------- |
12 | | event_id | The Hub Id of the event | `event_id=350909155450880` |
13 |
14 | **Example**
15 |
16 | ```bash
17 | curl http://127.0.0.1:2281/v1/eventById?id=350909155450880
18 |
19 | ```
20 |
21 | **Response**
22 |
23 | ```json
24 | {
25 | "type": "HUB_EVENT_TYPE_MERGE_USERNAME_PROOF",
26 | "id": 350909155450880,
27 | "mergeUsernameProofBody": {
28 | "usernameProof": {
29 | "timestamp": 1695049760,
30 | "name": "nftonyp",
31 | "owner": "0x23b3c29900762a70def5dc8890e09dc9019eb553",
32 | "signature": "xp41PgeO...hJpNshw=",
33 | "fid": 20114,
34 | "type": "USERNAME_TYPE_FNAME"
35 | }
36 | }
37 | }
38 | ```
39 |
40 | ## events
41 |
42 | Get a page of Hub events
43 |
44 | **Query Parameters**
45 | | Parameter | Description | Example |
46 | | --------- | ----------- | ------- |
47 | | from_event_id | An optional Hub Id to start getting events from. This is also returned from the API as `nextPageEventId`, which can be used to page through all the Hub events. Set it to `0` to start from the first event | `from_event_id=350909155450880` |
48 |
49 | **Note**
50 | Hubs prune events older than 3 days, so not all historical events can be fetched via this API
51 |
52 | **Example**
53 |
54 | ```bash
55 | curl http://127.0.0.1:2281/v1/events?from_event_id=350909155450880
56 |
57 | ```
58 |
59 | **Response**
60 |
61 | ```json
62 | {
63 | "nextPageEventId": 350909170294785,
64 | "events": [
65 | {
66 | "type": "HUB_EVENT_TYPE_MERGE_USERNAME_PROOF",
67 | "id": 350909155450880,
68 | "mergeUsernameProofBody": {
69 | "usernameProof": {
70 | "timestamp": 1695049760,
71 | "name": "nftonyp",
72 | "owner": "0x23b3c29900762a70def5dc8890e09dc9019eb553",
73 | "signature": "xp41PgeOz...9Jw5vT/eLnGphJpNshw=",
74 | "fid": 20114,
75 | "type": "USERNAME_TYPE_FNAME"
76 | }
77 | }
78 | },
79 | ...
80 | ]
81 | }
82 | ```
83 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/fids.md:
--------------------------------------------------------------------------------
1 | # Fids API
2 |
3 | ## fids
4 |
5 | Get a list of all the FIDs
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | | This endpoint accepts no parameters | |
11 |
12 | **Example**
13 |
14 | ```bash
15 | curl http://127.0.0.1:2281/v1/fids
16 | ```
17 |
18 | **Response**
19 |
20 | ```json
21 | {
22 | "fids": [1, 2, 3, 4, 5, 6],
23 | "nextPageToken": "AAAnEA=="
24 | }
25 | ```
26 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/info.md:
--------------------------------------------------------------------------------
1 | # Info API
2 |
3 | ## info
4 |
5 | Get the Hub's info
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | dbstats | Whether to return DB stats | `dbstats=1` |
11 |
12 | **Example**
13 |
14 | ```bash
15 | curl http://127.0.0.1:2281/v1/info?dbstats=1
16 |
17 | ```
18 |
19 | **Response**
20 |
21 | ```json
22 | {
23 | "version": "1.5.5",
24 | "isSyncing": false,
25 | "nickname": "Farcaster Hub",
26 | "rootHash": "fa349603a6c29d27041225261891bc9bc846bccb",
27 | "dbStats": {
28 | "numMessages": 4191203,
29 | "numFidEvents": 20287,
30 | "numFnameEvents": 20179
31 | },
32 | "peerId": "12D3KooWNr294AH1fviDQxRmQ4K79iFSGoRCWzGspVxPprJUKN47",
33 | "hubOperatorFid": 6833
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/links.md:
--------------------------------------------------------------------------------
1 | # Links API
2 |
3 | A Link represents a relationship between two users (e.g. follow)
4 |
5 | The Links API will accept the following values for the `link_type` field.
6 |
7 | | String | Description |
8 | | ------ | ----------------------------- |
9 | | follow | Follow from FID to Target FID |
10 |
11 | ## linkById
12 |
13 | Get a link by its FID and target FID.
14 |
15 | **Query Parameters**
16 | | Parameter | Description | Example |
17 | | --------- | ----------- | ------- |
18 | | fid | The FID of the link's originator | `fid=6833` |
19 | | target_fid | The FID of the target of the link | `target_fid=2` |
20 | | link_type | The type of link, as a string value| `link_type=follow` |
21 |
22 | **Example**
23 |
24 | ```bash
25 | curl http://127.0.0.1:2281/v1/linkById?fid=6833&target_fid=2&link_type=follow
26 | ```
27 |
28 | **Response**
29 |
30 | ```json
31 | {
32 | "data": {
33 | "type": "MESSAGE_TYPE_LINK_ADD",
34 | "fid": 6833,
35 | "timestamp": 61144470,
36 | "network": "FARCASTER_NETWORK_MAINNET",
37 | "linkBody": {
38 | "type": "follow",
39 | "targetFid": 2
40 | }
41 | },
42 | "hash": "0x58c23eaf4f6e597bf3af44303a041afe9732971b",
43 | "hashScheme": "HASH_SCHEME_BLAKE3",
44 | "signature": "sMypYEMqSyY...nfCA==",
45 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
46 | "signer": "0x0852c07b56...06e999cdd"
47 | }
48 | ```
49 |
50 | ## linksByFid
51 |
52 | Get all links from a source FID
53 |
54 | **Query Parameters**
55 | | Parameter | Description | Example |
56 | | --------- | ----------- | ------- |
57 | | fid | The FID of the reaction's creator | `fid=6833` |
58 | | link_type | The type of link, as a string value| `link_type=follow` |
59 |
60 | **Example**
61 |
62 | ```bash
63 | curl http://127.0.0.1:2281/v1/linksByFid?fid=6833
64 | ```
65 |
66 | **Response**
67 |
68 | ```json
69 | {
70 | "messages": [
71 | {
72 | "data": {
73 | "type": "MESSAGE_TYPE_LINK_ADD",
74 | "fid": 6833,
75 | "timestamp": 61144470,
76 | "network": "FARCASTER_NETWORK_MAINNET",
77 | "linkBody": {
78 | "type": "follow",
79 | "targetFid": 83
80 | }
81 | },
82 | "hash": "0x094e35891519c0e04791a6ba4d2eb63d17462f02",
83 | "hashScheme": "HASH_SCHEME_BLAKE3",
84 | "signature": "qYsfX08mS...McYq6IYMl+ECw==",
85 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
86 | "signer": "0x0852c0...a06e999cdd"
87 | }
88 | ],
89 | "nextPageToken": ""
90 | }
91 | ```
92 |
93 | ## linksByTargetFid
94 |
95 | Get all links to a target FID
96 |
97 | **Query Parameters**
98 | | Parameter | Description | Example |
99 | | --------- | ----------- | ------- |
100 | | target_fid | The FID of the reaction's creator | `fid=6833` |
101 | | link_type | The type of link, as a string value| `link_type=follow` |
102 |
103 | **Example**
104 |
105 | ```bash
106 | curl http://127.0.0.1:2281/v1/linksByTargetFid?target_fid=6833
107 | ```
108 |
109 | **Response**
110 |
111 | ```json
112 | {
113 | "messages": [
114 | {
115 | "data": {
116 | "type": "MESSAGE_TYPE_LINK_ADD",
117 | "fid": 302,
118 | "timestamp": 61144668,
119 | "network": "FARCASTER_NETWORK_MAINNET",
120 | "linkBody": {
121 | "type": "follow",
122 | "targetFid": 6833
123 | }
124 | },
125 | "hash": "0x78c62531d96088f640ffe7e62088b49749efe286",
126 | "hashScheme": "HASH_SCHEME_BLAKE3",
127 | "signature": "frIZJGIizv...qQd9QJyCg==",
128 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
129 | "signer": "0x59a04...6860ddfab"
130 | }
131 | ],
132 | "nextPageToken": ""
133 | }
134 | ```
135 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/onchain.md:
--------------------------------------------------------------------------------
1 | # On Chain API
2 |
3 | ## onChainSignersByFid
4 |
5 | Get a list of account keys (signers) provided by an FID
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | fid | The FID being requested | `fid=2` |
11 | | signer | The optional key of signer | `signer=0x0852c07b5695ff94138b025e3f9b4788e06133f04e254f0ea0eb85a06e999cdd` |
12 |
13 | **Example**
14 |
15 | ```bash
16 | curl http://127.0.0.1:2281/v1/onChainSignersByFid?fid=6833
17 | ```
18 |
19 | **Response**
20 |
21 | ```json
22 | {
23 | "events": [
24 | {
25 | "type": "EVENT_TYPE_SIGNER",
26 | "chainId": 10,
27 | "blockNumber": 108875854,
28 | "blockHash": "0xceb1cdc21ee319b06f0455f1cedc0cd4669b471d283a5b2550b65aba0e0c1af0",
29 | "blockTimestamp": 1693350485,
30 | "transactionHash": "0x76e20cf2f7c3db4b78f00f6bb9a7b78b0acfb1eca4348c1f4b5819da66eb2bee",
31 | "logIndex": 2,
32 | "fid": 6833,
33 | "signerEventBody": {
34 | "key": "0x0852c07b5695ff94138b025e3f9b4788e06133f04e254f0ea0eb85a06e999cdd",
35 | "keyType": 1,
36 | "eventType": "SIGNER_EVENT_TYPE_ADD",
37 | "metadata": "AAAAAAAAAAAA...AAAAAAAA",
38 | "metadataType": 1
39 | },
40 | "txIndex": 0
41 | }
42 | ]
43 | }
44 | ```
45 |
46 | ## onChainEventsByFid
47 |
48 | Get a list of account keys provided by an FID
49 |
50 | **Query Parameters**
51 | | Parameter | Description | Example |
52 | | --------- | ----------- | ------- |
53 | | fid | The FID being requested | `fid=2` |
54 | | event_type | The numeric of string value of the event type being requested. This parameter is required | `event_type=1` OR `event_type=EVENT_TYPE_STORAGE_RENT` |
55 |
56 | The onChainEventsByFid API will accept the following values for the `event_type` field.
57 |
58 | | String | Numerical value |
59 | | -------------------------- | --------------- |
60 | | EVENT_TYPE_SIGNER | 1 |
61 | | EVENT_TYPE_SIGNER_MIGRATED | 2 |
62 | | EVENT_TYPE_ID_REGISTER | 3 |
63 | | EVENT_TYPE_STORAGE_RENT | 4 |
64 |
65 | **Example**
66 |
67 | ```bash
68 | curl http://127.0.0.1:2281/v1/onChainEventsByFid?fid=3&event_type=1
69 | ```
70 |
71 | **Response**
72 |
73 | ```json
74 | {
75 | "events": [
76 | {
77 | "type": "EVENT_TYPE_SIGNER",
78 | "chainId": 10,
79 | "blockNumber": 108875456,
80 | "blockHash": "0x75fbbb8b2a4ede67ac350e1b0503c6a152c0091bd8e3ef4a6927d58e088eae28",
81 | "blockTimestamp": 1693349689,
82 | "transactionHash": "0x36ef79e6c460e6ae251908be13116ff0065960adb1ae032b4cc65a8352f28952",
83 | "logIndex": 2,
84 | "fid": 3,
85 | "signerEventBody": {
86 | "key": "0xc887f5bf385a4718eaee166481f1832198938cf33e98a82dc81a0b4b81ffe33d",
87 | "keyType": 1,
88 | "eventType": "SIGNER_EVENT_TYPE_ADD",
89 | "metadata": "AAAAAAAAA...AAAAA",
90 | "metadataType": 1
91 | },
92 | "txIndex": 0
93 | }
94 | ]
95 | }
96 | ```
97 |
98 | ## onChainIdRegistryEventByAddress
99 |
100 | Get a list of on chain events for a given Address
101 |
102 | **Query Parameters**
103 | | Parameter | Description | Example |
104 | | --------- | ----------- | ------- |
105 | | address | The ETH address being requested | `address=0x74232bf61e994655592747e20bdf6fa9b9476f79` |
106 |
107 | **Example**
108 |
109 | ```bash
110 | curl http://127.0.0.1:2281/v1/onChainIdRegistryEventByAddress?address=0x74232bf61e994655592747e20bdf6fa9b9476f79
111 | ```
112 |
113 | **Response**
114 |
115 | ```json
116 | {
117 | "type": "EVENT_TYPE_ID_REGISTER",
118 | "chainId": 10,
119 | "blockNumber": 108874508,
120 | "blockHash": "0x20d83804a26247ad8c26d672f2212b28268d145b8c1cefaa4126f7768f46682e",
121 | "blockTimestamp": 1693347793,
122 | "transactionHash": "0xf3481fc32227fbd982b5f30a87be32a2de1fc5736293cae7c3f169da48c3e764",
123 | "logIndex": 7,
124 | "fid": 3,
125 | "idRegisterEventBody": {
126 | "to": "0x74232bf61e994655592747e20bdf6fa9b9476f79",
127 | "eventType": "ID_REGISTER_EVENT_TYPE_REGISTER",
128 | "from": "0x",
129 | "recoveryAddress": "0x00000000fcd5a8e45785c8a4b9a718c9348e4f18"
130 | },
131 | "txIndex": 0
132 | }
133 | ```
134 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/storagelimits.md:
--------------------------------------------------------------------------------
1 | # Storage API
2 |
3 | ## storageLimitsByFid
4 |
5 | Get an FID's storage limits.
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | fid | The FID that's being requested | `fid=6833` |
11 |
12 | **Example**
13 |
14 | ```bash
15 | curl http://127.0.0.1:2281/v1/storageLimitsByFid?fid=6833
16 | ```
17 |
18 | **Response**
19 |
20 | ```json
21 | {
22 | "limits": [
23 | {
24 | "storeType": "STORE_TYPE_CASTS",
25 | "limit": 10000
26 | },
27 | {
28 | "storeType": "STORE_TYPE_LINKS",
29 | "limit": 5000
30 | },
31 | {
32 | "storeType": "STORE_TYPE_REACTIONS",
33 | "limit": 5000
34 | },
35 | {
36 | "storeType": "STORE_TYPE_USER_DATA",
37 | "limit": 100
38 | },
39 | {
40 | "storeType": "STORE_TYPE_USERNAME_PROOFS",
41 | "limit": 10
42 | },
43 | {
44 | "storeType": "STORE_TYPE_VERIFICATIONS",
45 | "limit": 50
46 | }
47 | ]
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/userdata.md:
--------------------------------------------------------------------------------
1 | # UserData API
2 |
3 | The UserData API will accept the following values for the `user_data_type` field.
4 |
5 | | String | Numerical value | Description |
6 | | ----------------------- | --------------- | ----------------------------- |
7 | | USER_DATA_TYPE_PFP | 1 | Profile Picture for the user |
8 | | USER_DATA_TYPE_DISPLAY | 2 | Display Name for the user |
9 | | USER_DATA_TYPE_BIO | 3 | Bio for the user |
10 | | USER_DATA_TYPE_URL | 5 | URL of the user |
11 | | USER_DATA_TYPE_USERNAME | 6 | Preferred Name for the user |
12 | | USER_DATA_TYPE_LOCATION | 7 | Location for the user |
13 | | USER_DATA_TYPE_TWITTER | 8 | Twitter username for the user |
14 | | USER_DATA_TYPE_GITHUB | 9 | GitHub username for the user |
15 |
16 | See [FIP-196](https://github.com/farcasterxyz/protocol/discussions/196) for more information on Location.
17 | See [FIP-19](https://github.com/farcasterxyz/protocol/discussions/199) for more information on Twitter/X and Github usernames.
18 |
19 | ## userDataByFid
20 |
21 | Get UserData for a FID.
22 |
23 | **Query Parameters**
24 | | Parameter | Description | Example |
25 | | --------- | ----------- | ------- |
26 | | fid | The FID that's being requested | `fid=6833` |
27 | | user_data_type | The type of user data, either as a numerical value or type string. If this is omitted, all user data for the FID is returned| `user_data_type=1` OR `user_data_type=USER_DATA_TYPE_DISPLAY` |
28 |
29 | **Example**
30 |
31 | ```bash
32 | curl http://127.0.0.1:2281/v1/userDataByFid?fid=6833&user_data_type=1
33 | ```
34 |
35 | **Response**
36 |
37 | ```json
38 | {
39 | "data": {
40 | "type": "MESSAGE_TYPE_USER_DATA_ADD",
41 | "fid": 6833,
42 | "timestamp": 83433831,
43 | "network": "FARCASTER_NETWORK_MAINNET",
44 | "userDataBody": {
45 | "type": "USER_DATA_TYPE_PFP",
46 | "value": "https://i.imgur.com/HG54Hq6.png"
47 | }
48 | },
49 | "hash": "0x327b8f47218c369ae01cc453cc23efc79f10181f",
50 | "hashScheme": "HASH_SCHEME_BLAKE3",
51 | "signature": "XITQZD7q...LdAlJ9Cg==",
52 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
53 | "signer": "0x0852...6e999cdd"
54 | }
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/usernameproof.md:
--------------------------------------------------------------------------------
1 | # Username Proofs API
2 |
3 | ## userNameProofByName
4 |
5 | Get an proof for a username by the Farcaster username
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | name | The Farcaster username or ENS address | `name=adityapk` OR `name=dwr.eth` |
11 |
12 | **Example**
13 |
14 | ```bash
15 | curl http://127.0.0.1:2281/v1/userNameProofByName?name=adityapk
16 | ```
17 |
18 | **Response**
19 |
20 | ```json
21 | {
22 | "timestamp": 1670603245,
23 | "name": "adityapk",
24 | "owner": "Oi7uUaECifDm+larm+rzl3qQhcM=",
25 | "signature": "fo5OhBP/ud...3IoJdhs=",
26 | "fid": 6833,
27 | "type": "USERNAME_TYPE_FNAME"
28 | }
29 | ```
30 |
31 | ## userNameProofsByFid
32 |
33 | Get a list of proofs provided by an FID
34 |
35 | **Query Parameters**
36 | | Parameter | Description | Example |
37 | | --------- | ----------- | ------- |
38 | | fid | The FID being requested | `fid=2` |
39 |
40 | **Example**
41 |
42 | ```bash
43 | curl http://127.0.0.1:2281/v1/userNameProofsByFid?fid=2
44 | ```
45 |
46 | **Response**
47 |
48 | ```json
49 | {
50 | "proofs": [
51 | {
52 | "timestamp": 1623910393,
53 | "name": "v",
54 | "owner": "0x4114e33eb831858649ea3702e1c9a2db3f626446",
55 | "signature": "bANBae+Ub...kr3Bik4xs=",
56 | "fid": 2,
57 | "type": "USERNAME_TYPE_FNAME"
58 | },
59 | {
60 | "timestamp": 1690329118,
61 | "name": "varunsrin.eth",
62 | "owner": "0x182327170fc284caaa5b1bc3e3878233f529d741",
63 | "signature": "zCEszPt...zqxTiFqVBs=",
64 | "fid": 2,
65 | "type": "USERNAME_TYPE_ENS_L1"
66 | }
67 | ]
68 | }
69 | ```
70 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/verification.md:
--------------------------------------------------------------------------------
1 | # Verifications API
2 |
3 | ## verificationsByFid
4 |
5 | Get a list of verifications provided by an FID
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | fid | The FID being requested | `fid=2` |
11 | | address | The optional ETH address to filter by | `address=0x91031dcfdea024b4d51e775486111d2b2a715871` |
12 |
13 | **Example**
14 |
15 | ```bash
16 | curl http://127.0.0.1:2281/v1/verificationsByFid?fid=2
17 | ```
18 |
19 | **Response**
20 |
21 | ```json
22 | {
23 | "messages": [
24 | {
25 | "data": {
26 | "type": "MESSAGE_TYPE_VERIFICATION_ADD_ETH_ADDRESS",
27 | "fid": 2,
28 | "timestamp": 73244540,
29 | "network": "FARCASTER_NETWORK_MAINNET",
30 | "verificationAddEthAddressBody": {
31 | "address": "0x91031dcfdea024b4d51e775486111d2b2a715871",
32 | "ethSignature": "tyxj1...x1cYzhyxw=",
33 | "blockHash": "0xd74860c4bbf574d5ad60f03a478a30f990e05ac723e138a5c860cdb3095f4296"
34 | }
35 | },
36 | "hash": "0xa505331746ec8c5110a94bdb098cd964e43a8f2b",
37 | "hashScheme": "HASH_SCHEME_BLAKE3",
38 | "signature": "bln1zIZM.../4riB9IVBQ==",
39 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
40 | "signer": "0x78ff9...b6d62558c"
41 | }
42 | ],
43 | "nextPageToken": ""
44 | }
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/reference/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | The reference sections documents API's, standards and protocols used commonly used by Farcaster developers.
4 |
5 |
6 | - [Mini Apps](https://miniapps.farcaster.xyz){target="_self"}- A specification for writing and rendering mini apps.
7 | - [Farcaster Client APIs](/reference/warpcast/api) - An overview of Farcaster Client APIs that are publicly available.
8 | - [Hubble](/reference/hubble/architecture) - A design overview and API reference for Farcaster Hubs.
9 | - [Replicator](/reference/replicator/schema) - An overview and schema for the replicator.
10 | - [Contracts](/reference/contracts/index) - A design overview and ABI reference for Farcaster contracts.
11 | - [FName Registry](/reference/fname/api) - An overview and API reference for the Farcaster Name Server.
12 | - [Neynar](/reference/third-party/neynar/index) - An overview of Neynar APIs that can help developers get started with Farcaster
13 |
--------------------------------------------------------------------------------
/docs/reference/third-party/neynar/index.md:
--------------------------------------------------------------------------------
1 | # Neynar
2 |
3 | [Neynar](https://neynar.com) is an independent 3rd party provider that offers the following services for Farcaster data:
4 |
5 | - [Hosted hubs](https://docs.neynar.com/docs/create-a-stream-of-casts)
6 | - [REST APIs](https://docs.neynar.com/reference/quickstart)
7 | - [Signer management](https://docs.neynar.com/docs/which-signer-should-you-use-and-why)
8 | - [New account creation](https://docs.neynar.com/docs/how-to-create-a-new-farcaster-account-with-neynar)
9 | - [Webhooks](https://docs.neynar.com/docs/how-to-create-webhooks-on-the-go-using-the-sdk)
10 | - [Data ingestion pipelines](https://docs.neynar.com/docs/how-to-choose-the-right-data-product-for-you)
11 |
12 | 🪐
13 |
--------------------------------------------------------------------------------
/docs/reference/warpcast/cast-composer-intents.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Warpcast Intents URLs
3 | ---
4 |
5 | # Intents URLs
6 |
7 | ## Cast Intent URLs
8 |
9 | Warpcast intents enable builders to direct authenticated users to a pre-filled cast composer.
10 |
11 | > [!IMPORTANT]
12 | > If you're building a Mini App and want to prompt the user to compose a cast, use the [composeCast action](https://miniapps.farcaster.xyz/docs/sdk/actions/compose-cast)
13 | > from the Mini App SDK.
14 |
15 | #### Compose with cast text
16 |
17 | ```
18 | https://warpcast.com/~/compose?text=Hello%20world!
19 | ```
20 |
21 | #### Compose with cast text and one embed
22 |
23 | ```
24 | https://warpcast.com/~/compose?text=Hello%20world!&embeds[]=https://farcaster.xyz
25 | ```
26 |
27 | #### Compose with cast text with mentions and two embeds
28 |
29 | ```
30 | https://warpcast.com/~/compose?text=Hello%20@farcaster!&embeds[]=https://farcaster.xyz&embeds[]=https://github.com/farcasterxyz/protocol
31 | ```
32 |
33 | #### Compose with cast text on a specific channel
34 |
35 | ```
36 | https://warpcast.com/~/compose?text=Hello%20world!&channelKey=farcaster
37 | ```
38 |
39 | #### Reply with cast text to a cast with hash
40 |
41 | ```
42 | https://warpcast.com/~/compose?text=Looks%20good!&parentCastHash=0x09455067393562d3296bcbc2ec1c2d6bba8ac1f1
43 | ```
44 |
45 | #### Additional details
46 |
47 | - Embeds are any valid URLs
48 | - URLs ending with `.png` `.jpg` or `.gif` will render as an image embed
49 | - Embedding the URL to a Zora mint page will render the NFT with a mint link below it.
50 | - You can check how embeds will be rendered in Warpcast at https://warpcast.com/~/developers/embeds
51 |
52 | ## Resource URLs
53 |
54 | #### View profile by FID
55 |
56 | ```
57 | https://warpcast.com/~/profiles/:fid
58 | ```
59 |
60 | #### View cast by hash
61 |
62 | ```
63 | https://warpcast.com/~/conversations/:hash
64 | ```
65 |
--------------------------------------------------------------------------------
/docs/reference/warpcast/direct-casts.md:
--------------------------------------------------------------------------------
1 | # Direct Casts
2 |
3 | This page documents public APIs provided by the official Farcaster client for direct casts. Direct casts are currently not part of the protocol. There are plans to add direct casts to the protocol later this year.
4 |
5 | #### Send / write API for direct casts
6 |
7 | - [Send direct casts via API](https://www.notion.so/warpcast/Public-Programmable-DCs-v1-50d9d99e34ac4d10add55bd26a91804f)
8 | - The above link also provides information on how to obtain direct cast API keys
9 |
10 | #### Direct cast intents
11 |
12 | Intents enable developers to direct authenticated users to a pre-filled direct cast composer via a URL.
13 |
14 | ```bash
15 | https://farcaster.xyz/~/inbox/create/[fid]?text=[message]
16 |
17 | https://farcaster.xyz/~/inbox/create/1?text=gm
18 | ```
19 |
--------------------------------------------------------------------------------
/docs/reference/warpcast/embeds.md:
--------------------------------------------------------------------------------
1 | # Farcaster Client Embeds Reference
2 |
3 | The Farcaster client follows the [Open Graph protocol](https://ogp.me) when rendering rich previews for URL embeds.
4 |
5 | Developers can reset existing embed caches on the Farcaster client at https://farcaster.xyz/~/developers/embeds.
6 |
7 | #### Additional details
8 |
9 | - Resetting an embed cache, does not reset Open Graph image caches. If you are experiencing a stale image on your Open Graph, change the image file path served as the `og:image`.
10 | - Developers have to be logged in to the Farcaster client to access this page.
11 | - To render rich previews of NFTs, follow the [Farcaster Frames spec](/developers/frames/spec).
12 |
--------------------------------------------------------------------------------
/docs/reference/warpcast/videos.md:
--------------------------------------------------------------------------------
1 | # How to have your video displayed on the Farcaster client
2 |
3 | 1. Ensure you serve your video as a streamable `.m3u8` file. This ensures clients only download what they need when viewing, and nothing more, providing a high performance experience.
4 |
5 | 2. Make sure that `.m3u8` manifest exposes the resolution(s) for your video. The Farcaster client uses this to determine the correct aspect ratio when rendering. A manifest file with resolution data looks something like:
6 |
7 | ```
8 | #EXTM3U
9 | #EXT-X-VERSION:3
10 |
11 | #EXT-X-STREAM-INF:BANDWIDTH=2444200,CODECS="avc1.64001f,mp4a.40.2",RESOLUTION=474x842
12 | 480p/video.m3u8
13 | #EXT-X-STREAM-INF:BANDWIDTH=4747600,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=720x1280
14 | 720p/video.m3u8
15 | ```
16 |
17 | 3. Ensure that at cast publish time the `.m3u8` file is available. The Farcaster client checks once and if there is no valid data, the cast will show no video.
18 |
19 | 4. Have the same URL when changed from ending in `/my-video.m3u8` to `/thumbnail.jpg` with a preview/thumbnail image to render before the user has interacted with the video.
20 |
21 | 5. Reach out to the Farcaster team and ask for us to enable videos for your domain. Tell us the format of your video URLs and we’ll configure our scrapers to display them correctly in the feed. Please make sure to complete all these steps above before reaching out for allowlisting. [Ping @gt on Farcaster](https://farcaster.xyz/~/inbox/create/302?text=Completed%20video%20setup).
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "www-farcaster-xyz",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "UNLICENSED",
6 | "devDependencies": {
7 | "husky": "^8.0.3",
8 | "lint-staged": "^15.2.0",
9 | "prettier": "^2.8.7",
10 | "vitepress": "^1.3.1"
11 | },
12 | "scripts": {
13 | "docs:dev": "vitepress dev docs",
14 | "docs:build": "vitepress build docs",
15 | "docs:preview": "vitepress preview docs",
16 | "lint": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md}\"",
17 | "lint:check": "prettier --config \"./.prettierrc.yml\" --check \"**/*.{json,md}\"",
18 | "postinstall": "husky install"
19 | },
20 | "lint-staged": {
21 | "*.md": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md}\""
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "cleanUrls": true,
3 | "redirects": [
4 | {
5 | "source": "/developers/frames/v2",
6 | "destination": "https://miniapps.farcaster.xyz/",
7 | "permanent": true
8 | },
9 | {
10 | "source": "/developers/frames/v2/",
11 | "destination": "https://miniapps.farcaster.xyz/",
12 | "permanent": true
13 | },
14 | {
15 | "source": "/developers/frames/v2/getting-started",
16 | "destination": "https://miniapps.farcaster.xyz/docs/getting-started",
17 | "permanent": true
18 | },
19 | {
20 | "source": "/developers/frames/v2/spec",
21 | "destination": "https://miniapps.farcaster.xyz/docs/specification",
22 | "permanent": true
23 | },
24 | {
25 | "source": "/developers/frames/v2/index",
26 | "destination": "https://miniapps.farcaster.xyz/",
27 | "permanent": true
28 | },
29 | {
30 | "source": "/developers/frames/v2/resources",
31 | "destination": "https://miniapps.farcaster.xyz/docs/specification",
32 | "permanent": true
33 | },
34 | {
35 | "source": "/developers/frames/v2/notifications_webhooks",
36 | "destination": "https://miniapps.farcaster.xyz/docs/guides/notifications",
37 | "permanent": true
38 | },
39 | {
40 | "source": "/auth-kit/introduction",
41 | "destination": "/auth-kit/",
42 | "permanent": true
43 | },
44 | {
45 | "source": "/docs/developers/frames",
46 | "destination": "https://miniapps.farcaster.xyz",
47 | "permanent": true
48 | },
49 | {
50 | "source": "/developers/frames/v2/getting-started",
51 | "destination": "https://miniapps.farcaster.xyz/docs/getting-started",
52 | "permanent": true
53 | },
54 | {
55 | "source": "/developers/frames/v2/notifications_webhooks",
56 | "destination": "https://miniapps.farcaster.xyz/docs/guides/notifications",
57 | "permanent": true
58 | },
59 | {
60 | "source": "/developers/frames/v2/spec",
61 | "destination": "https://miniapps.farcaster.xyz/docs/specification",
62 | "permanent": true
63 | },
64 | {
65 | "source": "/auth-kit/introduction",
66 | "destination": "/auth-kit/",
67 | "permanent": true
68 | },
69 | {
70 | "source": "/docs/developers/frames",
71 | "destination": "https://miniapps.farcaster.xyz",
72 | "permanent": true
73 | },
74 | {
75 | "source": "/docs/developers/frames/",
76 | "destination": "https://miniapps.farcaster.xyz",
77 | "permanent": true
78 | },
79 | {
80 | "source": "/developers/frames/v2/getting-started",
81 | "destination": "https://miniapps.farcaster.xyz/docs/getting-started",
82 | "permanent": true
83 | },
84 | {
85 | "source": "/developers/frames/v2/notifications_webhooks",
86 | "destination": "https://miniapps.farcaster.xyz/docs/guides/notifications",
87 | "permanent": true
88 | },
89 | {
90 | "source": "/developers/frames/v2/spec",
91 | "destination": "https://miniapps.farcaster.xyz/docs/specification",
92 | "permanent": true
93 | },
94 | {
95 | "source": "/reference/frames/spec",
96 | "destination": "https://miniapps.farcaster.xyz/docs/specification",
97 | "permanent": true
98 | }
99 | ]
100 | }
101 |
--------------------------------------------------------------------------------