├── vercel.json
├── docs
├── assets
│ ├── hub.png
│ ├── contracts.png
│ ├── frame_app.png
│ ├── frame_og.png
│ ├── frame_poll.png
│ ├── high-level.png
│ ├── usernames.png
│ ├── architecture.png
│ ├── actions
│ │ ├── frame_type.png
│ │ └── message_type.png
│ └── registry-contracts.png
├── developers
│ ├── utilities.md
│ ├── guides
│ │ ├── writing
│ │ │ ├── submit-messages.md
│ │ │ ├── verify-address.md
│ │ │ ├── casts.md
│ │ │ └── messages.md
│ │ ├── advanced
│ │ │ ├── query-signups.md
│ │ │ └── decode-key-metadata.md
│ │ ├── querying
│ │ │ ├── fetch-casts.md
│ │ │ ├── fetch-profile.md
│ │ │ ├── setting-up.md
│ │ │ └── fetch-channel-casts.md
│ │ ├── accounts
│ │ │ ├── find-by-name.md
│ │ │ ├── change-fname.md
│ │ │ ├── change-recovery.md
│ │ │ └── change-custody.md
│ │ ├── apps
│ │ │ └── replicate.md
│ │ └── frames
│ │ │ └── poll.md
│ ├── index.md
│ └── resources.md
├── public
│ ├── .DS_Store
│ ├── icon.png
│ └── og-image.png
├── .vitepress
│ └── theme
│ │ ├── index.js
│ │ └── custom.css
├── hubble
│ ├── tutorials.md
│ ├── hubble.md
│ ├── networks.md
│ ├── monitoring.md
│ └── troubleshooting.md
├── examples
│ └── contracts
│ │ ├── signer.ts
│ │ ├── clients.ts
│ │ └── metadata.ts
├── reference
│ ├── hubble
│ │ ├── httpapi
│ │ │ ├── fids.md
│ │ │ ├── info.md
│ │ │ ├── storagelimits.md
│ │ │ ├── verification.md
│ │ │ ├── usernameproof.md
│ │ │ ├── userdata.md
│ │ │ ├── events.md
│ │ │ ├── links.md
│ │ │ ├── onchain.md
│ │ │ ├── httpapi.md
│ │ │ └── casts.md
│ │ ├── grpcapi
│ │ │ ├── fids.md
│ │ │ ├── message.md
│ │ │ ├── events.md
│ │ │ ├── storagelimits.md
│ │ │ ├── grpcapi.md
│ │ │ ├── verification.md
│ │ │ ├── userdata.md
│ │ │ ├── casts.md
│ │ │ ├── usernameproof.md
│ │ │ ├── links.md
│ │ │ ├── onchain.md
│ │ │ ├── reactions.md
│ │ │ └── sync.md
│ │ └── architecture.md
│ ├── warpcast
│ │ ├── embeds.md
│ │ └── cast-composer-intents.md
│ ├── index.md
│ ├── contracts
│ │ ├── deployments.md
│ │ ├── index.md
│ │ ├── reference
│ │ │ ├── storage-registry.md
│ │ │ └── bundler.md
│ │ └── faq.md
│ └── fname
│ │ └── api.md
├── auth-kit
│ ├── examples.md
│ ├── introduction.md
│ ├── hooks
│ │ ├── use-sign-in-message.md
│ │ └── use-profile.md
│ ├── client
│ │ ├── introduction.md
│ │ ├── app
│ │ │ ├── client.md
│ │ │ ├── create-channel.md
│ │ │ ├── verify-sign-in-message.md
│ │ │ ├── status.md
│ │ │ └── watch-status.md
│ │ └── wallet
│ │ │ ├── parse-sign-in-uri.md
│ │ │ ├── client.md
│ │ │ ├── build-sign-in-message.md
│ │ │ └── authenticate.md
│ ├── auth-kit-provider.md
│ ├── installation.md
│ └── sign-in-button.md
├── learn
│ ├── contributing
│ │ ├── governance.md
│ │ ├── overview.md
│ │ └── fips.md
│ ├── architecture
│ │ ├── overview.md
│ │ ├── ens-names.md
│ │ ├── contracts.md
│ │ └── hubs.md
│ └── what-is-farcaster
│ │ ├── frames.md
│ │ ├── apps.md
│ │ ├── accounts.md
│ │ ├── channels.md
│ │ ├── usernames.md
│ │ └── messages.md
└── index.md
├── .husky
└── pre-commit
├── .prettierrc.yml
├── README.md
├── package.json
└── .gitignore
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "cleanUrls": true
3 | }
4 |
--------------------------------------------------------------------------------
/docs/assets/hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/hub.png
--------------------------------------------------------------------------------
/docs/developers/utilities.md:
--------------------------------------------------------------------------------
1 | # Links
2 |
3 | - https://github.com/a16z/awesome-farcaster
4 |
--------------------------------------------------------------------------------
/docs/public/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/public/.DS_Store
--------------------------------------------------------------------------------
/docs/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/public/icon.png
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | yarn lint-staged
5 |
--------------------------------------------------------------------------------
/docs/assets/contracts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/contracts.png
--------------------------------------------------------------------------------
/docs/assets/frame_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/frame_app.png
--------------------------------------------------------------------------------
/docs/assets/frame_og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/frame_og.png
--------------------------------------------------------------------------------
/docs/assets/frame_poll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/frame_poll.png
--------------------------------------------------------------------------------
/docs/assets/high-level.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/high-level.png
--------------------------------------------------------------------------------
/docs/assets/usernames.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/usernames.png
--------------------------------------------------------------------------------
/docs/public/og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/public/og-image.png
--------------------------------------------------------------------------------
/docs/assets/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/architecture.png
--------------------------------------------------------------------------------
/docs/assets/actions/frame_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/actions/frame_type.png
--------------------------------------------------------------------------------
/docs/assets/actions/message_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/actions/message_type.png
--------------------------------------------------------------------------------
/docs/assets/registry-contracts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fortunaaaa/docs/HEAD/docs/assets/registry-contracts.png
--------------------------------------------------------------------------------
/.prettierrc.yml:
--------------------------------------------------------------------------------
1 | semi: true
2 | trailingComma: 'es5'
3 | singleQuote: true
4 | printWidth: 80
5 | tabWidth: 2
6 | useTabs: false
7 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # docs.farcaster.xyz
2 |
3 | Documentation for the Farcaster Protocol
4 |
5 | ### Getting Started
6 |
7 | 1. Run `npm install -D vitepress`
8 | 2. Run `npm run docs:dev`
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/custom.css:
--------------------------------------------------------------------------------
1 | /* .vitepress/theme/custom.css */
2 | :root {
3 | --vp-c-green: #8a63d2;
4 | --vp-c-green-light: #9c83d5;
5 | --vp-c-green-lighter: #c2b2e5;
6 | --vp-c-green-dark: #6950a3;
7 | --vp-c-green-darker: #5d468e;
8 | --vp-c-green-dimm-1: rgba(138, 99, 210, 0.05);
9 | --vp-c-green-dimm-2: rgba(138, 99, 210, 0.2);
10 | --vp-c-green-dimm-3: rgba(138, 99, 210, 0.5);
11 | }
12 |
--------------------------------------------------------------------------------
/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/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/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/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/reference/warpcast/embeds.md:
--------------------------------------------------------------------------------
1 | # Warpcast Embeds Reference
2 |
3 | Warpcast follows the [Open Graph protocol](https://ogp.me) when rendering rich previews for URL embeds.
4 |
5 | Developers can reset existing embed caches on Warpcast at https://warpcast.com/~/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 Warpcast to access this page.
11 | - To render rich previews of NFTs, follow the [Farcaster Frames spec](/reference/frames/spec).
12 |
--------------------------------------------------------------------------------
/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/reference/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | The reference sections documents API's, standards and protocols used commonly used by Farcaster developers.
4 |
5 | - [Frames](/reference/frames/spec) - A specification for writing and rendering frames.
6 | - [Warpcast](/reference/warpcast/api) - An overview of Warpcast APIs that are publicly available.
7 | - [Hubble](/reference/hubble/architecture) - A design overview and API reference for Farcaster Hubs.
8 | - [Replicator](/reference/replicator/schema) - An overview and schema for the replicator.
9 | - [Contracts](/reference/contracts/index) - A design overview and ABI reference for Farcaster contracts.
10 | - [FName Registry](/reference/fname/api) - An overview and API reference for the Farcaster Name Server.
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.0.0-rc.41"
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 |
--------------------------------------------------------------------------------
/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/auth-kit/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ## Client Side
4 |
5 | A frontend-only app which lets users Sign in with Farcaster and shows them their profile picture and username.
6 |
7 |
8 |
9 | [Try Demo](https://farcaster-auth-kit-vite-demo.replit.app/) | [View Source](https://github.com/farcasterxyz/connect-monorepo/tree/main/examples/frontend-only)
10 |
11 | ## Server Side
12 |
13 | A Next.js app which lets users Sign in with Farcaster and handles sessions server-side.
14 |
15 |
16 |
17 | [Try Demo](https://farcaster-auth-kit-next-auth-demo.replit.app/) | [View Source](https://github.com/farcasterxyz/connect-monorepo/tree/main/examples/with-next-auth)
18 |
--------------------------------------------------------------------------------
/docs/auth-kit/introduction.md:
--------------------------------------------------------------------------------
1 | # AuthKit
2 |
3 | [](https://www.npmjs.com/package/@farcaster/auth-kit)
4 |
5 | AuthKit is a React library that lets users log in to your app with a Farcaster account.
6 |
7 |
8 |
9 | Click "Sign in With Farcaster" above to try it out on web or click [here](https://sign-in-with-farcaster-demo.replit.app/) for mobile.
10 |
11 | ### How does it work?
12 |
13 | It uses the [Sign In With Farcaster](#sign-in-with-farcaster-siwf) standard under the hood, which is conceptually like "Sign in with Google". When integrated, AuthKit will:
14 |
15 | 1. Show a "Sign in with Farcaster" button to the user.
16 | 2. Wait for the user to click, scan a QR code and approve the request in Warpcast.
17 | 3. Receive and verify a signature from Warpcast.
18 | 4. Show the logged in user's profile picture and username.
19 |
--------------------------------------------------------------------------------
/docs/auth-kit/hooks/use-sign-in-message.md:
--------------------------------------------------------------------------------
1 | # `useSignInMessage`
2 |
3 | Hook for reading the Sign in With Farcaster message and signature used to authenticate the user.
4 |
5 | If you're providing the message and signature to a backend API, you may want to use this hook.
6 |
7 | ```tsx
8 | import { useUserData } from '@farcaster/auth-kit';
9 |
10 | function App() {
11 | const { message, signature } = useSignInMessage();
12 |
13 | return (
14 |
15 |
You signed: {message}
16 |
Your signature: {signature}
17 |
18 | );
19 | }
20 | ```
21 |
22 | ## Returns
23 |
24 | ```ts
25 | {
26 | message: string;
27 | signature: Hex;
28 | }
29 | ```
30 |
31 | | Parameter | Description |
32 | | ----------- | -------------------------------------------------- |
33 | | `message` | SIWE message signed by the user. |
34 | | `signature` | Signature produced by the user's Farcaster wallet. |
35 |
--------------------------------------------------------------------------------
/docs/reference/warpcast/cast-composer-intents.md:
--------------------------------------------------------------------------------
1 | # Warpcast Cast Intents
2 |
3 | Warpcast intents enable builders to direct authenticated users to a pre-filled cast composer.
4 |
5 | #### Compose with cast text
6 |
7 | ```bash
8 | https://warpcast.com/~/compose?text=Hello%20world!
9 | ```
10 |
11 | #### Compose with cast text and one embed
12 |
13 | ```bash
14 | https://warpcast.com/~/compose?text=Hello%20world!&embeds[]=https://farcaster.xyz
15 | ```
16 |
17 | #### Compose with cast text with mentions and two embeds
18 |
19 | ```bash
20 | https://warpcast.com/~/compose?text=Hello%20@farcaster!&embeds[]=https://farcaster.xyz&embeds[]=https://github.com/farcasterxyz/protocol
21 | ```
22 |
23 | #### Additional details
24 |
25 | - Embeds are any valid URLs
26 | - URLs ending with `.png` `.jpg` or `.gif` will render as an image embed
27 | - Embedding the URL to a Zora mint page will render the NFT with a mint link below it.
28 | - You can check how embeds will be rendered in Warpcast at https://warpcast.com/~/developers/embeds
29 |
--------------------------------------------------------------------------------
/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 oif fids |
24 | | next_page_token | [bytes](#bytes) | optional | |
25 |
--------------------------------------------------------------------------------
/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/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/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/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/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 |
18 | ## Public Instances
19 |
20 | The Farcaster team runs an instance of Hubble for use by the public. This isn't guaranteed to be stable, and is
21 | read-only for now.
22 |
23 | ```bash
24 | url: nemes.farcaster.xyz
25 | httpapi_port: 2281
26 | gossipsub_port: 2282
27 | grpc_port: 2283
28 | ```
29 |
--------------------------------------------------------------------------------
/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 | - **Mainnet** - the stable version that everyone uses
8 | - **Testnet**- the latest beta release intended for developers
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 |
20 | FC_NETWORK_ID=2
21 | BOOTSTRAP_NODE=/dns/testnet1.farcaster.xyz/tcp/2282
22 | ```
23 |
24 | ## Mainnet
25 |
26 | Mainnet is the production environment that everyone uses.
27 |
28 | Set the following variables in your .env file in `apps/hubble`:
29 |
30 | ```sh
31 | FC_NETWORK_ID=1
32 | BOOTSTRAP_NODE=/dns/nemes.farcaster.xyz/tcp/2282
33 | ```
34 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/docs/learn/architecture/overview.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | Farcaster has a hybrid architecture that stores identity onchain and data offchain.
4 |
5 | 
6 |
7 | ## Onchain
8 |
9 | Farcaster's onchain systems are implemented as [contracts on OP Mainnet](./contracts.md). Actions are performed onchain only when security and consistency are critical. Use of onchain actions is kept at a minimum to reduce costs and improve performance.
10 |
11 | Only a handful of actions are performed onchain, including:
12 |
13 | - Creating an [account](../what-is-farcaster/accounts.md).
14 | - Paying rent to [store data](../what-is-farcaster/messages.md#storage).
15 | - Adding account keys for [connected apps](../what-is-farcaster/apps.md#connected-apps).
16 |
17 | ## Offchain
18 |
19 | Farcaster's offchain system is a peer-to-peer network of servers called [Hubs](./hubs.md) which store user data. The majority of user actions are performed offchain. These include:
20 |
21 | - Posting a new public message.
22 | - Following another user.
23 | - Reacting to a post.
24 | - Updating your profile picture.
25 |
26 | Actions are performed offchain when performance and cost are critical. Use of offchain actions is typically preferred when consistency isn't a strict requirement. Offchain systems achieve security by relying on signatures from onchain systems.
27 |
--------------------------------------------------------------------------------
/docs/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/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/developers/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ## Create frames
4 |
5 | Learn how to build frames, which are mini-apps that run inside a Farcaster feed.
6 |
7 | - [Overview](/learn/what-is-farcaster/frames) - Understand what a frame is and how it works
8 | - [Frame Speedrun](https://www.youtube.com/watch?v=JAIr8kyBxxU&list=PL0eq1PLf6eUecQKFj0pUFfO0fwm0k4zE4&index=2) - create your first frame in 5 minutes
9 | - [Specification](/reference/frames/spec) - A formal specification for the Frame standard
10 |
11 | ## Sign in with Farcaster
12 |
13 | Make it easy for users to sign in to your app with their Farcaster account.
14 |
15 | - [Examples](/auth-kit/examples.md) - see Sign in with Farcaster (SIWF) in action
16 | - [AuthKit](/auth-kit/installation.md) - a React toolkit to integrate SIWF
17 | - [FIP-11](https://github.com/farcasterxyz/protocol/discussions/110) - the formal standard for SWIF
18 |
19 | ## Analyze Farcaster data
20 |
21 | Sync the Farcaster network to a local machine so you can run queries on the data.
22 |
23 | - [Run a hub](/hubble/install.md) - get realtime access to Farcaster data on your machine.
24 | - [Write your first hub query](./guides/querying/fetch-casts.md) - get an account's casts from a hub.
25 | - [Set up the replicator](./guides/apps/replicate.md) - sync a hub to a postgres database to run advanced queries.
26 |
27 | ## Write to Farcaster
28 |
29 | - [Hello World](/developers/guides/basics/hello-world) - programatically create an account and publish a cast.
30 |
--------------------------------------------------------------------------------
/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/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/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/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
19 | the [`@farcaster/core`](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/core/src/eth/contracts/abis) package.
20 |
--------------------------------------------------------------------------------
/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/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/auth-kit/hooks/use-profile.md:
--------------------------------------------------------------------------------
1 | # `useProfile`
2 |
3 | Hook for reading information about the authenticated user.
4 |
5 | You can use this hook to read the authenticated user's profile information from other components inside your app.
6 |
7 | ```tsx
8 | import { useProfile } from '@farcaster/auth-kit';
9 |
10 | function App {
11 | const {
12 | isAuthenticated,
13 | profile: { username, fid, bio, displayName, pfpUrl },
14 | } = useProfile();
15 |
16 | return (
17 |
18 | {isAuthenticated ? (
19 |
20 | Hello, {username}! Your fid is: {fid}
21 |
22 | ) : (
23 |
You're not signed in.
24 | )}
25 |
26 | );
27 | };
28 | ```
29 |
30 | ## Returns
31 |
32 | ```ts
33 | {
34 | isAuthenticated: boolean;
35 | profile?: {
36 | fid?: number;
37 | username?: string;
38 | bio?: string;
39 | displayName?: string;
40 | pfpUrl?: string;
41 | custody?: Hex;
42 | verifications?: Hex[];
43 | },
44 | };
45 | ```
46 |
47 | | Parameter | Description |
48 | | ----------------------- | ---------------------------------- |
49 | | `isAuthenticated` | True when the user is logged in. |
50 | | `profile.fid` | User's Farcaster ID. |
51 | | `profile.username` | User's username. |
52 | | `profile.bio` | User's bio text. |
53 | | `profile.displayName` | User's display name. |
54 | | `profile.pfpUrl` | User's profile picture URL. |
55 | | `profile.custody` | User's FID custody address. |
56 | | `profile.verifications` | List of user's verified addresses. |
57 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/introduction.md:
--------------------------------------------------------------------------------
1 | # Auth client
2 |
3 | [](https://www.npmjs.com/package/@farcaster/auth-client)
4 |
5 | The `@farcaster/auth-client` library provides a framework agnostic client for Farcaster Auth. If you're not using React, want greater customizability, or want to interact with the Farcaster Auth relay directly, you can use the Auth client library to build your own Sign in With Farcaster flow.
6 |
7 | ## Getting Started
8 |
9 | ### Installation
10 |
11 | Install the Auth client and its peer dependency [viem](https://viem.sh/).
12 |
13 | ```sh
14 | npm install @farcaster/auth-client viem
15 | ```
16 |
17 | **Note:** This is a low level client library. If you're using React, take a look at [auth-kit](../introduction) 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/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 |
13 | ## userDataByFid
14 |
15 | Get UserData for a FID.
16 |
17 | **Query Parameters**
18 | | Parameter | Description | Example |
19 | | --------- | ----------- | ------- |
20 | | fid | The FID that's being requested | `fid=6833` |
21 | | user_data_type | The type of user data, either as a numerical value or type string. If this is ommited, all user data for the FID is returned| `user_data_type=1` OR `user_data_type=USER_DATA_TYPE_DISPLAY` |
22 |
23 | **Example**
24 |
25 | ```bash
26 | curl http://127.0.0.1:2281/v1/userDataByFid?fid=6833&user_data_type=1
27 | ```
28 |
29 | **Response**
30 |
31 | ```json
32 | {
33 | "data": {
34 | "type": "MESSAGE_TYPE_USER_DATA_ADD",
35 | "fid": 6833,
36 | "timestamp": 83433831,
37 | "network": "FARCASTER_NETWORK_MAINNET",
38 | "userDataBody": {
39 | "type": "USER_DATA_TYPE_PFP",
40 | "value": "https://i.imgur.com/HG54Hq6.png"
41 | }
42 | },
43 | "hash": "0x327b8f47218c369ae01cc453cc23efc79f10181f",
44 | "hashScheme": "HASH_SCHEME_BLAKE3",
45 | "signature": "XITQZD7q...LdAlJ9Cg==",
46 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
47 | "signer": "0x0852...6e999cdd"
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/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 |
18 | {/* Your App */}
19 |
20 | );
21 | };
22 | ```
23 |
24 | # Props
25 |
26 | | Prop | Type | Required | Description |
27 | | -------- | --------------- | -------- | ----------------------------------------------------- |
28 | | `config` | `AuthKitConfig` | No | Configuration object. See options in the table below. |
29 |
30 | `config` object options:
31 |
32 | | Parameter | Type | Required | Description | Default |
33 | | --------- | -------- | -------- | ---------------------------------- | ----------------------------- |
34 | | `domain` | `string` | No | The domain of your application. | `window.location.host` |
35 | | `siweUri` | `string` | No | The login URL of your application. | `window.location.href` |
36 | | `relay` | `string` | No | Farcaster Auth relay server URL | `https://relay.farcaster.xyz` |
37 | | `rpcUrl` | `string` | No | Optimism RPC server URL | `https://mainnet.optimism.io` |
38 | | `version` | `string` | No | Farcaster Auth version | `v1` |
39 |
--------------------------------------------------------------------------------
/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/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 | ### Frames
14 |
15 | - [@frame-js/frames](https://framesjs.org/) - next.js template for building and debugging frames.
16 | - [@coinbase/onchainkit](https://github.com/coinbase/onchainkit) - react toolkit to create frames.
17 |
18 | ### Apps
19 |
20 | - [farcaster kit](https://www.farcasterkit.com/) - react hooks for building Farcaster apps.
21 |
22 | ### Hubs
23 |
24 | - [@farcaster/hub-nodejs](https://www.npmjs.com/package/@farcaster/hub-nodejs) - lightweight, fast Typescript interface for Farcaster Hubs.
25 |
26 | ### Onchain
27 |
28 | - [farcaster-solidity](https://github.com/pavlovdog/farcaster-solidity/) - libraries for verifying and parsing Farcaster messages onchain
29 |
30 | ## Dashboards
31 |
32 | - [Farcaster Hub Map](https://farcaster.spindl.xyz/) - geographical map of Farcaster hubs
33 | - [Dune: Farcaster](https://dune.com/pixelhack/farcaster) - @pixelhack's dashboard for network stats
34 | - [Dune: Farcaster User Onchain Activities](https://dune.com/yesyes/farcaster-users-onchain-activities) - dashboard of farcaster user's onchain activity
35 |
36 | ## Open Source Examples
37 |
38 | - [quikcast](https://github.com/farcasterxyz/quikcast) - an end-to-end connected app implementation for Farcaster
39 | - [fc-polls](https://github.com/farcasterxyz/fc-polls) - a simple polling app built using frames
40 |
41 | ## Services
42 |
43 | - [Neynar](https://neynar.com/) - infrastructure and services for building farcaster apps.
44 |
--------------------------------------------------------------------------------
/docs/auth-kit/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | Install auth-kit and its peer dependency [viem](https://viem.sh/).
4 |
5 | ```sh
6 | npm install @farcaster/auth-kit viem
7 | ```
8 |
9 | **Note:** auth-kit is a [React](https://react.dev/) library. If you're using a different framework, take a look at the [client library](./client/introduction.md) instead.
10 |
11 | ### 1. Import the libraries
12 |
13 | Import auth-kit and CSS styles.
14 |
15 | ```tsx
16 | import '@farcaster/auth-kit/styles.css';
17 | import { AuthKitProvider } from '@farcaster/auth-kit';
18 | import { SignInButton } from '@farcaster/auth-kit';
19 | ```
20 |
21 | ### 2. Configure your provider
22 |
23 | Configure a provider with an Optimism RPC URL, your app's domain and login URL, and wrap your application in it.
24 |
25 | ```tsx
26 | const config = {
27 | rpcUrl: 'https://mainnet.optimism.io',
28 | domain: 'example.com',
29 | siweUri: 'https://example.com/login',
30 | };
31 |
32 | const App = () => {
33 | return (
34 | {/* Your App */}
35 | );
36 | };
37 | ```
38 |
39 | ### 3. Add a connect button
40 |
41 | Render the `SignInButton` component. When the user clicks this button, they will be prompted to complete sign in using their Farcaster wallet application.
42 |
43 | ```tsx
44 | export const Login = () => {
45 | return ;
46 | };
47 | ```
48 |
49 | ### 4. Read user profile
50 |
51 | Optionally, fetch details about the logged in user anywhere in your app with `useProfile`.
52 |
53 | ```tsx
54 | import { useProfile } from '@farcaster/auth-kit';
55 |
56 | export const UserProfile = () => {
57 | const {
58 | isAuthenticated,
59 | userData: { username, fid },
60 | } = useProfile();
61 | return (
62 |
63 | {isAuthenticated ? (
64 |
65 | Hello, {username}! Your fid is: {fid}
66 |
67 | ) : (
68 |
You're not signed in.
69 | )}
70 |
71 | );
72 | };
73 | ```
74 |
--------------------------------------------------------------------------------
/docs/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/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 | Hubble comes with a [replication app](https://github.com/farcasterxyz/hub-monorepo/tree/main/apps/replicator) that can
13 | be used to mirror Hubble's data to a Postgres DB for convenient access to the underlying data.
14 |
15 | ## Installation
16 |
17 | ```bash
18 | # Run the following script and answer the prompts
19 | curl -sSL https://download.farcaster.xyz/bootstrap-replicator.sh | bash
20 | ```
21 |
22 | Once the Docker images have finished downloading, you should start to see messages like:
23 |
24 | ```
25 | [13:24:18.141] INFO (73940): Backfill 13.42% complete. Estimated time remaining: 46 minutes, 41 seconds
26 | [13:24:23.228] INFO (73940): Backfill 13.52% complete. Estimated time remaining: 46 minutes, 50 seconds
27 | [13:24:28.389] INFO (73940): Backfill 13.60% complete. Estimated time remaining: 47 minutes, 3 seconds
28 | [13:24:33.502] INFO (73940): Backfill 13.71% complete. Estimated time remaining: 47 minutes, 10 seconds
29 | ```
30 |
31 | First time sync can take a couple of hours to a day, depending on how powerful your machine is.
32 |
33 | ## Connecting to postgres
34 |
35 | ```bash
36 | cd ~/replicator
37 | # Via docker
38 | docker compose exec postgres psql -U replicator replicator
39 | # Or directly, using the default port for the replicator docker container
40 | psql -U replicator -h localhost -p 6541 replicator
41 | ```
42 |
43 | ## Querying the data
44 |
45 | Get the 10 most recents casts for a user
46 |
47 | ```sql
48 | select timestamp, text, mentions, mentions_positions, embeds
49 | from casts
50 | where fid = 1
51 | order by timestamp desc
52 | limit 10;
53 | ```
54 |
55 | ## Schema
56 |
57 | For more information on the schema, see the [replicator schema](/reference/replicator/schema).
58 |
--------------------------------------------------------------------------------
/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/www) | 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 |
33 | ## Community
34 |
35 | - [Developer Telegram](https://t.me/farcasterdevchat) - Public chat for developer support.
36 |
--------------------------------------------------------------------------------
/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 be can 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/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: viem(),
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 = authClient.parseSignInURI({
11 | uri: 'farcaster://connect?channelToken=76be6229-bdf7-4ad2-930a-540fb2de1e08&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 UUID. |
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/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, viemConnecter } from '@farcaster/auth-client';
9 |
10 | const walletClient = createWalletClient({
11 | relay: 'https://relay.farcaster.xyz',
12 | ethereum: viem(),
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/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/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | next:
3 | text: 'Create Your Account'
4 | link: '/learn/what-is-farcaster/accounts'
5 | ---
6 |
7 | # Getting Started
8 |
9 | Farcaster is a [sufficiently decentralized](https://www.varunsrinivasan.com/2022/01/11/sufficient-decentralization-for-social-networks) social network built on Ethereum.
10 |
11 | It is a public social network similar to Twitter 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.
12 |
13 | :::tip Join Farcaster
14 | If you're not on Farcaster, get started by [creating your account](https://www.warpcast.com/) with Warpcast.
15 | :::
16 |
17 | ## Learn
18 |
19 | If you want to learn more, get started by diving into these concepts:
20 |
21 | - [Farcaster 101](https://www.youtube.com/playlist?list=PL0eq1PLf6eUdm35v_840EGLXkVJDhxhcF) - a walkthrough of the Farcaster protocol in short, 5 minute videos.
22 | - [Core Concepts](./learn/what-is-farcaster/accounts.md) - learn about the building blocks of Farcaster, starting with accounts.
23 | - [Architecture](./learn/architecture/overview.md) - a breakdown of Farcaster's onchain and offchain systems.
24 |
25 | ## Tutorials
26 |
27 | - [Build your first frame](./developers/guides/frames/poll.md) - Make mini-apps that run inside Farcaster.
28 | - [Sign in with Farcaster](./auth-kit/installation.md) - Let users login to your app with their Farcaster account.
29 | - [Write your first app](./developers/index.md) - Publish a "Hello World" message to Farcaster.
30 |
31 | Find more how-tos, guide and tutorials like this in the [developers](./developers/) section.
32 |
33 | ## Documentation
34 |
35 | - [Farcaster Spec](https://github.com/farcasterxyz/protocol) - Specifications for Farcaster, including its contracts and hubs.
36 | - [Frame Spec](./reference/frames/spec.md) - Specifications for writing and rendering frames in Farcaster apps.
37 | - [APIs](./reference/index) - Docs for API's and ABI's for onchain and offchain systems.
38 |
39 | ## Contributing
40 |
41 | To learn about how to contribute to the protocol, including this documentation site, check out
42 | the [Contributing](./learn/contributing/overview.md) section.
43 |
--------------------------------------------------------------------------------
/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/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/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/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 is force 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 it's peers. If this is less than 100%, try restarting the hub and waiting a while. If
55 | this
56 | persists, reach out on the [Developer Chat](https://t.me/farcasterdevchat) or file an issue on
57 | the [hub repo](https://github.com/farcasterxyz/hub-monorepo/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=bug%20%28hubble%29%3A).
58 |
59 | ## Managing your Peer ID
60 |
61 | 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.
62 |
--------------------------------------------------------------------------------
/docs/reference/contracts/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | Farcaster contracts are deployed on Optimism, an Ethereum layer 2 network. There are three core contracts:
4 | Id Registry, Key Registry, and Storage Registry. Write access to the ID and Key registry is gated through the Gateway
5 | contracts. There is also a Bundler helper contract to make it easy to register an fid, add a key and rent storage in one
6 | transaction.
7 |
8 | 
9 |
10 | ## Id Registry
11 |
12 | The Id Registry contract is used to keep track of Farcaster IDs. It maps an fid to an owning Ethereum
13 | address. The owner can also designate a "recovery address" which can be used to recover the fid if the owner loses
14 | access to the registering address. Registering an fid for the first time must be done through
15 | the [ID Gateway](#idgateway).
16 |
17 | ## Key Registry
18 |
19 | The Key Registry associates a Farcaster id to zero or more ed2559 public keys. Only messages signed by a key registered
20 | here are considered valid by the hubs. Registered keys can be revoked by the owner of the fid, but revoked keys can not
21 | be added to that fid again. The same key may be registered to multiple fids. Adding a key must be done through the
22 | [Key Gateway](#keygateway).
23 |
24 | ## Storage Registry
25 |
26 | The Storage Registry allows an fid to rent one or more "units" of storage on the farcaster network. The current cost of
27 | storage is 7$ USD per unit, for one year. This fee must be paid in ETH. The storage registry uses an ETH price oracle to
28 | determine the current cost in ETH and exposes functions to query this price. Overpayments are refunded to the caller.
29 |
30 | ## IdGateway
31 |
32 | The ID Gateway handles additional logic required for first time registration of an fid. To prevent spam, the
33 | gateway also requires renting 1 unit of storage.
34 |
35 | ## KeyGateway
36 |
37 | Similarly, the Key Gateway exists for the Key Registry. Adding a key to a fid must be done via the gateway.
38 |
39 | ## Bundler
40 |
41 | The Bundler makes first time sign up easier by allowing a user to register an fid, add a key and rent storage in one
42 | function call.
43 |
44 | ## Source code
45 |
46 | The contracts source repo can be found [here](https://github.com/farcasterxyz/contracts), including more low level
47 | documentation [here](https://github.com/farcasterxyz/contracts/blob/main/docs/docs.md).
48 |
--------------------------------------------------------------------------------
/docs/developers/guides/frames/poll.md:
--------------------------------------------------------------------------------
1 | # Creating a poll frame
2 |
3 | Frames can be used to create a poll that renders in a Farcaster feed.
4 |
5 | 
6 |
7 | ::: tip
8 | A working example of a poll frame server can be found [here](https://github.com/farcasterxyz/fc-polls).
9 | :::
10 |
11 | ### Creating the initial frame
12 |
13 | A Frame is created with simple OpenGraph tags. To create the poll screen above, create a URL which returns the following metadata:
14 |
15 | ```html
16 |
17 |
18 |
19 |
20 |
21 |
22 | ```
23 |
24 | If you share the URL in a cast, it will show up as a frame. To test that the frame works without casting, try the Warpcast [Frame Tools](https://warpcast.com/~/developers/frames).
25 |
26 | ### Parsing button clicks
27 |
28 | Warpcast sends a POST to the URL with the button id, user’s fid and other useful information when a button is clicked. The data is available in an unsigned form (untrustedData) and a signed form (trustedData).
29 |
30 | Polls require data to be signed so that we know that the vote wasn’t spoofed. The trusted data must be unpacked using the `verifiedMessage` endpoint on a Hub, and only data returned from that endpoint must be used. The untrusted data should be discarded and never trusted. Some apps that do not care about signed data are free to skip verification and use untrusted data.
31 |
32 | ### Responding to button clicks with a new frame
33 |
34 | After the response is verified and the vote is recorded, we need to send the poll results to the user. The server generates an image which shows the results of the poll with a tool like [satori](https://github.com/vercel/satori). It then responds to the POST with a 200 OK which includes a new frame with the results wrapped in a HTML object. Here’s how you would do this in a framework like Node.js
35 |
36 | ```javascript
37 | res.status(200).send(`
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | `);
46 | ```
47 |
--------------------------------------------------------------------------------
/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 controlled by your wallet. (e.g. @alice.eth)
7 |
8 | ENS names can only be used on Farcaster if they are <= 16 characters and contain only lowercase letters, numbers and hyphens.
9 |
10 | 
11 |
12 | ## Onchain ENS Names
13 |
14 | Users can use onchain ENS names like `@alice.eth` on Farcaster.
15 |
16 | Onchain ENS names are issued by ENS, end in .eth and must be registered on the Ethereum L1 blockchain. Anyone can register an ENS name by using the [ENS app](https://app.ens.domains/).
17 |
18 | Users must pay a fee to register an onchain ENS name, but once registered it is controlled by the user and cannot be revoked.
19 |
20 | ## Offchain ENS Names (Fnames)
21 |
22 | Users can use offchain ENS names like `@alice` on Farcaster.
23 |
24 | Offchain ENS names, also called Farcaster Names or fnames, are compliant with ENS but registered offchain. Fnames are free but are subject to a usage policy to prevent squatting and impersonation. They are also subject to the following requirements:
25 |
26 | 1. An account can only have one fname at a time.
27 | 2. An account can change its fname once every 28 days.
28 |
29 | ### Usage Policy
30 |
31 | Registering an fname is free but subject to the following policy:
32 |
33 | 1. Names connected to public figures or entities may be reclaimed (e.g. @google).
34 | 2. Names that haven't been used for 60+ days may be reclaimed.
35 | 3. Names that are registered for the sole purpose of resale may be reclaimed.
36 |
37 | Decisions are made by the Farcaster team and often require human judgement. 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/contracts.md:
--------------------------------------------------------------------------------
1 | # Contracts
2 |
3 | A Farcaster account is managed and secured onchain using the Farcaster contracts. This section provides a high level overview and avoids some implementation details. For the full picture, see the [contracts repository](https://github.com/farcasterxyz/contracts/).
4 |
5 |
6 |
7 | There are three main contracts deployed on OP Mainnet:
8 |
9 | - **Id Registry** - creates new accounts
10 | - **Storage Registry** - rents storage to accounts
11 | - **Key Registry** - adds and removes app keys from accounts
12 |
13 |
14 |
15 | 
16 |
17 | The contracts are deployed at the following addresses:
18 |
19 | | Contract | Address |
20 | | --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
21 | | IdRegistry | [0x00000000fc6c5f01fc30151999387bb99a9f489b](https://optimistic.etherscan.io/address/0x00000000fc6c5f01fc30151999387bb99a9f489b) |
22 | | StorageRegistry | [0x00000000fcce7f938e7ae6d3c335bd6a1a7c593d](https://optimistic.etherscan.io/address/0x00000000fcce7f938e7ae6d3c335bd6a1a7c593d) |
23 | | KeyRegistry | [0x00000000fc1237824fb747abde0ff18990e59b7e](https://optimistic.etherscan.io/address/0x00000000fc1237824fb747abde0ff18990e59b7e) |
24 |
25 | ### Id Registry
26 |
27 | The IdRegistry lets users register, transfer and recover Farcaster accounts. An account is identified by a unique number (the fid) which is assigned to an Ethereum address on registration. An Ethereum address may only own one account at a time, though it may transfer it freely to other accounts. It may also specify a recovery address which can transfer the account at any time.
28 |
29 | ### Storage Registry
30 |
31 | The Storage Registry lets accounts rent [storage](../what-is-farcaster/messages.md#storage) by making a payment in Ethereum. 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/what-is-farcaster/frames.md:
--------------------------------------------------------------------------------
1 | # Frames
2 |
3 | A Frame lets you turn any cast into an interactive app.
4 |
5 | It’s a standard for creating interactive and authenticated experiences on Farcaster. Create polls, live feeds or interactive galleries inside Warpcast or any other FC client.
6 |
7 | Frames extend the OpenGraph standard and turn static embeds into interactive experiences. The diagram below shows the difference between a standard OG and a Frame OG inside Warpcast.
8 |
9 | 
10 |
11 | Creating a frame is simple — choose an image to show and add buttons the user can click on. If a button is clicked, you get a callback and can send another image with more buttons.
12 |
13 | ## Resources
14 |
15 | A collection of the most popular utilities for creating and managing frames.
16 |
17 | ### Learning
18 |
19 | - [Specification](../../reference/frames/spec.md) - A formal specification for the Frame standard.
20 | - [Video: Frames 101](https://youtu.be/rp9X8rAPzPM?si=PWm3vBFCTtaoE_Ua) - A beginner's guide to frames.
21 | - [Tutorial: Polls](../../developers/guides/frames/poll.md) - Create a simple poll with frames.
22 |
23 | ### Tools
24 |
25 | - [Vercel OG](https://vercel.com/docs/functions/og-image-generation) - Use satori and resvg-js to generate PNG images from HTML and CSS.
26 | - [Warpcast Frame Validator](https://warpcast.com/~/developers/frames) - A debugger for testing frames in Warpcast UI.
27 | - [Neynar](https://docs.neynar.com/docs/how-to-build-farcaster-frames-with-neynar) - Infrastructure and tools for frame servers.
28 |
29 | ### Frameworks
30 |
31 | - [onchainkit](https://github.com/coinbase/onchainkit) - A React toolkit to create frames
32 | - [frames.js](https://framesjs.org/) - A Next.js template for building and debugging frames.
33 | - [Simplest Frame](https://github.com/depatchedmode/simplest-frame) - a zero-framework frame template.
34 | - [frog](https://frog.fm) - framework for frames.
35 |
36 | ### Examples
37 |
38 | - [Linktree](https://replit.com/@soren/Linktree-Frame?v=1) - a simple frame that links to four other pages.
39 | - [Onchain Cow](https://github.com/WillPapper/On-Chain-Cow-Farcaster-Frame) - a cow clicker-like game.
40 | - [FC Polls](https://github.com/farcasterxyz/fc-polls) - create and run polls within frames.
41 | - [Claim or Mint](https://github.com/horsefacts/base-mint-with-warps) - lets users claim an NFT if the meet certain criteria.
42 |
43 |
44 |
45 | A more detailed list of resources can be found at [awesome-frames](https://github.com/davidfurlong/awesome-frames).
46 |
--------------------------------------------------------------------------------
/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 Warpcast 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 | ### Warpcast
17 |
18 | Warpcast 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/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/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/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 |
25 | ## Returns
26 |
27 | ```ts
28 | {
29 | response: Response;
30 | data: {
31 | channelToken: string;
32 | url: string;
33 | nonce: string;
34 | }
35 | isError: boolean;
36 | error: Error;
37 | }
38 | ```
39 |
40 | | Parameter | Description |
41 | | ------------------- | ---------------------------------------------------------------------------------- |
42 | | `response` | HTTP response from the Connect relay server. |
43 | | `data.channelToken` | Connect relay channel token UUID. |
44 | | `data.url` | Sign in With Farcaster URL to present to the user. Links to Warpcast client in v1. |
45 | | `data.nonce` | Random nonce included in the Sign in With Farcaster message. |
46 | | `isError` | True when an error has occurred. |
47 | | `error` | `Error` instance. |
48 |
--------------------------------------------------------------------------------
/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 | });
14 | ```
15 |
16 | ## Parameters
17 |
18 | | Parameter | Type | Description | Required |
19 | | ----------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
20 | | `domain` | `string` | Domain of your application. Must match the domain in the provided SIWF message. | Yes |
21 | | `nonce` | `string` | A custom nonce. Must match the nonce in the provided SIWF message. | Yes |
22 | | `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 |
23 | | `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 |
24 |
25 | ## Returns
26 |
27 | ```ts
28 | {
29 | data: SiweMessage,
30 | success: boolean,
31 | fid: number
32 | isError: boolean
33 | error: Error
34 | }
35 | ```
36 |
37 | | Parameter | Description |
38 | | --------- | ----------------------------------------------- |
39 | | `data` | Parsed SIWF message, as a `SiweMessage` object. |
40 | | `success` | True if provided signature is valid. |
41 | | `fid` | FID of the user. |
42 | | `isError` | True when an error has occurred. |
43 | | `error` | `Error` instance. |
44 |
--------------------------------------------------------------------------------
/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/auth-kit/sign-in-button.md:
--------------------------------------------------------------------------------
1 | # `SignInButton`
2 |
3 | The main component. Renders a "Sign in With Farcaster" button that prompts the user to scan a QR code with their phone in a web browser or redirects on a mobile device. You can use the `onSuccess` callback prop or the `useProfile` hook to access the user's authentication status and profile information.
4 |
5 | **Note:** Make sure you've wrapped your application in an [`AuthKitProvider`](./auth-kit-provider.md) to use the `SignInButton` component.
6 |
7 | ```tsx
8 | import { SignInButton } from '@farcaster/auth-kit';
9 |
10 | export const Login = () => {
11 | return (
12 |
14 | console.log(`Hello, ${username}! Your fid is ${fid}.`)
15 | }
16 | />
17 | );
18 | };
19 | ```
20 |
21 | ## Props
22 |
23 | | Prop | Type | Description | Default |
24 | | ------------------ | ---------- | ----------------------------------------------------------------------------------- | --------------------- |
25 | | `timeout` | `number` | Return an error after polling for this long. | `300_000` (5 minutes) |
26 | | `interval` | `number` | Poll the relay server for updates at this interval. | `1500` (1.5 seconds) |
27 | | `nonce` | `string` | A random nonce to include in the Sign In With Farcaster message. | None |
28 | | `notBefore` | `string` | Time when the message becomes valid. ISO 8601 datetime string. | None |
29 | | `expirationTime` | `string` | Time when the message expires. ISO 8601 datetime string. | None |
30 | | `requestId` | `string` | An optional system-specific ID to include in the message. | None |
31 | | `onSuccess` | `function` | Callback invoked when sign in is complete and the user is authenticated. | None |
32 | | `onStatusResponse` | `function` | Callback invoked when the component receives a status update from the relay server. | None |
33 | | `onError` | `function` | Error callback function. | None |
34 | | `onSignOut` | `function` | Callback invoked when the user signs out. | None |
35 | | `hideSignOut` | `function` | Hide the Sign out button. | `false` |
36 | | `debug` | `boolean` | Render a debug panel displaying internal auth-kit state. | `false` |
37 |
38 | ## Examples
39 |
40 | ### Custom nonce
41 |
42 | ```tsx
43 | import { SignInButton } from '@farcaster/auth-kit';
44 |
45 | export const Login = ({ nonce }: { nonce: string }) => {
46 | return (
47 |
50 | console.log(`Hello, ${username}! Your fid is ${fid}.`)
51 | }
52 | />
53 | );
54 | };
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/developers/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 etehreurm 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://twitter.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://twitter.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://twitter.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://twitter.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/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 walletClient.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: 'nonce',
88 | args: [account],
89 | });
90 | };
91 | ```
92 |
93 | <<< @/examples/contracts/clients.ts
94 |
95 | :::
96 |
97 | ::: warning
98 | Transferring an fid does not reset its recovery address. To transfer an 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/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. A 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/architecture/hubs.md:
--------------------------------------------------------------------------------
1 | # Hubs
2 |
3 | Hubs are a distributed network of servers that store and validate Farcaster data.
4 |
5 | A computer can run software to become a Farcaster hub. It will download onchain Farcaster data from Ethereum and offchain Farcaster data from other Hubs. Each Hub stores a copy of all Farcaster data which can be accessed over an API.
6 |
7 | Hubs let you read and write data to Farcaster, and anyone building a Farcaster app will need to talk to one. Anyone can run a Hub on their laptop or on a cloud server. A full guide to setting up and running a Hub is available [here](https://www.thehubble.xyz).
8 |
9 | ## Design
10 |
11 | A Hub starts by syncing data from Farcaster contracts on the Optimism blockchain. It becomes aware of every user's account and their account keys.
12 |
13 | The lifecycle of a Farcaster message looks like this:
14 |
15 | 1. Alice creates a new "Hello World!" message.
16 | 2. Alice (or her app) signs the message with an account key.
17 | 3. Alice (or her app) uploads the message to a Hub.
18 | 4. The hub checks the message's validity.
19 | 5. The hub sends the message to peer hubs over gossip.
20 |
21 | 
22 |
23 | ### Validation
24 |
25 | Alice's message is validated by checking that it has a valid signature from one of her account keys. The hub also ensures that the message obeys the requirements of the message type. for example, a public message or "cast" must be less than 320 bytes. Message type requirements are specified in detail in the protocol spec
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. 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. Warpcast, a company building on Farcaster, gives Hub runners minor rewards but may change this in the future.
62 |
--------------------------------------------------------------------------------
/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 [Warpcast](https://www.warpcast.com/), a special Farcaster wallet 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 Warpcast 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/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 Warpcast 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 Warpcast 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 Warpcast while channels are in the experimental stage.
21 |
22 | ## Casting in Channels
23 |
24 | Anyone can post into a channel by using Warpcast and selecting the channel when creating the cast. Warpcast automatically sets the cast's `parentUrl` to `https://warpcast.com/~/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 Warpcast.
31 |
32 | Channel follows are not part of the protocol and are stored in Warpcast while channels are in the experimental stage.
33 |
34 | ## Cast Visibility
35 |
36 | If a user casts in a channel, Warpcast 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 | Warpcast 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 Warpcast'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. Warpcast 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 | - [Warpcast Channel APIs](../../reference/warpcast/api.md) - fetch a list of all known channels
74 |
--------------------------------------------------------------------------------
/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/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 } = authClient.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 serizalized as a string. |
47 | | `isError` | True when an error has occurred. |
48 | | `error` | `Error` instance. |
49 |
--------------------------------------------------------------------------------
/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 messsage, 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/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 authClient.authenticate({
7 | message: 'example.com wants you to sign in with your Ethereum account…',
8 | signature: '0x9335c3055d47780411a3fdabad293c68c84ea350a11794cdc811fd5…',
9 | fid: 1,
10 | username: 'alice',
11 | bio: "I'm a little teapot who didn't fill out my bio",
12 | displayName: 'Alice Teapot',
13 | pfpUrl: 'https://images.example.com/profile.png',
14 | });
15 | ```
16 |
17 | ## Parameters
18 |
19 | | Parameter | Type | Description | Required |
20 | | -------------- | -------- | ----------------------------------------------------------------------------------------- | -------- |
21 | | `authKey` | `string` | Farcaster Auth API key. Farcaster Auth v1 restricts calls to `/authenticate` to Warpcast. | Yes |
22 | | `channelToken` | `string` | Farcaster Auth channel token. | Yes |
23 | | `message` | `string` | The Sign in With Farcaster message produced by your wallet app and signed by the user. | 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 | | `fid` | `number` | Wallet user's fid. | Yes |
27 | | `username` | `string` | Wallet user's Farcaster username. | Yes |
28 | | `bio` | `string` | Wallet user's bio. | Yes |
29 | | `displayName` | `string` | Wallet user's display name. | Yes |
30 | | `pfpUrl` | `string` | Wallet user's profile photo URL. | Yes |
31 |
32 | ## Returns
33 |
34 | ```ts
35 | {
36 | response: Response
37 | data: {
38 | state: 'completed'
39 | nonce: string
40 | message?: string
41 | signature?: `Hex`
42 | fid?: number
43 | username?: string
44 | bio?: string
45 | displayName?: string
46 | pfpUrl?: string
47 | }
48 | isError: boolean
49 | error: Error
50 | }
51 | ```
52 |
53 | | Parameter | Description |
54 | | ------------------ | ----------------------------------------------------------------- |
55 | | `response` | HTTP response from the Connect relay server. |
56 | | `data.state` | Status of the sign in request, either `"pending"` or `"complete"` |
57 | | `data.nonce` | Random nonce used in the SIWE message. |
58 | | `data.message` | The generated SIWE message. |
59 | | `data.signature` | Hex signature produced by the user's Warpcast wallet. |
60 | | `data.fid` | User's Farcaster ID. |
61 | | `data.username` | User's Farcaster username. |
62 | | `data.bio` | User's Farcaster bio. |
63 | | `data.displayName` | User's Farcaster display name. |
64 | | `data.pfpUrl` | User's Farcaster profile picture URL. |
65 | | `isError` | True when an error has occurred. |
66 | | `error` | `Error` instance. |
67 |
--------------------------------------------------------------------------------
/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. Names must be less than 17 characters with only lowercase alphabets, numbers or hyphens to prevent homoglyph attacks.
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 Warpcast to set this up for you.
21 |
22 | 
23 |
24 | ### Offchain ENS Names
25 |
26 | - Offchain ENS names, also called fnames, are free and issued by Farcaster.
27 | - Any Ethereum account can get one unique fname by calling the [Fname Registry](/learn/architecture/ens-names).
28 | - Fnames are free but they can be revoked by Farcaster at any time.
29 |
30 | ### Onchain ENS fnames
31 |
32 | - Onchain ENS names, also called .eth names, are onchain and issued by ENS.
33 | - Any Ethereum account can get an ENS by calling the [ENS Registry](https://docs.ens.domains/dapp-developer-guide/the-ens-registry).
34 | - Names are not free but they cannot be revoked by Farcaster.
35 |
36 | ## Resources
37 |
38 | ### Specifications
39 |
40 | - [Farcaster Name](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#5-fname-specifications) - An ENSIP-10 offchain ENS name usable within Farcaster.
41 | - [UserData: Username](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#23-user-data) - Sets a valid Username Proof as the current username.
42 | - [Username Proof](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#17-username-proof) - Proves ownership of an onchain or offchain username.
43 | - [Verifications](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#25-verifications) - Proves ownership of an address, required for onchain Username Proofs.
44 |
45 | ### APIs
46 |
47 | - [UserData API](../../reference/hubble/httpapi/userdata) - Fetch the UserData for a user's current username.
48 | - [Username Proofs API](../../reference/hubble/httpapi/usernameproof) - Fetch a user's Username Proofs from a hub.
49 | - [Verification Proofs API](../../reference/hubble/httpapi/verification) - Fetch a user's Verifications from a hub.
50 | - [Fname Registry API](../../reference/fname/api.md) - Register and track fname ownership programatically.
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/auth-kit/client/app/status.md:
--------------------------------------------------------------------------------
1 | # `status`
2 |
3 | Get current status of a Farcaster Auth request.
4 |
5 | Returns the current state of the request, either `'pending'` if the user's Farcaster wallet app has not yet sent back a signature, or `'completed'` once the wallet app has returned a response.
6 |
7 | In `'completed'` state, the response includes the generated Sign in With Farcaster message, a signature from the user's custody address, the user's verified fid, and user profile information.
8 |
9 | ```ts
10 | const status = await appClient.status({
11 | channelToken: '210f1718-427e-46a4-99e3-2207f21f83ec',
12 | });
13 | ```
14 |
15 | ## Parameters
16 |
17 | | Parameter | Type | Description | Required | Example |
18 | | -------------- | -------- | ----------------------------- | -------- | -------------------------------------- |
19 | | `channelToken` | `string` | Farcaster Auth channel token. | Yes | `8d0494d9-e0cf-402b-ab0a-394ac7fe07a0` |
20 |
21 | ## Returns
22 |
23 | ```ts
24 | {
25 | response: Response
26 | data: {
27 | state: 'pending' | 'completed'
28 | nonce: string
29 | message?: string
30 | signature?: Hex
31 | fid?: number
32 | username?: string
33 | bio?: string
34 | displayName?: string
35 | pfpUrl?: string
36 | custody?: Hex;
37 | verifications?: Hex[];
38 | }
39 | isError: boolean
40 | error: Error
41 | }
42 | ```
43 |
44 | | Parameter | Description |
45 | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
46 | | `response` | HTTP response from the Connect relay server. |
47 | | `data.state` | Status of the sign in request, either `"pending"` or `"complete"` |
48 | | `data.nonce` | Random nonce used in the SIWE message. If you don't provide a custom nonce as an argument to the hook, you should read this value. |
49 | | `data.message` | The generated SIWE message. |
50 | | `data.signature` | Hex signature produced by the user's Warpcast wallet. |
51 | | `data.fid` | User's Farcaster ID. |
52 | | `data.username` | User's Farcaster username. |
53 | | `data.bio` | User's Farcaster bio. |
54 | | `data.displayName` | User's Farcaster display name. |
55 | | `data.pfpUrl` | User's Farcaster profile picture URL. |
56 | | `data.custody` | User's FID custody address. |
57 | | `data.verifications` | List of user's verified addresses. |
58 | | `isError` | True when an error has occurred. |
59 | | `error` | `Error` instance. |
60 |
--------------------------------------------------------------------------------
/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/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 | An "app fid" is no different than any other Farcaster ID: it just represents an application rather than an individual user. 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.
58 |
--------------------------------------------------------------------------------
/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/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 transfer object:
52 |
53 | ```json
54 | {
55 | "transfer": {
56 | "id": 1,
57 | "timestamp": 1628882891,
58 | "username": "farcaster",
59 | "owner": "0x8773442740c17c9d0f0b87022c722f9a136206ed",
60 | "from": 0,
61 | "to": 1,
62 | "user_signature": "0xa6fdd2a69deab5633636f32a30a54b21b27dff123e6481532746eadca18cd84048488a98ca4aaf90f4d29b7e181c4540b360ba0721b928e50ffcd495734ef8471b",
63 | "server_signature": "0xb7181760f14eda0028e0b647ff15f45235526ced3b4ae07fcce06141b73d32960d3253776e62f761363fb8137087192047763f4af838950a96f3885f3c2289c41b"
64 | }
65 | }
66 | ```
67 |
68 | ### Register or transfer an fname
69 |
70 | To register a new fid, e.g. `hubble`, first make sure the fname is not already registered.
71 |
72 | Then make a POST request to `/transfers` with the following body:
73 |
74 | ```yaml
75 | {
76 | "name": "hubble", // Name to register
77 | "from": 0, // Fid to transfer from (0 for a new registration)
78 | "to": 123, // Fid to transfer to (0 to unregister)
79 | "fid": 123, // Fid making the request (must match from or to)
80 | "owner": "0x...", // Custody address of fid making the request
81 | "timestamp": 1641234567, // Current timestamp in seconds
82 | "signature": "0x..." // EIP-712 signature signed by the custody address of the fid
83 | }
84 | ```
85 |
86 | To generate the EIP-712 signature, use the following code:
87 |
88 | ```js
89 | import { makeUserNameProofClaim, EIP712Signer } from '@farcaster/hub-nodejs';
90 |
91 | const accountKey: EIP712Signer = undefined; // Account key for the custody address (use appropriate subclass from hub-nodejs for ethers or viem)
92 |
93 | const claim = makeUserNameProofClaim({
94 | name: 'hubble',
95 | owner: '0x...',
96 | timestamp: Math.floor(Date.now() / 1000),
97 | });
98 | const signature = (
99 | await accountKey.signUserNameProofClaim(claim)
100 | )._unsafeUnwrap();
101 | ```
102 |
103 | This is the exact same kind of signature used in the ENS UsernameProofs provided to hubs to prove ownership of an ENS
104 | name.
105 |
106 | e.g.
107 |
108 | ```bash
109 | curl -X POST https://fnames.farcaster.xyz/transfers \
110 | -H "Content-Type: application/json" \
111 | -d \
112 | '{"name": "hubble", "owner": "0x...", "signature": "0x...", "from": 0, "to": 1000, "timestamp": 1641234567, fid: 1000}'
113 | ```
114 |
115 | Once a name is registered, it still needs a [UserData](/reference/hubble/datatypes/messages#_2-userdata) message
116 | to be sent to the hub in order to actually
117 | set the username for the user. See examples in
118 | the [hub-nodejs](https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/hub-nodejs/examples/hello-world) repo.
119 |
--------------------------------------------------------------------------------
/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, emoji, 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 | Emoji 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 emoji 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/messages.md:
--------------------------------------------------------------------------------
1 | # Create messages
2 |
3 | A message represents an action taken by a user (e.g. alice says "hello world")
4 |
5 | There are many types of messages, and this tutorial will walk you through the most common ones. Other tutorials will cover the more advanced message types.
6 |
7 | ## Setup
8 |
9 | You will need:
10 |
11 | - Write access to a hubble instance
12 | - Private key of a signer registered to an fid
13 | - `hub-nodejs` and helper functions imported and shown below
14 |
15 | ```ts
16 | import {
17 | makeCastAdd,
18 | makeCastRemove,
19 | makeLinkAdd,
20 | makeLinkRemove,
21 | makeReactionAdd,
22 | makeReactionRemove,
23 | makeUserDataAdd,
24 | NobleEd25519Signer,
25 | FarcasterNetwork,
26 | } from '@farcaster/hub-nodejs';
27 |
28 | const ACCOUNT_PRIVATE_KEY: Hex = '0x...'; // Your account key's private key
29 | const FID = -1; // Your fid
30 | const ed25519Signer = new NobleEd25519Signer(ACCOUNT_PRIVATE_KEY);
31 | const dataOptions = {
32 | fid: FID,
33 | network: FC_NETWORK,
34 | };
35 | const FC_NETWORK = FarcasterNetwork.MAINNET;
36 | ```
37 |
38 | ## Casts
39 |
40 | Casts are public messages created by a user.
41 |
42 | A cast is created by issuing a CastAdd message with the text of the cast and optional embeds, mentions, and emoji. The example below shows the creation of a simple cast.
43 |
44 | ```typescript
45 | const cast = await makeCastAdd(
46 | {
47 | text: 'This is a cast!', // Text can be up to 320 bytes long
48 | embeds: [],
49 | embedsDeprecated: [],
50 | mentions: [],
51 | mentionsPositions: [],
52 | },
53 | dataOptions,
54 | ed25519Signer
55 | );
56 | ```
57 |
58 | A cast can be removed by issuing a CastRemove message with the hash of the CastAdd message and a later timestamp.
59 |
60 | ```typescript
61 | const castRemove = await makeCastRemove(
62 | {
63 | targetHash: castReplyingToAUrl._unsafeUnwrap().hash,
64 | },
65 | dataOptions,
66 | ed25519Signer
67 | );
68 | ```
69 |
70 | To create casts with embeds, mentions, channels emoji, see the [casts](../writing/casts.md) tutorial.
71 |
72 | ## Reactions
73 |
74 | Reactions are strongly typed relationships between a user and a cast (e.g. a like).
75 |
76 | A user "likes" a cast by producing a ReactionAdd message with type set to `like` and the target set to the hash of the cast and the fid of it's author.
77 |
78 | ```typescript
79 | const reactionAdd = await makeReactionAdd(
80 | {
81 | type: ReactionType.LIKE,
82 | targetCastId: { fid: createdCast.data.fid, hash: createdCast.hash },
83 | },
84 | dataOptions,
85 | ed25519Signer
86 | );
87 | ```
88 |
89 | The like can be negated by broadcasting a ReactionRemove message with the information and a later timestamp.
90 |
91 | ```typescript
92 | const reactionRemove = await makeReactionRemove(
93 | {
94 | type: ReactionType.LIKE,
95 | targetCastId: { fid: createdCast.data.fid, hash: createdCast.hash },
96 | },
97 | dataOptions, // Timestamp provided must be higher
98 | ed25519Signer
99 | );
100 | ```
101 |
102 | A user can "recast" with a very similar process.
103 |
104 | ```typescript
105 | const recastAdd = await makeReactionAdd(
106 | {
107 | type: ReactionType.RECAST,
108 | targetCastId: { fid: createdCast.data.fid, hash: createdCast.hash },
109 | },
110 | dataOptions,
111 | ed25519Signer
112 | );
113 |
114 | const recastRemove = await makeReactionRemove(
115 | {
116 | type: ReactionType.RECAST,
117 | targetCastId: { fid: createdCast.data.fid, hash: createdCast.hash },
118 | },
119 | dataOptions,
120 | ed25519Signer
121 | );
122 | ```
123 |
124 | ## User Data
125 |
126 | UserData is a strongly typed set of messages that represent metadata about a user (e.g. bio, profile picture).
127 |
128 | A `UserData` message has a type and a string value which can be set. The example below shows a user updating their bio.
129 |
130 | ```typescript
131 | // Update user bio. Other fields are similar, just change the type. Value is always a string.
132 | const bioUpdate = await makeUserDataAdd(
133 | {
134 | type: UserDataType.BIO,
135 | value: 'new bio',
136 | },
137 | dataOptions,
138 | ed25519Signer
139 | );
140 | ```
141 |
142 | ## Links
143 |
144 | Links are loosely typed relationships between users (e.g. alice follows bob).
145 |
146 | A user creates a Link by issuing a LinkAdd message with a string type and the target user's fid. The most commonly supported link on all clients is 'follow'.
147 |
148 | ```typescript
149 | const follow = await makeLinkAdd(
150 | {
151 | type: 'follow',
152 | targetFid: 1,
153 | },
154 | dataOptions,
155 | ed25519Signer
156 | );
157 |
158 | const unfollow = await makeLinkRemove(
159 | {
160 | type: 'unfollow',
161 | targetFid: 1,
162 | },
163 | dataOptions,
164 | ed25519Signer
165 | );
166 | ```
167 |
--------------------------------------------------------------------------------
/docs/reference/hubble/grpcapi/sync.md:
--------------------------------------------------------------------------------
1 | # Sync API
2 |
3 | These APIs are used by Hubs to synchronize their state with other Hubs. Not meant for use by external applications.
4 |
5 | ## API
6 |
7 | | Method Name | Request Type | Response Type | Description |
8 | | ----------------------- | ----------------- | ------------------------ | --------------------------------------------- |
9 | | GetInfo | HubInfoRequest | HubInfoResponse | Returns metadata about the hub's state. |
10 | | GetSyncStatus | SyncStatusRequest | SyncStatusResponse | Returns the hub's sync status. |
11 | | GetAllSyncIdsByPrefix | TrieNodePrefix | SyncIds | Get all the SyncIds for a particular prefix |
12 | | GetAllMessagesBySyncIds | SyncIds | MessagesResponse | Get all messages given corresponding sync ids |
13 | | GetSyncMetadataByPrefix | TrieNodePrefix | TrieNodeMetadataResponse | Get Sync metadata for a particular prefix |
14 | | GetSyncSnapshotByPrefix | TrieNodePrefix | TrieNodeSnapshotResponse | Get sync snapshot for a particular prefix |
15 |
16 | ## HubInfoRequest
17 |
18 | | Field | Type | Label | Description |
19 | | -------- | ------------- | ----- | ----------- |
20 | | db_stats | [bool](#bool) | | |
21 |
22 | ## HubInfoResponse
23 |
24 | Response Types for the Sync RPC Methods
25 |
26 | | Field | Type | Label | Description |
27 | | ---------- | ------------------- | ----- | ----------- |
28 | | version | [string](#string) | | |
29 | | is_syncing | [bool](#bool) | | |
30 | | nickname | [string](#string) | | |
31 | | root_hash | [string](#string) | | |
32 | | db_stats | [DbStats](#DbStats) | | |
33 |
34 | ## SyncStatusRequest
35 |
36 | | Field | Type | Label | Description |
37 | | ------ | ----------------- | -------- | ----------- |
38 | | peerId | [string](#string) | optional | |
39 |
40 | ## SyncStatusResponse
41 |
42 | | Field | Type | Label | Description |
43 | | ----------- | ------------------------- | -------- | ----------- |
44 | | is_syncing | [bool](#bool) | | |
45 | | sync_status | [SyncStatus](#SyncStatus) | repeated | |
46 |
47 | ## SyncStatus
48 |
49 | | Field | Type | Label | Description |
50 | | -------------------- | ----------------- | ----- | ----------- |
51 | | peerId | [string](#string) | | |
52 | | inSync | [string](#string) | | |
53 | | shouldSync | [bool](#bool) | | |
54 | | divergencePrefix | [string](#string) | | |
55 | | divergenceSecondsAgo | [int32](#int32) | | |
56 | | theirMessages | [uint64](#uint64) | | |
57 | | ourMessages | [uint64](#uint64) | | |
58 | | lastBadSync | [int64](#int64) | | |
59 |
60 | ## TrieNodePrefix
61 |
62 | | Field | Type | Label | Description |
63 | | ------ | --------------- | ----- | ----------- |
64 | | prefix | [bytes](#bytes) | | |
65 |
66 | ## SyncIds
67 |
68 | | Field | Type | Label | Description |
69 | | -------- | --------------- | -------- | ----------- |
70 | | sync_ids | [bytes](#bytes) | repeated | |
71 |
72 | ## TrieNodeMetadataResponse
73 |
74 | | Field | Type | Label | Description |
75 | | ------------ | ----------------------------------------------------- | -------- | ----------- |
76 | | prefix | [bytes](#bytes) | | |
77 | | num_messages | [uint64](#uint64) | | |
78 | | hash | [string](#string) | | |
79 | | children | [TrieNodeMetadataResponse](#TrieNodeMetadataResponse) | repeated | |
80 |
81 | ## TrieNodeSnapshotResponse
82 |
83 | | Field | Type | Label | Description |
84 | | --------------- | ----------------- | -------- | ----------- |
85 | | prefix | [bytes](#bytes) | | |
86 | | excluded_hashes | [string](#string) | repeated | |
87 | | num_messages | [uint64](#uint64) | | |
88 | | root_hash | [string](#string) | | |
89 |
90 | ## DbStats
91 |
92 | | Field | Type | Label | Description |
93 | | ---------------- | ----------------- | ----- | ----------- |
94 | | num_messages | [uint64](#uint64) | | |
95 | | num_fid_events | [uint64](#uint64) | | |
96 | | num_fname_events | [uint64](#uint64) | | |
97 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/httpapi.md:
--------------------------------------------------------------------------------
1 | # HTTP API
2 |
3 | Hubble serves a HTTP API on port 2281 by default.
4 |
5 | ## Using the API
6 |
7 | The API can be called from any programing language or browser by making a normal HTTP request.
8 |
9 | **View the API responses in a browser**
10 |
11 | Simply open the URL in a browser
12 |
13 | ```url
14 | http://127.0.0.1:2281/v1/castsByFid?fid=2
15 | ```
16 |
17 | **Call the API using curl**
18 |
19 | ```bash
20 | curl http://127.0.0.1:2281/v1/castsByFid?fid=2
21 | ```
22 |
23 | **Call the API via Javascript, using the axios library**
24 |
25 | ```Javascript
26 | import axios from "axios";
27 |
28 | const fid = 2;
29 | const server = "http://127.0.0.1:2281";
30 |
31 | try {
32 | const response = await axios.get(`${server}/v1/castsByFid?fid=${fid}`);
33 |
34 | console.log(`API Returned HTTP status ${response.status}`);
35 | console.log(`First Cast's text is ${response.messages[0].data.castAddBody.text}`);
36 | } catch (e) {
37 | // Handle errors
38 | console.log(response);
39 | }
40 | ```
41 |
42 | **OpenAPI Spec**
43 |
44 | An OpenAPI spec is provided for the Hubble REST API. It can be viewed [here](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/farcasterxyz/hub-monorepo/main/packages/hub-nodejs/spec.yaml).
45 |
46 | ## Response encoding
47 |
48 | Responses from the API are encoded as `application/json`, and can be parsed as normal JSON objects.
49 |
50 | 1. Hashes, ETH addresses, keys etc... are all encoded as hex strings starting with `0x`
51 | 2. Signatures and other binary fields are encoded in base64
52 | 3. Constants are encoded as their string types. For example, the `hashScheme` is encoded as `HASH_SCHEME_BLAKE3` which is equivalent to the `HASH_SCHEME_BLAKE3 = 1` from the protobuf schema.
53 |
54 | ## Timestamps
55 |
56 | Messages contain timestamps which are seconds since the Farcaster Epoch, which began on Jan 1, 2021 00:00:00 UTC.
57 |
58 | ## Paging
59 |
60 | Most endpoints support paging to get a large number of responses.
61 |
62 | **Pagination Query Parameters**
63 |
64 | | Parameter | Description | Example |
65 | | --------- | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------- |
66 | | pageSize | Maximum number of messages to return in a single response | `pageSize=100` |
67 | | reverse | Reverse the sort order, returning latest messages first | `reverse=1` |
68 | | pageToken | The page token returned by the previous query, to fetch the next page. If this parameters is empty, fetch the first page | `pageToken=AuzO1V0Dta...fStlynsGWT` |
69 |
70 | The returned `nextPageToken` is empty if there are no more pages to return.
71 |
72 | Pagination query parameters can be combined with other query parameters supported by the endpoint. For example, `/v1/casts?fid=2&pageSize=3`.
73 |
74 | **Example**
75 |
76 | Fetch all casts by FID `2`, fetching upto 3 casts per Page
77 |
78 | ```bash
79 | # Fetch first page
80 | http://127.0.0.1:2281/v1/castsByFid?fid=2&pageSize=3
81 |
82 | # Fetch next page. The pageToken is from the previous response(`response.nextPageToken`)
83 | http://127.0.0.1:2281/v1/castsByFid?fid=2&pageSize=3&pageToken=AuzO1V0DtaItCwwa10X6YsfStlynsGWT
84 | ```
85 |
86 | **Javascript Example**
87 |
88 | ```Javascript
89 | import axios from "axios";
90 |
91 | const fid = 2;
92 | const server = "http://127.0.0.1:2281";
93 |
94 | let nextPageToken = "";
95 | do {
96 | const response = await axios.get(`${server}/v1/castsByFid?fid=${fid}&pageSize=100&nextPageToken=${nextPageToken}`);
97 | // Process response....
98 | nextPageToken = response.nextPageToken;
99 | } while (nextPageToken !== "")
100 | ```
101 |
102 | ## Handling Errors
103 |
104 | If there's an API error, the HTTP status code is set to `400` or `500` as appropriate. The response is a JSON object with `detail`, `errCode` and `metadata` fields set to identify and debug the errors.
105 |
106 | **Example**
107 |
108 | ```bash
109 | $ curl "http://127.0.0.1:2281/v1/castById?fid=invalid"
110 | {
111 | "errCode": "bad_request.validation_failure",
112 | "presentable": false,
113 | "name": "HubError",
114 | "code": 3,
115 | "details": "fid must be an integer",
116 | "metadata": {
117 | "errcode": [
118 | "bad_request.validation_failure",
119 | ],
120 | },
121 | }
122 | ```
123 |
124 | ## CORS
125 |
126 | You can set a custom CORS header in the HTTP server by using the `--http-cors-origin` parameter when running your Hubble instance. Setting this to `*` will allow requests from any origin.
127 |
128 | ## Limitations
129 |
130 | The HTTP API currently does not support any of the Sync APIs that are available in the gRPC vesion. When Hubs sync with each other, they will use the gRPC APIs instead of the HTTP APIs.
131 |
--------------------------------------------------------------------------------
/docs/auth-kit/client/app/watch-status.md:
--------------------------------------------------------------------------------
1 | # `watchStatus`
2 |
3 | Poll for the current status of a Farcaster Auth request.
4 |
5 | When the status changes to `'complete'` this action resolves with the final channel value, including the Sign In With Farcaster message, signature, and user profile information.
6 |
7 | ```ts
8 | const status = await appClient.watchStatus({
9 | channelToken: '210f1718-427e-46a4-99e3-2207f21f83ec',
10 | timeout: 60_000,
11 | interval: 1_000,
12 | onResponse: ({ response, data }) => {
13 | console.log('Response code:', response.status);
14 | console.log('Status data:', data);
15 | },
16 | });
17 | ```
18 |
19 | ## Parameters
20 |
21 | | Parameter | Type | Description | Required | Example |
22 | | -------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------- |
23 | | `channelToken` | `string` | Farcaster Auth channel token. | Yes | `8d0494d9-e0cf-402b-ab0a-394ac7fe07a0` |
24 | | `timeout` | `number` | Polling timeout, in milliseconds. If the connect request is not completed before the timeout, `watchStatus` returns an error. | No | `300_000` |
25 | | `interval` | `number` | Polling interval, in milliseconds. The client will check for updates at this frequency. | No | `1_000` |
26 | | `onResponse` | `function` | Callback function invoked each time the client polls for an update and receives a response from the relay server. Receives the return value of the latest `status` request. | No | `({ data }) => console.log(data.fid)` |
27 |
28 | ## Returns
29 |
30 | ```ts
31 | {
32 | response: Response
33 | data: {
34 | state: 'pending' | 'completed'
35 | nonce: string
36 | message?: string
37 | signature?: Hex
38 | fid?: number
39 | username?: string
40 | bio?: string
41 | displayName?: string
42 | pfpUrl?: string
43 | custody?: Hex;
44 | verifications?: Hex[];
45 | }
46 | isError: boolean
47 | error: Error
48 | }
49 | ```
50 |
51 | | Parameter | Description |
52 | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
53 | | `response` | HTTP response from the Connect relay server. |
54 | | `data.state` | Status of the sign in request, either `"pending"` or `"complete"` |
55 | | `data.nonce` | Random nonce used in the SIWE message. If you don't provide a custom nonce as an argument to the hook, you should read this value. |
56 | | `data.message` | The generated SIWE message. |
57 | | `data.signature` | Hex signature produced by the user's Warpcast wallet. |
58 | | `data.fid` | User's Farcaster ID. |
59 | | `data.username` | User's Farcaster username. |
60 | | `data.bio` | User's Farcaster bio. |
61 | | `data.displayName` | User's Farcaster display name. |
62 | | `data.pfpUrl` | User's Farcaster profile picture URL. |
63 | | `data.custody` | User's FID custody address. |
64 | | `data.verifications` | List of user's verified addresses. |
65 | | `isError` | True when an error has occurred. |
66 | | `error` | `Error` instance. |
67 |
--------------------------------------------------------------------------------
/docs/reference/contracts/reference/bundler.md:
--------------------------------------------------------------------------------
1 | ---
2 | outline: [2, 3]
3 | ---
4 |
5 | # Bundler
6 |
7 | The Bundler makes first time sign up easier by allowing a user to register an fid, add a key and rent storage in one transaction.
8 |
9 | If you want to create a new Farcaster account in a single transaction, use the Bundler.
10 |
11 | ## Read
12 |
13 | ### price
14 |
15 | Get the price in wei to register an fid, including 1 storage unit. To add additional storage units to the calculation, use the `extraStorage` parameter.
16 |
17 | | Parameter | type | Description |
18 | | ------------ | --------- | --------------------------------------------- |
19 | | extraStorage | `uint256` | Number of extra units to include in the price |
20 |
21 | ## Write
22 |
23 | ### register
24 |
25 | Register an fid, add one or more keys, and rent storage in a single step. For a detailed usage example, see the [signup demo app](https://farcaster-signup-demo.vercel.app/bundler).
26 |
27 | | Parameter | type | Description |
28 | | -------------- | -------------------- | --------------------------------------------- |
29 | | `msg.value` | `wei` | Payment amount for registration |
30 | | registerParams | `RegistrationParams` | Registration related parameters and signature |
31 | | signerParams | `SignerParams[]` | Key related parameters and signature |
32 | | extraStorage | `uint256` | Additional storage units to rent |
33 |
34 | **RegistrationParams struct**
35 |
36 | The `RegistrationParams` struct includes registration parameters and an IdGateway [`Register`](/reference/contracts/reference/id-gateway#register-signature) signature from the fid recipient.
37 |
38 | | Parameter | type | Description |
39 | | --------- | --------- | -------------------------------------------------------------------------------------------------------------- |
40 | | to | `address` | Address to register the fid to |
41 | | recovery | `address` | Recovery address for the new fid |
42 | | deadline | `uint256` | Signature expiration timestamp signature |
43 | | sig | `bytes` | EIP-712 [`Register`](/reference/contracts/reference/key-gateway#add-signature) signature from the `to` address |
44 |
45 | **SignerParams struct**
46 |
47 | The `SignerParams` struct includes signer key parameters and a KeyGateway [`Add`](/reference/contracts/reference/key-gateway#add-signature) signature from the fid recipient. Callers may provide multiple `SignerParams` structs to add multiple keys at registration time.
48 |
49 | | Parameter | type | Description |
50 | | ------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
51 | | keyType | `uint32` | Must be set to `1`. This is currently the only supported `keyType`. |
52 | | key | `bytes` | Public key to add |
53 | | metadataType | `uint8` | Must be set to `1`. This is currenlty the only supported `metadataType`. |
54 | | metadata | `bytes` | Encoded [`SignedKeyRequestMetadata`](/reference/contracts/reference/signed-key-request-validator#signedkeyrequestmetadata-struct) |
55 | | deadline | `uint256` | Signature expiration timetamp |
56 | | sig | `bytes` | EIP-712 [`Add`](/reference/contracts/reference/key-gateway#add-signature) signature from `registrationParams.to` address |
57 |
58 | ## Errors
59 |
60 | | Error | Selector | Description |
61 | | ---------------- | ---------- | ------------------------------------------------------------------------------------------------------------ |
62 | | InvalidPayment | `3c6b4b28` | The caller provided insufficient payment. |
63 | | InvalidMetadata | `bcecb64a` | The signed metadata provided with the key is invalid. |
64 | | InvalidSignature | `8baa579f` | The provided signature is invalid. It may be incorrectly formatted, or signed by the wrong address. |
65 | | SignatureExpired | `0819bdcd` | The provided signature has expired. Collect a new signature from the signer with a later deadline timestamp. |
66 |
67 | ## Source
68 |
69 | [`Bundler.sol`](https://github.com/farcasterxyz/contracts/blob/1aceebe916de446f69b98ba1745a42f071785730/src/Bundler.sol)
70 |
--------------------------------------------------------------------------------
/docs/learn/what-is-farcaster/messages.md:
--------------------------------------------------------------------------------
1 | # Messages
2 |
3 | Farcaster accounts interact by signing and publishing messages. Alice can create a message that says "_Hello @bob_" and sign it with her key.
4 |
5 | Messages are stored on a peer-to-peer network of nodes. A node in the Farcaster network is called a Hub, and each Hub stores a copy of the entire network. A user can publish a message to one Hub and it will propagate to the entire network in a few seconds. Farcaster's compact message format and eventually consistent model lets this architecture scale to millions of users.
6 |
7 | An account can generate a [key](./accounts.md#adding-account-keys) and give it to an app which can use it to sign messages. Users can use multiple apps with the same account, and each application can have its own key. Separating the signing keys from the ownership keys helps keep the account secure.
8 |
9 | ## Types
10 |
11 | Accounts can publish five different kinds of messages to the network:
12 |
13 | | Type | Description | Example |
14 | | ------------- | --------------------------------------------- | ------------------------------ |
15 | | Casts | Public messages that can be seen by anyone. | "Hello world!" |
16 | | Reactions | A relationship between an account and a cast. | Alice liked Bob's cast. |
17 | | Links | A relationship between two accounts. | Alice follows Bob. |
18 | | Profile Data | Metadata about the account. | Profile picture, display name. |
19 | | Verifications | A proof of ownership of something. | An Ethereum address. |
20 |
21 | ## Storage
22 |
23 | An account must pay rent to keep their messages on the Farcaster network. Charging rent prevents users from spamming the network.
24 |
25 | An account can rent a unit of storage by making an onchain transaction to the Storage Registry. A unit of storage costs $7 today, lasts for one year and lets each account store a certain number of messages of each type. The limits for each type today are:
26 |
27 | - 5000 Casts
28 | - 2500 Reactions
29 | - 2500 Links
30 | - 50 Profile Data
31 | - 50 Verifications
32 |
33 | If an account exceeds its limit for a message type, the oldest message is pruned to make space for the new one. The user can keep using the network without paying for more storage and Hubs can keep the storage load under control. An account can always purchase more storage to increase its limits.
34 |
35 | An account that lets its storage expire may lose all its messages. There is a 30-day grace period after a storage unit expires during which an account must renew or lose its messages.
36 |
37 | The price and size of each storage unit is re-calculated periodically to balance growth and quality of the network. See [FIP-6](https://github.com/farcasterxyz/protocol/discussions/98)
38 | for more details.
39 |
40 | ## Deletion
41 |
42 | An account can delete messages at any time by publishing a corresponding delete message. The delete message will remove the contents of the original message, leaving a tombstone in its place. A deleted message will still count towards the account's storage limit until it expires by being pushed out by a newer message.
43 |
44 | ## Timestamps
45 |
46 | Messages have timestamps which count seconds from the Farcaster Epoch, which began on `Jan 1, 2021 00:00:00 UTC`. Using a recent epoch makes timestamps and messages much smaller, which is important for the network.
47 |
48 | Timestamps are unverified and can be backdated by users, similar to a blog post. They cannot be more than 15 minutes into the future, as the network will reject such messages.
49 |
50 | ## Resources
51 |
52 | ### Specifications
53 |
54 | - [Messages](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#2-message-specifications) - the atomic unit of change on Farcaster
55 | - [CRDTs](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#31-crdts) - rules for keeping messages in sync on the network
56 | - [Storage Registry](https://github.com/farcasterxyz/protocol/blob/main/docs/SPECIFICATION.md#13-storage-registry) - contract to acquire storage units
57 |
58 | ### APIs
59 |
60 | - [Get Casts](../../reference/hubble/httpapi/casts) - fetch an account's casts from a hub
61 | - [Get Reactions](../../reference/hubble/httpapi/reactions) - fetch an account's reactions from a hub
62 | - [Get Links](../../reference/hubble/httpapi/links) - fetch an account's links or follows from a hub
63 | - [Get UserData](../../reference/hubble/httpapi/userdata) - fetch an account's profile data from a hub
64 | - [Submit Message](../../reference/hubble/httpapi/message#submitmessage) - broadcast a message to the hub network
65 | - [Validate Message](../../reference/hubble/httpapi/message#validatemessage) - verify a message's authenticity with a hub
66 | - [Storage Registry](../../reference/contracts/reference/storage-registry) - Acquire or check storage units for an account
67 |
68 | ### Tutorials
69 |
70 | - [Get casts](../../developers/guides/querying/fetch-casts) - Get an account's casts from a hub.
71 | - [Get profile](../../developers/guides/querying/fetch-profile) - Get an account's profile from a hub.
72 | - [Create common message types](../../developers/guides/writing/messages) - Create casts, links, reactions and userdata.
73 | - [Create casts with advanced features](../../developers/guides/writing/casts) - Create casts with embeds, emoji and mentions.
74 |
--------------------------------------------------------------------------------
/docs/reference/hubble/httpapi/casts.md:
--------------------------------------------------------------------------------
1 | # Casts API
2 |
3 | ## castById
4 |
5 | Get a cast by its FID and Hash.
6 |
7 | **Query Parameters**
8 | | Parameter | Description | Example |
9 | | --------- | ----------- | ------- |
10 | | fid | The FID of the cast's creator | `fid=6833` |
11 | | hash | The cast's hash | `hash=0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9` |
12 |
13 | **Example**
14 |
15 | ```bash
16 | curl http://127.0.0.1:2281/v1/castById?fid=2&hash=0xd2b1ddc6c88e865a33cb1a565e0058d757042974
17 | ```
18 |
19 | **Response**
20 |
21 | ```json
22 | {
23 | "data": {
24 | "type": "MESSAGE_TYPE_CAST_ADD",
25 | "fid": 2,
26 | "timestamp": 48994466,
27 | "network": "FARCASTER_NETWORK_MAINNET",
28 | "castAddBody": {
29 | "embedsDeprecated": [],
30 | "mentions": [],
31 | "parentCastId": {
32 | "fid": 226,
33 | "hash": "0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9"
34 | },
35 | "text": "Cast Text",
36 | "mentionsPositions": [],
37 | "embeds": []
38 | }
39 | },
40 | "hash": "0xd2b1ddc6c88e865a33cb1a565e0058d757042974",
41 | "hashScheme": "HASH_SCHEME_BLAKE3",
42 | "signature": "3msLXzxB4eEYe...dHrY1vkxcPAA==",
43 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
44 | "signer": "0x78ff9a...58c"
45 | }
46 | ```
47 |
48 | ## castsByFid
49 |
50 | Fetch all casts for authored by an FID.
51 |
52 | **Query Parameters**
53 | | Parameter | Description | Example |
54 | | --------- | ----------- | ------- |
55 | | fid | The FID of the cast's creator | `fid=6833` |
56 |
57 | **Example**
58 |
59 | ```bash
60 | curl http://127.0.0.1:2281/v1/castsByFid?fid=2
61 | ```
62 |
63 | **Response**
64 |
65 | ```json
66 | {
67 | "messages": [
68 | {
69 | "data": {
70 | "type": "MESSAGE_TYPE_CAST_ADD",
71 | "fid": 2,
72 | "timestamp": 48994466,
73 | "network": "FARCASTER_NETWORK_MAINNET",
74 | "castAddBody": {... },
75 | "text": "Cast Text",
76 | "mentionsPositions": [],
77 | "embeds": []
78 | }
79 | },
80 | "hash": "0xd2b1ddc6c88e865a33cb1a565e0058d757042974",
81 | "hashScheme": "HASH_SCHEME_BLAKE3",
82 | "signature": "3msLXzxB4eEYeF0Le...dHrY1vkxcPAA==",
83 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
84 | "signer": "0x78ff9a768cf1...2eca647b6d62558c"
85 | }
86 | ]
87 | "nextPageToken": ""
88 | }
89 | ```
90 |
91 | ## castsByParent
92 |
93 | Fetch all casts by parent cast's FID and Hash OR by the parent's URL
94 |
95 | **Query Parameters**
96 | | Parameter | Description | Example |
97 | | --------- | ----------- | ------- |
98 | | fid | The FID of the parent cast | `fid=6833` |
99 | | hash | The parent cast's hash | `hash=0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9` |
100 | | url | The URL of the parent cast | `url=chain://eip155:1/erc721:0x39d89b649ffa044383333d297e325d42d31329b2` |
101 |
102 | **Note**
103 | You can use either `?fid=...&hash=...` OR `?url=...` to query this endpoint
104 |
105 | **Example**
106 |
107 | ```bash
108 | curl http://127.0.0.1:2281/v1/castsByParent?fid=226&hash=0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9
109 | ```
110 |
111 | **Response**
112 |
113 | ```json
114 | {
115 | "messages": [
116 | {
117 | "data": {
118 | "type": "MESSAGE_TYPE_CAST_ADD",
119 | "fid": 226,
120 | "timestamp": 48989255,
121 | "network": "FARCASTER_NETWORK_MAINNET",
122 | "castAddBody": {
123 | "embedsDeprecated": [],
124 | "mentions": [],
125 | "parentCastId": {
126 | "fid": 226,
127 | "hash": "0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9"
128 | },
129 | "text": "Cast's Text",
130 | "mentionsPositions": [],
131 | "embeds": []
132 | }
133 | },
134 | "hash": "0x0e501b359f88dcbcddac50a8f189260a9d02ad34",
135 | "hashScheme": "HASH_SCHEME_BLAKE3",
136 | "signature": "MjKnOQCTW42K8+A...tRbJfia2JJBg==",
137 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
138 | "signer": "0x6f1e8758...7f04a3b500ba"
139 | }
140 | ],
141 | "nextPageToken": ""
142 | }
143 | ```
144 |
145 | ## castsByMention
146 |
147 | Fetch all casts that mention an FID
148 |
149 | **Query Parameters**
150 | | Parameter | Description | Example |
151 | | --------- | ----------- | ------- |
152 | | fid | The FID that is mentioned in a cast | `fid=6833` |
153 |
154 | **Note**
155 | Use the `mentionsPositions` to extract the offset in the cast text where the FID was mentioned
156 |
157 | **Example**
158 |
159 | ```bash
160 | curl http://127.0.0.1:2281/v1/castsByMention?fid=6833
161 | ```
162 |
163 | **Response**
164 |
165 | ```json
166 | {
167 | "messages": [
168 | {
169 | "data": {
170 | "type": "MESSAGE_TYPE_CAST_ADD",
171 | "fid": 2,
172 | "timestamp": 62298143,
173 | "network": "FARCASTER_NETWORK_MAINNET",
174 | "castAddBody": {
175 | "embedsDeprecated": [],
176 | "mentions": [15, 6833],
177 | "parentCastId": {
178 | "fid": 2,
179 | "hash": "0xd5540928cd3daf2758e501a61663427e41dcc09a"
180 | },
181 | "text": "cc and ",
182 | "mentionsPositions": [3, 8],
183 | "embeds": []
184 | }
185 | },
186 | "hash": "0xc6d4607835197a8ee225e9218d41e38aafb12076",
187 | "hashScheme": "HASH_SCHEME_BLAKE3",
188 | "signature": "TOaWrSTmz+cyzPMFGvF...OeUznB0Ag==",
189 | "signatureScheme": "SIGNATURE_SCHEME_ED25519",
190 | "signer": "0x78ff9a768c...647b6d62558c"
191 | }
192 | ],
193 | "nextPageToken": ""
194 | }
195 | ```
196 |
--------------------------------------------------------------------------------