# 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