Coder Social home page Coder Social logo

farcaster-js's Introduction

Farcaster.js

A collection of tools for interacting with the Farcaster social network.

NPM NPM GitHub Workflow Status

Farcaster Hub REST API

Farcaster hubs expose a public REST API which can be used for simple queries.

Setup:

# Install all farcaster-js tools
npm install axios @standard-crypto/farcaster-js

# ...or install only the Hub REST API client
npm install axios @standard-crypto/farcaster-js-hub-rest

Example:

import { HubRestAPIClient, ExternalEd25519Signer } from '@standard-crypto/farcaster-js';

import { NobleEd25519Signer } from '@farcaster/core';

const client = new HubRestAPIClient();
console.log(await client.getHubInfo());

// Use a private key
const signerPrivateKey = '0x...';
const fid = 111;
const writeClient = new HubRestAPIClient({ hubUrl: 'https://hub.farcaster.standardcrypto.vc:2281' });

const publishCastResponse = await writeClient.submitCast({ text: 'This is a test cast submitted from farcaster-js' }, fid, signerPrivateKey);
console.log(`new cast hash: ${publishCastResponse.hash}`);

// Use an external signer
const nobleSigner = new NobleEd25519Signer(new Uint8Array([]));
const _signMessage = async(messageHash: Uint8Array): Promise<Uint8Array> => {
  const res = await nobleSigner.signMessageHash(messageHash);
  if (res.isErr()) {
    throw res.error;
  }
  return res._unsafeUnwrap();
};
const _getPublicKey = async(): Promise<Uint8Array> => {
  const res = await nobleSigner.getSignerKey();
  if (res.isErr()) {
    throw res.error;
  }
  return res._unsafeUnwrap();
};
const externalSigner = new ExternalEd25519Signer(_signMessage, _getPublicKey);

const publishCastExternalSignerResponse = await writeClient.submitCast({ text: 'This is a test cast submitted from farcaster-js using an external signer' }, fid, externalSigner);
console.log(`new cast hash with external signer: ${publishCastExternalSignerResponse.hash}`);

See the @standard-crypto/farcaster-js-hub-rest package for more info.

Neynar REST APIs

Setup:

# Install all farcaster-js tools
npm install axios @standard-crypto/farcaster-js

# ...or install only the Neynar API client
npm install axios @standard-crypto/farcaster-js-neynar

Example:

import { NeynarAPIClient, NeynarV2 } from '@standard-crypto/farcaster-js';

const signerUuid = 'approvedSignerUUID';
const client = new NeynarAPIClient('apiKey');

// Publish cast
const cast = await client.v2.publishCast(signerUuid, 'This is a test cast.');

// React to cast
await client.v2.reactToCast(signerUuid, NeynarV2.ReactionType.Like, cast.hash);

Signers

Signers are required to write data to Farcaster. You can learn more about signers from these resources (Farcaster, Neynar, Privy).

This package includes a CLI for creating signers. You can run the code below to generate a signer:

farcaster-js create-signer

Read more about the CLI in farcaster-js-cli.

Additionally, signers may be created programmatically without use of the CLI. See the examples in farcaster-js-neynar or follow this guide from Privy for logging users in with Farcaster and authorizing a signer.

Privy

Privy enables users to easily log in to your app using their Farcaster account. Follow this guide to enable Farcaster login and begin writing messages. See the example below for usage once logging in with Farcaster is integrated.

import { HubRestAPIClient, ExternalEd25519Signer } from '@standard-crypto/farcaster-js';
import { useExperimentalFarcasterSigner, usePrivy } from '@privy-io/react-auth';

const client = new HubRestAPIClient();
console.log(await client.getHubInfo());

const { user } = usePrivy();
const { getFarcasterSignerPublicKey, signFarcasterMessage } = useExperimentalFarcasterSigner();

// Use a Privy embedded signer
const privySigner = new ExternalEd25519Signer(signFarcasterMessage, getFarcasterSignerPublicKey);
const fid = user.farcaster.fid!;

const publishCastExternalSignerResponse = await client.submitCast({ text: 'This is a test cast submitted from farcaster-js using an external signer' }, fid, privySigner);
console.log(`new cast hash with privy embedded signer signer: ${publishCastExternalSignerResponse.hash}`);

Usage Versus Hub APIs:

The REST APIs exposed by a Farcaster hub are designed to provide protocol entities optimized for the transport and indexing layer. Neynar APIs are designed for building at the application-layer.

Neynar v1 APIs are designed to replicate the deprecated Warpcast APIs to ensure that the ecosystem of products built on those APIs can continue thriving with minimal switching costs. The Neynar v1 APIs should act serve a drop-in replacement for applications using farcaster-js pre-version 6.0.

Neynar v2 APIs bring in additional support for new Farcaster protocol primitives like channels and signer management with much more support for storage, sign in with farcaster and new features delivered regularly.

See https://neynar.com/ for API access and more details.

See the @standard-crypto/farcaster-js-neynar package for more on the Neynar API client.

farcaster-js's People

Contributors

dependabot[bot] avatar gsgalloway avatar piratekev avatar semantic-release-bot avatar whatrocks avatar payton avatar

Stargazers

Elijah Spina, PhD avatar Arti Villa avatar r48Bit avatar DK avatar C O M P Ξ Z avatar Bhavya Gosai avatar Zenix avatar 0xshanks avatar Blocksage avatar Iggy avatar Alex Kubica 🇮🇱 avatar  avatar Alexandros Panayi avatar agung senjaya avatar 0x000Saji avatar Brian Cooper avatar Melvin Kosisochukwu avatar Matthias Merkel avatar beeman avatar Lakshman Sankar avatar behkod avatar  avatar codingsh avatar Darryl Yeo avatar @artlu99 avatar Jonathan Zinger avatar Dylan Steck avatar guanbinrui avatar  avatar Milad Nekofar avatar  avatar Saksham Thapa avatar Darwin avatar Jayme Hoffman avatar jaybuidl avatar Jack Yeh avatar Derek Brown avatar Sandeep Kalidindi avatar Sam avatar Max Jackson avatar Paul Fletcher-Hill avatar joshcs.eth avatar  avatar Alex Reyes avatar Nick Beattie avatar Cameron Armstrong avatar Miguel Parramón Teixidó avatar Maurelian avatar lesgreys avatar Knoise avatar Alexey Elizarov avatar Kiren Srinivasan avatar DAR avatar Stone Gao avatar  avatar sfter avatar Lungoupao Khongsai avatar Eddy Lazzarin avatar Liang avatar Seve Kim avatar David Furlong avatar Peter Ferguson avatar Skylar Barrera avatar Dan Romero avatar Dimitris Lamprinos avatar Maindrop avatar mattwelter avatar Qibing avatar Breck Yunits avatar Madhav Jha avatar Ken Goldfarb avatar Nick Sawinyh avatar mikey avatar Andrew Lovett-Barron avatar  avatar Nikita avatar Gavin avatar Christopher Wallace avatar  avatar Harsh Vakharia avatar Justin Hunter avatar MrPreet avatar yathish.eth avatar Jacob Shiohira avatar Gabriel Castillo avatar Erick Martinez Jr. avatar Kevin Neaton avatar John Johnson avatar wijuwiju avatar soju avatar pugson avatar Jake Casey avatar Nero One avatar Steve Godlewski avatar yash karthik avatar Albert Putra Purnama avatar tani.eth avatar John Moore avatar arturs avatar Zach Terrell avatar

Watchers

Michael Demarais avatar  avatar

farcaster-js's Issues

Cloudflare Workers Compatibility

Describe the bug
It is not possible to use this library within Cloudflare Workers due to lack of Node.js runtime. To be specific, lack of Buffer causes this error. As recommended by the Node documentation, likely an import is going to solve this problem.

To Reproduce
Steps to reproduce the behavior:

  1. Import farcaster-js within a Cloudflare Workers function
  2. Try to share a cast using the library

Expected behavior
We are expecting to cast on Farcaster.

Desktop (please complete the following information):

  • OS: macOS 13.2
  • Node version: 18.0
  • Code Version: latest

Additional context

Cloudflare Workers have compatibility flags for Node APIs. If Buffer can be imported from node:buffer, this problem is likely to be solved.

Timestamp for posts returns a date far in the future

Describe the bug
After getting casts with fetchCastsForUser, whenever I print out the timestamp I get a unix timestamp that's far, far far ahead in the future.

Example value: 1678166638000 which is Sat, 25 Dec 55148

To Reproduce

  1. Get post with fetchCastsForUser()
  2. Print timestamp value

Expected behavior
A real timestamp

Desktop (please complete the following information):

  • OS: macOS 13.2
  • Node version: v16.19.1
  • Code Version: 5.5.3

Basic example failing with 401

Describe the bug
Hey there, I'm trying to run the basic example and it seems that it fails with a 401 HTTP code.
Am I missing anything? Thank you in advance!

To Reproduce
Steps to reproduce the behavior:

  1. Run the following code:
import { MerkleAPIClient } from "@standard-crypto/farcaster-js";
import { ethers } from "ethers";

const wallet = new ethers.createRandom();
const client = new MerkleAPIClient(wallet);

const main = async () => {
	// by username
	await client.lookupUserByUsername("dwr");
}
main()

Thank you

Hey just wanted to say a big thank you for this library - it's helped me tremendously cut down the amount of code I need to write and the types are also super useful.

I've run into two little things while using this library, and thought it would make sense to leave them here in case they're useful.

  1. The fetchUserCastLikes function has an unusual type and comment that might be a mistake: https://github.com/standard-crypto/farcaster-js/blob/develop/docs/classes/index.MerkleAPIClient.md#fetchusercastlikes "Fetch the latest cast for the user, if there is one". The return type is a Cast although GET /v2/user-cast-likes returns a form of Like object with different properties.
  2. The errors by the library when a request fails don't seem to include the farcaster API request error message. The farcaster api response body usually includes a JSON body { errors: Array<{ message: string }> when it errors, and it would be super useful to have an easy way to get this. There may already be a way that I'm missing - I saw that I can get this error via the logger, but not via the rejected promise.

Anyways I really appreciate the work on this library 🙏

Feel free to close this issue, and I hope I haven't done too big a faux pas by ignoring the issue template

fetchUserAssetCollections endpoint changed

New URL is v2/grouped-assets?limit=20&ownerFid=3

new response schema is

{
   "result":{
      "groups":[
         {
            "collection":{
               "id":"wdlaty",
               "name":"We Don't Live a Thousand Years",
               "description":"The NFT that unlocks the WDLaTY book!",
               "itemCount":1,
               "ownerCount":398,
               "farcasterOwnerCount":88,
               "imageUrl":"https://i.seadn.io/gcs/files/9a3c37ae680e5c56eb48cbd213677895.png?w=500&auto=format",
               "floorPrice":"0.02",
               "volumeTraded":"4.830334610000002",
               "externalUrl":"http://book.borodutch.com",
               "openSeaUrl":"https://opensea.io/collection/wdlaty",
               "collectionOwners":[
                  {
                     "fid":3,
                     "username":"dwr.eth",
                     "displayName":"Dan Romero",
                     "pfp":{
                        "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                        "verified":false
                     },
                     "profile":{
                        "bio":{
                           "text":"Working on Farcaster and Warpcast.",
                           "mentions":[
                              
                           ]
                        },
                        "location":{
                           "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                           "description":"Los Angeles, CA, USA"
                        }
                     },
                     "followerCount":12720,
                     "followingCount":2388,
                     "activeOnFcNetwork":true,
                     "viewerContext":{
                        
                     },
                     "protocolBudgets":{
                        "canAddLinks":true
                     }
                  }
               ],
               "chain":"ethereum"
            },
            "assets":[
               {
                  "id":"0189e2fa-5fdd-7852-d770-a1430329169a",
                  "name":"WDLaTY Download Token",
                  "contractAddress":"0x495f947276749ce646f68ac8c248420045cb7b5e",
                  "tokenId":"86597206928702930307486193712987064466367043993614253349341663474748447785515",
                  "imageUrl":"https://i.seadn.io/gae/q4zbrMUEGZ_FaqHQw-tbAVhQq6emSr6JJuX1q8ESny4FSPadGiTXrEtyEp37rEZ-aZJ_UKnjnn6XbrYEdL9STnzY_fu5ri1BSKmBCw?w=500&auto=format",
                  "externalUrl":"https://opensea.io/assets/ethereum/0x495f947276749ce646f68ac8c248420045cb7b5e/86597206928702930307486193712987064466367043993614253349341663474748447785515",
                  "openSeaUrl":"https://opensea.io/assets/ethereum/0x495f947276749ce646f68ac8c248420045cb7b5e/86597206928702930307486193712987064466367043993614253349341663474748447785515",
                  "likeCount":3,
                  "uri":"chain://eip155:1/erc721:0x495f947276749Ce646f68AC8c248420045cb7b5e/86597206928702930307486193712987064466367043993614253349341663474748447785515",
                  "collection":{
                     "id":"wdlaty",
                     "name":"We Don't Live a Thousand Years",
                     "description":"The NFT that unlocks the WDLaTY book!",
                     "itemCount":1,
                     "ownerCount":398,
                     "farcasterOwnerCount":88,
                     "imageUrl":"https://i.seadn.io/gcs/files/9a3c37ae680e5c56eb48cbd213677895.png?w=500&auto=format",
                     "floorPrice":"0.02",
                     "volumeTraded":"4.830334610000002",
                     "externalUrl":"http://book.borodutch.com",
                     "openSeaUrl":"https://opensea.io/collection/wdlaty",
                     "collectionOwners":[
                        {
                           "fid":3,
                           "username":"dwr.eth",
                           "displayName":"Dan Romero",
                           "pfp":{
                              "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                              "verified":false
                           },
                           "profile":{
                              "bio":{
                                 "text":"Working on Farcaster and Warpcast.",
                                 "mentions":[
                                    
                                 ]
                              },
                              "location":{
                                 "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                                 "description":"Los Angeles, CA, USA"
                              }
                           },
                           "followerCount":12720,
                           "followingCount":2388,
                           "activeOnFcNetwork":true,
                           "viewerContext":{
                              
                           },
                           "protocolBudgets":{
                              "canAddLinks":true
                           }
                        }
                     ],
                     "chain":"ethereum"
                  },
                  "owner":{
                     "fid":3,
                     "username":"dwr.eth",
                     "displayName":"Dan Romero",
                     "pfp":{
                        "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                        "verified":false
                     },
                     "profile":{
                        "bio":{
                           "text":"Working on Farcaster and Warpcast.",
                           "mentions":[
                              
                           ]
                        },
                        "location":{
                           "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                           "description":"Los Angeles, CA, USA"
                        }
                     },
                     "followerCount":12720,
                     "followingCount":2388,
                     "activeOnFcNetwork":true,
                     "referrerUsername":"farcaster",
                     "viewerContext":{
                        "following":false
                     },
                     "protocolBudgets":{
                        "canAddLinks":true
                     }
                  },
                  "viewerContext":{
                     "liked":false,
                     "owns":false
                  }
               }
            ]
         },
         {
            "collection":{
               "id":"boredapeyachtclub",
               "name":"Bored Ape Yacht Club",
               "description":"The Bored Ape Yacht Club is a collection of 10,000 unique Bored Ape NFTs— unique digital collectibles living on the Ethereum blockchain. Your Bored Ape doubles as your Yacht Club membership card, and grants access to members-only benefits, the first of which is access to THE BATHROOM, a collaborative graffiti board. Future areas and perks can be unlocked by the community through roadmap activation. Visit www.BoredApeYachtClub.com for more details.",
               "itemCount":9998,
               "ownerCount":5558,
               "farcasterOwnerCount":59,
               "imageUrl":"https://i.seadn.io/gae/Ju9CkWtV-1Okvf45wo8UctR-M9He2PjILP0oOvxE89AyiPPGtrR3gysu1Zgy0hjd2xKIgjJJtWIc0ybj4Vd7wv8t3pxDGHoJBzDB?w=500&auto=format",
               "floorPrice":"26.88",
               "volumeTraded":"1270191.7206593272",
               "externalUrl":"http://www.boredapeyachtclub.com/",
               "openSeaUrl":"https://opensea.io/collection/boredapeyachtclub",
               "twitterUsername":"BoredApeYC",
               "schemaName":"ERC721",
               "collectionOwners":[
                  {
                     "fid":3,
                     "username":"dwr.eth",
                     "displayName":"Dan Romero",
                     "pfp":{
                        "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                        "verified":false
                     },
                     "profile":{
                        "bio":{
                           "text":"Working on Farcaster and Warpcast.",
                           "mentions":[
                              
                           ]
                        },
                        "location":{
                           "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                           "description":"Los Angeles, CA, USA"
                        }
                     },
                     "followerCount":12720,
                     "followingCount":2388,
                     "activeOnFcNetwork":true,
                     "viewerContext":{
                        
                     },
                     "protocolBudgets":{
                        "canAddLinks":true
                     }
                  }
               ],
               "chain":"ethereum"
            },
            "assets":[
               {
                  "id":"0189e781-fbdc-f2bf-b694-ce77d8a9bffb",
                  "name":"Bored Ape Yacht Club #5080",
                  "contractAddress":"0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
                  "tokenId":"5080",
                  "imageUrl":"https://i.seadn.io/gae/cEGkUDEANqvBu2ILg0XFM8tui9naGSzM5bT_YfQvk4acDOL2FEsU5Oss7yCEGl1YpxlQUbWhMaZAQtOeROXy1CC4X1DJNsQYKC5l?w=500&auto=format",
                  "externalUrl":"https://opensea.io/assets/ethereum/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/5080",
                  "openSeaUrl":"https://opensea.io/assets/ethereum/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/5080",
                  "likeCount":2,
                  "uri":"chain://eip155:1/erc721:0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D/5080",
                  "collection":{
                     "id":"boredapeyachtclub",
                     "name":"Bored Ape Yacht Club",
                     "description":"The Bored Ape Yacht Club is a collection of 10,000 unique Bored Ape NFTs— unique digital collectibles living on the Ethereum blockchain. Your Bored Ape doubles as your Yacht Club membership card, and grants access to members-only benefits, the first of which is access to THE BATHROOM, a collaborative graffiti board. Future areas and perks can be unlocked by the community through roadmap activation. Visit www.BoredApeYachtClub.com for more details.",
                     "itemCount":9998,
                     "ownerCount":5558,
                     "farcasterOwnerCount":59,
                     "imageUrl":"https://i.seadn.io/gae/Ju9CkWtV-1Okvf45wo8UctR-M9He2PjILP0oOvxE89AyiPPGtrR3gysu1Zgy0hjd2xKIgjJJtWIc0ybj4Vd7wv8t3pxDGHoJBzDB?w=500&auto=format",
                     "floorPrice":"26.88",
                     "volumeTraded":"1270191.7206593272",
                     "externalUrl":"http://www.boredapeyachtclub.com/",
                     "openSeaUrl":"https://opensea.io/collection/boredapeyachtclub",
                     "twitterUsername":"BoredApeYC",
                     "schemaName":"ERC721",
                     "collectionOwners":[
                        {
                           "fid":3,
                           "username":"dwr.eth",
                           "displayName":"Dan Romero",
                           "pfp":{
                              "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                              "verified":false
                           },
                           "profile":{
                              "bio":{
                                 "text":"Working on Farcaster and Warpcast.",
                                 "mentions":[
                                    
                                 ]
                              },
                              "location":{
                                 "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                                 "description":"Los Angeles, CA, USA"
                              }
                           },
                           "followerCount":12720,
                           "followingCount":2388,
                           "activeOnFcNetwork":true,
                           "viewerContext":{
                              
                           },
                           "protocolBudgets":{
                              "canAddLinks":true
                           }
                        }
                     ],
                     "chain":"ethereum"
                  },
                  "owner":{
                     "fid":3,
                     "username":"dwr.eth",
                     "displayName":"Dan Romero",
                     "pfp":{
                        "url":"https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA",
                        "verified":false
                     },
                     "profile":{
                        "bio":{
                           "text":"Working on Farcaster and Warpcast.",
                           "mentions":[
                              
                           ]
                        },
                        "location":{
                           "placeId":"ChIJE9on3F3HwoAR9AhGJW_fL-I",
                           "description":"Los Angeles, CA, USA"
                        }
                     },
                     "followerCount":12720,
                     "followingCount":2388,
                     "activeOnFcNetwork":true,
                     "referrerUsername":"farcaster",
                     "viewerContext":{
                        "following":false
                     },
                     "protocolBudgets":{
                        "canAddLinks":true
                     }
                  },
                  "viewerContext":{
                     "liked":false,
                     "owns":false
                  }
               }
            ]
         }
      ]
   },
   "next":{
      "cursor":"eyJwYWdlIjoxLCJsaW1pdCI6MjAsIm93bmVyRmlkIjozfQ"
   }
}

`publishCast` fails when user's latest action was a recast

when calling publishCast with a wallet that has the latest activity as recast of other accounts, the function throws an error saying cast address and signer address don’t match (because FC api now returns body.address of the user who got recasted not the user who recasted).

CJS / ESM Issue

Describe the bug
I'm migrating from 5.x to 6.x. I'm getting an exception when importing and using the latest version of this lib:

file:///Users/colinarms/src/papyrus-monorepo-v2/node_modules/@standard-crypto/farcaster-js-hub-rest/dist/esm/hubRestApiClient.js:1
import axios, { AxiosError } from 'axios';
                ^^^^^^^^^^
SyntaxError: Named export 'AxiosError' not found. The requested module 'axios' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'axios';
const { AxiosError } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:128:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:194:5)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
    at async importModuleDynamicallyWrapper (node:internal/vm/module:437:15)

Node.js v17.8.0

To Reproduce
Steps to reproduce the behavior:

  1. import { NeynarAPIClient } from "@standard-crypto/farcaster-js" in ESM environment
  2. run node esbuild.mjs

My esbuild:

import esbuild from "esbuild"
import fs from "fs/promises"
import path from "path"
import { execSync } from "child_process"

const distDir = "./dist"
const copyFilesScript = "yarn copy-files"
const fileExtensions = [".js", ".ts", ".json"]

// Remove the dist folder
execSync(`rm -rf ${distDir}`)

// Traverse the directory and collect all files with specified extensions
async function collectFiles(dir, fileList = []) {
  const files = await fs.readdir(dir)

  for (const file of files) {
    const filePath = path.join(dir, file)
    const stat = await fs.stat(filePath)

    if (stat.isDirectory()) {
      if (!filePath.includes("node_modules")) {
        await collectFiles(filePath, fileList)
      }
    } else {
      if (fileExtensions.includes(path.extname(file))) {
        fileList.push(filePath)
      }
    }
  }

  return fileList
}

console.log("Collecting files...")
const entryPoints = await collectFiles("./")
console.log("Collected " + entryPoints.length + " files")

// Bundle the files using esbuild
try {
  console.log("Building...")
  await esbuild.build({
    entryPoints,
    sourcemap: true,
    loader: { ".json": "copy" },
    format: "esm",
    platform: "node",
    target: "node17",
    outdir: distDir,
    allowOverwrite: true,
    tsconfig: "./tsconfig.json",
  })
  console.log("Copying files...")

  // Copy additional files after bundling is complete
  execSync(copyFilesScript)
} catch (err) {
  console.error(err)
  process.exit(1)
}

Expected behavior
I can import and use the package successfully in an ESM environment

Desktop (please complete the following information):
v 6.0.3

Notification type `cast-mention` and `cast-reply` doesn't have `content.cast` type

Describe the bug
I fetched notification with v2MentionAndReplyNotificationsGet(), and filter out the notification where type is cast-mention and cast-reply. The farcaster-js type for that data doesn't have the content.cast field.

To Reproduce
Steps to reproduce the behavior:

  1. const notifications = v2MentionAndReplyNotificationsGet()
  2. notifications.map(notification => notification.content.cast)
  3. TypeScript throws error, that's a valid data returned from Merkle's Hub

Expected behavior
Type in farcaster-js should have the content.cast field.

Screenshots
Screenshot from 2023-01-12 18-56-49
Screenshot from 2023-01-12 18-57-45
Screenshot from 2023-01-12 18-58-10

Desktop (please complete the following information):

  • OS: [e.g. Ubuntu 22.04, macOS 11.4]
  • Node version [e.g 16.4.2]
  • Code Version [e.g. 1.1.0]

Additional context
Add any other context about the problem here.

Direct casts

Is your feature request related to a problem? Please describe.
Problem: you can build 90% of a farcaster client only using farcasterjs (which is amazing!) but it's missing direct casts.

Describe the solution you'd like
An API for retrieving and sending direct casts

Describe alternatives you've considered
Haven't looked into it too much but the alternative is to mess with farcaster hubs

Support arbitrary strings for cast targets

As per FIP-2, we need to support arbitrary cast targets. Currently the library enforces that cast targets match a regex for cast hashes only.

Example: chain://eip155:base/erc721:0x9a9AcbA3c0799018C85A71DcD8A5C916468C9618

Support hub APIs

Is your feature request related to a problem? Please describe.
This library generated a client off of outdated openapi specs and requires manual modification over generated code for ongoing maintenance, which is not ideal.

Farcaster hubs are launching soon, but we still need to rely on the Warpcast API to retrieve data such as a user's follower graph from Wrapcast.

We should redirect some of the API helpers in this library to point to farcaster hubs instead of Warpcast APIs.

Describe the solution you'd like

  • Generate Typescript bindings off of farcaster's protobuf specs
  • Combine grpc client with MerkleAPI client to support necessary Warpcast API methods
  • Mark duplicate Warpcast API methods as legacy (or just remove them)
  • Remove everything generated from the outdated openapi specifications

Describe alternatives you've considered
Simply re-export farcaster packages in index.ts

export * from '@farcaster/protobufs';
export * from '@farcaster/utils';

But we'll have to deal with the hub client and the Merkle client which is bad developer ergonomics.

Additional context
Add any other context or screenshots about the feature request here.

Add ability to use 'embeds' and 'mentions' when publishing casts

Is your feature request related to a problem? Please describe.
Warpcast no longer processes text to generate embeds: https://warpcast.com/gt/0xfca6bf

We run a bot that posts content from our users. Historically, Warpcast crawled links contained within our casts, then used that as the cast image, which was great. Now, according to the above, the Warpcast team does not parse text anymore, so we manually need to add images/links to the embeds array when publishing a cast.

This package does not support adding in fields beyond text when publishing a cast.

Describe the solution you'd like

  • modify publishCast to support adding in the embeds/mentions array; or,
  • create a new method to add more complex publishing options like embeds/mentions, and leave publishCast to be a simple text cast

Describe alternatives you've considered
We can use hubs directly, eg https://github.com/farcasterxyz/hub-monorepo/blob/main/packages/hub-nodejs/examples/make-cast/index.ts, but we already rely on this package so would prefer not to migrate.

Additional context
Weeks ago, when Warpcast crawled links (beautiful):

image

Now (ugly):

image

Bring the swagger doc up to current API spec

The original API bindings were generated from an OpenAPI 2.0 spec provided by the Warpcast API team, but was deprecated in favor of written API documentation and has not been kept up-to-date by neither myself nor the Warpcast team.

This of course makes adding new API bindings a nuisance, as the OpenAPI generators cannot be used to create new bindings, and a rather hacky alternative has been used instead -- which is to copy existing generated code and make manual edits to produce bindings for the new endpoints.

The obvious next step is to take over ownership of the OpenAPI spec, bring it up to date, and ensure that the OpenAPI-generated code is readable and accurate.

In addition to making maintenance of this package easier, this can help others interacting with the Warpcast API in different languages.

The automated release is failing 🚨

🚨 The automated release from the main branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the main branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


No npm token specified.

An npm token must be created and set in the NPM_TOKEN environment variable on your CI environment.

Please make sure to create an npm token and to set it in the NPM_TOKEN environment variable on your CI environment. The token must allow to publish to the registry https://registry.npmjs.org/.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Prevent users getting stuck with 401s due to too many Auth Tokens

There's some degenerate behavior where once a user has too many API tokens active at once, they start hitting 401 errors from the Warpcast API.

Here's a TG thread showcasing the issue: https://t.me/farcasterdevchat/3441

Here is a script people have been using to wipe all outstanding tokens: https://github.com/davidfurlong/farcaster-auth-tokens/blob/main/revoke-all.ts

We should:

  • Reproduce the issue in a test
  • Understand the user story that results in this situation. I think it's user's just re-instantiating the MerkleAPIClient class over and over instead of reusing it. Which is a valid thing to want to do, and would surprise a user when it eventually leads to 401s.
  • Add in the function to help users wipe all existing auth tokens
  • Add code or documentation to prevent users from running into this problem

Add Wrapcast API methods for signer requests

Is your feature request related to a problem? Please describe.
Add wrapper methods for new Warpcast APIs supporting the signer request flow:
https://warpcast.notion.site/Warpcast-v2-API-Documentation-c19a9494383a4ce0bd28db6d44d99ea8#13cb11cba1114002adc928c5fa679364

Describe the solution you'd like
n/a

Describe alternatives you've considered
n/a

Additional context
https://warpcast.notion.site/Warpcast-API-Docs-Signer-Requests-Public-e02ef71883374d2ca8d27239a8cc35d5

The automated release is failing 🚨

🚨 The automated release from the 4.0.x branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the 4.0.x branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


The release 4.0.1 on branch 4.0.x cannot be published as it is out of range.

Based on the releases published on other branches, only versions within the range >=4.0.0 <4.0.0 can be published from branch 4.0.x.

The following commits are responsible for the invalid release:

  • ci: run CI on 4.0.x maintenance branch (96ed4df)
  • fix: rewrite api client to mask some server-side changes to the API (f7f38d6)
  • docs: simplify import from example (6870c57)

Those commits should be moved to a valid branch with git merge or git cherry-pick and removed from branch 4.0.x with git revert or git reset.

A valid branch could be main.

See the workflow configuration documentation for more details.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Did you mean to import ethers/lib/utils.js?

Describe the bug
Trying to publish a cast as instructed in the README throws the following error:

node:internal/process/esm_loader:94
    internalBinding('errors').triggerUncaughtException(
                              ^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/kn/repos/kn/ncbot/node_modules/ethers/lib/utils' imported from /Users/kn/repos/kn/ncbot/node_modules/@standard-crypto/farcaster-js/dist/esm/index.mjs
Did you mean to import ethers/lib/utils.js?
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:418:11)
    at moduleResolve (node:internal/modules/esm/resolve:983:10)
    at defaultResolve (node:internal/modules/esm/resolve:1080:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:530:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:251:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:79:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Here is the script

To Reproduce
Steps to reproduce the behavior:

  1. Pull the kn/ncbot repo
  2. Run yarn run bot

Expected behavior
Successfully post a cast

Desktop (please complete the following information):

  • OS: macOS 12.6
  • Node version: v16.14.2
  • Code Version 3.0.3

Looking up user by address or name returns error

Describe the bug
The lookup functions in UserRegistry always return error, even though it's obviously not.

await userRegistry.lookupByUsername("dwr");

Even that errors out. Contracts are currently being upgraded to v2. Could be the cause?

To Reproduce
Steps to reproduce the behavior:

  1. Install a fresh Next.js app
  2. Copy-paste code in "Look up a user" in the README

Expected behavior
User that exist in the network should not return error, likewise with custody address that has fid.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: Fedora 34
  • Node version: 16.16
  • Code Version: 1.1.0

Additional context
Add any other context about the problem here.

Add the ability to pass an authentication token instead of a wallet to the MerkleApiClient constructor

Is your feature request related to a problem? Please describe.

If I want to authenticate a request on behalf of a user who has generated an authentication token and given it to my app via a signature, I can't currently do it. Some endpoints in fact require this user's authentication token rather than someone else's, like publishCast.

Describe the solution you'd like

Add the ability to pass an authentication token instead of a wallet to the MerkleApiClient constructor.
https://farcasterxyz.notion.site/Merkle-v2-API-Documentation-c19a9494383a4ce0bd28db6d44d99ea8#c8290028e8f64238bdd2db8938b29b9b

Describe alternatives you've considered

Using fetch directly instead of this sdk

Additional context

none

Add methods for unimplimented Neynar V2 endpoints

Describe the solution you'd like
The latest Neynar V2 spec includes the following new endpoints:

GET /farcaster/user/bulk
POST & DELETE /farcaster/user/verification
GET /farcaster/user/custody-address
GET /farcaster/notifications
GET /farcaster/followers/relevant

Implement methods to expose the functionality of these endpoints. The following methods should be implemented in the Neynar V2 client and have tests added:

getUsers(fids: string[])
addVerification(signerUuid: string, address: string, blockHash: string, ethSignature: string)
deleteVerification(signerUuid: string, address: string, blockHash: string, ethSignature: string)
getUserByVerificationAddress(address: string)
getUserNotifications(fid: string)
getUserRelevantFollowers(targetFid: string, viewerFid: string)

Additional context
For the new verification methods, it's worth looking into abstracting away signing the message from the user, similar to what's done in the hub-rest package for signing verifications.

The Neynar V2 spec can be found here: neynarxyz/OAS/blob/main/src/v2/spec.yaml.

There are some manual steps to clean up the spec so that it works for us:

  1. Delete the Parameter ApiKey everywhere it occurs
  2. Replace the security and securitySchemes blocks in the swagger. The first 20 lines of the file should look like this:
openapi: 3.0.0
info:
  title: Farcaster API V2
  version: "2.0"
servers:
  - url: https://api.neynar.com/v2
security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
      description: API key required for authentication. use value --> NEYNAR_API_DOCS<-- for testing
  schemas:

Unable to install @standard-crypto/farcaster-js package

Describe the bug
When running the command yarn add @standard-crypto/farcaster-js, the following error is encountered

yarn add v1.22.19
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > [email protected]" has unmet peer dependency "@types/node@*".
warning " > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^8.56.0".
warning "@typescript-eslint/eslint-plugin > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^8.56.0".
warning "@typescript-eslint/eslint-plugin > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^8.56.0".
warning " > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^8.56.0".
warning "@standard-crypto/farcaster-js > @standard-crypto/[email protected]" has incorrect peer dependency "axios@~1.5.1".
warning " > @standard-crypto/[email protected]" has incorrect peer dependency "axios@~1.5.1".
[4/4] 🔨  Building fresh packages...
[-/3] ⠁ waiting...
[2/3] ⠁ ref-napi
error /Users/pranavprakash/workspace/merokudao/farcaster_cli/node_modules/ref-napi: Command failed.
Exit code: 1
Command: node-gyp-build
Arguments: 
Directory: /Users/pranavprakash/workspace/merokudao/farcaster_cli/node_modules/ref-napi
Output:
node:events:492
      throw er; // Unhandled 'error' event
      ^

Error: spawn node-gyp ENOENT
    at ChildProcess._handle.onexit (node:internal/child_process:286:19)
    at onErrorNT (node:internal/child_process:484:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
Emitted 'error' event on ChildProcess instance at:
    at ChildProcess._handle.onexit (node:internal/child_process:292:12)
    at onErrorNT (node:internal/child_process:484:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'spawn node-gyp',
  path: 'node-gyp',
  spawnargs: [ 'rebuild' ]
}

To Reproduce
Steps to reproduce the behavior:

  1. Run yarn add @standard-crypto/farcaster-js
  2. Note the error

Expected behavior
The package should get installed correctly

Desktop (please complete the following information):

  • OS: macOS 14.4.1 (23E224), Macbook Air M1 2020
  • Node version: v20.9.0
  • Yarn Version: 1.22.19
  • Code Version: latest

Unable to submitCast into channel / missing parentUrl

Describe the bug

 const writeClient = new HubRestAPIClient({ hubUrl });
 const publishCastResponse = await writeClient.submitCast(data, fid, signerPrivateKey)

cannot send parentUrl in data, so cannot submit casts into channels

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.