# Farcaster Messages *Contributors: Paul Fletcher-Hill, Shane da Silva, Varun Srinivasan* - Why? Helps developers align on how Farcaster Messages should work. - What? Specifies how farcaster messages should be constructed (the schema), how big they can become(sizes) and other restrictions (validation rules). - Not: the rules of sets or x-message validation ## Message - Represent any action taken by a user like making a post, etc etc - Tamper-proof self authenticating objects signed by an fid - contain a flexible data body that is defined by the sub type - signature is usually an eddsa signature, with a few exceptions where messages are signed by ethereum addresses using eth typed signature and explain the signer. - Messages are constructed using flatbuffers because of performance reasons ```rust table Message { data: [ubyte] (nested_flatbuffer: "Farcaster.MessageData", required); signature: [ubyte] (required); signature_scheme: SignatureScheme = 1; signer: [ubyte] (required); } enum SignatureScheme: uint8 { Ed25519 = 1, EthSignTypedData = 2 // should this be called EIP712 instead? } ``` - Contains a body and type which is metadata about the body - Contains 3 other parameters that are common in every message - Timestamp is the 32-bit epoch timestamp starting on Feb 1, 2021 - Fid is the farcaster id of the username on the appropriate netwokr - Network defines which network we are operating on The data object carries the payload of the message. All messages must contain a few common parameters: - `fid` — fid of the signer of the message - `network` — id that prevents replaying of messages between testnet and mainnet - `timestamp` — epoch timestamp in seconds starting from Jan 1, 2021 - `type` — type of farcaster message The `body` must also be a table that matches the type declared in the `type` enumeration. ```rust table MessageData type: MessageType = 1; body: MessageBody (required); fid: [ubyte] (required); network: FarcasterNetwork = 1; timestamp: uint64; } union MessageBody { CastAddBody, CastRemoveBody, ReactionBody, FollowBody // TODO: Signers, Verifications, ... } enum MessageType: uint16 { CastAdd = 1, CastRemove = 2, ReactionAdd = 3, ReactionRemove = 4, FollowAdd = 5, FollowRemove = 6, VerificationAddEthAddress = 7, VerificationRemove = 8, // SignerAdd = 9, SignerRemove = 10, UserDataAdd = 11 } enum FarcasterNetwork: uint8 { Mainnet = 1, Testnet = 2, Devnet = 3 } ``` ### Casts - Cast is a public broadcast - Two types of messages, adding and removing ```rust table CastAddBody { embeds: [string]; mentions: [UserID]; parent: CastID; text: string (required); } table CastRemoveBody { hash: [ubyte] (required); } ``` ### Reactions ```rust table ReactionBody { cast: CastID (required); type: ReactionType = 1; } enum ReactionType: uint16 { Like = 1, Recast = 2 } ``` ```rust table FollowBody { user: UserID (required); } ``` ### Helpers ```rust // TODO: should this be fid + timestash + hash ? table CastID { fid: [ubyte] (required) timestampHash: [ubyte] (required); } table UserID { fid: [ubyte] (required); } ``` ## Casts * `embeds` - allows upto two URI strings, each of which can be 256 chars * `mentions` - upto 5 fids // 320 character limit with tokens (i.e. $0$) for each mention ```rust table CastAddBody { embeds?: URI[]; // Up to 2 URIs (max 256 chars each) mentions?: [ubyte][32]; // Up to 5 fids parent?: CastID; // <fid>:<hash> text: [ubyte][320]; } ``` ## Todo - [ ] Add Recasts back into MessageType and other parts of the spec