├── .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 | [![NPM Version](https://img.shields.io/npm/v/@farcaster/auth-client)](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 | 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 | ![Sign In with Farcaste demo](./siwf_demo.avifs) 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 |
mkdir farcaster-hub
 27 | cd farcaster-hub
 28 | nano main.tf
 29 | 
30 | 31 | Now paste the content of below into your main.tf \ 32 | Replace "$YOUR_PROJECT_ID" with your personal ID. 33 | 34 |
35 | 36 | This is the configuration of your GCP virtual machine that will be created. 37 | 38 | ``` 39 | provider "google" { 40 | project = "$YOUR_PROJECT_ID" 41 | region = "us-central1" 42 | } 43 | 44 | resource "google_compute_instance" "farcaster-hub-vm" { 45 | name = "farcaster-hub-vm" 46 | machine_type = "e2-standard-4" # 4 vCPUs, 16 GB memory 47 | zone = "us-central1-a" # Specify the zone here 48 | 49 | 50 | boot_disk { 51 | initialize_params { 52 | image = "ubuntu-2004-focal-v20231213" # Ubuntu 20.04 LTS image URL 53 | size = 160 # 160 GB disk size 54 | } 55 | } 56 | 57 | network_interface { 58 | network = "default" 59 | access_config { 60 | // This will assign a public IP address to the instance 61 | } 62 | } 63 | 64 | tags = ["allow-farcaster-p2p-ports"] # For firewall rule 65 | 66 | metadata = { 67 | # You can add any additional metadata here if needed 68 | } 69 | } 70 | 71 | resource "google_compute_firewall" "farcaster-p2p-ports" { 72 | name = "farcaster-p2p-ports" 73 | network = "default" 74 | 75 | # allow incoming traffic for ports 2282-2285 76 | allow { 77 | protocol = "tcp" 78 | ports = ["2282-2285"] 79 | } 80 | 81 | source_ranges = ["0.0.0.0/0"] 82 | } 83 | ``` 84 | 85 | Execute this command: 86 | 87 | ``` 88 | terraform init # to initialize terraform in your farcaster-hub folder 89 | ``` 90 | 91 | Execute this command: 92 | 93 | ``` 94 | terraform plan # this will simulate your terraform configuration & check if it is correct 95 | ``` 96 | 97 | Example output: 98 | 99 |

Example output of terraform plan

100 | 101 | Enable Compute Engine API 102 | 103 |
104 | 105 | Now execute this command: 106 | 107 | ```bash 108 | terraform apply 109 | ``` 110 | 111 |

Example output of Terraform apply

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 | ![Registry Contracts](/assets/registry-contracts.png) 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 | ![Usernames](/assets/usernames.png) 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 | ![Hub](/assets/hub.png) 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 | ![Architecture](/assets/architecture.png) 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 | ![Usernames](/assets/usernames.png) 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 | ![contracts.png](/assets/contracts.png) 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 | --------------------------------------------------------------------------------