{"id":13776353,"url":"https://github.com/PinataCloud/pinata-fdk","last_synced_at":"2025-05-11T10:31:00.271Z","repository":{"id":221764012,"uuid":"754949753","full_name":"PinataCloud/pinata-fdk","owner":"PinataCloud","description":"Farcaster Development Kit","archived":false,"fork":false,"pushed_at":"2024-05-22T13:57:59.000Z","size":2825,"stargazers_count":38,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T12:35:07.119Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://next-pages-router-example.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PinataCloud.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-09T05:00:53.000Z","updated_at":"2025-03-16T17:33:01.000Z","dependencies_parsed_at":"2024-02-09T23:25:51.575Z","dependency_job_id":"0f25f019-5ca0-47b0-b92a-b46cc0ce1d0f","html_url":"https://github.com/PinataCloud/pinata-fdk","commit_stats":null,"previous_names":["pinatacloud/pinata-fdk"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PinataCloud%2Fpinata-fdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PinataCloud%2Fpinata-fdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PinataCloud%2Fpinata-fdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PinataCloud%2Fpinata-fdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PinataCloud","download_url":"https://codeload.github.com/PinataCloud/pinata-fdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253551526,"owners_count":21926310,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:23.690Z","updated_at":"2025-05-11T10:30:57.859Z","avatar_url":"https://github.com/PinataCloud.png","language":"TypeScript","funding_links":[],"categories":["Useful Tools \u0026 Libraries","Uncategorized"],"sub_categories":["Developer libraries for building frames","Uncategorized"],"readme":"\n# Farcaster Development Kit\n\nAn SDK to easily create Farcaster Frames, manage frame analytics and pin images to IPFS using Pinata. \n\nView the full documentation [here](https://docs.pinata.cloud/farcaster/fdk). \n\n\n## Getting Started\n\n### Installation\n```javascript\nnpm i pinata-fdk\n```\n```javascript\nyarn add pinata-fdk\n```\n\n### Initialization\n\nIf you want to leverage IPFS pinning capabilities, you must enter your Pinata JWT and a Pinata gateway during intialization. \n```javascript\nimport { PinataFDK } from \"pinata-fdk\";\nconst fdk = new PinataFDK({\n    pinata_jwt: \"\u003cYOUR_PINATA_JWT\u003e\",\n    pinata_gateway: \"\u003cYOUR_PINATA_GATEWAY\u003e\"}, \n);\n```\nIf you are only using the frame metadata functionality, you do not need to enter your credentials. \n```javascript \nimport { PinataFDK } from \"pinata-fdk\";\nconst fdk = new PinataFDK();\n```\n\n## Farcaster Auth\n\nThe FDK makes it easy to give your Farcaster app write access for users so you can do things like sending casts or following other users. To get a better concept of the flow of Farcaster Auth, check out the guide [here](/farcaster/farcaster-auth).\n\n## `createSigner`\n\nThis function will create a signer with Farcaster Auth, sign the key with your Farcaster App mnemonic phrase and FID, then send a request to Warpcast to register the signer. For more info on those please see [these docs](https://docs.pinata.cloud/farcaster/farcaster-auth#getting-started). \n\nIn order to use it make sure the mnemonic and FID are included with the PinataFDK instance.\n\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: 'YOUR_PINATA_JWT',\n  pinata_gateway: 'YOUR_GATEWAY',\n  app_fid: 'APP_FID',\n  app_mnemonic: 'APP_MNEMONIC'\n})\n```\n\n### Example\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n  app_fid: `${process.env.APP_FID}`\n  app_mnemonic: `${process.env.FARCASTER_DEVELOPER_MNEMONIC}`\n})\n\nconst signerData: WarpcastPayload = await fdk.createSigner() \n```\n\nAfter creating the signer the user would visit the `signerData.deep_link_url` which would open Warpcast on their account to approve the signer. The user will have to pay warps since it is not sponsored.\n\n### Response\n\n```typescript\n{\n  signer_id: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n  token: \"0xe3bffad26b16cf825f3d062d\",\n  deep_link_url: \"farcaster://signed-key-request?token=0xe3bffad26b16cf825f3d062d\",\n  status: \"pending_approval\"\n}\n```\n\n## `createSponsoredSigner`\n\nSponsored signers is very similar to `createSigner` except the end user will not have to pay warps to approve the signer. However there may be limits to how many sponsored signers you can use based on your Pinata plan. You still need the `app_mnemonic` to sign the key being used.\n\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: 'YOUR_PINATA_JWT',\n  pinata_gateway: 'YOUR_GATEWAY',\n  app_fid: 'APP_FID',\n  app_mnemonic: 'APP_MNEMONIC'\n})\n```\n\n### Example\n\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n  app_fid: `${process.env.APP_FID}`,\n  app_mnemonic: `${process.env.FARCASTER_DEVELOPER_MNEMONIC}`\n})\n\nconst signerData: WarpcastPayload = await fdk.createSponsoredSigner() \n```\n\nAfter creating the signer the user would visit the `signerData.deep_link_url` which would open Warpcast on their account to approve the signer. Since it is sponsored the user will not have to pay warps to sign in, however it will show Pinata as the app.\n\n### Response\n\n```typescript\n{\n  signer_id: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n  token: \"0x21658c8fa560aca0f35a5e4a\",\n  deep_link_url: \"farcaster://signed-key-request?token=0x21658c8fa560aca0f35a5e4a\",\n  status: \"pending_approval\"\n}\n```\n\n## `pollSigner`\n\nAfter creating a signer and giving the user the `deep_link_url` you will want to poll the signer to see if they have approved it and record the response to your account.\n\n### Params\n\n`pollSigner` takes a parameter of `token` which is provided in either `createSigner` or `createSponsoredSigner`.\n\n### Example\n\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n  app_fid: `${process.env.APP_FID}`\n})\n\nconst pollData = await fdk.pollSigner(\"0x21658c8fa560aca0f35a5e4a\") \n```\n\n### Returns\n\n```typescript\n{\n  token: \"0x321bbb927d9009232a7c26d6\",\n  deeplinkUrl: \"farcaster://signed-key-request?token=0x321bbb927d9009232a7c26d6\",\n  key: \"0x858e9ed1af97ec0c1cf06e7d769a2bca9ec324c152f320ee34b253af27b486f4\",\n  requestFid: 20918,\n  state: \"pending\",\n  isSponsored: false\n}\n```\n\n## `getSigner`\n\nAfter you have created a signer and it has been polled as complete, you can fetch the signer at any time using `getSigner`\n\n### Params\n\n- fid - A number/integer of the FID you want to query. (Optional)\n\n### Example\n\n```typescript\nimport { PinataFDK } from \"pinata-fdk\"\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n  app_fid: `${process.env.APP_FID}`\n})\n\nconst pollData = await fdk.getSigner(6023) \n```\n### Returns\n\n```typescript\n{\n  signers: [\n    {\n      id: 57,\n      signer_uuid: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n      fid: 6023,\n      public_key: \"dad973170c63739f7c812d188fab1df074eb1cd48facf6556e2ef9cbb76b4c18\",\n      signer_approved: true,\n      revoked: false\n    }\n  ],\n  next_page_token: \"eyJvZmZzZXQiOiI1NyJ9\"\n}\n```\n\n## Farcaster Writes\n\nThese methods can be used to create casts, react to them, or even follow users. All of them require a `signerId` which is a result of using Farcaster Auth, as well as the PinataFDK initialization with a Pinata JWT.\n\nAll of these methods also return the same response, which is the direct response from the Pinata Hub.\n\n```typescript\ntype CastResponse = {\n  data: {\n    type: string;\n    fid: number;\n    timestamp: number;\n    network: string;\n    castAddBody: {\n      embedsDeprecated: any[];\n      mentions: any[];\n      text: string;\n      mentionsPositions: any[];\n      embeds: any[];\n    };\n  };\n  hash: string;\n  hashScheme: string;\n  signature: string;\n  signatureScheme: string;\n  signer: string;\n  dataBytes: string;\n};\n```\n\n\n### `sendCast`\n\nWith the `sendCast` method you can effortlessly post to Farcaster using a `signerId`. \n\n#### Params\n\n- CastRequest - An object that contains the `signerId` and the `castAddBody` which follows the [Farcaster Hub standard for sending casts](https://docs.farcaster.xyz/reference/hubble/datatypes/messages#_3-1-castaddbody).\n\n```typescript\ntype CastRequest = {\n  signerId: string;\n  castAddBody: CastBody;\n}\n\ntype CastBody = {\n  embedsDeprecated?: string[];\n  mentions?: number[];\n  parentCastId?: CastId | null;\n  parentUrl?: string | null;\n  text?: string | null;\n  mentionsPositions?: number[] | null;\n  embeds?: Embed[] | null;\n}\n\ntype CastId = {\n  fid: number;\n  hash: string;\n}\n\ntype Embed = {\n  url?: string | null;\n  castId?: CastId | null;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst res: CastResponse = await fdk.sendCast({\n  castAddBody: {\n    text: \"Hello World from  !\",\n    mentions: [6023],\n    mentionsPositions: [18],\n    parentUrl: \"https://warpcast.com/~/channel/pinata\",\n    embeds: [\n      {\n        url: \"https://pinata.cloud\"\n      },\n      {\n        castId: {\n          fid: 6023\n          hash: \"0xcae8abd9badbb60c9b610ec264f42ed9f1785c6f\",\n        }\n      }\n    ],\n    parentCastId: {\n      fid: 6023,\n      hash: \"0xcae8abd9badbb60c9b610ec264f42ed9f1785c6f\"\n    }\n  },\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\"\n});\n```\n\n### `deleteCast`\n\nThis method can delete a cast with a provided target hash.\n\n#### Params\n\n- hash - Target hash of the cast that needs to be deleted\n- signerId - Signer for the cast\n\n```typescript\ntype CastDelete = {\n  hash: string;\n  signerId: string;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst deleteReq: CastResponse = await fdk.deleteCast({\n  hash: \"0x490889854a4f3233433b1ad0560f016f04feeeff\",\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `likeCast`\n\nThis method can like a cast based on the provided target hash.\n\n#### Params\n\n- hash - Hash of the target cast to be liked\n- signerId - Signer of the user liking the cast\n\n```typescript\ntype LikeCast = {\n  hash: string,\n  signerId: string\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst likeReq: CastResponse = await fdk.likeCast({\n  hash: \"0x490889854a4f3233433b1ad0560f016f04feeeff\",\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `unlikeCast`\n\nIf a cast is already liked by the user, this method will unlike it.\n\n#### Params\n\n- hash - Hash of the target cast to be unliked\n- signerId - Signer of the user unliking the cast\n\n```typescript\ntype LikeCast = {\n  hash: string,\n  signerId: string\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst unlikeReq: CastResponse = await fdk.unlikeCast({\n  hash: \"0x490889854a4f3233433b1ad0560f016f04feeeff\",\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `recastCast`\n\nThis method will recast a cast based on the target hash.\n\n#### Params\n\n- hash - Hash of the target cast to be recast\n- signerId - Signer of the user recasting target cast\n\n```typescript\ntype RecastCast = {\n  hash: string;\n  signerId: string;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst recastCastReq: CastResponse = await fdk.recastCast({\n  hash: \"0x490889854a4f3233433b1ad0560f016f04feeeff\",\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `removeRecast`\n\nWorks just like `recastCast` but removes an existing recast based on a hash of the target cast.\n\n#### Params\n\n- hash - Hash of the target cast to remove recast\n- signerId - Signer of the user removing the recast\n\n```typescript\ntype RecastCast = {\n  hash: string;\n  signerId: string;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst removeRecastReq: CastResponse = await fdk.removeRecast({\n  hash: \"0x490889854a4f3233433b1ad0560f016f04feeeff\",\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `followUser`\n\nFollows a target user based on their FID.\n\n#### Params\n\n- fid - The FID of the target user to follow\n- signerId - The signer for the user following the target user\n\n```typescript\ntype FollowUser = {\n  fid: number;\n  signerId: string;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst followUserReq: CastResponse = await fdk.followUser({\n  fid: 6023,\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n### `unfollowUser`\n\nUnfollows a user that the signer is already following.\n\n#### Params\n\n- fid - The FID of the target user to unfollow\n- signerId - The signer for the user unfollowing the target user\n\n```typescript\ntype FollowUser = {\n  fid: number;\n  signerId: string;\n}\n```\n\n#### Example\n\n```typescript\nimport { CastResponse, PinataFDK } from \"pinata-fdk\";\n\nconst fdk = new PinataFDK({\n  pinata_jwt: `${process.env.PINATA_JWT}`,\n  pinata_gateway: \"\",\n});\n\nconst unfollowUserReq: CastResponse = await fdk.unfollowUser({\n  fid: 6023,\n  signerId: \"ba2d9f6d-7514-4967-8b52-5a040b7da4a1\",\n};\n```\n\n## Frames\n\n### `getFrameMetadata`\n\nYou can use this function to easily create the Farcaster specific metadata needed for your frame. \n**The only required input is `cid` or `image`.**\n\n#### Params\n\n- `buttons` - An array of button specifications (max 4). (Optional)\n- `image` - A string for a valid hosted image url. \n- `cid` - A string representing the cid of an IPFS pinned image. \n- `input` - A string representing the text displayed for text input. (Optional)\n- `post_url` - A string which contains a valid URL to send the Signature Packet to. (Optional)\n- `refresh_period` - A string representing the refresh period for the image used. (Optional)\n- `aspect_ratio` - A string representing the aspect ratio for the image used. (Optional)\n- `state` - An object (e.g. JSON) representing the state data for the frame. (Optional)\n  \n**Note:** state should only be included in response frames, not initial frames.\n\n```javascript\ntype FrameHTMLType = {\n  buttons?: [FrameButtonMetadata, ...FrameButtonMetadata[]]; \n  image?: {url: string};\n  cid?: string;\n  input?: FrameInputMetadata;\n  post_url?: string;\n  refresh_period?: number;\n  aspect_ratio?: \"1.91:1\" | \"1:1\",\n  state?: object\n} \u0026 (\n  { image: {url: string}}| { cid: string }\n);\n```\n```javascript \ntype FrameButtonMetadata = {\n  label: string;\n  action?: \"post\" | \"post_redirect\" | \"mint\" | \"link\" | \"tx\";\n  target?: string;\n}\n```\n```javascript \ntype FrameInputMetadata = {\n    text: string;\n};\n```\n\n#### Example Code\n```javascript\n const frameMetadata = fdk.getFrameMetadata({\n    post_url: `\u003cYOUR_DOMAIN\u003e/api/test`,\n    input: {text: \"Hello, world!\"},\n    aspectRatio: \"1.91:1\",\n    buttons: [\n      { label: 'Click me', action: 'post'},\n      { label: 'Button 2', action: \"post_redirect\"},\n      { label: 'Button 3', action: \"mint\" },\n      { label: 'Button 4', action: \"link\" },\n    ],\n    cid: \"\u003cYOUR_CID\u003e\", \n    state: {counter: 1}\n  });\n  ```\n#### Response \n```javascript\n\u003cmeta name=\"fc:frame\" content=\"vNext\"\u003e\n\u003cmeta name=\"og:image\" content=\"https://\u003cYOUR_GATEWAY\u003e/ipfs/\u003cYOUR_CID\u003e\"\u003e\n\u003cmeta name=\"fc:frame:image\" content=\"https://\u003cYOUR_GATEWAY\u003e/ipfs/\u003cYOUR_CID\u003e\"\u003e\n\u003cmeta name=\"fc:frame:aspectRatio\" content=\"1.91:1\"\u003e\n\u003cmeta name=\"fc:frame:input:text\" content=\"Hello, world!\"\u003e\n\u003cmeta name=\"fc:frame:button:1\" content=\"Click me\"\u003e\n\u003cmeta name=\"fc:frame:button:1:action\" content=\"post\"\u003e\n\u003cmeta name=\"fc:frame:button:2\" content=\"Button 2\"\u003e\n\u003cmeta name=\"fc:frame:button:2:action\" content=\"post_redirect\"\u003e\n\u003cmeta name=\"fc:frame:button:3\" content=\"Button 3\"\u003e\n\u003cmeta name=\"fc:frame:button:3:action\" content=\"mint\"\u003e\n\u003cmeta name=\"fc:frame:button:4\" content=\"Button 4\"\u003e\n\u003cmeta name=\"fc:frame:button:4:action\" content=\"link\"\u003e\n\u003cmeta name=\"fc:frame:post_url\" content=\"\u003cYOUR_DOMAIN\u003e/api/test\"\u003e\n\u003cmeta name=\"fc:frame:state\" content=\"%7B%22counter%22%3A1%7D\"\u003e\n```\n\n#### Images for `getFrameMetadata`\nThere are two different ways to set the images of your frame metadata. \n\n⚡️ Raw URL \n\n⚡️ CID\n\n\n#### Raw URL\nSpecify a hosted url image link. \n\n```javascript\nconst frameMetadata = fdk.getFrameMetadata({\n    image: { url: \"\u003cYOUR_URL\u003e\"}\n  });\n```\n\n#### CID\nSpecify a CID from your Pinata account. \n\n```javascript\nconst frameMetadata = fdk.getFrameMetadata({\n    cid: \"QmX63EYiDk9cExrv4GDmZ5soJKkgqoUJv9LbtPyugLBtV2\"\n  });\n  \n//Must insert Pinata credentials when intializing SDK.    \n```\n\n### `convertUrlToIPFS`\n\nUploads an image to IPFS from a url. This url may be passed to the `getFrameMetadata` function.\n#### Params\n\n- `url` - A string for a valid hosted url image.\n\n#### Example Code\n\n```javascript \n const ipfsUrl = await fdk.convertUrlToIPFS(\"https://example.com\");\n const frameMetadata = fdk.getFrameMetadata({\n    image: { url: ipfsUrl}\n  });\n```\n#### Response\n```javascript\nhttps://\u003cYOUR_GATEWAY\u003e/ipfs/\u003cYOUR_CID\u003e\n```\n\n\n### `validateFrameMessage`\n\nReturns a Promise that indicates wether a message signature is valid by querying Pinata's Farcaster hub. \n\n#### Params\n\n- `body` - An object representing the raw payload of an action frame produced by Farcaster.\n```\n{\n  untrustedData: {\n    fid: 2,\n    url: \"https://fcpolls.com/polls/1\",\n    messageHash: \"0xd2b1ddc6c88e865a33cb1a565e0058d757042974\",\n    timestamp: 1706243218,\n    network: 1,\n    buttonIndex: 2,\n    inputText: \"hello world\", // \"\" if requested and no input, undefined if input not requested\n    castId: {\n      fid: 226,\n      hash: \"0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9\",\n    },\n  },\n  trustedData: {\n    messageBytes: \"d2b1ddc6c88e865a33cb1a565e0058d757042974...\",\n  },\n};\n```\n#### Example Code\n\n```javascript \nconst { isValid, message } = await fdk.validateFrameMessage(body);\n```\n\n#### Response\n``` javascript\n{\n  isValid: true,\n  message: {\n    data: {\n      type: 13,\n      fid: 15974,\n      timestamp: 98469569,\n      network: 1,\n      castAddBody: undefined,\n      castRemoveBody: undefined,\n      reactionBody: undefined,\n      verificationAddAddressBody: undefined,\n      verificationRemoveBody: undefined,\n      userDataBody: undefined,\n      linkBody: undefined,\n      usernameProofBody: undefined,\n      frameActionBody: [Object]\n    },\n    hash: \u003cBuffer 46 f2 c3 eb ee 56 92 4f 14 47 2e f0 22 de 41 b6 26 52 a8 4d\u003e,\n    hashScheme: 1,\n    signature: \u003cBuffer 7a a0 5e b1 5a f9 59 a7 08 e9 d0 19 d2 24 47 f7 4b 15 d8 70 a8 fb 7e 36 f1 b6 06 14 c2 63 db 7f eb 98 4c 8a e7 98 5c 0d 72 27 04 f3 e9 19 08 10 e7 e9 ... 14 more bytes\u003e,\n    signatureScheme: 1,\n    signer: \u003cBuffer 1d 46 b7 63 1c 6f 15 7b 86 3a c1 9a 64 cd ba 7e b1 cc 2a cb 81 53 37 99 e8 69 e1 49 11 c4 81 4e\u003e,\n    dataBytes: undefined\n  }\n}\n```\n\n### `getAddressForFid`\nReturns the connected Ethereum address for an FID.\n\n#### Params\n\n- `fid` - A number representing the fid of the user.\n\n#### Example Code\n\n```javascript \nconst address = await fdk.getAddressForFid(15974);\n```\n\n#### Response\n```\n\"0x9b7c18a71a98acd2f1271e2d1fe63750a70bc52b\"\n```\n\n### `getUserByFid`\nReturns the user datadata for an FID.\n\n#### Params\n\n- `fid` - A number representing the fid of the user.\n\n#### Example Code\n\n```javascript\nconst userData = await fdk.getUserByFid(20591);\n```\n\n#### Response\n\n```\n{\n  fid: 20591,\n  username: 'kyletut',\n  pfp: 'https://i.imgur.com/TLMFnH6.jpg',\n  bio: 'Everyone is from somewhere. Cofounder and CEO of Pinata. https://www.pinata.cloud/farcaster'\n}\n```\n\n## Frame Analytics\nTo get started visit the [Integrations page](https://app.pinata.cloud/integrations) by clicking on the profile button in the top right, then selecting Integrations. \n\n*Note: You must have Warpcast integrated in the web app to use this functionality.*\n\nIn any of your POST endpoints for frames, you can send analytics like this:*\n\n### `sendAnalytics`\nSends data to Pinata analytics for a specific frame.\n\n#### Params\n\n- `frame_data` - An object representing the raw payload of an action frame produced by Farcaster.\n- `frame_id` - A string representing the frame you want to track.\n- `custom_id`: A string representing a unique identifier to segment requests within the specified frame. (Optional)\n\n#### Example Code\n\n```javascript\n// This should be the raw payload from the frame action\nconst frame_data = {\n  untrustedData: {\n    fid: 2,\n    url: \"https://fcpolls.com/polls/1\",\n    messageHash: \"0xd2b1ddc6c88e865a33cb1a565e0058d757042974\",\n    timestamp: 1706243218,\n    network: 1,\n    buttonIndex: 2,\n    inputText: \"hello world\", // \"\" if requested and no input, undefined if input not requested\n    castId: {\n      fid: 226,\n      hash: \"0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9\",\n    },\n  },\n  trustedData: {\n    messageBytes: \"d2b1ddc6c88e865a33cb1a565e0058d757042974...\",\n  },\n};\nconst frame_id = \"my-unique-frame-name\"\nconst custom_id = \"my_custom_id\"\n\n\nawait fdk.sendAnalytics(frame_id, frame_data, custom_id)\n```\n\n#### Response\n```\n{success: true}\n```\n\nAfter this is deployed you will see the analytics on the [Frame Analytics Page](https://app.pinata.cloud/frames-analytics). \n\n### Frog Analytics Plug-in 🐸\n\nIf you are using the Frog framework, you can utilize Pinata Frame analytics by importing our custom middleware function `analyticsMiddleware`. \n\n``` typescript\nimport { PinataFDK } from \"pinata-fdk\";\nconst fdk = new PinataFDK({\n    pinata_jwt: \"\u003cYOUR_PINATA_JWT\u003e\",\n    pinata_gateway: \"\u003cYOUR_PINATA_GATEWAY\u003e\"}, \n);\n\nconst app = new Frog({\n  basePath: '/api',\n  // hubApiUrl: \"https://hub.pinata.cloud\"\n})\n\napp.use(\"/\", fdk.analyticsMiddleware({ frameId: \"frame_id\", customId: \"custom_id\"}));\n```\n\n\n## Pin Files from CLI\n### npx pin\n\nPin files directly from your `src` folder using the **pinata-fdk** `npx pin` command.\n\nCreate a `pins` folder located under your `src` folder\n\n```jsx\nsrc\n-pins/\n```\n\nAdd any images you want uploaded to IPFS! \n\n```jsx\nsrc\n-pins/\n--image.png\n```\n\nRun the command:\n\n```jsx\nnpx pin \u003cYOUR_PINATA_JWT\u003e\n```\n\nCheck your `src/pins` folder for a  `pins_list.json` file. Here you can easily access your CID to input into `getFrameMetadata`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPinataCloud%2Fpinata-fdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPinataCloud%2Fpinata-fdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPinataCloud%2Fpinata-fdk/lists"}