Skip to content
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

feat: Add more storage options to Lens Client #1394

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

jonathangus
Copy link
Contributor

@jonathangus jonathangus commented Dec 23, 2024

Risks

Low/Medium

Background

What does this PR do?

Enable more storage options in Lens Client. With this PR we now support:

  • Arweave
  • Storj (default, to not introduce any breaking changes)
  • Pinata

Fix: ImprovegetProfilePictureUri to use correct types instead of any

What kind of change is this?

Improvements

Why are we doing this? Any context or related work?

Wanted to use Lens Client and posts where stored on Storj that required a beta account so wanted to introduce more options.

Fix TODO for packages/client-lens/src/actions.ts in #1223

Documentation changes needed?

Testing

Where should a reviewer start?

Create an agent with Lens Client enabled

Detailed testing steps

Change the environment variables for each storage provider

Storj:

LENS_STORAGE_PROVIDER=storj
STORJ_API_USERNAME=
STORJ_API_PASSWORD=

Arweave:

LENS_STORAGE_PROVIDER=arweave
ARWEAVE_JWK=

Pinata:

LENS_STORAGE_PROVIDER=pinata
PINATA_JWT=
PINATA_GATEWAY_URL=

Discord username

@0xheavydev

Summary by CodeRabbit

  • Configuration

    • Added new environment variables for Lens Protocol integration
    • Introduced configuration options for storage providers (Arweave, Pinata, Storj)
  • New Features

    • Enhanced storage provider flexibility
    • Added support for multiple storage backends
    • Improved Lens Protocol interaction management
  • Dependencies

    • Added Arweave library (version 1.15.5)
  • Improvements

    • Refactored storage provider interfaces
    • Updated profile picture URI handling
    • Improved error logging and configuration management

@jonathangus jonathangus changed the title Feat: Add more storage options to Lens Client feat: Add more storage options to Lens Client Dec 23, 2024
@jonathangus
Copy link
Contributor Author

@imthatcarlos wdyt?

@imthatcarlos
Copy link
Contributor

good stuff @jonathangus - i was hoping someone would take care of this 😅

@jonathangus
Copy link
Contributor Author

Have tested Pinata and Arweave but would love someone confirming Storj still works as expected. Was not able to get API keys

@imthatcarlos
Copy link
Contributor

@jonathangus I've looked thru the storj provider changes and it should be fine. Plus, I think the vast majority of Lens eco uses Arweave anyways.

LGTM

Copy link
Contributor

coderabbitai bot commented Jan 10, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/client-lens/src/actions.ts

Oops! Something went wrong! :(

ESLint: 9.18.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

📝 Walkthrough

Walkthrough

The pull request introduces comprehensive enhancements to the Lens Protocol client, focusing on expanding storage provider capabilities and configuration options. The changes include adding new environment variables, implementing a flexible storage provider interface, and creating provider-specific classes for Arweave, Pinata, and Storj. The modifications enable more dynamic and configurable media storage and publication processes within the Lens Protocol integration.

Changes

File Change Summary
.env.example Added configuration variables for Lens Protocol, including profile ID, storage providers, and API credentials
packages/client-lens/package.json Added arweave dependency at version 1.15.5
packages/client-lens/src/... Replaced StorjProvider with generic StorageProvider across multiple files, updated import statements and method signatures
packages/client-lens/src/providers/ Added new provider classes: ArweaveProvider, PinataProvider, StorageProvider, and updated StorjProvider

Possibly related PRs

Suggested labels

Needs Testing, Plugin_new

Finishing Touches

  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

jonathangus

This comment was marked as outdated.

@jonathangus jonathangus reopened this Jan 19, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
packages/client-lens/src/providers/AreweaveProvider.ts (3)

23-28: Consider making 'ARWEAVE_JWK' mandatory

While a warning is logged when ARWEAVE_JWK is missing, consider throwing an error to prevent runtime issues since the JWK is essential for transactions.


38-69: Handle potential network errors in 'uploadFile'

Consider implementing retry logic or additional error handling for network failures during transaction posting to enhance reliability.


71-103: Enhance 'uploadJson' with error handling

Similar to uploadFile, adding retries or handling network exceptions in uploadJson will improve robustness.

packages/client-lens/src/providers/PinataProvider.ts (1)

23-27: Make 'PINATA_JWT' a required setting

Since PINATA_JWT is crucial for authentication, consider throwing an error if it's not provided to prevent unexpected failures.

packages/client-lens/src/providers/StorageProvider.ts (1)

14-23: Consider using a more specific type for uploadJson.

The Record<string, any> type is quite permissive. Consider defining a stricter interface for the JSON structure if possible.

packages/client-lens/src/providers/StorjProvider.ts (1)

22-26: Fix typo in warning message.

There's a typo in the warning message: "envornment" should be "environment".

-                "To use Storj ipfs pinning service you need to set STORJ_API_USERNAME or STORJ_API_PASSWORD in envornment variables. Get your keys at https://storj.io"
+                "To use Storj ipfs pinning service you need to set STORJ_API_USERNAME or STORJ_API_PASSWORD in environment variables. Get your keys at https://storj.io"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ace85ae and b0285d0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .env.example (2 hunks)
  • packages/client-lens/package.json (2 hunks)
  • packages/client-lens/src/actions.ts (1 hunks)
  • packages/client-lens/src/index.ts (2 hunks)
  • packages/client-lens/src/interactions.ts (3 hunks)
  • packages/client-lens/src/post.ts (3 hunks)
  • packages/client-lens/src/providers/AreweaveProvider.ts (1 hunks)
  • packages/client-lens/src/providers/PinataProvider.ts (1 hunks)
  • packages/client-lens/src/providers/StorageProvider.ts (1 hunks)
  • packages/client-lens/src/providers/StorjProvider.ts (5 hunks)
  • packages/client-lens/src/utils.ts (2 hunks)
🔇 Additional comments (20)
packages/client-lens/src/index.ts (5)

6-12: Imports updated for new storage providers

The added imports for StorageProvider, StorageProviderEnum, StorjProvider, PinataProvider, and ArweaveProvider correctly incorporate the new storage options.


20-20: Property 'storage' replaces 'ipfs'

Updating the property from ipfs to storage enhances flexibility by generalizing the storage mechanism.


46-46: Initialize storage provider dynamically

Assigning this.storage = this.getStorageProvider(); correctly initializes the storage provider based on configuration.


65-94: Implement 'getStorageProvider' method

The getStorageProvider() method efficiently selects the storage provider. Ensure all providers are correctly mapped in storageProviderMap.


97-99: Conditionally initialize storage provider

Checking if (this.storage.initialize) before calling initialize() ensures compatibility with providers that may not require initialization.

packages/client-lens/src/providers/AreweaveProvider.ts (1)

30-36: Robust error handling for JWK parsing

Properly catching and logging errors during JWK parsing aids in debugging invalid key formats.

packages/client-lens/src/providers/PinataProvider.ts (3)

29-33: Optional 'PINATA_GATEWAY_URL' with fallback

Informing the user about the benefits of setting PINATA_GATEWAY_URL is helpful. Ensure the default gateway functions effectively if not specified.


46-77: Ensure large file upload support in 'uploadFile'

The uploadFile method is correctly implemented. Verify that the configuration handles large files appropriately.


105-111: Correctly resolve content URLs

The resolveUrl method constructs the access URL based on PINATA_GATEWAY_URL, defaulting to Pinata's gateway if not set.

packages/client-lens/src/providers/StorageProvider.ts (2)

3-6: LGTM! Clean interface design for upload responses.

The UploadResponse interface clearly defines the expected structure with both CID and URL.


8-12: LGTM! Well-defined enum for storage providers.

The enum values match the expected provider names in lowercase.

packages/client-lens/src/actions.ts (1)

31-41: LGTM! Robust error handling for storage uploads.

Good addition of try-catch block with informative warning message including the provider context.

packages/client-lens/src/utils.ts (1)

68-84: LGTM! Excellent type safety improvements.

The function now properly handles different image types with proper TypeScript types instead of any.

packages/client-lens/src/providers/StorjProvider.ts (2)

97-98: Verify the implications of using Infinity for content length limits.

Setting both maxContentLength and maxBodyLength to Infinity could potentially lead to memory issues with large files.

Consider implementing reasonable limits or documenting the maximum supported file size.


Line range hint 51-79: LGTM! Clean implementation of uploadJson.

Good type handling for both string and object inputs, with proper buffer conversion.

packages/client-lens/src/post.ts (2)

14-14: LGTM! Storage provider abstraction looks good.

The change from StorjProvider to StorageProvider interface enables flexible storage options while maintaining backward compatibility.

Also applies to: 24-24


108-108: LGTM! Storage parameter update is consistent.

The sendPublication call correctly uses the new storage parameter.

packages/client-lens/src/interactions.ts (1)

26-26: LGTM! Storage provider changes are consistent with post.ts.

The implementation maintains consistency with the changes in post.ts.

Also applies to: 35-35

packages/client-lens/package.json (1)

25-25: Verify arweave package version compatibility.

Let's ensure version 1.15.5 is the latest stable version and check for any security advisories.

✅ Verification successful

✅ arweave@1.15.5 is verified

Latest stable version with no known security vulnerabilities.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check arweave package version and security advisories

# Check npm for latest versions
curl -s https://registry.npmjs.org/arweave | jq '.["dist-tags"].latest'

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "arweave") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 423

.env.example (1)

361-364: LGTM! Environment variables are well documented.

The configuration includes:

  • Storage provider selection with Storj as default
  • Provider-specific credentials
  • Clear documentation for each variable

Also applies to: 366-372, 531-531

Comment on lines +79 to +103
async uploadJson(
json: Record<string, any> | string
): Promise<UploadResponse> {
const data = typeof json === "string" ? JSON.parse(json) : json;

const { data: result } = await this.client.post(
"/pinning/pinJSONToIPFS",
{
pinataOptions: {
cidVersion: 1,
},
pinataMetadata: {
name: "content.json",
},
pinataContent: data,
}
);

const url = this.resolveUrl(result.IpfsHash);

return {
cid: data.IpfsHash,
url,
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix variable reference when returning 'cid'

In uploadJson, cid: data.IpfsHash should be cid: result.IpfsHash since data refers to the input, not the response.

Apply this diff to correct the error:

-    cid: data.IpfsHash,
+    cid: result.IpfsHash,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async uploadJson(
json: Record<string, any> | string
): Promise<UploadResponse> {
const data = typeof json === "string" ? JSON.parse(json) : json;
const { data: result } = await this.client.post(
"/pinning/pinJSONToIPFS",
{
pinataOptions: {
cidVersion: 1,
},
pinataMetadata: {
name: "content.json",
},
pinataContent: data,
}
);
const url = this.resolveUrl(result.IpfsHash);
return {
cid: data.IpfsHash,
url,
};
}
async uploadJson(
json: Record<string, any> | string
): Promise<UploadResponse> {
const data = typeof json === "string" ? JSON.parse(json) : json;
const { data: result } = await this.client.post(
"/pinning/pinJSONToIPFS",
{
pinataOptions: {
cidVersion: 1,
},
pinataMetadata: {
name: "content.json",
},
pinataContent: data,
}
);
const url = this.resolveUrl(result.IpfsHash);
return {
cid: result.IpfsHash,
url,
};
}

.env.example Outdated
Comment on lines +373 to +377
# Lens Protocol Configuration
LENS_PROFILE_ID= # Your Lens Protocol profile ID (format: 0x1234)
LENS_DRY_RUN= # Set to 'true' to simulate posts without actually publishing
LENS_POLL_INTERVAL= # Interval in seconds to check for new interactions (default: 60)
LENS_STORAGE_PROVIDER= # Storage provider for media: 'arweave', 'pinata', or 'storj'. Default "storj"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate Lens Protocol configuration.

These variables are duplicates of the ones defined above.

-# Lens Protocol Configuration
-LENS_PROFILE_ID=                # Your Lens Protocol profile ID (format: 0x1234)
-LENS_DRY_RUN=                   # Set to 'true' to simulate posts without actually publishing
-LENS_POLL_INTERVAL=             # Interval in seconds to check for new interactions (default: 60)
-LENS_STORAGE_PROVIDER=          # Storage provider for media: 'arweave', 'pinata', or 'storj'. Default "storj"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants