generated from NEARBuilders/project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add farcaster plugin #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dungpt99
wants to merge
1
commit into
main
Choose a base branch
from
feat/farcaster_plugin
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| --- | ||
| sidebar_position: 9 | ||
| --- | ||
|
|
||
| # 🟣 Farcaster Plugin | ||
|
|
||
| The Farcaster plugin enables distribution of curated content to [Farcaster](https://farcaster.xyz) using the Neynar API. | ||
|
|
||
| ## 🔧 Setup Guide | ||
|
|
||
| 1. **Get Neynar API Credentials** | ||
| - Sign up at [Neynar](https://neynar.com) and obtain your API key. | ||
| - Create a signer in the Neynar dashboard and copy the `signerUuid`. | ||
|
|
||
| 2. **Add the Plugin to Your Configuration** | ||
|
|
||
| In your `curate.config.json` or via the Plugin Manager UI, add the Farcaster plugin: | ||
|
|
||
| ```json | ||
| { | ||
| "outputs": { | ||
| "stream": { | ||
| "enabled": true, | ||
| "distribute": [ | ||
| { | ||
| "plugin": "@curatedotfun/farcaster", | ||
| "config": { | ||
| "apiKey": "{FARCASTER_API_KEY}", | ||
| "signerUuid": "{FARCASTER_SIGNER_UUID}" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > **Tip:** Use environment variable placeholders (e.g., `{FARCASTER_API_KEY}`) and set them in your `.env` file for security. | ||
|
|
||
| ## ⚙️ Configuration | ||
|
|
||
| | Parameter | Type | Required | Description | | ||
| |------------|--------|----------|---------------------------------------------| | ||
| | apiKey | string | Yes | Your Neynar API key | | ||
| | signerUuid | string | Yes | The UUID of your Neynar signer | | ||
|
|
||
| - Get your API key and signer UUID from the [Neynar dashboard](https://neynar.com). | ||
|
|
||
| ## 🚀 Usage | ||
|
|
||
| Once configured, the plugin will post content to Farcaster using the Neynar API whenever a distribution action is triggered. | ||
|
|
||
| No additional setup is required after configuration. The plugin will use the provided credentials to publish casts. | ||
|
|
||
| ## 🛡️ Security Notes | ||
|
|
||
| - **Never commit your API key or signer UUID to version control.** | ||
| - Store sensitive credentials in environment variables or a secure configuration management system. | ||
|
|
||
| ## 📝 Example | ||
|
|
||
| ```typescript | ||
| import { FarcasterPlugin } from '@curatedotfun/farcaster'; | ||
|
|
||
| const plugin = new FarcasterPlugin(); | ||
| await plugin.initialize({ | ||
| apiKey: process.env.FARCASTER_API_KEY!, | ||
| signerUuid: process.env.FARCASTER_SIGNER_UUID! | ||
| }); | ||
| await plugin.distribute({ input: 'Hello, Farcaster!', config: plugin["config"] }); | ||
| ``` | ||
|
|
||
| ## 🔗 Resources | ||
| - [Farcaster](https://farcaster.xyz) | ||
| - [Neynar API](https://docs.neynar.com/) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # @curatedotfun/farcaster | ||
|
|
||
| A Farcaster plugin for curatedotfun that allows posting content to the Farcaster network using the Neynar API. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| npm install @curatedotfun/farcaster | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```typescript | ||
| import { FarcasterPlugin } from '@curatedotfun/farcaster'; | ||
|
|
||
| // Initialize the plugin with your Neynar API credentials | ||
| const farcasterPlugin = new FarcasterPlugin({ | ||
| apiKey: 'your-neynar-api-key', // Get from https://neynar.com | ||
| signerUuid: 'your-signer-uuid' // Get from Neynar dashboard | ||
| }); | ||
|
|
||
| // Initialize the plugin | ||
| await farcasterPlugin.initialize(); | ||
|
|
||
| // Post content to Farcaster | ||
| await farcasterPlugin.post('Hello, Farcaster!'); | ||
|
|
||
| // Cleanup when done | ||
| await farcasterPlugin.shutdown(); | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| The plugin requires the following configuration: | ||
|
|
||
| - `apiKey`: Your Neynar API key (get it from https://neynar.com) | ||
| - `signerUuid`: Your signer UUID from Neynar dashboard | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| 1. A Neynar API key (get it from https://neynar.com) | ||
| 2. A signer UUID from your Neynar dashboard | ||
|
|
||
| ## Security Notes | ||
|
|
||
| - Never commit your API key or signer UUID to version control | ||
| - Store sensitive credentials in environment variables or a secure configuration management system | ||
|
|
||
| ## License | ||
|
|
||
| MIT | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| { | ||
| "name": "@curatedotfun/farcaster", | ||
| "version": "0.0.1", | ||
| "description": "Farcaster plugin for curatedotfun", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "type": "module", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/index.js" | ||
| } | ||
| }, | ||
| "license": "MIT", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "files": [ | ||
| "dist", | ||
| "package.json" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/potlock/curatedotfun-plugins.git", | ||
| "directory": "packages/farcaster" | ||
| }, | ||
| "keywords": [ | ||
| "curatedotfun", | ||
| "farcaster", | ||
| "distribute", | ||
| "plugin" | ||
| ], | ||
| "scripts": { | ||
| "build": "rspack build && tsc -p tsconfig.build.json", | ||
| "dev": "rspack serve", | ||
| "lint": "tsc --noEmit", | ||
| "test": "vitest" | ||
| }, | ||
| "devDependencies": { | ||
| "@curatedotfun/types": "workspace:*", | ||
| "@curatedotfun/utils": "workspace:*", | ||
| "@rspack/cli": "latest", | ||
| "@types/jest": "^29.5.14", | ||
| "typescript": "^5.0.0", | ||
| "vitest": "^3.0.7" | ||
| }, | ||
| "dependencies": { | ||
| "@module-federation/node": "^2.7.2", | ||
| "@neynar/nodejs-sdk": "^2.46.0" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| const path = require("path"); | ||
| const { rspack } = require("@rspack/core"); | ||
| const pkg = require("./package.json"); | ||
| const { getNormalizedRemoteName } = require("@curatedotfun/utils"); | ||
|
|
||
| module.exports = { | ||
| entry: "./src/index", | ||
| mode: process.env.NODE_ENV === "development" ? "development" : "production", | ||
| target: "async-node", | ||
| devtool: "source-map", | ||
| output: { | ||
| uniqueName: getNormalizedRemoteName(pkg.name), | ||
| publicPath: "auto", | ||
| path: path.resolve(__dirname, "dist"), | ||
| clean: true, | ||
| library: { type: "commonjs-module" }, | ||
| }, | ||
| devServer: { | ||
| static: path.join(__dirname, "dist"), | ||
| hot: true, | ||
| port: 3013, // Using a different port than translate plugin | ||
| devMiddleware: { | ||
| writeToDisk: true, | ||
| }, | ||
| }, | ||
| module: { | ||
| rules: [ | ||
| { | ||
| test: /\.tsx?$/, | ||
| use: "builtin:swc-loader", | ||
| exclude: /node_modules/, | ||
| }, | ||
| ], | ||
| }, | ||
| resolve: { | ||
| extensions: [".tsx", ".ts", ".js"], | ||
| }, | ||
| plugins: [ | ||
| new rspack.container.ModuleFederationPlugin({ | ||
| name: getNormalizedRemoteName(pkg.name), | ||
| filename: "remoteEntry.js", | ||
| runtimePlugins: [ | ||
| require.resolve("@module-federation/node/runtimePlugin"), | ||
| ], | ||
| library: { type: "commonjs-module" }, | ||
| exposes: { | ||
| "./plugin": "./src/index.ts", | ||
| }, | ||
| shared: {}, | ||
| }), | ||
| ], | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import { NeynarAPIClient } from "@neynar/nodejs-sdk"; | ||
| import type { DistributorPlugin, ActionArgs } from "@curatedotfun/types"; | ||
|
|
||
| interface FarcasterConfig extends Record<string, unknown> { | ||
| apiKey: string; | ||
| signerUuid: string; | ||
| } | ||
|
|
||
| export class FarcasterPlugin | ||
| implements DistributorPlugin<{ content: string }, FarcasterConfig> | ||
| { | ||
| readonly type = "distributor" as const; | ||
| private client!: NeynarAPIClient; | ||
| private config!: FarcasterConfig; | ||
|
|
||
| constructor() { | ||
| // Initialize without config, will be set in initialize() | ||
| } | ||
|
|
||
| async initialize(config?: FarcasterConfig): Promise<void> { | ||
| if (!config?.apiKey) { | ||
| throw new Error("Neynar API key is required"); | ||
| } | ||
| if (!config?.signerUuid) { | ||
| throw new Error("Signer UUID is required"); | ||
| } | ||
|
|
||
| this.config = config; | ||
| this.client = new NeynarAPIClient({ | ||
| apiKey: this.config.apiKey, | ||
| }); | ||
| } | ||
|
|
||
| async distribute({ | ||
| input, | ||
| }: ActionArgs<{ content: string }, FarcasterConfig>): Promise<void> { | ||
| if (!input) { | ||
| throw new Error("Input is required"); | ||
| } | ||
|
|
||
| try { | ||
| await this.client.publishCast({ | ||
| signerUuid: this.config.signerUuid, | ||
| text: input.content, | ||
| }); | ||
| } catch (error) { | ||
| console.error("Error posting to Farcaster:", error); | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| async shutdown(): Promise<void> { | ||
| // No cleanup needed | ||
| } | ||
| } | ||
|
|
||
| export default FarcasterPlugin; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "extends": "./tsconfig.json", | ||
| "exclude": ["**/*.test.ts", "**/*.spec.ts"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "extends": "../../tsconfig.json", | ||
| "compilerOptions": { | ||
| "outDir": "./dist", | ||
| "rootDir": "./src", | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@/*": ["./src/*"] | ||
| } | ||
| }, | ||
| "include": ["src/**/*"], | ||
| "exclude": ["node_modules", "dist"] | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the incorrect usage example.
The usage example contains several errors that don't match the actual implementation:
farcasterPlugin.post()doesn't exist - should befarcasterPlugin.distribute()initialize()method should receive the config, not the constructorApply this diff to correct the usage example:
```typescript import { FarcasterPlugin } from '@curatedotfun/farcaster'; -// Initialize the plugin with your Neynar API credentials -const farcasterPlugin = new FarcasterPlugin({ - apiKey: 'your-neynar-api-key', // Get from https://neynar.com - signerUuid: 'your-signer-uuid' // Get from Neynar dashboard -}); +// Create the plugin instance +const farcasterPlugin = new FarcasterPlugin(); -// Initialize the plugin -await farcasterPlugin.initialize(); +// Initialize the plugin with your Neynar API credentials +await farcasterPlugin.initialize({ + apiKey: 'your-neynar-api-key', // Get from https://neynar.com + signerUuid: 'your-signer-uuid' // Get from Neynar dashboard +}); // Post content to Farcaster -await farcasterPlugin.post('Hello, Farcaster!'); +await farcasterPlugin.distribute({ + input: 'Hello, Farcaster!' +}); // Cleanup when done await farcasterPlugin.shutdown();In packages/farcaster/README.md between lines 13 and 30, the usage example
incorrectly passes config to the constructor, uses a non-existent post() method,
and calls initialize() without parameters. Fix this by instantiating
FarcasterPlugin without arguments, passing the config object to initialize(),
and replacing post() with distribute() called with an input object containing
the message string.