diff --git a/.example.env.local b/.example.env.local index 7a4bd50..a8a29bc 100644 --- a/.example.env.local +++ b/.example.env.local @@ -1,3 +1,6 @@ OPENAI_API_KEY= -PINECONE_API_KEY= -PINECONE_ENVIRONMENT= \ No newline at end of file +CONTEXT_ID= +TABLE_ID= +ETHEREUM_PRIVATE_KEY= +LIT_TOKEN_ID= +ORBIS_SEED= diff --git a/README.md b/README.md index b0a4559..0add30c 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ -# Langchain, Pinecone, and GPT with Next.js - Full Stack Starter +# OrbisDB, Lit Protocol, and Langchain Starter This is a basic starter project for building with the following tools and APIs: - Next.js - LangchainJS -- Pineceone Vector Database - GPT3 - -When I started diving into all of this, I felt while I understood some of the individual pieces, it was hard to piece together everything into a cohesive project. I hope this project is useful for anyone looking to build with this stack, and just needing something to start with. +- OrbisDB +- Lit Protocol ### What we're building -We are building an app that takes text (text files), embeds them into vectors, stores them into Pinecone, and allows semantic searching of the data. - -For anyone wondering what Semantic search is, here is an overview (taken directly from ChatGPT4): +We are building an app that takes text (text files), embeds them into vectors, stores them into OrbisDB, and allows semantic searching of the data. -__Semantic search refers to a search approach that understands the user's intent and the contextual meaning of search queries, instead of merely matching keywords.__ - -__It uses natural language processing and machine learning to interpret the semantics, or meaning, behind queries. This results in more accurate and relevant search results. Semantic search can consider user intent, query context, synonym recognition, and natural language understanding. Its applications range from web search engines to personalized recommendation systems.__ +We've also enabled data privacy using Lit Protocol to encrypt the corresponding text for each embedding, and programmatically decrypts based on access control conditions. ## Running the app @@ -28,48 +23,162 @@ In this section I will walk you through how to deploy and run this app. To run this app, you need the following: 1. An [OpenAI](https://platform.openai.com/) API key -2. [Pinecone](https://app.pinecone.io/) API Key +2. A modified [OrbisDB] instance (outlined below) +3. Docker +4. A [Lit](https://www.litprotocol.com/) token ID (also shown below) -### Up and running +## Initial Setup To run the app locally, follow these steps: -1. Clone this repo +1. Clone this repo and install the dependencies + +```sh +git clone https://github.com/ceramicstudio/orbis-lit-langchain +cd orbis-lit-langchain +yarn install +``` + +2. In a separate terminal, clone this modified version of OrbisDB and install the dependencies ```sh -git clone git@github.com:dabit3/semantic-search-nextjs-pinecone-langchain-chatgpt.git +git clone https://github.com/mzkrasner/orbisdb +cd orbisdb +npm install ``` -2. Change into the directory and install the dependencies using either NPM or Yarn +3. In your orbisdb terminal, start the database process + +```sh +# Ensure that you have your Docker Daemon running in the background first +npm run dev +``` -3. Copy `.example.env.local` to a new file called `.env.local` and update with your API keys and environment. +Your OrbisDB instance will need to initially be configured using the GUI running on `localhost:7008`. Navigate to this address in your browser and follow these steps: - __Be sure your environment is an actual environment given to you by Pinecone, like `us-west4-gcp-free`__ +a. For "Ceramic node URL" enter the following value: `https://ceramic-orbisdb-mainnet-direct.hirenodes.io/` -4. (Optional) - Add your own custom text or markdown files into the `/documents` folder. +b. For "Ceramic Seed" simply click "generate a new one" and go to the next page -5. Run the app: +c. For "Database configuration" enter the following: + +```sh +User=postgres +Database=postgres +Password=postgres +Host=localhost +Port=5432 +``` + +Go to the next page + +d. Click next on the presets page (do not select anything) + +e. Connect with your Metamask account and click "Get started". Keep the Orbis Studio UI in your browser as we will navigate back to it later + +4. Go to your `orbis-lit-langchain` terminal and copy the example env file + +```sh +cp .env.example.local .env.local +``` + +5. Navigate to your browser running the OrbisDB UI and create a new context. You can call this anything you want. Once saved, click into your new context and copy the value prefixed with "k" into your `.env.local` file + +```sh +CONTEXT_ID="" +``` + +6. Next, we will create an OrbisDB seed to self-authenticate onto the Ceramic Network using the Orbis SDK + +```sh +yarn gen-seed +``` + +Copy only the array of numbers into your `.env.local` file + +```sh +# enter as a string like "[2, 19, 140, 10...]" +ORBIS_SEED="your-array-here" +``` + +Make sure the final number in your array does not contain a trailing comma + +7. Copy an active and funded OpenAI API key into your `.env.local` file next to `OPENAI_API_KEY` + +8. Choose or create a dummy Metamask address and claim Lit Protocol Testnet tokens using that address by visiting `https://chronicle-yellowstone-faucet.getlit.dev/` + +9. Navigate to `https://explorer.litprotocol.com/` in your browser and sign in with the same dummy address as the previous step. Once signed in, click "Mint a new PKP". After minting, copy the value under "Token ID" into your `.env.local` file + +```sh +LIT_TOKEN_ID="" +``` + +10. Grab the private key from your dummy Metamask wallet (used in the two steps above) and enter it into your `.env.local` file + +```sh +ETHEREUM_PRIVATE_KEY="" +``` + +11. Finally, deploy your OrbisDB data model we will use to create and query via vector search + +```sh +yarn deploy-model +``` + +Copy the value prefixed with "k" into your `.env.local` file + +```sh +TABLE_ID="" +``` + +## Running the Application + +Now that our environment is configured, run the following to start the application from within your `orbis-lit-langchain` terminal ```sh npm run dev ``` -### Need to know +Make sure that OrbisDB is still running in your other terminal. -When creating the embeddings and the index, it can take up to 2-4 minutes for the index to fully initialize. There is a settimeout function of 180 seconds in the `utils` that waits for the index to be created. +Navigate to `localhost:3000` in your browser. -If the initialization takes longer, then it will fail the first time you try to create the embeddings. If this happens, visit [the Pinecone console](https://app.pinecone.io/) to watch and wait for the status of your index being created to finish, then run the function again. +### Create embeddings -### Running a query +This repository contains a small portion of the [Ceramic Developer Docs](https://developers.ceramic.network/) (specifically information on Decentralized Identifiers) that the application will use to create encrypted embeddings. Feel free to replace this with other documentation if you wish -__The pre-configured app data is about the [Lens protocol developer documentation](https://docs.lens.xyz/docs/overview), so it will only understand questions about it unless you replace it with your own data. Here are a couple of questions you might ask it with the default data__ +Click on "Create index and embeddings" and observe your terminal logs in both your `orbisdb` and `orbis-lit-langchain` terminals. -1. What is the difference between Lens and traditional social platforms -2. What is the difference between the Lens SDK and the Lens API -3. How to query Lens data in bulk? +Once finished, your browser console will notify you that the data has been successfully created and loaded into OrbisDB. -> The base of this project was guided by [this Node.js tutorial](https://www.youtube.com/watch?v=CF5buEVrYwo), with some restructuring and ported over to Next.js. You can also follow them [here](https://twitter.com/Dev__Digest/status/1656744114409406467) on Twitter! +### Run a query -### Getting your data +Since the dataset is limited to special knowledge about DIDs, try the following query + +`tell me about decentralized identifiers in ceramic` + +Since this is knowledge contained in the embeddings we just created, your LLM's response will find these embeddings based on cosine similarity search and use it as context in the response (after decrypting the values). You can observe your terminal's logs to see what decrypted context it's using. + +**Ensure that the dummy wallet you spun up contains 0.000001 ETH or more** + +## Access control + +At the moment, very simple access control conditions are being leveraged based on whether the wallet trying to read the data contains >=0.000001 ETH (found in [utils](./utils.ts)) + +```typescript +const accessControlConditions = [ + { + contractAddress: "", + standardContractType: "", + chain: "ethereum", + method: "eth_getBalance", + parameters: [":userAddress", "latest"], + returnValueTest: { + comparator: ">=", + value: "1000000000000", // 0.000001 ETH + }, + }, +]; +``` -I recommend checking out [GPT Repository Loader](https://github.com/mpoon/gpt-repository-loader) which makes it simple to turn any GitHub repo into a text format, preserving the structure of the files and file contents, making it easy to chop up and save into pinecone using my codebase. \ No newline at end of file +There is a wide array of access control conditions you can use or create. For more information, visit [Lit's Access Control documentation](https://developer.litprotocol.com/sdk/access-control/intro). \ No newline at end of file diff --git a/app/api/read/route.ts b/app/api/read/route.ts index 26a089b..cd6a65c 100644 --- a/app/api/read/route.ts +++ b/app/api/read/route.ts @@ -1,21 +1,44 @@ -import { NextRequest, NextResponse } from 'next/server' -import { PineconeClient } from '@pinecone-database/pinecone' -import { - queryPineconeVectorStoreAndQueryLLM, -} from '../../../utils' -import { indexName } from '../../../config' +import { NextRequest, NextResponse } from "next/server"; +import { queryLLM } from "../../../utils"; +import { OrbisDB } from "@useorbis/db-sdk"; +import { OpenAIEmbeddings } from "langchain/embeddings/openai"; +import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; export async function POST(req: NextRequest) { - const body = await req.json() - const client = new PineconeClient() - await client.init({ - apiKey: process.env.PINECONE_API_KEY || '', - environment: process.env.PINECONE_ENVIRONMENT || '' - }) + const body = await req.json(); + console.log("body: ", body); + const db = new OrbisDB({ + ceramic: { + gateway: "https://ceramic-orbisdb-mainnet-direct.hirenodes.io/", + }, + nodes: [ + { + gateway: "http://localhost:7008", + }, + ], + }); - const text = await queryPineconeVectorStoreAndQueryLLM(client, indexName, body) + const textSplitter = new RecursiveCharacterTextSplitter({ + chunkSize: 1000, + }); + console.log("Splitting query into chunks..."); + // 5. Split text into chunks (documents) + const chunks = await textSplitter.createDocuments([body]); + + const array = await new OpenAIEmbeddings().embedDocuments( + chunks.map((chunk) => chunk.pageContent.replace(/\n/g, " ")) + ); + const formattedEmbedding = `ARRAY[${array.join(", ")}]::vector`; + const query = ` + SELECT content, embedding <=> ${formattedEmbedding} AS similarity + FROM ${process.env.TABLE_ID} + ORDER BY similarity ASC + LIMIT 5; + `; + const context = await db.select().raw(query).run(); + const res = await queryLLM(body, context); return NextResponse.json({ - data: text - }) -} \ No newline at end of file + data: res, + }); +} diff --git a/app/api/setup/route.ts b/app/api/setup/route.ts index 6b9aa63..d9701f6 100644 --- a/app/api/setup/route.ts +++ b/app/api/setup/route.ts @@ -1,38 +1,26 @@ -import { NextResponse } from 'next/server' -import { PineconeClient } from '@pinecone-database/pinecone' -import { TextLoader } from 'langchain/document_loaders/fs/text' -import { DirectoryLoader } from 'langchain/document_loaders/fs/directory' -import { PDFLoader } from 'langchain/document_loaders/fs/pdf' -import { - createPineconeIndex, - updatePinecone -} from '../../../utils' -import { indexName } from '../../../config' +import { NextResponse } from "next/server"; +import { TextLoader } from "langchain/document_loaders/fs/text"; +import { DirectoryLoader } from "langchain/document_loaders/fs/directory"; +import { PDFLoader } from "langchain/document_loaders/fs/pdf"; +import { updateOrbis } from "../../../utils"; export async function POST() { - const loader = new DirectoryLoader('./documents', { + const loader = new DirectoryLoader("./documents", { ".txt": (path) => new TextLoader(path), ".md": (path) => new TextLoader(path), - ".pdf": (path) => new PDFLoader(path) - }) + ".pdf": (path) => new PDFLoader(path), + }); - const docs = await loader.load() - const vectorDimensions = 1536 - - const client = new PineconeClient() - await client.init({ - apiKey: process.env.PINECONE_API_KEY || '', - environment: process.env.PINECONE_ENVIRONMENT || '' - }) + const docs = await loader.load(); try { - await createPineconeIndex(client, indexName, vectorDimensions) - await updatePinecone(client, indexName, docs) + const { CONTEXT_ID, TABLE_ID } = process.env; + await updateOrbis(docs, CONTEXT_ID, TABLE_ID); } catch (err) { - console.log('error: ', err) + console.log("error: ", err); } return NextResponse.json({ - data: 'successfully created index and loaded data into pinecone...' - }) -} \ No newline at end of file + data: "successfully created index and loaded data into OrbisDB...", + }); +} diff --git a/app/page.tsx b/app/page.tsx index 2969530..0777f21 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,70 +1,66 @@ -'use client' -import { - useState -} from 'react' -import { Button } from '@/components/ui/button' -import { PieChartIcon } from '@radix-ui/react-icons' +"use client"; +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { PieChartIcon } from "@radix-ui/react-icons"; export default function Home() { - const [query, setQuery] = useState('') - const [result, setResult] = useState('') - const [loading, setLoading] = useState(false) + const [query, setQuery] = useState(""); + const [result, setResult] = useState(""); + const [loading, setLoading] = useState(false); async function createIndexAndEmbeddings() { try { - const result = await fetch('/api/setup', { - method: "POST" - }) - const json = await result.json() - console.log('result: ', json) + const result = await fetch("/api/setup", { + method: "POST", + }); + const json = await result.json(); + console.log("result: ", json); } catch (err) { - console.log('err:', err) + console.log("err:", err); } } async function sendQuery() { - if (!query) return - setResult('') - setLoading(true) + if (!query) return; + setResult(""); + setLoading(true); try { - const result = await fetch('/api/read', { + const result = await fetch("/api/read", { method: "POST", - body: JSON.stringify(query) - }) - const json = await result.json() - setResult(json.data) - setLoading(false) + body: JSON.stringify(query), + }); + const json = await result.json(); + console.log("result: ", json); + setResult(json.data); + setLoading(false); } catch (err) { - console.log('err:', err) - setLoading(false) + console.log("err:", err); + setLoading(false); } } return (
-

- Langchain, Pinecone, and GPT with Next.js +

+ OrbisDB, Lit Protocol, and Langchain

setQuery(e.target.value)} /> + text-black px-2 py-1" + onChange={(e) => setQuery(e.target.value)} + /> + + {loading && } + {result &&

{result}

} + {/* consider removing this button from the UI once the embeddings are created ... */} - { - loading && - } - { - result && ( -

{result}

- ) - } - { /* consider removing this button from the UI once the embeddings are created ... */} - + className="w-[400px] mt-2" + variant="outline" + onClick={createIndexAndEmbeddings} + > + Create index and embeddings +
- ) + ); } diff --git a/config.ts b/config.ts deleted file mode 100644 index 42afc10..0000000 --- a/config.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const indexName = 'my-test-pinecone-index' -export const timeout = 180000 \ No newline at end of file diff --git a/documents/Client SDK/client-sdk-reference.md b/documents/Client SDK/client-sdk-reference.md deleted file mode 100644 index 23646f5..0000000 --- a/documents/Client SDK/client-sdk-reference.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: "All modules and methods" -slug: "client-sdk-reference" -hidden: false -createdAt: "2023-03-03T12:49:12.385Z" -updatedAt: "2023-04-11T16:38:35.477Z" ---- -# Reference - -Here you can find all methods available in the LensClient SDK grouped by module. - -## Legend: - -- [A] method call requires a client instance to be authenticated (see Authentication) -- [P] method response supports pagination (see PaginatedResult type) -- [H] method is a helper function, there is no API interaction - -## Environments - -- `production`, `development` - -## Client and Authentication - -The client manages the access token lifecycle and storage - -- `new LensClient(config)`- [read more](doc:lensclient-sdk) -- `client.authentication.generateChallenge(address)` -- `client.authentication.authenticate(address, signature)` -- [H] `client.authentication.isAuthenticated()` - -## Explore - -- [P] `client.explore.publications(request)` -- [P] `client.explore.profiles(request)` - -## Feed - -- [AP] `client.feed.fetch(request)` -- [AP] `client.feed.fetchHighlights(request)` - -## Modules - -- [A] `client.modules.fetchEnabledCurrencies()` -- [A] `client.modules.fetchEnabled()` -- [A] `client.modules.approvedAllowanceAmount(request)` -- [A] `client.modules.generateCurrencyApprovalData(request)` - -## NFTs - -- [P] `client.nfts.fetch(request)` - -- [A] `client.nfts.ownershipChallenge(request)` - -- `client.nfts.fetchGalleries(request)` - -- [A] `client.nfts.createGallery(request)` - -- [A] `client.nfts.updateGalleryInfo(request)` - -- [A] `client.nfts.updateGalleryItems(request)` - -- [A] `client.nfts.updateGalleryOrder(request)` - -- [A] `client.nfts.deleteGallery(request)` - -## Notifications - -- [AP] `client.notifications.fetch(request)` - -## Profile + Dispatcher - -### Query profile - -- `client.profile.fetch(request)` - -- [P] `client.profile.fetchAll(request)` - -- [P] `client.profile.mutualFollowers({ viewingProfileId, yourProfileId })` - -- `client.profile.stats(request)` - -- `client.profile.allRecommended()` - -- [A] `client.profile.dismissRecommended(request)` - -### Edit profile - -- [A] `client.profile.create(request)` - -- [A] `client.profile.createSetProfileMetadataTypedData(request)` - -- [A] `client.profile.createSetProfileMetadataViaDispatcher(request)` - -- [A] `client.profile.createSetProfileImageURITypedData(request)` - -- [A] `client.profile.createSetProfileImageURIViaDispatcher(request)` - -- [A] `client.profile.createBurnProfileTypedData(request)` - -- [A] `client.profile.createSetDefaultProfileTypedData(request)` - -- [A] `client.profile.createSetDispatcherTypedData(request)` - -- `client.profile.allInterests()` - -- [A] `client.profile.addInterests(request)` - -- [A] `client.profile.removeInterests(request)` - -### Helpers - -- [H] `isValidProfileHandle(handle)` - -### Follow profile - -- [A] `client.profile.createFollowTypedData(request)` - -- [A] `client.profile.createUnfollowTypedData(request)` - -- [A] `client.profile.createSetFollowModuleTypedData(request)` - -- [A] `client.profile.createSetFollowNFTUriTypedData(request)` - -- [AP] `client.profile.pendingApprovalFollows(request)` - -- `client.profile.doesFollow(request)` - -- [P] `client.profile.allFollowing({ address })` - -- [P] `client.profile.allFollowers({ profileId })` - -- `client.profile.followerNftOwnedTokenIds({ address, profileId })` - -## Publication(s) - -### Query publications - -- `client.publication.fetch(request)` -- [P] `client.publication.fetchAll(request)` -- `client.publication.validateMetadata(request)` -- [P] `client.publication.allWalletsWhoCollected({ publicationId })` -- [P] `client.publication.allForSale({ profileId })` -- `client.publication.metadataStatus(request)` -- `client.publication.stats(request)` - -### Create or edit publications - -- [A] `client.publication.createPostTypedData(request)` - -- [A] `client.publication.createPostViaDispatcher(request)` - -- [A] `client.publication.createCommentTypedData(request)` - -- [A] `client.publication.createCommentViaDispatcher(request)` - -- [A] `client.publication.createMirrorTypedData(request)` - -- [A] `client.publication.createMirrorViaDispatcher(request)` - -- [A] `client.publication.createCollectTypedData(request)` - -- [A] `client.publication.hide({ publicationId })` - -- `client.publication.createAttachMediaData(request)` - -- [A] `client.publication.report(request)` - -### Helpers - -- [H] `buildReportingReasonInputParams(PublicationReportReason)` - -## ProtocolStats - -- `client.stats.fetch(request)` - -## UserSigNonces - -- [A] `client.nonces.fetch()` - -## Proxy actions - -- [A] `client.proxyAction.freeFollow({ profileId })` -- [A] `client.proxyAction.freeCollect({ publicationId })` -- [A] `client.proxyAction.checkStatus(proxyActionId)` -- [A] `client.proxyAction.waitForStatusComplete(proxyActionId)` - -### Helpers - -- [H] `isProxyActionError()` -- [H] `isProxyActionQueued()` -- [H] `isProxyActionStatusResult()` - -## Reactions - -- [A] `client.reactions.add(request)` -- [A] `client.reactions.remove(request)` -- [P] `client.reactions.toPublication({ publicationId })` - -## Revenue - -- [P] `client.revenue.profilePublications({ profileId, limit })` -- `client.revenue.profileFollow({ profileId })` -- `client.revenue.publication({ publicationId })` - -## Search - -- [P] `client.search.profiles({ query, limit })` -- [P] `client.search.publications({ query, limit })` - -## Transaction - -- [A] `client.transaction.broadcast(request)` -- [A] `client.transaction.wasIndexed(txId)` -- [A] `client.transaction.waitForIsIndexed(txId)` - -### Helpers - -- [H] `isRelayerResult()` -- [H] `isRelayerError()` -- [H] `isTransactionIndexedResult()` -- [H] `isTransactionError()` \ No newline at end of file diff --git a/documents/Client SDK/client-sdk-types.md b/documents/Client SDK/client-sdk-types.md deleted file mode 100644 index 10d7fc3..0000000 --- a/documents/Client SDK/client-sdk-types.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "TypeScript Types" -slug: "client-sdk-types" -hidden: false -createdAt: "2023-03-03T14:26:13.060Z" -updatedAt: "2023-03-14T12:13:37.573Z" ---- -# TypeScript Types - -This page explains a few important concepts used by the Client SDK that you need to understand to correctly use the features offered by the package. - -## `PromiseResult` and `Result` return types - -All methods that require authentication return `PromiseResult` object. Actually, that is a `Result` type wrapped in a `Promise` so if you `await` the method call, you will get a `Result` object. Check the example: - -```typescript -const promiseResult = lensClient.transaction.broadcast(); - -const result = await lensClient.transaction.broadcast(); // or await promiseResult; - -// now what can we do with the Result object - -// check if success or failure -result.isSuccess(); -result.isFailure(); - -// access the value if success -if(result.isSuccess()) { - const value = result.value; -} - -// access the error if failure -if(result.isFailure()) { - throw result.error; -} - -// unwrap to see what is inside -// it returns value if success and throws error if failure -result.unwrap(); -``` - - - -## `PaginatedResult` return type - -The result of a type of `PaginatedResult` offers you the utility of requesting more results for the same query. Check the example below. - -```typescript -const paginatedResult = await lensClient.explore.profiles({ - limit: 10 -}); - -// now what can we do with the PaginatedResult object - -const firstTenItems = [...paginatedResult.items]; // clone as items will be overwritten when calling .next() - -// fetch next batch of items -await paginatedResult.next() - -const nextTenItems = [...paginatedResult.items]; - -// you can also request previous batch -await paginatedResult.prev() - -``` \ No newline at end of file diff --git a/documents/Creating a Module/creating-a-module.md b/documents/Creating a Module/creating-a-module.md deleted file mode 100644 index 30c225a..0000000 --- a/documents/Creating a Module/creating-a-module.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: "Creating a Module" -slug: "creating-a-module" -excerpt: "Build your first module!" -hidden: false -createdAt: "2022-02-04T20:16:45.318Z" -updatedAt: "2022-02-07T13:06:51.974Z" ---- -[block:callout] -{ - "type": "info", - "body": "This tutorial assumes that:\n\na) you are working with the Lens Protocol repository and have your environment set up correctly. See the \"Walkthrough\" section for more, and...\nb) You are at least *vaguely* familiar with solidity smart contract development or programming in general.", - "title": "Getting Set Up" -} -[/block] -## Creating the Contract -So here's the plan: We're going to create a follow module that only allows users to follow if they include a special code. Of course, this is just for fun, and in practice, this makes no sense as the code would inherently be **public** on the blockchain. But, humor me for a bit! - -Let's start off by creating a file called `SecretCodeFollowModule.sol` in the `contracts/core/modules/follow/` directory. We're working with `solidity 0.8.10`, so we'll use that as our [pragma](https://docs.soliditylang.org/en/v0.8.10/layout-of-source-files.html#pragmas). - -Since we're building a follow module, let's import the interface (which is basically a "blueprint" detailing every function we should include). We're also importing another contract that implements one of the interface's functions for us, and one that exposes the hub contract as an immutable with a modifier. - -``` -pragma solidity 0.8.10; - -import {IFollowModule} from '../../../interfaces/IFollowModule.sol'; -import {ModuleBase} from '../ModuleBase.sol'; -import {FollowValidatorFollowModuleBase} from './FollowValidatorFollowModuleBase.sol'; - -``` - -Next up, let's define our contract. We'll inherit from the imported interface: -``` -... -contract SecretCodeFollowModule is IFollowModule { - -} -``` - -At this point, your linter or compiler is probably pretty upset, and with good reason! We're inheriting from an interface, but we aren't implementing any of the functions. The interface is like an outline, we've got to fill in the blanks now, and implement our functions! - -That's right, it's time to actually build the contract. :sunglasses: -[block:callout] -{ - "type": "info", - "title": "Privacy On-Chain", - "body": "This is just an example, keep in mind that nothing published on-chain is ever private, including our passcodes here. Even *before* something is pushed on-chain, it's visible unless you use a special privacy-preserving provider that obscures transaction pool transactions, but that's beyond the scope of this guide!" -} -[/block] -## Implementing Follow Module Functions -So, if we take a quick look at the `IFollowModule` interface (or in the specification section on the left), we can see the different functions we've got to implement to have our follow module ready. These are: - -1. `InitializeFollowModule()` which is called when a profile sets this module as its follow module. -2. `ProcessFollow()` which is called when a user attempts to follow a given profile with this module set as its follow module. -3. `FollowModuleTransferHook()` which is called when a FollowNFT associated with a profile that has this module set as its follow module is transferred (we won't be needing to do anything here) and... -4. `ValidateFollow()` which is called to validate whether a follow is still valid (**Note:** this is implemented by the `FollowValidatorFollowModuleBase` contract, so we don't have to worry about it!) - -Before we copy over the functions, let's go ahead and include a constructor. All we've got to do is construct the `ModuleBase` contract, which is inherited from the `FollowValidatorFollowModuleBase`, which we in turn inherit from: -``` -... - constructor(address hub) ModuleBase(hub) {} -... -``` - -Great! Now we can access the immutable hub address via an address variable called `HUB`! We've also got access to a modifier `onlyHub()`, which we'll use for our one state-changing function. - -Before we get ahead of ourselves, let's appease our angry linter and finally copy over the interface functions in our contract, adding empty brackets (which is equivalent to implementing no logic) and the `onlyHub` modifier to our `initializeFollowModule` implementation so only the hub can call it: -``` -... - function initializeFollowModule(uint256 profileId, bytes calldata data) - external - override - onlyHub - returns (bytes memory) - {} - - function processFollow( - address follower, - uint256 profileId, - bytes calldata data - ) external override {} - - function followModuleTransferHook( - uint256 profileId, - address from, - address to, - uint256 followNFTTokenId - ) external override {} -... -``` - -Sweet! At this point, we've appeased our compiler overlord, and it's time to start implementing our logic! - -## Implementing Custom Logic -Alright, so here's how this module is going to work: -1. Allow profile owners to set a secret number as a passcode on follow module initialization -2. Only allow users to follow if they pass the correct passcode - -We're going to need some additional features to satisfy the criteria outlined above. First, somewhere to store the passcodes; second, a way for profile owners to set them on initialization; and third, a way to validate that users attempting to follow pass the correct passcode. - -Let's go back above our constructor and create a new mapping called `_passcodeByProfile` and a new error (which we'll throw when users pass the wrong passcode) called `PasscodeInvalid()`: - -``` -... -contract SecretCodeFollowModule is IFollowModule, FollowValidatorFollowModuleBase { - error PasscodeInvalid(); - - mapping(uint256 => uint256) internal _passcodeByProfile; - - constructor... -``` - -This mapping we just created will use profile IDs as keys and their respective passcodes as values. Simple enough! Now it's time to build our initialization mechanism, for which we'll use the `initializeFollowModule()` function: -``` -... - function initializeFollowModule(uint256 profileId, bytes calldata data) - external - override - onlyHub - returns (bytes memory) - { - uint256 passcode = abi.decode(data, (uint256)); - _passcodeByProfile[profileId] = passcode; - return data; - } -... -``` -As a quick explanation, first we decode the passcode from the arbitrary data (passed by the profile owner), then we set it as the profile's passcode. - -At this point, you might be wondering about why this function returns a `bytes memory` parameter. This is basically any state-altering data that should be emitted by an event. In our case, we'll just pass the original data as that includes the passcode which we're using to alter state. - -We're almost there! The last step is to validate that users pass the correct passcode when attempting to follow. Since this function does *not* modify state, but reads from it, we can restrict its visibility to `view`, too: -``` -... - function processFollow( - address follower, - uint256 profileId, - bytes calldata data - ) external view override { - uint256 passcode = abi.decode(data, (uint256)); - if (passcode != _passcodeByProfile[profileId]) revert PasscodeInvalid(); - } -... -``` - -To go over what we just built, the first line decodes the passcode from the arbitrary data (passed by the user attempting to follow) and the second line reverts the execution if it's not the right passcode. -[block:callout] -{ - "type": "info", - "title": "Solidity Tip", - "body": "As good practice, it's always a good idea to restrict function scope as much as possible within reason. Solidity functions that don't modify state but read from it should be marked `view`, and functions that neither read nor modify state should be marked `pure`. In this case, you might have noticed that the `followModuleTransferHook()` can be marked pure, too, although this serves no purpose as the function is empty." -} -[/block] -## Recap -And that's it! You've successfully created your own follow module. Let's take a look at our full `SecretCodeFollowModule.sol` file: -``` -pragma solidity 0.8.10; - -import {IFollowModule} from '../../../interfaces/IFollowModule.sol'; -import {ModuleBase} from '../ModuleBase.sol'; -import {FollowValidatorFollowModuleBase} from './FollowValidatorFollowModuleBase.sol'; - -contract SecretCodeFollowModule is IFollowModule, FollowValidatorFollowModuleBase { - error PasscodeInvalid(); - - mapping(uint256 => uint256) internal _passcodeByProfile; - - constructor(address hub) ModuleBase(hub) {} - - function initializeFollowModule(uint256 profileId, bytes calldata data) - external - override - onlyHub - returns (bytes memory) - { - uint256 passcode = abi.decode(data, (uint256)); - _passcodeByProfile[profileId] = passcode; - return data; - } - - function processFollow( - address follower, - uint256 profileId, - bytes calldata data - ) external view override { - uint256 passcode = abi.decode(data, (uint256)); - if (passcode != _passcodeByProfile[profileId]) revert PasscodeInvalid(); - } - - function followModuleTransferHook( - uint256 profileId, - address from, - address to, - uint256 followNFTTokenId - ) external override {} -} -``` - -Before we move on the testing, let's make sure everything compiles: - -**Note:** This assumes you're inside the`contracts-env` container! If you're not sure how that works, check out the walkthrough! -``` -$ npm run compile -``` - -Assuming nothing broke, let's go ahead and write a Hardhat task testing that everything works as intended. It's time to put this shiny new module to good use! \ No newline at end of file diff --git a/documents/Creating a Module/module-interfaces.md b/documents/Creating a Module/module-interfaces.md deleted file mode 100644 index dbb99a3..0000000 --- a/documents/Creating a Module/module-interfaces.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Introduction to Modules" -slug: "module-interfaces" -excerpt: "Learn to understand and work with modules!" -hidden: false -createdAt: "2022-02-03T22:58:05.149Z" -updatedAt: "2022-02-06T18:20:54.858Z" ---- -## Getting Started -Modules are an integral part of the Lens Protocol: they allow profile owners to include unique, custom functionality on follow, collect and reference (i.e. mirrors and comments). This *vastly* opens the door to exciting new community-created features that greatly expand on the basic Lens Protocol social graph! - -From a more technical perspective, modules are whitelisted smart contracts that adhere to a specified interface which are called at defined execution steps. In other terms, modules present code akin to "hooks" that are run at predetermined points. - -With all that out of the way, this tutorial will guide you through the development and testing of your very own module! Although there are three different kinds of modules that you can build, their construction is fundamentally similar, so this should provide a good foundation. - -Let's start by digging into the three types of modules (for examples, check out the bottom of this page!)... - -### Follow Modules -Follow modules are called when a user attempts to follow a profile. Profile owners can set their follow module at profile creation and can change it at any time thereafter. Profile owners can also opt to have no follow module, allowing anyone to follow them any number of times. - -These modules allow for logic such as a "fee-on-follow" or even a "subscription" mechanism -- and frankly, basically anything else you can think up! - -### Collect Modules -Collect modules are called when a user attempts to collect a given profile's publication. Unlike follow modules, these are set once at publication creation and are **immutable** once the publication is live! Furthermore, all publications must have a collect module attached to them. - -There's a ton of stuff that can be built with collect modules -- just off the top of my head, aside from a simple "fee-on-collect" collect module, there's nothing stopping a collect module from holding evolving state. - -### Reference Modules -Reference modules are called when a profile attempts to reference a given profile's publication. Similar to collect modules, these are set once at publication creation and are **immutable** too! However, *unlike collect modules,* publications can opt to have no reference module, allowing any profile to comment on or mirror the publication. - -Custom rule sets can be built for reference modules--for example, you may want to allow only specific Follower NFT ID holders to comment and follow. In addition, reference modules include separate functions for validating mirrors and comments, so the rules can be different for each! (With the limitation that the functions are called on the same contract.) - -## Next Up -Alright, now that you're at least vaguely familiar with how modules work throughout the protocol, it's time to hit the ground running and build your own module! - -We'll be creating a custom follow module from scratch and it's going to be *amazing*. It's recommended, however, that you're at least a little bit familiar with the development environment; see the *Walkthrough* section for a clear-cut introduction! - -LFG. \ No newline at end of file diff --git a/documents/Creating a Module/publishing-a-module.md b/documents/Creating a Module/publishing-a-module.md deleted file mode 100644 index 788b5a6..0000000 --- a/documents/Creating a Module/publishing-a-module.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "Publishing a Module" -slug: "publishing-a-module" -hidden: false -createdAt: "2023-02-08T21:53:07.113Z" -updatedAt: "2023-04-25T12:14:34.426Z" ---- -> 🚧 Module whitelisting is paused but will resume soon - -Developers wishing to whitelist a module to the Lens Protocol should provide information and documentation about the Module [here](https://airtable.com/shrOj1sS5xNhn501x). - -Modules only need to be whitelisted for Testnet and Mainnet. Modules can permissionlessly be published to testnet. - -Below is a short summary of the relevant requirements and criteria: - -## General - -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/19374b9-generalwl.jpg", - null, - "General Module WL Info" - ], - "align": "center", - "caption": "General Module Whitelist Information" - } - ] -} -[/block] - -## Testnet - -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/e0fa279-testnetwl.jpg", - null, - "Testnet Module Whitelist Information" - ], - "align": "center", - "caption": "Testnet Module Whitelist Information " - } - ] -} -[/block] - -## Mainnet - -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/41f90ec-mainnetwl.jpg", - null, - "Testnet Module Whitelist Information" - ], - "align": "center", - "caption": "Testnet Module Whitelist Information" - } - ] -} -[/block] \ No newline at end of file diff --git a/documents/Creating a Module/testing-a-module.md b/documents/Creating a Module/testing-a-module.md deleted file mode 100644 index b40b3cb..0000000 --- a/documents/Creating a Module/testing-a-module.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: "Testing a Module" -slug: "testing-a-module" -excerpt: "Deploy and interact with your module locally!" -hidden: false -createdAt: "2022-02-04T21:46:55.302Z" -updatedAt: "2022-05-31T14:45:03.609Z" ---- -[block:callout] -{ - "type": "info", - "title": "Getting Set Up", - "body": "If you don't yet know how to run the Docker container and interact with your own local blockchain, or if you find yourself a little confused, check out the walkthrough! \n\nThis tutorial also assumes your environment is set up and you're operating from within the Docker container." -} -[/block] -## Creating the Custom Task -Let's create a file called `test-module.ts` in the `tasks/` directory and add a few imports: -``` -import { defaultAbiCoder } from 'ethers/lib/utils'; -import { task } from 'hardhat/config'; -import { - FollowNFT__factory, - LensHub__factory, - SecretCodeFollowModule__factory, -} from '../typechain-types'; -import { CreateProfileDataStruct } from '../typechain-types/LensHub'; -import { - waitForTx, - initEnv, - getAddrs, - ProtocolState, - ZERO_ADDRESS, - deployContract, -} from './helpers/utils'; -``` - -If your linter is upset at the `SecretCodeFollowModule__factory`, make sure you've compiled the contracts that should generate the missing typechain binding. - -Next up, let's go ahead and start writing our task. We're going to want to unpause the protocol, whitelist the user for profile creation, and create a profile. -``` -... -task('test-module', 'tests the SecretCodeFollowModule').setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - - await waitForTx(lensHub.setState(ProtocolState.Unpaused)); - await waitForTx(lensHub.whitelistProfileCreator(user.address, true)); - - const inputStruct: CreateProfileDataStruct = { - to: user.address, - handle: 'zer0dot', - imageURI: - 'https://ipfs.fleek.co/ipfs/ghostplantghostplantghostplantghostplantghostplantghostplan', - followModule: ZERO_ADDRESS, - followModuleInitData: [], - followNFTURI: - 'https://ipfs.fleek.co/ipfs/ghostplantghostplantghostplantghostplantghostplantghostplan', - }; - await waitForTx(lensHub.connect(user).createProfile(inputStruct)); -}); -... -``` -Note that we connected the hub to the user to create the profile. And with that, we're ready to deploy, whitelist, set and finally test the follow module! - -## Setting Up the New Module -In order to deploy a new contract, we're going to use the typechain factory, here's how: -``` -... - const secretCodeFollowModule = await deployContract( - new SecretCodeFollowModule__factory(governance).deploy(lensHub.address) - ); -... -``` - -Note that we're using a custom wrapper function (`deployContract()`) that just ensures that the execution is paused until the contract is confirmed to have been deployed. - -To briefly explain what's going on here, we're constructing the factory with the governance signer and passing the hub address in the module's constructor at deployment. - -Next up, we'll want to whitelist the module: -``` -... - await waitForTx(lensHub.whitelistFollowModule(secretCodeFollowModule.address, true)); -... -``` - -Now we're on to the last step before we put it to the test, let's set this new module as our follow module: -``` -... - const data = defaultAbiCoder.encode(['uint256'], ['42069']); - await waitForTx(lensHub.connect(user).setFollowModule(1, secretCodeFollowModule.address, data)); -... -``` -Here's where we're using that `defaultAbiCoder` we imported earlier since we've got to pass encoded data to be decoded in the follow module's initialization. - -One more thing: if you're running this on a chain you've interacted with before, make sure you're specifying the correct profile ID in our case, this is 1, since this is the only profile in existence! - -Finally, we're ready to test out our new module! - -## Testing the New Module -If everything went well, we know that if we pass the same number we encoded in our `data` parameter earlier, the follow should be successful. - -Let's go ahead and use a `try {} catch {}` statement to validate the unsuccessful case, and then validate the successful case. We'll log the same data as we did in the walkthrough section for following: - -``` -... - const badData = defaultAbiCoder.encode(['uint256'], ['1337']); - - try { - await waitForTx(lensHub.connect(user).follow([1], [badData])); - } catch (e) { - console.log(`Expected failure occurred! Error: ${e}`); - } - await waitForTx(lensHub.connect(user).follow([1], [data])); - - const followNFTAddr = await lensHub.getFollowNFT(1); - const followNFT = FollowNFT__factory.connect(followNFTAddr, user); - - const totalSupply = await followNFT.totalSupply(); - const ownerOf = await followNFT.ownerOf(1); - - console.log(`Follow NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Follow NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); -... -``` - -Alright, that about wraps it up! - -## Recap -Before we execute our hardhat task, let's take a quick look at what the `test-module.ts` file looks like in its entirety: - -``` -import { defaultAbiCoder } from 'ethers/lib/utils'; -import { task } from 'hardhat/config'; -import { - FollowNFT__factory, - LensHub__factory, - SecretCodeFollowModule__factory, -} from '../typechain-types'; -import { CreateProfileDataStruct } from '../typechain-types/LensHub'; -import { - deployContract, - getAddrs, - initEnv, - ProtocolState, - waitForTx, - ZERO_ADDRESS, -} from './helpers/utils'; - -task('test-module', 'tests the SecretCodeFollowModule').setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - - await waitForTx(lensHub.setState(ProtocolState.Unpaused)); - await waitForTx(lensHub.whitelistProfileCreator(user.address, true)); - - const inputStruct: CreateProfileDataStruct = { - to: user.address, - handle: 'zer0dot', - imageURI: - 'https://ipfs.fleek.co/ipfs/ghostplantghostplantghostplantghostplantghostplantghostplan', - followModule: ZERO_ADDRESS, - followModuleInitData: [], - followNFTURI: - 'https://ipfs.fleek.co/ipfs/ghostplantghostplantghostplantghostplantghostplantghostplan', - }; - await waitForTx(lensHub.connect(user).createProfile(inputStruct)); - - const secretCodeFollowModule = await deployContract( - new SecretCodeFollowModule__factory(governance).deploy(lensHub.address) - ); - await waitForTx(lensHub.whitelistFollowModule(secretCodeFollowModule.address, true)); - - const data = defaultAbiCoder.encode(['uint256'], ['42069']); - await waitForTx(lensHub.connect(user).setFollowModule(1, secretCodeFollowModule.address, data)); - - const badData = defaultAbiCoder.encode(['uint256'], ['1337']); - - try { - await waitForTx(lensHub.connect(user).follow([1], [badData])); - } catch (e) { - console.log(`Expected failure occurred! Error: ${e}`); - } - await waitForTx(lensHub.connect(user).follow([1], [data])); - - const followNFTAddr = await lensHub.getFollowNFT(1); - const followNFT = FollowNFT__factory.connect(followNFTAddr, user); - - const totalSupply = await followNFT.totalSupply(); - const ownerOf = await followNFT.ownerOf(1); - - console.log(`Follow NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Follow NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); -}); -``` - -As a quick rundown, we've unpaused the protocol, created a profile, deployed a new follow module, whitelisted it, set it as the follow module for our profile and tested it. -[block:callout] -{ - "type": "info", - "title": "On Testing", - "body": "In this example, we used a rudimentary `try {} catch {}` statement to test our functionality, this isn't actually recommended (we use Waffle and Chai with Hardhat). For a more in-depth look at how these contracts are tested, check out the `test/` directory and [Hardhat's testing documentation!](https://hardhat.org/guides/waffle-testing.html)" -} -[/block] -Alright, it's all or nothing. You know the drill, let's run the task against our local chain (if you don't have one spun up, no worries--check out the walkthrough section). - -Here goes: -``` -$ npx hardhat test-module --network localhost -``` - -If everything went according to plan, here's what your terminal output should look like: -``` -Expected failure occurred! Error: ProviderError: Error: VM Exception while processing transaction: reverted with custom error 'PasscodeInvalid()' -Follow NFT total supply (should be 1): 1 -Follow NFT owner of ID 1: 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2, user address (should be the same): 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2 -``` - -And on that note, congratulations! You've successfully created and tested an entirely new module. This means you're now geared-up to start building and proposing your own custom modules to the Lens Protocol community. - -Happy hacking! \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/collecting-publications.md b/documents/Deploying the Lens smart contracts/collecting-publications.md deleted file mode 100644 index d0d3e9f..0000000 --- a/documents/Deploying the Lens smart contracts/collecting-publications.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: "Collecting Publications" -slug: "collecting-publications" -excerpt: "Collect your epic post and get your hands on a snazzy new Collect NFT!" -hidden: false -createdAt: "2022-01-26T19:43:55.830Z" -updatedAt: "2022-05-12T14:40:21.517Z" ---- -## Creating the Custom Task -Let's go ahead and create a new task in a file called `collect.ts`. For this task, we'll be following the same initialization procedure as we did for the `follow` task, but we'll replace the `FollowNFT__factory` with a `CollectNFT__factory`, here's how that looks: -``` -import { task } from 'hardhat/config'; -import { LensHub__factory, CollectNFT__factory } from '../typechain-types'; -import { getAddrs, initEnv, waitForTx, } from './helpers/utils'; - -task('collect', 'collects a post').setAction(async ({}, hre) => { - const [, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], user); -}); -``` - -## Collecting the Post -Alright, it's time to collect our first post! Keep in mind that posts, comments, and mirrors can be collected, except collecting a mirror collects the mirrored post/comment with a referral. - -Let's add the collect function call to our task: -``` -... - await waitForTx(lensHub.collect(1, 1, [])); -... -``` - -Just so we're on the same page, this function takes three parameters: - -1. The profile ID of the profile that created the publication we're collecting (in our case, 1), -2. The publication ID of the publication we're collecting and... -3. The arbitrary data to pass to the collect module. - -In this situation, we're collecting the first publication from the first profile, so the first two parameters are both `1`. Next, we've got the data we want to pass to the collect module: recall that our publication's collect module is the `FreeCollectModule,` which doesn't require any data (it allows collects for free, and can be configured, at initialization, to require holding a profile's follow NFT to be able to collect, which has been done in our publication), so we'll pass an empty byte array, or `[]`. - -The last thing we'll want to do is print out some information on the console to make sure everything worked as intended, and we've got our Collect NFT. We'll also validate that the collect NFT's URI corresponds to our post's content URI. Here's what that looks like: - -``` -... - const collectNFTAddr = await lensHub.getCollectNFT(1, 1); - const collectNFT = CollectNFT__factory.connect(collectNFTAddr, user); - - const publicationContentURI = await lensHub.getContentURI(1, 1); - const totalSupply = await collectNFT.totalSupply(); - const ownerOf = await collectNFT.ownerOf(1); - const collectNFTURI = await collectNFT.tokenURI(1); - - console.log(`Collect NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Collect NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); - console.log( - `Collect NFT URI: ${collectNFTURI}, publication content URI (should be the same): ${publicationContentURI}` - ); -... -``` - -## Recap -Alright! We're almost there; let's take a look at how our `collect.ts` file looks in its entirety: -``` -import { task } from 'hardhat/config'; -import { LensHub__factory, CollectNFT__factory } from '../typechain-types'; -import { getAddrs, initEnv, waitForTx } from './helpers/utils'; - -task('collect', 'collects a post').setAction(async ({}, hre) => { - const [, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], user); - - await waitForTx(lensHub.collect(1, 1, [])); - - const collectNFTAddr = await lensHub.getCollectNFT(1, 1); - const collectNFT = CollectNFT__factory.connect(collectNFTAddr, user); - - const publicationContentURI = await lensHub.getContentURI(1, 1); - const totalSupply = await collectNFT.totalSupply(); - const ownerOf = await collectNFT.ownerOf(1); - const collectNFTURI = await collectNFT.tokenURI(1); - - console.log(`Collect NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Collect NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); - console.log( - `Collect NFT URI: ${collectNFTURI}, publication content URI (should be the same): ${publicationContentURI}` - ); -}); -``` - -Now there's just one thing left to do: -``` -npx hardhat collect --network localhost -``` - -If everything went according to plan, our terminal output should look a little something like this: -``` -Collect NFT total supply (should be 1): 1 -Collect NFT owner of ID 1: 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2, user address (should be the same): 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2 -Collect NFT URI: https://ipfs.fleek.co/ipfs/plantghostplantghostplantghostplantghostplantghostplantghos, publication content URI (should be the same): https://ipfs.fleek.co/ipfs/plantghostplantghostplantghostplantghostplantghostplantghos -``` - -Congratulations! At this point in the walkthrough, you've managed to complete every essential interaction with the Lens Protocol. You've created your profile, interacted with it, and validated that things are how they should be! - -Now, it's time to graduate to building on top of the protocol by creating an entirely new follow module. \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/creating-a-profile.md b/documents/Deploying the Lens smart contracts/creating-a-profile.md deleted file mode 100644 index a7f04d8..0000000 --- a/documents/Deploying the Lens smart contracts/creating-a-profile.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: "Creating a Profile" -slug: "creating-a-profile" -excerpt: "Create a full-fledged profile on your local Lens deployment!\n##### Jump to [Recap](#recap) to get the full source code 🌿" -hidden: false -createdAt: "2022-01-17T19:08:28.222Z" -updatedAt: "2022-08-17T17:53:42.067Z" ---- -Creating The Custom Task ------------------------- - -Just like the previous step where we created a Hardhat task to unpause the protocol, we will create another task to create a profile. This allows us to publish new posts, comments, and mirrors on-chain! - -First, let's create a new `create-profile.ts` file in our `tasks/` directory. Then, we've only got a few things to import: - -``` -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { CreateProfileDataStruct } from '../typechain-types/LensHub'; -import { waitForTx, initEnv, getAddrs, ZERO_ADDRESS } from './helpers/utils'; -``` - -Furthermore, we'll create our task and initialize our environment like so: - -``` -task('create-profile', 'creates a profile').setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); -}); -``` - -We'll need the governance signer because Lens uses a profile creator whitelist. Let's go ahead and whitelist the user; then, we can dive into the fun stuff and create our profile! - -``` -... - await waitForTx(lensHub.whitelistProfileCreator(user.address, true)); -... -``` - -Creating the Profile --------------------- - -We've whitelisted the user to create profiles; all that's left now is to create the profile itself. Let's first take a look at the input struct required for profile creation (from `contracts/libraries/Datatypes.sol`): - -``` -// NOTE: This struct is defined in the contracts/libraries/Datatypes.sol library - - /** - * @notice A struct containing the parameters required for the `createProfile()` function. - * - * @param to The address receiving the profile. - * @param handle The handle to set for the profile, must be unique and non-empty. - * @param imageURI The URI to set for the profile image. - * @param followModule The follow module to use, can be the zero address. - * @param followModuleInitData The follow module initialization data, if any. - * @param followNFTURI The URI to use for the follow NFT. - */ - struct CreateProfileData { - address to; - string handle; - string imageURI; - address followModule; - bytes followModuleInitData; - string followNFTURI; - } -``` - -With that out of the way, let's go ahead and build our input struct. We want the profile NFT recipient to be ourselves (the user), our handle and URI can be mock values, and we don't want a follow module so that anyone can follow us: - -``` -... - const inputStruct: CreateProfileDataStruct = { - to: user.address, - handle: 'zer0dot', - imageURI: 'https://ipfs.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX', - followModule: ZERO_ADDRESS, - followModuleInitData: [], - followNFTURI: 'https://ipfs.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS', - }; -... -``` - -Lastly, we've just got to send the transaction! We will connect the `lensHub` contract instance to our user and send the transaction with the input struct provided above. We'll also include some checks, so we know it worked on the console: - -``` -... - await waitForTx(lensHub.connect(user).createProfile(inputStruct)); - - console.log(`Total supply (should be 1): ${await lensHub.totalSupply()}`); - console.log( - `Profile owner: ${await lensHub.ownerOf(1)}, user address (should be the same): ${user.address}` - ); - console.log( - `Profile ID by handle: ${await lensHub.getProfileIdByHandle( - 'zer0dot' - )}, user address (should be the same): ${user.address}` - ); -... -``` - -Recap ------ - -Create the file `tasks/create-profile.ts` with the following code: - -``` -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { CreateProfileDataStruct } from '../typechain-types/LensHub'; -import { waitForTx, initEnv, getAddrs, ZERO_ADDRESS } from './helpers/utils'; - -task('create-profile', 'creates a profile').setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - - await waitForTx(lensHub.whitelistProfileCreator(user.address, true)); - - const inputStruct: CreateProfileDataStruct = { - to: user.address, - handle: 'zer0dot', - imageURI: 'https://ipfs.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX', - followModule: ZERO_ADDRESS, - followModuleInitData: [], - followNFTURI: 'https://ipfs.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS', - }; - - await waitForTx(lensHub.connect(user).createProfile(inputStruct)); - - console.log(`Total supply (should be 1): ${await lensHub.totalSupply()}`); - console.log( - `Profile owner: ${await lensHub.ownerOf(1)}, user address (should be the same): ${user.address}` - ); - console.log(`Profile ID by handle: ${await lensHub.getProfileIdByHandle('zer0dot')}`); -}); - -``` - -With all that done, there's just one thing left to do-- let's run the task with the following command: - -``` -$ npx hardhat create-profile --network localhost -``` - -If all is well, we should have an output like so: - -``` -Total supply (should be 1): 1 -Profile owner: 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2, user address (should be the same): 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2 -Profile ID by the handle: 1 -``` - -Congratulations! You've successfully created a profile and received a profile NFT; now, the possibilities are endless. But we're not done yet! Next up, we're going to dig into publishing a post! \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/creating-publications.md b/documents/Deploying the Lens smart contracts/creating-publications.md deleted file mode 100644 index a36ea1b..0000000 --- a/documents/Deploying the Lens smart contracts/creating-publications.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Publishing Posts" -slug: "creating-publications" -excerpt: "Publish your first post and in doing so, learn to publish whatever you like!\n##### Jump to [Recap](#recap) to get the full source code 🌿" -hidden: false -createdAt: "2022-01-17T21:38:03.900Z" -updatedAt: "2022-10-27T22:38:45.486Z" ---- -## Creating the Custom Task - -I'm sure you're used to it by now; we'll start by creating a new file called `post.ts` in the `tasks/` directory. - -We'll also include our usual imports and basic initialization. We're also going to be using the `FreeCollectModule,` which allows any follower to collect our post for free into perpetuity. Here's what the file should look like: - -``` -import { defaultAbiCoder } from 'ethers/lib/utils'; -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { PostDataStruct } from '../typechain-types/LensHub'; -import { getAddrs, initEnv, waitForTx, ZERO_ADDRESS } from './helpers/utils'; - -task('post', 'publishes a post') - .setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const freeCollectModuleAddr = addrs['free collect module']; - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - }); - -``` - - - -## Whitelisting the Collect Module - -The protocol only allows whitelisted collect modules to be used in posts and comments (mirrors don't have a collect module associated with them), so we've got to whitelist our free collect module: - -``` -... - await waitForTx(lensHub.whitelistCollectModule(freeCollectModuleAddr, true)); -... -``` - - - -## Creating the Post - -Now that we've whitelisted the collect module, we're ready to create our post! Like profile creation, publishing functions (in our case, we're only looking at `post()`) use an input data struct. Here's what the data struct we need looks like (from `contracts/libraries/Datatypes.sol`): - -``` -// NOTE: This struct is defined in the contracts/libraries/Datatypes.sol library - - /** - * @notice A struct containing the parameters required for the `post()` function. - * - * @param profileId The token ID of the profile to publish to. - * @param contentURI The URI to set for this new publication. - * @param collectModule The collect module to set for this new publication. - * @param collectModuleInitData The data to pass to the collect module's initialization. - * @param referenceModule The reference module to set for the given publication, must be whitelisted. - * @param referenceModuleInitData The data to be passed to the reference module for initialization. - */ - struct PostData { - uint256 profileId; - string contentURI; - address collectModule; - bytes collectModuleInitData; - address referenceModule; - bytes referenceModuleInitData; - } -``` - - - -Now we're ready to move forward with building our input struct! We want the profile ID to be 1 since we own the only profile in existence. The content URI can be mocked. The collect module will be the newly whitelisted `FreeCollectModule,` which takes no data, and lastly, the reference module and its associated data field are free. - -> In production you will want to make sure the content saved for the `contentURI` conforms to the metadata standards outlined [here](https://docs.lens.xyz/docs/metadata-standards). - -Here's how that should look: - -``` -... - const inputStruct: PostDataStruct = { - profileId: 1, - contentURI: 'https://ipfs.io/ipfs/Qmby8QocUU2sPZL46rZeMctAuF5nrCc7eR1PPkooCztWPz', - collectModule: freeCollectModuleAddr, - collectModuleInitData: defaultAbiCoder.encode(['bool'], [true]), - referenceModule: ZERO_ADDRESS, - referenceModuleInitData: [], - }; -... -``` - - - -Alright, now we're just about ready to execute the transaction. Like profile creation, we'll connect the `lensHub` instance to our `user` signer and send the transaction! To be sure, we're also going to add some logging to ensure everything works exactly how we expect it to: - -``` -... - await waitForTx(lensHub.connect(user).post(inputStruct)); - console.log(await lensHub.getPub(1, 1)); -... -``` - - - -## Recap - -Create file `tasks/post.ts` with the following code: - -``` -import { defaultAbiCoder } from 'ethers/lib/utils'; -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { PostDataStruct } from '../typechain-types/LensHub'; -import { getAddrs, initEnv, waitForTx, ZERO_ADDRESS } from './helpers/utils'; - -task('post', 'publishes a post').setAction(async ({}, hre) => { - const [governance, , user] = await initEnv(hre); - const addrs = getAddrs(); - const freeCollectModuleAddr = addrs['free collect module']; - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - - await waitForTx(lensHub.whitelistCollectModule(freeCollectModuleAddr, true)); - - const inputStruct: PostDataStruct = { - profileId: 1, - contentURI: 'https://ipfs.io/ipfs/Qmby8QocUU2sPZL46rZeMctAuF5nrCc7eR1PPkooCztWPz', - collectModule: freeCollectModuleAddr, - collectModuleInitData: defaultAbiCoder.encode(['bool'], [true]), - referenceModule: ZERO_ADDRESS, - referenceModuleInitData: [], - }; - - await waitForTx(lensHub.connect(user).post(inputStruct)); - console.log(await lensHub.getPub(1, 1)); -}); -``` - - - -Finally, let's go ahead and run the task: - -``` -$ npx hardhat post --network localhost -``` - - - -If everything went according to plan, the console should output something like this: - -``` -[ - BigNumber { _hex: '0x00', _isBigNumber: true }, - BigNumber { _hex: '0x00', _isBigNumber: true }, - 'https://ipfs.io/ipfs/Qmby8QocUU2sPZL46rZeMctAuF5nrCc7eR1PPkooCztWPz', - '0x0000000000000000000000000000000000000000', - '0x20Ce94F404343aD2752A2D01b43fa407db9E0D00', - '0x0000000000000000000000000000000000000000', - profileIdPointed: BigNumber { _hex: '0x00', _isBigNumber: true }, - pubIdPointed: BigNumber { _hex: '0x00', _isBigNumber: true }, - contentURI: 'https://ipfs.io/ipfs/Qmby8QocUU2sPZL46rZeMctAuF5nrCc7eR1PPkooCztWPz', - referenceModule: '0x0000000000000000000000000000000000000000', - collectModule: '0x20Ce94F404343aD2752A2D01b43fa407db9E0D00', - collectNFT: '0x0000000000000000000000000000000000000000' -] -``` - - - -Awesome! That checks out -- we've created our first profile and published our first post. Now, naturally, our profile and post are a bit lonely, out there in the void, so let's move forward with following our profile and collecting the post! \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/deploying-the-protocol.md b/documents/Deploying the Lens smart contracts/deploying-the-protocol.md deleted file mode 100644 index 95a4deb..0000000 --- a/documents/Deploying the Lens smart contracts/deploying-the-protocol.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Deploying the Protocol" -slug: "deploying-the-protocol" -excerpt: "Spin up your own blockchain with Hardhat and locally deploy your own Lens Protocol!" -hidden: false -createdAt: "2022-01-13T22:21:43.351Z" -updatedAt: "2023-04-25T15:33:30.396Z" ---- -## Spinning up Your Local Blockchain - -Alright, so we've got two terminals running in the Docker container we're running with Docker Compose. We will be using the first one to run our local blockchain and the second one to deploy the protocol. - -Recall we're also using Hardhat, which provides a fantastic tool to spin up a local chain in mere seconds, complete with multiple mock pre-funded addresses to have fun with! - -> 🚧 CREATE 2 NEW TERMINALS WITHOUT DOCKER -> -> Leave the previous terminal you used for docker alone and create 2 new terminals for running the commands. Ending up with 3 terminals in total. But remember you don't need docker for the new terminals. - -### Start the Blockchain (First terminal) - -In the **first** terminal write: - -``` -$ npm install -$ npm run compile -$ npx hardhat node -``` - - - -This compiles everything, then spins up a custom local blockchain using Hardhat. - -### Deploy the Protocol (Second terminal) - -In the **second** terminal write: - -``` -$ npm run full-deploy-local -``` - - - -This executes the `full-deploy` Hardhat task (which you can find in the `tasks` directory) on the local hardhat network. Once that's done, you should see a list of all newly deployed addresses, don't worry about jotting it down as it's also copied to an `addresses.json` file in the repository's root directory. - -You'll also see all the executed transactions in the first terminal if you want to see what's happening behind the scenes. - -On that note, so far, we've spun up our local blockchain and deployed the entire protocol to it. It's time to create a profile and start interacting with it! \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/following-a-profile.md b/documents/Deploying the Lens smart contracts/following-a-profile.md deleted file mode 100644 index 06d9097..0000000 --- a/documents/Deploying the Lens smart contracts/following-a-profile.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Following Profiles" -slug: "following-a-profile" -excerpt: "Follow your lonesome profile and get that Follow NFT!\n##### Jump to [Recap](#recap) to get the full source code 🌿" -hidden: false -createdAt: "2022-01-25T21:34:46.461Z" -updatedAt: "2022-08-17T17:55:24.533Z" ---- -## Creating the Custom Task -You know the drill! Let's start by setting up our task in a new file called `follow.ts.` Note that we're also importing the `FollowNFT__factory` and initializing our `lensHub` to be connected with the user! -``` -import { task } from 'hardhat/config'; -import { LensHub__factory, FollowNFT__factory } from '../typechain-types'; -import { getAddrs, initEnv, waitForTx } from './helpers/utils'; - -task('follow', 'follows a profile').setAction(async ({}, hre) => { - const [, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], user); -}); -``` - -## Following the Profile -Recall that we didn't use a follow module when we created our profile -- this means any wallet can follow our profile without worry! So, let's go ahead and follow our own profile: -``` -... - await waitForTx(lensHub.follow([1], [[]])); -... -``` - -To clarify what we're doing here, the `follow()` function takes two parameters, both of which are arrays: - -1. The array of profile IDs to follow and... -2. The array of arbitrary data to pass to corresponding follow modules. - -In our case, we want to follow the profile with ID "1" and pass no data since there's no follow module. The reason we need nested brackets *(this weird thing: `[[]]`)* is that the contracts ensure that both input arrays are of equal length. We need to pass one empty data parameter in our array. - -Finally, let's add some logging to check if everything worked as intended. First, we'll fetch the follow NFT address; then we'll connect the `FollowNFT__factory` to it and fetch some relevant data: -``` -... - const followNFTAddr = await lensHub.getFollowNFT(1); // Retrieve the follow NFT for a given profile ID - const followNFT = FollowNFT__factory.connect(followNFTAddr, user); // Connect our typechain bindings - - const totalSupply = await followNFT.totalSupply(); // Fetch the total supply - const ownerOf = await followNFT.ownerOf(1); // Fetch the owner of the follow NFT with id 1 (NFT IDs in Lens start at 1, not 0!) - - console.log(`Follow NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Follow NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); -... -``` - -## Recap -Create file `tasks/follow.ts` with the following code: - -``` -import { task } from 'hardhat/config'; -import { LensHub__factory, FollowNFT__factory } from '../typechain-types'; -import { getAddrs, initEnv, waitForTx } from './helpers/utils'; - -task('follow', 'follows a profile').setAction(async ({}, hre) => { - const [, , user] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], user); - - await waitForTx(lensHub.follow([1], [[]])); - - const followNFTAddr = await lensHub.getFollowNFT(1); - const followNFT = FollowNFT__factory.connect(followNFTAddr, user); - - const totalSupply = await followNFT.totalSupply(); - const ownerOf = await followNFT.ownerOf(1); - - console.log(`Follow NFT total supply (should be 1): ${totalSupply}`); - console.log( - `Follow NFT owner of ID 1: ${ownerOf}, user address (should be the same): ${user.address}` - ); -}); -``` - -Not too shabby, right? Now, the moment we've been waiting for… Let's give it a shot: -``` -$ npx hardhat follow --network localhost -``` - -If nothing broke (which, granted, it often does in programming), your terminal output should look a little something like this: -``` -Follow NFT total supply (should be 1): 1 -Follow NFT owner of ID 1: 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2, user address (should be the same): 0x92561F28Ec438Ee9831D00D1D59fbDC981b762b2 -``` - -Alright! We've managed to follow the profile. As a quick recap, we've successfully spun up our own blockchain, deployed the protocol locally, created a profile, published a post, and followed the profile; pretty sweet, huh? The next step is to collect the post! \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/primer.md b/documents/Deploying the Lens smart contracts/primer.md deleted file mode 100644 index 8614057..0000000 --- a/documents/Deploying the Lens smart contracts/primer.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Primer" -slug: "primer" -excerpt: "A quick summary as to what to expect from this guide." -hidden: false -createdAt: "2022-01-12T23:52:06.590Z" -updatedAt: "2023-01-13T21:23:18.852Z" ---- -![](https://files.readme.io/27b2bc4-illustration_tend.svg "illustration_tend.svg") - -## Summary - -This section walks you through how to deploy the entire protocol in a local hardhat network and write some custom tasks to interact with it. - -> For developers looking to build with the existing Lens deployment on Polygon, they should instead view the [API documentation](https://docs.lens.xyz/docs/introduction) and the [Quickstart Guide](https://docs.lens.xyz/docs/developer-quickstart). - -We'll first start with the repository and environment setup. You'll learn how to create a profile from scratch, publish a post, follow, collect, and even create your own custom module. We'll be using [ethers](https://www.npmjs.com/package/ethers), [hardhat](https://hardhat.org/), and [typescript](https://www.typescriptlang.org/) to interact with the protocol. - -> 📘 Before You Get Started -> -> You're going to need to have [Git](https://git-scm.com/) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your system (this helps keep consistency between development machines and reduces OS/versioning errors!) \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/quick-setup.md b/documents/Deploying the Lens smart contracts/quick-setup.md deleted file mode 100644 index ddf77c7..0000000 --- a/documents/Deploying the Lens smart contracts/quick-setup.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Quick Setup" -slug: "quick-setup" -excerpt: "Get set up and hit the ground running in a matter of minutes!" -hidden: false -createdAt: "2022-01-13T22:02:31.920Z" -updatedAt: "2023-04-25T14:55:23.496Z" ---- -## Setting up Your Local Repository - -To set things up, we're going first to clone the [repository,](https://github.com/lens-protocol/lens-protocol) set up the environment, and finally, build and enter our Docker container! - -As mentioned previously, you'll need Git and Docker Compose. - -### 1. Clone the Repository - -``` -git clone git@github.com:lens-protocol/core.git -``` - - - -### 2. Create Your `.env` File - -(Note: It can be blank for local development!) - -``` -cd core -touch .env -``` - - - -### 3. Start Docker Compose - -**Note:** This is only tested on Unix-based systems, Docker facilitates development, but users can still opt not to use it. Windows users, if running into trouble, can consider setting up the [WSL](https://docs.microsoft.com/en-us/windows/wsl/about). - -``` -export USERID=$UID && docker-compose build && docker-compose run --name lens contracts-env bash -``` - - - -Alright, next up, we're going to spin up our own local blockchain and deploy the entire protocol on it. - -*** - - - -#### Enter The Container in Another Terminal - -Open up an **additional terminal** and execute the following command: - -``` -docker exec -it lens bash -``` - - - -#### Clean container - -To clean up leftover running containers, just execute the following command: - -``` -USERID=$UID docker-compose down -``` \ No newline at end of file diff --git a/documents/Deploying the Lens smart contracts/unpausing-the-protocol.md b/documents/Deploying the Lens smart contracts/unpausing-the-protocol.md deleted file mode 100644 index 030f7e5..0000000 --- a/documents/Deploying the Lens smart contracts/unpausing-the-protocol.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: "Unpausing the Protocol" -slug: "unpausing-the-protocol" -excerpt: "Unpause the protocol with your custom Hardhat task!\n##### Jump to [Recap](#recap) to get the full source code 🌿" -hidden: false -createdAt: "2022-01-13T03:52:39.789Z" -updatedAt: "2022-08-17T17:53:25.288Z" ---- -Creating The Custom Task ------------------------- - -The repository's `hardhat.config.ts` is set up to import all tasks in the `tasks/` directory, which means all we've got to do to start interacting with our local deployment is create a new task. - -Create a file `unpause.ts` in the `tasks/` directory and open it up in your editor of choice. The first thing you'll want to do is import some modules. - -Since we're working with hardhat tasks, we can use the instance of `ethers` injected into the Hardhat runtime environment, we won't be needing to import it in this specific task, but it's used behind the scenes. We'll also be using [typechain](https://www.npmjs.com/package/typechain), which creates convenient typescript bindings that we can connect to our deployed contracts. - -Below are all the imports we'll need to set the protocol state (i.e., Unpause it); we'll explain how we use each one down the line. - -``` -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { ProtocolState, waitForTx, initEnv, getAddrs } from './helpers/utils'; -``` - -Next, we've got to create the hardhat task (which will automatically be imported in our Hardhat config file if this `custom` file exists). Our actual code to be executed will be a callback function in the tasks' `setAction` property. - -``` -task('unpause', 'unpauses the protocol').setAction(async ({}, hre) => {}); -``` - -Getting Ready to Interact With Our Local Deployment ---------------------------------------------------- - -Alright, so we've created our Hardhat task. Now we've got to instantiate our signers (a wallet that can sign and send transactions) and begin interacting with the protocol! Our local deployment uses the default signers connected to the injected `ethers` instance and automatically maps them to different protocol roles. - -For our purposes, the 0-indexed account is the deployer, the 1-indexed account is the governance address, the 2-indexed account is the treasury, and the 3-indexed account is our general-purpose user. We also need to know the addresses of our deployed contracts, so let's use [fs](https://nodejs.dev/learn/the-nodejs-fs-module) to read the addresses JSON file and store that too. - -The following functions are **not** in the same task file but are imported from the `./tasks/helpers/utils.ts` file. It's just worth noting how it works. - -``` -// NOTE: These functions are in tasks/helpers/utils.ts and imported into our task file! - -export async function initEnv(hre: HardhatRuntimeEnvironment): Promise { - const ethers = hre.ethers; // This allows us to access the hre (Hardhat runtime environment)'s injected ethers instance easily - - const accounts = await ethers.getSigners(); // This returns an array of the default signers connected to the hre's ethers instance - const governance = accounts[1]; // We'll use this signer to, for example, unpause the protocol - const treasury = accounts[2]; // This is the treasury address, which we won't use - const user = accounts[3]; // We'll use this signer as our general purpose user - - return [governance, treasury, user]; -} - -export function getAddrs(): any { - const json = fs.readFileSync('addresses.json', 'utf8'); // Read the 'addresses.json' file - const addrs = JSON.parse(json); // Parse the JSON into an object - return addrs; -} -``` - -We're just going to call the above helper functions to fetch the data we need in our task. We only want the governance and addresses object: - -``` -... - const [governance] = await initEnv(hre); - const addrs = getAddrs(); -... -``` - -The last thing we've got to instantiate is our interface to the contract itself, there are many ways to do this, but we're going to use our imported type chain binding, and we'll start by connecting it to our governance signer. - -Let's add the following line inside our task's callback function: - -``` -... - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); -... -``` - -Executing a Transaction ------------------------ - -So far, we've created a new Hardhat task, instantiated our signers, and instantiated an interface to our contract. We're just about ready to start sending transactions! - -Before we start creating a profile, we've got a little housekeeping to do, and this will serve as a great test to see if everything's set up correctly. - -Upon deployment, the protocol is paused by default. Let's go ahead and unpause it by adding the following lines to our tasks' callback function: - -``` -... - console.log(await lensHub.getState()); - await waitForTx(lensHub.setState(ProtocolState.Unpaused)); - console.log(await lensHub.getState()); -... -``` - -Note that we're typically using a wrapper instead of just sending the transaction; this simply ensures that we wait for the transaction to be mined before proceeding. - -As a quick side note, the smart contract ABI (Application Binary Interface) treats enums as regular unsigned integers, which also happens with our JavaScript/typescript code; so the `ProtocolState` enum is just a set of integers behind the scenes! - -Recap ------ - -Create file `tasks/unpause.ts` with the following code: - -``` -import { task } from 'hardhat/config'; -import { LensHub__factory } from '../typechain-types'; -import { ProtocolState, waitForTx, initEnv, getAddrs } from './helpers/utils'; - -task('unpause', 'unpauses the protocol').setAction(async ({}, hre) => { - const [governance] = await initEnv(hre); - const addrs = getAddrs(); - const lensHub = LensHub__factory.connect(addrs['lensHub proxy'], governance); - console.log(await lensHub.getState()); - await waitForTx(lensHub.setState(ProtocolState.Unpaused)); - console.log(await lensHub.getState()); -}); -``` - -And now it's the moment of truth! Go ahead and run it with the following command: - -``` -$ npx hardhat unpause --network localhost -``` - -if things go well, we should have the following output in our terminal: - -``` -2 -0 -``` - -This is great! 2 is the value for `ProtocolState.Paused` and 0 is the value for `ProtocolState.Unpaused`. - -Next up, we will create a new task to whitelist the user and create our first profile! \ No newline at end of file diff --git a/documents/Documentation/authentication-quickstart-api.md b/documents/Documentation/authentication-quickstart-api.md deleted file mode 100644 index df31c9e..0000000 --- a/documents/Documentation/authentication-quickstart-api.md +++ /dev/null @@ -1,246 +0,0 @@ ---- -title: "Authentication Quickstart - Lens API" -slug: "authentication-quickstart-api" -hidden: false -metadata: -createdAt: "2022-10-27T22:40:52.852Z" -updatedAt: "2023-05-25T20:38:42.840Z" ---- -In this guide you'll learn how to implement user authentication with the Lens API in a full stack web application using React and Next.js. - -While this tutorial is written in React and using React APIs, the general concepts should be easy to understand and implement across any JavaScript framework. - -### Why Authentication? - -While reading data from the Lens API is as simple as sending a GraphQL query, in order to post to the network you need to either be authenticated or write a transaction directly to the Lens smart contracts. - -This includes any state change, like following, unfollowing, creating a post, and creating a mirror. - -While there is quite a bit of documentation out there for writing transactions to a blockchain, we thought it would be helpful to provide a full stack guide for authenticating with the Lens API for developers enabling state changing functionality in their apps. - -It's also important to understand how to implement authentication in order to be able to take advantage of Lens API features like [typed data](https://eips.ethereum.org/EIPS/eip-712) (a way to show the users what they are signing in a more readable format), [gasless transactions](https://docs.lens.xyz/docs/proxy-action-gasless), or to use the [dispatcher](https://docs.lens.xyz/docs/dispatcher). - -### Getting started - -To get started, first create a new Next.js application: - -```shell -npx create-next-app lens-app - -✔ Would you like to use TypeScript with this project? No -✔ Would you like to use ESLint with this project? Yes -✔ Would you like to use Tailwind CSS with this project? Yes -✔ Would you like to use `src/` directory with this project? No -✔ Use App Router (recommended)? Yes -✔ Would you like to customize the default import alias? No -``` - -Next, change into the new directory and install the following dependencies: - -``` -npm install @apollo/client graphql ethers@5.7.2 -``` - -## Setting up the API - -Next, we'd like to configure the GraphQL client. This is what we'll use to send requests to the Lens API. - -Create a file named `api.js` in the root of the project and add the following code: - -```javascript -import { ApolloClient, InMemoryCache, gql } from '@apollo/client' - -const API_URL = 'https://api.lens.dev' - -export const client = new ApolloClient({ - uri: API_URL, - cache: new InMemoryCache() -}) -``` - -### Defining the GraphQL queries and mutations - -In GraphQL, read operations are known as `queries`, and write operations (create, update, delete, etc) are known as `mutations`. - -Now that we've created the GraphQL client, let's define the queries and mutations we'll need to authenticate. - -To authenticate takes two server actions. The first is to generate a challenge from the server ([`challenge`](https://docs.lens.xyz/docs/login#challenge)). The second is for the user to sign that challenge with their Ethereum wallet and send the signature to the Lens server to generate a valid JWT access token and refresh token ([`authenticate`](https://docs.lens.xyz/docs/login#authenticate)). - -Add the following code to `api.js`: - -```javascript -export const challenge = gql` - query Challenge($address: EthereumAddress!) { - challenge(request: { address: $address }) { - text - } - } -` - -export const authenticate = gql` - mutation Authenticate( - $address: EthereumAddress! - $signature: Signature! - ) { - authenticate(request: { - address: $address, - signature: $signature - }) { - accessToken - refreshToken - } - } -` -``` - -## Building the authentication flow - -Now that the GraphQL client is configured, let's build out the authentication flow. Update `app/page.js` with the following code: - -```javascript -'use client' -import { useEffect, useState } from 'react' -import { ethers } from 'ethers' -import { client, challenge, authenticate } from '../api' - -export default function Home() { - /* local state variables to hold user's address and access token */ - const [address, setAddress] = useState() - const [token, setToken] = useState() - useEffect(() => { - /* when the app loads, check to see if the user has already connected their wallet */ - checkConnection() - }, []) - async function checkConnection() { - const provider = new ethers.providers.Web3Provider(window.ethereum) - const accounts = await provider.listAccounts() - if (accounts.length) { - setAddress(accounts[0]) - } - } - async function connect() { - /* this allows the user to connect their wallet */ - const account = await window.ethereum.send('eth_requestAccounts') - if (account.result.length) { - setAddress(account.result[0]) - } - } - async function login() { - try { - /* first request the challenge from the API server */ - const challengeInfo = await client.query({ - query: challenge, - variables: { address } - }) - const provider = new ethers.providers.Web3Provider(window.ethereum); - const signer = provider.getSigner() - /* ask the user to sign a message with the challenge info returned from the server */ - const signature = await signer.signMessage(challengeInfo.data.challenge.text) - /* authenticate the user */ - const authData = await client.mutate({ - mutation: authenticate, - variables: { - address, signature - } - }) - /* if user authentication is successful, you will receive an accessToken and refreshToken */ - const { data: { authenticate: { accessToken }}} = authData - console.log({ accessToken }) - setToken(accessToken) - } catch (err) { - console.log('Error signing in: ', err) - } - } - - return ( -
- { /* if the user has not yet connected their wallet, show a connect button */ } - { - !address && - } - { /* if the user has connected their wallet but has not yet authenticated, show them a login button */ } - { - address && !token && ( -
- -
- ) - } - { /* once the user has authenticated, show them a success message */ } - { - address && token &&

Successfully signed in!

- } -
- ) -} -``` - -Next, run the app to test it out: - -```javascript -npm run dev -``` - -When the app loads, you should be able to sign in and the `accessToken` should be logged out to the console upon success. - -🎉 Congratulations, you've successfully implemented user authentication in a Lens application! - -## Sending authenticated requests - -Once the user has been authenticated, you can send the access token in the headers to make authenticated requests. - -For example, this is what it might look like with the Apollo client: - -```javascript -const result = await client.mutate({ - mutation: createPostTypedData, - variables: { - request, - }, - context: { - headers: { - Authorization: `Bearer ${token}` - } - } -}) -``` - -### Apollo Link - -You can also consider using Apollo Link to automatically add an authorization header to every HTTP request. This would change the way you configure your client: - -```javascript -import { ApolloClient, InMemoryCache, gql, createHttpLink } from '@apollo/client' -import { setContext } from '@apollo/client/link/context'; - -const authLink = setContext((_, { headers }) => { - const token = window.localStorage.getItem('your-storage-key') - return { - headers: { - ...headers, - authorization: token ? `Bearer ${token}` : "", - } - } -}) - -const httpLink = createHttpLink({ - uri: API_URL -}) - -export const client = new ApolloClient({ - link: authLink.concat(httpLink), - cache: new InMemoryCache() -}) -``` - -## Next steps - -Now that you've learned how to implement authentication, it's time to explore more of [the Lens API!](https://docs.lens.xyz/docs/introduction) - -Consider diving into [modules](https://docs.lens.xyz/docs/module-interfaces), the [dispatcher](https://docs.lens.xyz/docs/dispatcher), or learning about [gasless transactions](https://docs.lens.xyz/docs/proxy-action-gasless). Also check out [this](https://github.com/dabit3/lens-create-publication-example) example project showing how to authenticate a user and then post a publication to the network. - -Also consider adding the following features to your app: - -1. Following a user -2. Searching for users -3. Creating a post \ No newline at end of file diff --git a/documents/Documentation/authentication-quickstart.md b/documents/Documentation/authentication-quickstart.md deleted file mode 100644 index a1a733e..0000000 --- a/documents/Documentation/authentication-quickstart.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -title: "Authentication Quickstart" -slug: "authentication-quickstart" -hidden: false -metadata: -createdAt: "2023-05-23T22:03:30.002Z" -updatedAt: "2023-05-25T20:38:50.306Z" ---- -This tutorial walks you through the recommended way to build an authentication flow on Lens, leveraging the [Lens React Hooks SDK](https://docs.lens.xyz/docs/sdk-react-intro). - -The Lens React Hooks SDK abstracts away the need to write a lot of lower level GraphQL boilerplate for API calls to Lens, making it much easier to build web and mobile apps on Lens. - -It's worth noting that this tutorial only supports React and React Native. If you'd like to build with other frameworks or clients such as other JavaScript frameworks or native iOS, consider using the [Lens Client SDK](https://docs.lens.xyz/docs/client-sdk-reference), or the [Lens API](https://docs.lens.xyz/docs/introduction) directly. - -### Why authentication? - -While reading data from the Lens API is as simple as sending a query, but in order to post updates to the network the user needs to be authenticated. - -This includes any state change, like following, unfollowing, creating a post, and creating a mirror. - -This is why authentication is important, and why we have created this guide for you to learn how to set up a simple authentication flow. - -## Tutorial overview - -In this tutorial you'll learn how to use Next.js, TypeScript, Lens Protocol, and the Lens SDK to build out a simple authentication flow. - -The app we'll be building will have the following features: - -1. When the app loads, it will prompt the user to sign in. -2. Once the user is signed in, we will display some information about their profile, and a button to sign out. -3. When the user signs out, the UI will update and the session will be removed, showing the user the sign in button again. - -By the end of this tutorial you should be able to easily authenticate users in a Lens application with TypeScript and the Lens SDK. - -### Getting started - -To get started, create a new Next.js application: - -```sh -npx create-next-app lens-app - -✔ Would you like to use TypeScript with this project? Yes -✔ Would you like to use ESLint with this project? Yes -✔ Would you like to use Tailwind CSS with this project? Yes -✔ Would you like to use `src/` directory with this project? No -✔ Use App Router (recommended)? Yes -✔ Would you like to customize the default import alias? No -``` - -Next, change into the new directory and install the following dependencies: - -```sh -cd lens-app - -npm install @lens-protocol/react-web ethers@legacy-v5 wagmi@0.12.7 @lens-protocol/wagmi -``` - -## app/layout.tsx - -Next, we want to configure our app to use the Lens SDK. - -This is typically done at the entrypoint of the app, and only needs to be done once. - -This is a decent amount of code, but once it's set up it makes using the SDK very easy in the rest of your app. - -Update `app/layout.tsx` with the following code: - -```typescript -'use client' -import './globals.css' -import { configureChains, createClient, WagmiConfig } from 'wagmi' -import { mainnet, polygon } from 'wagmi/chains' -import { publicProvider } from 'wagmi/providers/public' -import { LensProvider, LensConfig, production } from '@lens-protocol/react-web' -import { bindings as wagmiBindings } from '@lens-protocol/wagmi' -const { provider, webSocketProvider } = configureChains([polygon, mainnet], [publicProvider()]) - -const client = createClient({ - autoConnect: true, - provider, - webSocketProvider, -}); - -const lensConfig: LensConfig = { - bindings: wagmiBindings(), - environment: production, -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - - - {children} - - - - ) -} -``` - -## app/page.tsx - -Now that the app is successfully configured with the Lens SDK, let's create the authentication flow. - -To do so, open `app/page.tsx` and add the following code: - -```typescript typescript -'use client' -import { useWalletLogin, useWalletLogout, useActiveProfile } from '@lens-protocol/react-web'; -import { useAccount, useConnect, useDisconnect } from 'wagmi'; -import { InjectedConnector } from 'wagmi/connectors/injected'; - -export default function Authentication() { - const { execute: login, isPending: isLoginPending } = useWalletLogin(); - const { execute: logout } = useWalletLogout(); - const { data: wallet, loading } = useActiveProfile(); - const { isConnected } = useAccount(); - const { disconnectAsync } = useDisconnect(); - - const { connectAsync } = useConnect({ - connector: new InjectedConnector(), - }); - - const onLoginClick = async () => { - if (isConnected) { - await disconnectAsync(); - } - const { connector } = await connectAsync(); - if (connector instanceof InjectedConnector) { - const signer = await connector.getSigner(); - await login(signer); - } - } - - return ( -
- { - loading &&

Loading...

- } - { - !wallet && !loading && ( - - ) - } - { - wallet && !loading && ( -
-

{wallet.handle}

-

{wallet.bio}

- -
- ) - } -
- ); -} -``` - -#### What's happening? - -In this component, we are using 3 Lens Hooks: - -`useWalletLogin` allows you to sign a user in by passing in a `signer`. - -`useWalletLogout` provides a simple way to sign a user out. - -`useActiveProfile` allows you to easily get the profile details of a signed in user. - -In the UI itself, there are three main views: - -1. If the app is in a loading state, we show a loading indicator. -2. If there is no signed in user, we show the **Sign In** button -3. If the user is signed in, we show the **Sign Out** button. - -### Testing it out - -To run the app, run the following command: - -```sh -npm run dev -``` - -### Next steps - -Now that you've authenticated a user, try creating a post. Check out [this guide](https://docs.lens.xyz/docs/create-first-post) to get you started. \ No newline at end of file diff --git a/documents/Documentation/community-faq.md b/documents/Documentation/community-faq.md deleted file mode 100644 index 03f09cc..0000000 --- a/documents/Documentation/community-faq.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "Community FAQ" -slug: "community-faq" -hidden: false -createdAt: "2022-12-01T11:37:18.557Z" -updatedAt: "2023-04-17T15:29:04.854Z" ---- -The Lens ecosystem is growing at speed 🚀 - -We’ve noticed on Social and our Discord server a few questions around similar topics so wanted to give you all an update on these - -## How to get a Lens handle? - -We have allocated some profiles to targeted communities over the last few months, and the response and feedback have been amazing so far will continue to work with partners to allowlist some communities. If you see an announcement explaining how to get access from one of these communities ✅ this will be your best option for now - -We also participate, support, and host various events around the globe 🌎 - -⚒️ If you wish to build on Lens at these events our team can help get you a profile on the ground at the event - -🤝 If you are visiting our booth or talking with our team, there is usually a POAP close by which can get you access. - -## Wen Lens open for all? - -We’re still in closed Beta, we are doing this to attain feedback and improve the experience for when we fully open to the masses - -We are excited to get you all enjoying Lens, but we want to do it at the right time to give you the best experience possible - -If you haven't been able to get access to Lens yet, but would like to learn more about the growing Lens ecosystem, here's an awesome [article](https://medium.com/@fabriguespe/lens-protocol-application-ecosystem-update-october-d8381c635dcc) from our developer relations team - -Head to our [Lensverse](https://lens.xyz/apps) page to discover hundreds of applications built 🛠 on Lens Protocol - -## How much time do I have to claim my profile once eligible? - -You will have 30 days to claim your profile once you have been allowlisted off of the waitlist. After that period, you will lose your opportunity to claim your Lens profile. - -## What are reserved handles? Why do I get an error saying the handle is reserved? - -Certain handles have been reserved for multiple reasons, for example, certain famous brands are limited from claiming to avoid user confusion around the ownership of those handles. - -It is possible that certain reserved handles may be coincident with your desired lens profile. We are working on this as our plan is to reduce the amount of reserved Lens handles going forward. - -## How can I transfer a Lens Profile? - -Similarly as you would do with any NFT, by sending them into any other wallet or interface that supports Polygon NFTs. - -## I represent a project, protocol, community, etc, and I love what you guys are doing. How can I interact with you regarding integrations, partnerships and so? - -The best way to be in touch with the community is to be active on Discord, as well as in any Lens protocol interfaces. - -However, you can always send any inquiries regarding integrations, partnerships and so on to ecosystem@lens.xyz - -## Do you have a Discord? - -Sure, the Lens Protocol Discord link can be found [here](https://discord.gg/lensprotocol). - -Please take into account that there are some users impersonating admins. Please note, that admins will never DM you first or share any business opportunities, or ask you for favours, your seed phrase, funds, etc. \ No newline at end of file diff --git a/documents/Documentation/deployed-contract-addresses.md b/documents/Documentation/deployed-contract-addresses.md deleted file mode 100644 index 4ed1916..0000000 --- a/documents/Documentation/deployed-contract-addresses.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: "Deployed Contract Addresses" -slug: "deployed-contract-addresses" -hidden: false -createdAt: "2022-02-07T15:05:22.059Z" -updatedAt: "2023-03-29T18:34:10.878Z" ---- -## Polygon Mainnet Addresses - -The official block explorer can be found here: - -- [Polygon Mainnet Block Explorer](https://polygonscan.com/) - -| Contract | Address | -| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | -| LensHub Proxy _(use this one for interactions!)_ | [0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d](https://polygonscan.com/address/0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d) | -| LensHub Implementation | [0xeCd1d11B69FFd9794d45269247f9Fc139462bC12](https://polygonscan.com/address/0xeCd1d11B69FFd9794d45269247f9Fc139462bC12) | -| PublishingLogic | [0x931519D41797C73b9CE993B52c1af900373b5b43](https://polygonscan.com/address/0x931519D41797C73b9CE993B52c1af900373b5b43) | -| InteractionLogic | [0xe71291f49C4b572EF6e864Ba54E50C13A6D407e7](https://polygonscan.com/address/0xe71291f49C4b572EF6e864Ba54E50C13A6D407e7) | -| ProfileTokenURILogic | [0x3FA902A571E941dCAc6081d57917994DDB0F9A9d](https://polygonscan.com/address/0x3FA902A571E941dCAc6081d57917994DDB0F9A9d) | -| FeeCollectModule | [0x1292E6dF9a4697DAAfDDBD61D5a7545A634af33d](https://polygonscan.com/address/0x1292E6dF9a4697DAAfDDBD61D5a7545A634af33d) | -| LimitedFeeCollectModule | [0xEF13EFa565FB29Cd55ECf3De2beb6c69bD988212](https://polygonscan.com/address/0xEF13EFa565FB29Cd55ECf3De2beb6c69bD988212) | -| TimedFeeCollectModule | [0xbf4E6C28d7f37C867CE62cf6ccb9efa4C7676F7F](https://polygonscan.com/address/0xbf4E6C28d7f37C867CE62cf6ccb9efa4C7676F7F) | -| LimitedTimedFeeCollectModule | [0x7B94f57652cC1e5631532904A4A038435694636b](https://polygonscan.com/address/0x7B94f57652cC1e5631532904A4A038435694636b) | -| RevertCollectModule | [0xa31FF85E840ED117E172BC9Ad89E55128A999205](https://polygonscan.com/address/0xa31FF85E840ED117E172BC9Ad89E55128A999205) | -| FreeCollectModule | [0x23b9467334bEb345aAa6fd1545538F3d54436e96](https://polygonscan.com/address/0x23b9467334bEb345aAa6fd1545538F3d54436e96) | -| FeeFollowModule | [0x80ae0e6048d6e295Ee6520b07Eb6EC4485193FD6](https://polygonscan.com/address/0x80ae0e6048d6e295Ee6520b07Eb6EC4485193FD6) | -| ProfileFollowModule | [0x057ccDf5153bE1081830a6C3D507C9dfE1ac8e4E](https://polygonscan.com/address/0x057ccDf5153bE1081830a6C3D507C9dfE1ac8e4E) | -| RevertFollowModule | [0x6640e4Fb3fd56a6d7DfF3C351dFd9Ab7E57fb769](https://polygonscan.com/address/0x6640e4Fb3fd56a6d7DfF3C351dFd9Ab7E57fb769) | -| FollowerOnlyReferenceModule | [0x17317F96f0C7a845FFe78c60B10aB15789b57Aaa](https://polygonscan.com/address/0x17317F96f0C7a845FFe78c60B10aB15789b57Aaa) | -| FollowNFT | [0xb0298c5540f4cfb3840c25d290be3ef3fe09fa8c](https://polygonscan.com/address/0xb0298c5540f4cfb3840c25d290be3ef3fe09fa8c) | -| CollectNFT | [0x2172758ebb894c43e0be01e37d065118317d7eec](https://polygonscan.com/address/0x2172758ebb894c43e0be01e37d065118317d7eec) | -| LensPeriphery | [0xeff187b4190E551FC25a7fA4dFC6cf7fDeF7194f](https://polygonscan.com/address/0xeff187b4190E551FC25a7fA4dFC6cf7fDeF7194f) | -| ModuleGlobals | [0x3Df697FF746a60CBe9ee8D47555c88CB66f03BB9](https://polygonscan.com/address/0x3Df697FF746a60CBe9ee8D47555c88CB66f03BB9) | -| ProfileCreationProxy | [0x1eeC6ecCaA4625da3Fa6Cd6339DBcc2418710E8a](https://polygonscan.com/address/0x1eeC6ecCaA4625da3Fa6Cd6339DBcc2418710E8a) | -| UIDataProvider | [0x8b0A28a8DE1de77668260A876c6DCF0330183742](https://polygonscan.com/address/0x8b0A28a8DE1de77668260A876c6DCF0330183742) | - -## Mumbai Testnet Addresses - -The official faucet and block explorer can be found here: - -- [Polygon Testnet Faucet](https://faucet.polygon.technology/) -- [Polygon Mumbai Block Explorer](https://mumbai.polygonscan.com/) - -**Note:** The `MockProfileCreationProxy` is a whitelisted profile creator that allows anyone to create a profile via `function proxyCreateProfile(DataTypes.CreateProfileData calldata vars)`. This function takes in the exact same parameters required by the standard `createProfile(DataTypes.CreateProfileData calldata vars)` function on the `LensHub`. - -| Contract | Address | -| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -| LensHub Proxy _(use this one for interactions!)_ | [0x60Ae865ee4C725cd04353b5AAb364553f56ceF82](https://mumbai.polygonscan.com/address/0x60Ae865ee4C725cd04353b5AAb364553f56ceF82) | -| LensHub Implementation | [0x45cf9Ba12b43F6c8B7148E06A6f84c5B9ad3Dd44](https://mumbai.polygonscan.com/address/0x45cf9Ba12b43F6c8B7148E06A6f84c5B9ad3Dd44) | -| PublishingLogic | [0x7f9bfF8493F821111741b93429A6A6F79DC546F0](https://mumbai.polygonscan.com/address/0x7f9bfF8493F821111741b93429A6A6F79DC546F0) | -| InteractionLogic | [0x845242e2Cd249af8D4f0D7085DefEAc3381815E3](https://mumbai.polygonscan.com/address/0x845242e2Cd249af8D4f0D7085DefEAc3381815E3) | -| ProfileTokenURILogic | [0xf62c27B7B70A33739A7C088097fc20609A80eE58](https://mumbai.polygonscan.com/address/0xf62c27B7B70A33739A7C088097fc20609A80eE58) | -| FeeCollectModule | [0xeb4f3EC9d01856Cec2413bA5338bF35CeF932D82](https://mumbai.polygonscan.com/address/0xeb4f3EC9d01856Cec2413bA5338bF35CeF932D82) | -| LimitedFeeCollectModule | [0xFCDA2801a31ba70dfe542793020a934F880D54aB](https://mumbai.polygonscan.com/address/0xFCDA2801a31ba70dfe542793020a934F880D54aB) | -| TimedFeeCollectModule | [0x36447b496ebc97DDA6d8c8113Fe30A30dC0126Db](https://mumbai.polygonscan.com/address/0x36447b496ebc97DDA6d8c8113Fe30A30dC0126Db) | -| LimitedTimedFeeCollectModule | [0xDa76E44775C441eF53B9c769d175fB2948F15e1C](https://mumbai.polygonscan.com/address/0xDa76E44775C441eF53B9c769d175fB2948F15e1C) | -| RevertCollectModule | [0x5E70fFD2C6D04d65C3abeBa64E93082cfA348dF8](https://mumbai.polygonscan.com/address/0x5E70fFD2C6D04d65C3abeBa64E93082cfA348dF8) | -| FreeCollectModule | [0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c](https://mumbai.polygonscan.com/address/0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c) | -| FeeFollowModule | [0xe7AB9BA11b97EAC820DbCc861869092b52B65C06](https://mumbai.polygonscan.com/address/0xe7AB9BA11b97EAC820DbCc861869092b52B65C06) | -| ProfileFollowModule | [0x8c32203df6b1A04E25145346e2DaAD0B4712C20D](https://mumbai.polygonscan.com/address/0x8c32203df6b1A04E25145346e2DaAD0B4712C20D) | -| RevertFollowModule | [0x8c822Fc029EBdE62Da1Ed1072534c5e112dAE48c](https://mumbai.polygonscan.com/address/0x8c822Fc029EBdE62Da1Ed1072534c5e112dAE48c) | -| FollowerOnlyReferenceModule | [0x7Ea109eC988a0200A1F79Ae9b78590F92D357a16](https://mumbai.polygonscan.com/address/0x7Ea109eC988a0200A1F79Ae9b78590F92D357a16) | -| FollowNFT | [0x1a2bb1bc90aa5716f5eb85fd1823338bd1b6f772](https://mumbai.polygonscan.com/address/0x1a2bb1bc90aa5716f5eb85fd1823338bd1b6f772) | -| CollectNFT | [0x39dcB881eBdB0DF708412754468c99B4EbD2E370](https://mumbai.polygonscan.com/address/0x39dcB881eBdB0DF708412754468c99B4EbD2E370) | -| LensPeriphery | [0xD5037d72877808cdE7F669563e9389930AF404E8](https://mumbai.polygonscan.com/address/0xD5037d72877808cdE7F669563e9389930AF404E8) | -| ModuleGlobals | [0x1353aAdfE5FeD85382826757A95DE908bd21C4f9](https://mumbai.polygonscan.com/address/0x1353aAdfE5FeD85382826757A95DE908bd21C4f9) | -| MockProfileCreationProxy | [0x420f0257D43145bb002E69B14FF2Eb9630Fc4736](https://mumbai.polygonscan.com/address/0x420f0257D43145bb002E69B14FF2Eb9630Fc4736) | -| UIDataProvider | [0x4fF8EB275b2817fB2e7893bFF7ae7994e54e0730](https://mumbai.polygonscan.com/address/0x4fF8EB275b2817fB2e7893bFF7ae7994e54e0730) | - -## Sandbox Mumbai Testnet Addresses - -This Lens version does not have whitelist restrictions for the modules & currencies. - -The official faucet and block explorer can be found here: - -- [Polygon Testnet Faucet](https://faucet.polygon.technology/) -- [Polygon Mumbai Block Explorer](https://mumbai.polygonscan.com/) - -**Note:** The `MockProfileCreationProxy` is a whitelisted profile creator that allows anyone to create a profile via `function proxyCreateProfile(DataTypes.CreateProfileData calldata vars)`. This function takes in the exact same parameters required by the standard `createProfile(DataTypes.CreateProfileData calldata vars)` function on the `LensHub`. - -**Note 2:** The `MockSandboxGovernance` is a mock Governance contract that can Whitelist Follow/Reference/Collect modules without checking for `onlyGov` permissions. The functions for whitelisting modules are the same as in LensHub and follow the same standard: `whitelistFollowModule(address followModule, bool whitelist)`, `whitelistReferenceModule(address referenceModule, bool whitelist)`, `whitelistCollectModule(address collectModule, bool whitelist)` - -| Contract | Address | -| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -| LensHub Proxy _(use this one for interactions!)_ | [0x7582177F9E536aB0b6c721e11f383C326F2Ad1D5](https://mumbai.polygonscan.com/address/0x7582177F9E536aB0b6c721e11f383C326F2Ad1D5) | -| LensHub Implementation | [0x7836c7cb79b7f3d53e92c95bf43798ada212fe4e](https://mumbai.polygonscan.com/address/0x7836c7cb79b7f3d53e92c95bf43798ada212fe4e) | -| PublishingLogic | [0xDaDB107743e91249929C55132A238a3E735eA7eC](https://mumbai.polygonscan.com/address/0xDaDB107743e91249929C55132A238a3E735eA7eC) | -| InteractionLogic | [0xB91F340BEab90580d557F1332704bF5DB9c35A9D](https://mumbai.polygonscan.com/address/0xB91F340BEab90580d557F1332704bF5DB9c35A9D) | -| ProfileTokenURILogic | [0x5A39B7A9507044509Ef97D4EA306Dc8bA9DB818e](https://mumbai.polygonscan.com/address/0x5A39B7A9507044509Ef97D4EA306Dc8bA9DB818e) | -| FeeCollectModule | [0xD57C675b542bFC24242a1088514306fFaeaFc6Fb](https://mumbai.polygonscan.com/address/0xD57C675b542bFC24242a1088514306fFaeaFc6Fb) | -| LimitedFeeCollectModule | [0x27742f7e82356e1c1e4177C11f627B5Dc18E4686](https://mumbai.polygonscan.com/address/0x27742f7e82356e1c1e4177C11f627B5Dc18E4686) | -| TimedFeeCollectModule | [0x6Bf382f52398DAdD3969Fb9C1AB3a1Bab8268F4E](https://mumbai.polygonscan.com/address/0x6Bf382f52398DAdD3969Fb9C1AB3a1Bab8268F4E) | -| LimitedTimedFeeCollectModule | [0x75Df383C587B0de2EB00FeA95B9b8e3AF35EbCe6](https://mumbai.polygonscan.com/address/0x75Df383C587B0de2EB00FeA95B9b8e3AF35EbCe6) | -| RevertCollectModule | [0x75fe7513709E6Ca573d017cE979F7d35192CE0d5](https://mumbai.polygonscan.com/address/0x75fe7513709E6Ca573d017cE979F7d35192CE0d5) | -| FreeCollectModule | [0x11C45Cbc6fDa2dbe435C0079a2ccF9c4c7051595](https://mumbai.polygonscan.com/address/0x11C45Cbc6fDa2dbe435C0079a2ccF9c4c7051595) | -| FeeFollowModule | [0xE98a40DB1170B3A46ffa7bA84335A0A0e9A65C2d](https://mumbai.polygonscan.com/address/0xE98a40DB1170B3A46ffa7bA84335A0A0e9A65C2d) | -| ProfileFollowModule | [0x62D0EcAB45428087d91a94EE33E141B7496Ad7c3](https://mumbai.polygonscan.com/address/0x62D0EcAB45428087d91a94EE33E141B7496Ad7c3) | -| RevertFollowModule | [0x65004331Ae1c3D35DF81aEC6E8C259167Bbe64E2](https://mumbai.polygonscan.com/address/0x65004331Ae1c3D35DF81aEC6E8C259167Bbe64E2) | -| FollowerOnlyReferenceModule | [0xB080AAc00E53FBeb04917F22096721d602c70759](https://mumbai.polygonscan.com/address/0xB080AAc00E53FBeb04917F22096721d602c70759) | -| FollowNFT | [0xf51b134ca8f54fdf19eb49001fe337b1e93cf707](https://mumbai.polygonscan.com/address/0xf51b134ca8f54fdf19eb49001fe337b1e93cf707) | -| CollectNFT | [0x57F4040B6a38C26e8a92527e3495EB936496CCc9](https://mumbai.polygonscan.com/address/0x57F4040B6a38C26e8a92527e3495EB936496CCc9) | -| LensPeriphery | [0xa6bcF4398824A199965f89094796DFCcEa81b1a6](https://mumbai.polygonscan.com/address/0xa6bcF4398824A199965f89094796DFCcEa81b1a6) | -| ModuleGlobals | [0xcbCC5b9611d22d11403373432642Df9Ef7Dd81AD](https://mumbai.polygonscan.com/address/0xcbCC5b9611d22d11403373432642Df9Ef7Dd81AD) | -| MockProfileCreationProxy | [0x4fe8deB1cf6068060dE50aA584C3adf00fbDB87f](https://mumbai.polygonscan.com/address/0x4fe8deB1cf6068060dE50aA584C3adf00fbDB87f) | -| MockSandboxGovernance | [0x1677d9cc4861f1c85ac7009d5f06f49c928ca2ad](https://mumbai.polygonscan.com/address/0x1677d9cc4861f1c85ac7009d5f06f49c928ca2ad) | -| UIDataProvider | [0x5dDD1d6c04E805D830574A31Bf7979D416c6d7c5](https://mumbai.polygonscan.com/address/0x5dDD1d6c04E805D830574A31Bf7979D416c6d7c5) | - -## Sandbox Polygon zkEVM Testnet Addresses - -This Lens version does not have whitelist restrictions for the modules & currencies. - -The zkEVM Testnet is linked to the Ethereum Goerli Testnet, information can be found here: - -- [zkEVM Bridge](https://public.zkevm-test.net/l) -- [zkEVM Block Explorer](https://zkevm.polygonscan.com/) - -**Note:** The `MockProfileCreationProxy` is a whitelisted profile creator that allows anyone to create a profile via `function proxyCreateProfile(DataTypes.CreateProfileData calldata vars)`. This function takes in the exact same parameters required by the standard `createProfile(DataTypes.CreateProfileData calldata vars)` function on the `LensHub`. - -| Contract | Address | -| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -| LensHub Proxy _(use this one for interactions!)_ | [0x28af365578586eD5Fd500A1Dc0a3E20Fc7b2Cffa](https://public.zkevm-test.net:8443/address/0x28af365578586eD5Fd500A1Dc0a3E20Fc7b2Cffa) | -| LensHub Implementation | [0x1b30F214c192EF4B7F8c9926c47C4161016955DA](https://public.zkevm-test.net:8443/address/0x1b30F214c192EF4B7F8c9926c47C4161016955DA) | -| PublishingLogic | [0xfAAdCf7EA45FDE28FC05d584B8bc206C79f7c4cA](https://public.zkevm-test.net:8443/address/0xfAAdCf7EA45FDE28FC05d584B8bc206C79f7c4cA) | -| InteractionLogic | [0xe88145bCB599E6b9984707651e23fb7bd485EDD3](https://public.zkevm-test.net:8443/address/0xe88145bCB599E6b9984707651e23fb7bd485EDD3) | -| ProfileTokenURILogic | [0x4E0d5b0a41196b0EDee8Ecd3C97C8889c502f041](https://public.zkevm-test.net:8443/address/0x4E0d5b0a41196b0EDee8Ecd3C97C8889c502f041) | -| FeeCollectModule | [0x3Dfe8C165929f4AbB02ffb3a46ccE6BdA4e5fABE](https://public.zkevm-test.net:8443/address/0x3Dfe8C165929f4AbB02ffb3a46ccE6BdA4e5fABE) | -| LimitedFeeCollectModule | [0xcafdB2Acb9a30D00E614817533A204100163432D](https://public.zkevm-test.net:8443/address/0xcafdB2Acb9a30D00E614817533A204100163432D) | -| TimedFeeCollectModule | [0x53C1998e9695Da499bd3Ec2eFfeACCab14c850CF](https://public.zkevm-test.net:8443/address/0x53C1998e9695Da499bd3Ec2eFfeACCab14c850CF) | -| LimitedTimedFeeCollectModule | [0x86CDBB3D663888676365960D93A1c7B727506ed5](https://public.zkevm-test.net:8443/address/0x86CDBB3D663888676365960D93A1c7B727506ed5) | -| RevertCollectModule | [0x3111B932cF33a980De37734a4dA10163b2b84077](https://public.zkevm-test.net:8443/address/0x3111B932cF33a980De37734a4dA10163b2b84077) | -| FreeCollectModule | [0xBe4d2f15dc26626A5a2BAd27d96AcEf054D7d33A](https://public.zkevm-test.net:8443/address/0xBe4d2f15dc26626A5a2BAd27d96AcEf054D7d33A) | -| FeeFollowModule | [0x218fcF793FA1e4fDA220Fb7e55aDF9d8fe0b8C96](https://public.zkevm-test.net:8443/address/0x218fcF793FA1e4fDA220Fb7e55aDF9d8fe0b8C96) | -| ProfileFollowModule | [0x3AF998eB454a418c4a66780c903CDF45d69265f9](https://public.zkevm-test.net:8443/address/0x3AF998eB454a418c4a66780c903CDF45d69265f9) | -| RevertFollowModule | [0xE24c9cd6aD3ea09e328BC0eb128FCb0d17737f96](https://public.zkevm-test.net:8443/address/0xE24c9cd6aD3ea09e328BC0eb128FCb0d17737f96) | -| FollowerOnlyReferenceModule | [0xC6396dcDA9E8830EFD44717da003B0D99b786621](https://public.zkevm-test.net:8443/address/0xC6396dcDA9E8830EFD44717da003B0D99b786621) | -| FollowNFT | [0x9d7c6e30345fc68be670017bbcc6840b35978a7a](https://public.zkevm-test.net:8443/address/0x9d7c6e30345fc68be670017bbcc6840b35978a7a) | -| CollectNFT | [0xe4419a822f6e53fe4d25ff22f51fa5de54e10f53](https://public.zkevm-test.net:8443/address/0xe4419a822f6e53fe4d25ff22f51fa5de54e10f53) | -| LensPeriphery | [0x0e1F86F248fBc407BfFc4217042b5A55Db289385](https://public.zkevm-test.net:8443/address/0x0e1F86F248fBc407BfFc4217042b5A55Db289385) | -| ModuleGlobals | [0x20d35ea7c5186879E7d5Ec6d0941d451bBa54F4b](https://public.zkevm-test.net:8443/address/0x20d35ea7c5186879E7d5Ec6d0941d451bBa54F4b) | -| MockProfileCreationProxy | [0x923e7786176Ef21d0B31645fB1353b1392Dd0e40](https://public.zkevm-test.net:8443/address/0x923e7786176Ef21d0B31645fB1353b1392Dd0e40) | -| UIDataProvider | [0x1e20C5D968C543245Ab4f6749e5f863a82842337](https://public.zkevm-test.net:8443/address/0x1e20C5D968C543245Ab4f6749e5f863a82842337) | \ No newline at end of file diff --git a/documents/Documentation/developer-quickstart-api.md b/documents/Documentation/developer-quickstart-api.md deleted file mode 100644 index 0959235..0000000 --- a/documents/Documentation/developer-quickstart-api.md +++ /dev/null @@ -1,363 +0,0 @@ ---- -title: "Developer Quickstart - Lens API" -slug: "developer-quickstart-api" -hidden: false -metadata: -createdAt: "2022-10-19T21:51:23.077Z" -updatedAt: "2023-05-25T20:38:30.608Z" ---- -The recommended way to get started building on Lens is to use the Lens SDK and [this quickstart guide](https://docs.lens.xyz/docs/developer-quickstart-1). - -If you are instead interested in using the lower level Lens GraphQL API, this tutorial is for you! - -### Tutorial overview - -In this guide you'll learn how to build a full stack web application with Lens Protocol, [Next.js](https://nextjs.org/), and [Tailwind CSS](https://tailwindcss.com/). - -![](https://files.readme.io/05a6bcf-overviewoofapp.jpg) - -## Basic concepts - -Lens Protocol allows developers to quickly and easily build web3 social applications. - -As a developer you can either use the Lens deployment on Polygon or [deploy the protocol yourself](https://docs.lens.xyz/docs/quick-setup) to any EVM compatible blockchain network. - -_In this tutorial you'll use the [Lens API](https://docs.lens.xyz/docs/introduction) to fetch and render a social media feed, navigate to view an individual profile, and fetch and view the user's publications._ - -The Lens API can be tested at any time [here](https://api.lens.dev/) using any of the GraphQL queries in [the API docs](https://docs.lens.xyz/docs/introduction). - -### Prerequisites - -To complete this tutorial successfully, you must have [Node.js](https://nodejs.org/en/) installed on your machine. - -- Install Node.js [with NVM](https://github.com/nvm-sh/nvm) -- Install Node.js [with FNM](https://github.com/Schniz/fnm) - -## Getting started - -To get started we'll first create and configure the Next.js application. - -To generate a new Next.js app, run the following command from your terminal: - -```shell -npx create-next-app lens-app - -✔ Would you like to use TypeScript with this project? Yes -✔ Would you like to use ESLint with this project? Yes -✔ Would you like to use Tailwind CSS with this project? Yes -✔ Would you like to use `src/` directory with this project? No -✔ Use App Router (recommended)? Yes -✔ Would you like to customize the default import alias? No -``` - -Next, change into the new directory and install these dependencies for the GraphQL client: - -```shell -npm install @apollo/client graphql -``` - -Next, update the `tsconfig.json` and add the following to the `compilerOptions` configuration: - -```Text json - "noImplicitAny": false, -``` - -## Creating the API - -Creating a basic GraphQL API is simple, we can do it in just a couple of lines of code. We'll also define the first GraphQL query we'll be using in our app. - -Create a new file named `api.ts` in the root of the new project and add the following code: - -```typescript -import { ApolloClient, InMemoryCache, gql } from '@apollo/client' - -const API_URL = 'https://api.lens.dev' - -/* create the API client */ -export const client = new ApolloClient({ - uri: API_URL, - cache: new InMemoryCache() -}) - -/* define a GraphQL query */ -export const exploreProfiles = gql` -query ExploreProfiles { - exploreProfiles(request: { sortCriteria: MOST_FOLLOWERS }) { - items { - id - name - bio - handle - picture { - ... on MediaSet { - original { - url - } - } - } - stats { - totalFollowers - } - } - } -} -` -``` - -The query we've defined here will fetch a list of [profiles](https://docs.lens.xyz/docs/explore-profiles) from Lens based on the profile sort criteria pass in, in our case `MOST_FOLLOWERS`. You can view all of the sort criteria [here](https://docs.lens.xyz/docs/explore-profiles#sortcriteria), and experiment with other profile queries [here](https://docs.lens.xyz/docs/profiles). - -## Fetching and rendering profiles - -We can now fetch data using the new API with a single line of code: - -```typescript -const response = await client.query({ query: exploreProfiles }) -``` - -With that in mind, we'd like to fetch the profiles using this API, then render and style them in our app. - -To do so, let's update `app/page.tsx` in our app with the following code: - -```typescript -/* app/page.tsx */ -'use client' - -import { useEffect, useState } from 'react' -import { client, exploreProfiles } from '../api' -import Link from 'next/link' - -export default function Home() { - /* create initial state to hold array of profiles */ - const [profiles, setProfiles] = useState([]) - useEffect(() => { - fetchProfiles() - }, []) - async function fetchProfiles() { - try { - /* fetch profiles from Lens API */ - let response = await client.query({ query: exploreProfiles }) - /* loop over profiles, create properly formatted ipfs image links */ - let profileData = await Promise.all(response.data.exploreProfiles.items.map(async profileInfo => { - let profile = { ...profileInfo } - let picture = profile.picture - if (picture && picture.original && picture.original.url) { - if (picture.original.url.startsWith('ipfs://')) { - let result = picture.original.url.substring(7, picture.original.url.length) - profile.avatarUrl = `http://lens.infura-ipfs.io/ipfs/${result}` - } else { - profile.avatarUrl = picture.original.url - } - } - return profile - })) - - /* update the local state with the profiles array */ - setProfiles(profileData) - } catch (err) { - console.log({ err }) - } - } - return ( -
-
-

Hello Lens 🌿

- { - profiles.map(profile => ( -
- -

{profile.name}

-

{profile.bio}

- -

{profile.handle}

- -

{profile.stats.totalFollowers} followers

-
- )) - } -
-
- ) -} -``` - -Next, run the app: - -```shell -npm run dev -``` - -When the app loads, you should see a list of Lens profiles with their image, name, bio, and handle. - -![](https://files.readme.io/9106b7d-lens-list.jpg) - -### 🎉 Congratulations! You've built your first Lens application! - -Next, we'd like to be able to click on a user's handle and view more details about the user, like their latest posts. - -## Viewing an individual profile - -For the individual profile view we'll need two new API calls: - -1. To fetch the [profile details](https://docs.lens.xyz/docs/get-profile) for the individual user -2. To fetch the [publications](https://docs.lens.xyz/docs/get-publications) for the individual user - -To enable this, open `api.ts` and add the following two queries: - -```typescript -export const getProfile = gql` -query Profile($handle: Handle!) { - profile(request: { handle: $handle }) { - id - name - bio - picture { - ... on MediaSet { - original { - url - } - } - } - handle - } -} -` - -export const getPublications = gql` - query Publications($id: ProfileId!, $limit: LimitScalar) { - publications(request: { - profileId: $id, - publicationTypes: [POST], - limit: $limit - }) { - items { - __typename - ... on Post { - ...PostFields - } - } - } - } - fragment PostFields on Post { - id - metadata { - ...MetadataOutputFields - } - } - fragment MetadataOutputFields on MetadataOutput { - content - } -` -``` - -In `app/page.tsx` you'll notice that we're linking to the user's handle in the html: - -```typescript - -

{profile.handle}

- -``` - -Right now, the `/profile/${profile.handle}` route does not yet exist, so let's create it. - -To do so, create a new folder in the app directory named `profile`. Inside the `profile` folder, create a new folder named `[id]`. In the `[id]` folder, create a new file named `page.tsx`. - -In this file add the following code: - -```typescript -/* app/profile/[id]/page.tsx */ -'use client' -import { useState, useEffect } from 'react' -import { usePathname } from 'next/navigation'; -import { client, getPublications, getProfile } from '../../../api' - -export default function Profile() { - /* create initial state to hold user profile and array of publications */ - const [profile, setProfile] = useState() - const [publications, setPublications] = useState([]) - /* using the router we can get the lens handle from the route path */ - const pathName = usePathname() - const handle = pathName?.split('/')[2] - - useEffect(() => { - if (handle) { - fetchProfile() - } - }, [handle]) - - async function fetchProfile() { - try { - /* fetch the user profile using their handle */ - const returnedProfile = await client.query({ - query: getProfile, - variables: { handle } - }) - const profileData = { ...returnedProfile.data.profile } - /* format their picture if it is not in the right format */ - const picture = profileData.picture - if (picture && picture.original && picture.original.url) { - if (picture.original.url.startsWith('ipfs://')) { - let result = picture.original.url.substring(7, picture.original.url.length) - profileData.avatarUrl = `http://lens.infura-ipfs.io/ipfs/${result}` - } else { - profileData.avatarUrl = profileData.picture.original.url - } - } - setProfile(profileData) - /* fetch the user's publications from the Lens API and set them in the state */ - const pubs = await client.query({ - query: getPublications, - variables: { - id: profileData.id, limit: 50 - } - }) - setPublications(pubs.data.publications.items) - } catch (err) { - console.log('error fetching profile...', err) - } - } - - if (!profile) return null - - return ( -
-
- -

{profile.handle}

-

{profile.bio}

- { - publications.map(pub => ( -
-

{pub.metadata.content}

-
- )) - } -
-
- ) -} -``` - -Now, run the app: - -```javascript -npm run dev -``` - -When the app loads, you should be able to click on a user's handle and navigate to their profile. In this view, you'll see the user's profile along with a feed of their latest posts! - -![User profile feed](https://files.readme.io/8d8829f-aavefeed.jpg) - -## Next steps - -Now that you've built your first basic application, it's time to explore more of [the Lens API!](https://docs.lens.xyz/docs/introduction) - -Consider diving into [authentication](https://docs.lens.xyz/docs/authentication), [modules](https://docs.lens.xyz/docs/module-interfaces), or learning about [gasless transactions](https://docs.lens.xyz/docs/proxy-action-gasless) and the [dispatcher](https://docs.lens.xyz/docs/dispatcher). - -Also consider adding the following features to your new app: - -1. Following a user -2. Searching for users -3. Creating a post \ No newline at end of file diff --git a/documents/Documentation/developer-quickstart.md b/documents/Documentation/developer-quickstart.md deleted file mode 100644 index 90a290e..0000000 --- a/documents/Documentation/developer-quickstart.md +++ /dev/null @@ -1,456 +0,0 @@ ---- -title: "Developer Quickstart" -slug: "developer-quickstart" -hidden: false -createdAt: "2023-05-22T22:58:56.135Z" -updatedAt: "2023-05-25T20:39:07.091Z" ---- -This tutorial walks you through the recommended way to build on Lens, leveraging the [Lens React Hooks SDK](https://docs.lens.xyz/docs/sdk-react-intro). - -The Lens React Hooks SDK abstracts away the need to write a lot of lower level GraphQL boilerplate for API calls to Lens, making it much easier to build web and mobile apps on Lens. - -It's worth noting that this tutorial only supports React and React Native. If you'd like to build with other frameworks or clients such as other JavaScript frameworks or native iOS, consider using the [Lens Client SDK](https://docs.lens.xyz/docs/client-sdk-reference), or the [Lens API](https://docs.lens.xyz/docs/introduction) directly. - -## Tutorial overview - -In this tutorial you'll learn how to use Next.js, TypeScript, Lens Protocol, and the Lens SDK to build out a social application. - -The app we'll be building will have the following features: - -1. When the app loads, it will render a list of recommended users from the Lens API along with their profile picture and bio -2. When we click on a user, we will navigate to a detail view where we will see all of their publications as well as more profile details -3. The user profile view will also have the option for a user to sign in and follow another user. - -By the end of this tutorial you'll have a good understanding of how to get started building on Lens with TypeScript and the Lens SDK. - -### Getting started - -To get started, create a new Next.js application: - -```sh -npx create-next-app lens-app - -✔ Would you like to use TypeScript with this project? Yes -✔ Would you like to use ESLint with this project? Yes -✔ Would you like to use Tailwind CSS with this project? Yes -✔ Would you like to use `src/` directory with this project? No -✔ Use App Router (recommended)? Yes -✔ Would you like to customize the default import alias? No -``` - -Next, change into the new directory and install the following dependencies: - -```sh -cd lens-app - -npm install @lens-protocol/react-web ethers@legacy-v5 wagmi@0.12.7 @lens-protocol/wagmi -``` - -## app/layout.tsx - -Next, we want to configure our app to use the Lens SDK. - -This is typically done at the entrypoint of the app, and only needs to be done once. - -This is a decent amount of code, but once it's set up it makes using the SDK very easy in all of the rest of our components. - -Update `app/layout.tsx` with the following code: - -```typescript -'use client' -import './globals.css' -import { configureChains, createClient, WagmiConfig } from 'wagmi' -import { mainnet, polygon } from 'wagmi/chains' -import { publicProvider } from 'wagmi/providers/public' -import { LensProvider, LensConfig, production } from '@lens-protocol/react-web' -import { bindings as wagmiBindings } from '@lens-protocol/wagmi' -const { provider, webSocketProvider } = configureChains([polygon, mainnet], [publicProvider()]) - -const client = createClient({ - autoConnect: true, - provider, - webSocketProvider, -}); - -const lensConfig: LensConfig = { - bindings: wagmiBindings(), - environment: production, -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - - - {children} - - - - ) -} -``` - -## Format picture utility - -Next, we'll need a helper function to format the pictures coming back to use with IPFS and Arweave gateways. By default, we'll only have the hash. - -In the root directory, create a file named `utils.ts` and add the following code: - -```typescript -// utils.ts -export function formatPicture(picture: any) { - if (picture.__typename === 'MediaSet') { - if (picture.original.url.startsWith('ipfs://')) { - let result = picture.original.url.substring(7, picture.original.url.length) - return `http://lens.infura-ipfs.io/ipfs/${result}` - } else if (picture.original.url.startsWith('ar://')) { - let result = picture.original.url.substring(4, picture.original.url.length) - return `http://arweave.net/${result}` - } else { - return picture.original.url - } - } else { - return picture - } -} -``` - -## app/page.tsx - -Next, let's query for profiles and render them in our app. - -To do so, open `app/page.tsx` and add the following code: - -```typescript -// app/page.tsx -'use client' -import { useExploreProfiles } from '@lens-protocol/react-web' -import Link from 'next/link' -import { formatPicture } from '../utils' - -export default function Home() { - const { data: profiles } = useExploreProfiles({ - limit: 25 - }) - - return ( -
-

My Lens App

- { - profiles?.map((profile, index) => ( - -
- { - profile.picture && profile.picture.__typename === 'MediaSet' ? ( - {profile.handle} - ) :
- } -

{profile.handle}

-

{profile.bio}

-
- - )) - } -
- ) -} - -``` - -#### What's happening? - -In `useExploreProfiles`, we are calling the Lens API to fetch a list of recommended profiles. - -The `formatPicture` function updates the image metadata to provide either an IPFS or Arweave gateway to each hash. - -### Testing it out - -To run the app, run the following command: - -```sh -npm run dev -``` - -## Profile View - -In the above code, we've added a link to each profile that, when clicked, will navigate to `/profile/profile.id`. What we want to happen is that when a user navigates to that page, they are able to view more details about that profile. - -This functionality does not yet exist, so let's create it. - -### Profile view - -In the `app` directory, create a new folder named `profile`. - -In the `profile` directory create a new folder named `[id]`. - -In the `[id]` folder, create a new file named `page.tsx`. - -In this file, add the following code: - -```typescript -// app/profile/[id]/page.tsx -'use client' -import { usePathname } from 'next/navigation'; -import { - useProfile, usePublications, Profile -} from '@lens-protocol/react-web'; -import { formatPicture } from '../../../utils'; - -export default function Profile() { - const pathName = usePathname() - const handle = pathName?.split('/')[2] - - let { data: profile, loading } = useProfile({ handle }) - - if (loading) return

Loading ...

- - return ( -
-
- { - profile?.picture?.__typename === 'MediaSet' && ( - {profile.handle} - ) - } -

{profile?.handle}

-

{profile?.bio}

- { profile && } -
-
- ) -} - -function Publications({ - profile -}: { - profile: Profile -}) { - let { data: publications } = usePublications({ - profileId: profile.id, - limit: 10, - }) - publications = publications?.map(publication => { - if (publication.__typename === 'Mirror') { - return publication.mirrorOf - } else { - return publication - } - }) - - return ( - <> - { - publications?.map((pub: any, index: number) => ( -
-

{pub.metadata.content}

- { - pub.metadata?.media[0]?.original && ['image/jpeg', 'image/png'].includes(pub.metadata?.media[0]?.original.mimeType) && ( - {profile.handle} - ) - } -
- )) - } - - ) -} -``` - -#### What's happening - -`useProfile` allows you to get a user's profile details by passing in a Lens handle or profile ID - -`usePublications` allows you to fetch a user's publications by passing in a profile - -### Testing it out - -To run the app, run the following command: - -```sh -npm run dev -``` - -When you click on a profile, you should navigate to the profile details and be able to view the user publications. - -## Adding authentication and following a user - -Next, let's add some additional functionality that will allow a user to sign and and then follow another user. - -```typescript -// app/profile/[id]/page.tsx -'use client' -import { usePathname } from 'next/navigation'; -// new imports -import { - useProfile, usePublications, useFollow, useWalletLogin, useWalletLogout, useActiveProfile, - Profile, ProfileOwnedByMe, NotFoundError -} from '@lens-protocol/react-web'; -import { useAccount, useConnect, useDisconnect } from 'wagmi'; -import { InjectedConnector } from 'wagmi/connectors/injected'; -import { formatPicture } from '../../../utils'; - -export default function Profile() { - // new hooks - const { execute: login } = useWalletLogin(); - const { execute: logout } = useWalletLogout(); - const { data: wallet } = useActiveProfile(); - const { isConnected } = useAccount(); - const { disconnectAsync } = useDisconnect(); - - const pathName = usePathname() - const handle = pathName?.split('/')[2] - - let { data: profile, loading } = useProfile({ handle }) - - const { connectAsync } = useConnect({ - connector: new InjectedConnector(), - }); - - // new login function - const onLoginClick = async () => { - if (isConnected) { - await disconnectAsync(); - } - const { connector } = await connectAsync(); - if (connector instanceof InjectedConnector) { - const signer = await connector.getSigner(); - await login(signer); - } - } - - if (loading) return

Loading ...

- - return ( -
-
- { - !wallet && ( - - ) - } - { - wallet && profile && ( - <> - - - - ) - } - { - profile && profile.picture?.__typename === 'MediaSet' && ( - {profile.handle} - ) - } -

{profile?.handle}

-

{profile?.bio}

- { profile && } -
-
- ) -} - -// new component -function FollowComponent({ - wallet, - profile, - isConnected -} : { - isConnected: boolean, - profile: Profile, - wallet: ProfileOwnedByMe -}) { - const { execute: follow } = useFollow({ followee: profile, follower: wallet }); - return ( - <> - { - isConnected && ( - - ) - } - - ) -} - -function Publications({ - profile -}: { - profile: Profile -}) { - let { data: publications } = usePublications({ - profileId: profile.id, - limit: 20, - }) - publications = publications?.map(publication => { - if (publication.__typename === 'Mirror') { - return publication.mirrorOf; - } else { - return publication; - } - }); - - return ( - <> - { - publications?.map((pub: any, index: number) => ( -
-

{pub.metadata.content}

- { - pub.metadata?.media[0]?.original && ['image/jpeg', 'image/png'].includes(pub.metadata?.media[0]?.original.mimeType) && ( - {profile.handle} - ) - } -
- )) - } - - ) -} -``` - -When you run the app, you should now be able to sign in and follow another user. - -### Next Steps - -Now that you've built your first basic application, it's time to explore more of the Lens SDK! - -Consider adding search, enabling functionality to let users create a post, diving into modules, or learning about gasless transactions and the dispatcher! \ No newline at end of file diff --git a/documents/Documentation/faq.md b/documents/Documentation/faq.md deleted file mode 100644 index cf65388..0000000 --- a/documents/Documentation/faq.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: "Developers FAQ" -slug: "faq" -hidden: false -createdAt: "2022-05-16T11:47:48.265Z" -updatedAt: "2022-12-01T11:36:16.651Z" ---- -## I am developing but have some doubts, where can I discuss these? - -The best place to ask any dev related questions is the discord channel [here](https://discord.gg/lensprotocol) -Head to the developer & QA section and a team member will be able to help you! - -## I want to apply for a grant to build on Lens Protocol, how can I do this? - -You can learn more about the Lens Protocol grants program [here](https://www.notion.so/aave/Grants-Application-eec79f59fbad4e34b51acc3c936073a2). You can apply for a grant by filling out [this form](https://airtable.com/shrUkRIxqcKgS05dX). - -## If I have queries about grants, integrations, and partnerships, where’s the best place to direct them? - -You can direct such queries to [ecosystem@lens.xyz](mailto:ecosystem@lens.xyz) - -## Where can I get Lens API? - -You can find Lens API [here](https://docs.lens.dev/docs/api-links). - -## Are there developer resources for Windows? - -We do not offer formal support yet for non-UNIX based machines. You might want to try to work with WSL2 or move to UNIX based environment. - -## Who pays the network-related “gas fees” for transactions on Lens Protocol? - -It depends. Users can pay their own gas fees for any transactions on the Lens Protocol. However, certain interfaces might use a relayer to allow “gas free” usage of the network for Lens Protocol transactions or may even subsidize part of the gas fees. - -## How do I unfollow a profile? - -To unfollow a profile, you either need to burn or transfer the specific follow NFT from your wallet. To burn it, send it to the address 0x00..00. - -## How can I track the follow actions of a list of addresses? - -To do this, you will need to listen to the follow events and save them every time the action happens. You will also need to look out for each profile’s follower NFTs to see when someone unfollows (aka burns) or otherwise use the API to get it from there. - -## How do I follow profiles that have specific follow module logic? - -You can just call createFollowTypedData and it will map it all for you. You can find an example [here](https://docs.lens.dev/docs/create-follow-typed-data). - -## How do I apply to have my address enabled to mint profiles? - -The reason profile creation is protected by an allowlist for now is to allow as many users as possible to claim the handle they would like and deter mass claiming. It also allows users to reserve certain usernames and other names they own on web3. Once everyone on the allowlist has claimed their handle and the process of claiming is more mature, it may be possible that the allowlist could be revoked to allow anyone to create a profile. - -## How do comments point to each other? - -Comments are linked to their publication and can have an unlimited depth of pointers. When creating a comment, it is pointed to a publication which allows the UI interface to define the structure of how these publications are shown and loaded. Each comment has reference to the pointer so you can always get back to the start recursively. - -## Which API categories require the auth token? - -To see which categories, require the auth token, visit Lens protocol docs [here](https://docs.lens.dev/docs/introduction) to see at the top whether it is required or not. - -## Can any kind of address be used to post publications or contracts? - -Any Ethereum address can post publications. Therefore, a contract can post if they own the profile. There is a feature on the contracts called “dispatcher” which allows you to put an Ethereum address on the allowlist which then enables that address to post publications and perform other actions on behalf of the owner. - -## Do we have to supply the publication ID when creating a comment? - -Yes, you need to provide a publication ID but this will be specific to your profile. For example, your first publication might be id 1, second id 2, etc. - -## Do we need to use Lens native NFT contracts, or can we deploy on other testing and mainnet networks? - -For testing purposes you can, and it is highly encouraged to use the Lens testnet deployment on Mumbai. You can also deploy your own version locally or on whichever testnet or mainnet you prefer, but if you do so, there won’t be API support. - -## How could a mirrored post be displayed? - -Mirrors are the Lens equivalent to reposting or re-amplifying exisiting content. For example, if Karen sees Chad's post and wants to repost it, this action is called a "mirroring" on Lens. You can store additional data to the post you are mirroring, meaning you can also provide commentary. For example, if Karen mirrors Chad's post, she can also add to the post by herself adding "Love this post, Chad!" - -## Is It possible to build any type of application on Lens even if there are other similar applications (for example, if there is one messaging application, can I build another?) - -The possibilities of building on top of Lens are infinite and whilst the chances of duplicate applications being built are there, each will have its own unique metric. Just make sure you do not infringe on anyone else’s IP when you’re building. - -## Do you have to follow a profile to collect its publications? - -Not necessarily; it depends on the logic of the collect module. - -## Is there an API call to edit publications? - -No, it is not possible to edit publications directly. However, If the content URI points to some editable storage, then you can edit publications via updating what the URI returns. - -## Is it possible to register an NFT profile? - -Profile NFTs are resolved for you with on-chain svgs; you cannot set your own profile NFT as handles (usernames). Your profile picture is taken from the image set into the NFT. - -## Can Lens Protocol be used to develop a social platform that is 90% audio? - -Yes, Lens is a protocol that defines how social content can be relational on chain. Any form of content—text, audio, or video—can be used with Lens Protocol. - -## I got the error HANDLE_TAKEN whilst trying to create a profile. What do I do? - -This error means that the handle you are requesting is already in use for another profile and you will need to request a different one. All handles are unique and cannot be duplicated. - -## How do I fetch all the profile IDs owned by a specific address? - -You can do this by using the API call “get profile” and filtering by “owned by”. Find more details on this [here](https://docs.lens.dev/docs/get-profiles). - -## Does the protocol collect fees? - -The protocol has capacity to take fees, but this is currently disabled. - -## How does the publication’s format work? - -It is required to conform to the metadata standards if you wish to use the API and have common ground with the UIs, you can find out more about this standard [here](https://docs.lens.dev/docs/metadata-standards). The standard outlined allows the publication NFTs to be supported on Open Sea and other marketplaces. That said, the protocol has no constraints on this standard so if you wanted to set your own standard that is fine. However, if you do this, it may not work on other UIs and may also not be compatible with the API, therefore it is heavily advised that you use our standards for compatibility across all Dapps. - -## Do profiles follow other profiles, or what about other types of interactions? - -No, in Lens Protocol the specific wallet is the one following profiles and holding the Follow NFTs that represent this. The follow interaction is not based on a profile but on a specific wallet. Other interactions such as posts, mirrors, and comments will be performed by profiles. - -## What is the default profile variable for and how do I set up a different profile per interaction? - -Because an address can hold multiple profiles and there are address-based interactions such as follow or collect, the default profile variable allows the owner to select one profile as its default. This gives interfaces the ability to shape how such interactions are displayed based on the default profile rather than just an address. For example, a profile may want to display the interaction of Alice following Bob rather than Alice’s address which followed Bob. You can use the set default profile function to choose a new profile to interact with by default. To do this, view the code for the specific command [here](https://docs.lens.dev/docs/create-set-default-profile-typed-data). - -## How can I adapt the core protocol? - -It isn’t possible to change the core protocol, but you can create follow, reference, and collect modules and even extend the protocol by building contracts on top of it. - -## How can I set up where the collected fees are directed? - -It depends on how the collect module set for the publication has been built. For example, one collect module could let the publisher decide which address or addresses will receive the fees, but another could have a fixed fee recipient or other logic. - -## Where is the data created by Lens Protocol’s interactions stored? - -Lens Protocol is agnostic of the content storage; it can be stored on decentralized, immutable solutions such as IPFS or in centralized services, depending on the use case. In the future, this could open room for the possibility of hosting content in a storage service that has not yet been invented! \ No newline at end of file diff --git a/documents/Documentation/lensverse.md b/documents/Documentation/lensverse.md deleted file mode 100644 index b8dcbc6..0000000 --- a/documents/Documentation/lensverse.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Lensverse" -slug: "lensverse" -hidden: false -createdAt: "2022-10-22T12:26:33.227Z" -updatedAt: "2022-10-22T12:30:50.434Z" ---- -Lens Protocol evolves and thrives on the contributions of its community. Feedback on improving the Lens Ecosystem is collected and presented in the Inspiration for Builders below. - -> 👍 CHECK OUT THE #[LENSVERSE](https://www.notion.so/aave/Lensverse-a5926eab1d8148eda10053af9f4e28a0) \ No newline at end of file diff --git a/documents/Documentation/overview.md b/documents/Documentation/overview.md deleted file mode 100644 index f873cd7..0000000 --- a/documents/Documentation/overview.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: "Overview" -slug: "overview" -hidden: false -createdAt: "2021-12-15T21:42:25.254Z" -updatedAt: "2022-02-10T01:49:19.784Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/407b49a-illustration_profile.svg", - "illustration_profile.svg", - 536, - 240, - "#e5ffbe" - ] - } - ] -} -[/block] -The purpose of the Lens Protocol is to empower creators to own the links between themselves and their community, forming a fully composable, decentralized social graph. This is achieved by allowing users to create profiles and interact with each other via these profiles. "Profile" (as used here) refers specifically to Lens profiles; "user" refers to standard crypto-wallets. - -The protocol is built from the ground up with modularity in mind. Lens Protocol is currently overseen by a multisig, which will be expanded to a broader DAO, which can develop and vote on new modules and expanded functionality. - -## Architecture - -Let's first dig into profile creation and publishing. Users must create a profile on the hub, for which they will receive a sequentially ID'd profile NFT. This NFT controls the profile, and thus, its owner becomes the de facto controller of the given profile. - -Profile owners can: - -1. Publish to the profile. Publication types are: - 1. Post: A standard piece of content. - 2. Comment: A standard piece of content with a pointer to another publication. - 1. Since comments include a pointer, this executes the pointed publication's "reference module" logic, if any. - 3. Mirror: The equivalent of a "share" in a traditional sense, having no content but a pointer to another publication. - 1. Since mirrors only include a pointer, this executes the pointed publication's "reference module" logic, if any. -2. Set the profile's "follow module": - 1. This whitelisted logic contract determines the logic that must be executed when a wallet attempts to follow the given profile; for example, some followers may incur a fee to the profile owner via the fee follow module contract. -3. Set the profile's image URI -4. Set the profile's "dispatcher": - 1. This is an address that can act on behalf of a profile's owner; it can: - 1. Publish to the given profile. - 2. Set the given profile's URI. - -Regular wallets can: - -1. Follow profiles: - 1. This executes the profile's "follow module" logic, if any. - 2. This mints the following wallet a "follow NFT" unique to that profile and sequentially ID'd. - 1. Follow NFTs have a custom URI set by profile owners. -2. Collect publications: - 1. This executes any logic in the publication's "collect module." - 1. If the publication is a mirror, this is executed on the originally mirrored publication with a referral. - 2. This mints the collecting wallet a "collect NFT" unique to that publication and sequentially ID'd. - 1. Collect NFT URIs point to the collected publication's URI. - -### Tokenization - -The Lens protocol has three layers of tokenization via ERC721 NFTs. All three are ERC721-compliant and fully composable. - -The `LensHub` upgradeable contract is the core entry point for the majority of interactions in the Lens Protocol. Nearly all interactions begin and doubles as the ERC721 NFT contract for profile NFTs, which are minted upon profile creation. - -Upon a profile's first follow, a `FollowNFT` contract is deployed (via minimal proxy cloning), unique to the profile; this is the ERC721 NFT contract that represents follower positions. - -Lastly, upon a publication's first collect, a `CollectNFT` contract is deployed (again, via minimal proxy cloning), unique to the publication; this is the ERC721 NFT contract that represents collected publications. - -Note that follow and collect NFTs are deployed only upon the first follow/collect, respectively. This reduces gas overhead for profile creation. - -### Modularity - -Modularity is at the core of the Lens protocol. Everything is built with community expansion and the continued development of new, innovative features in mind. - -Modules are standalone, governance-whitelisted contracts that adhere to a specific interface. They hold state and are unlimited in potential scope beyond adhering to the interface. - -There are three types of modules: - -1. Follow modules: - a. These modules are tied to a profile and contain logic to be executed upon a user attempting to follow the given profile. -2. Collect modules: - a. These modules are tied to specific publications (except mirrors, which cannot be collected) and contain logic to be executed upon a user attempting to collect the given publication. -3. Reference modules: - a. These modules are tied to specific publications and contain logic to be executed upon a user attempting to comment or mirror the given publication. - b. Note that the original content and its reference module are used in the case where a mirror attempts to point to a mirror. - -## Closing Notes - -The Lens Protocol is a composable social graph protocol built to be community-owned and ever-evolving. It empowers its users by allowing them to decide *how* they want their social graph to be built and how they want it to be monetized, if at all. - -Furthermore, the protocol is engineered with the concept of modularity at its core, allowing for an infinitely expanding amount of use cases. This, from the user's perspective, translates to a new paradigm of ownership and customization that isn't possible (or financially feasible) in Web2. \ No newline at end of file diff --git a/documents/Documentation/what-is-lens.md b/documents/Documentation/what-is-lens.md deleted file mode 100644 index 2d227d1..0000000 --- a/documents/Documentation/what-is-lens.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "What is Lens? 🌿" -slug: "what-is-lens" -hidden: false -createdAt: "2022-01-25T14:47:59.952Z" -updatedAt: "2022-02-09T01:10:16.515Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/c2459de-illustration_grow.svg", - "illustration_grow.svg", - 372, - 340, - "#00501e" - ], - "caption": "" - } - ] -} -[/block] -## Introduction - -The Lens Protocol is a Web3 social graph on the Polygon Proof-of-Stake blockchain. It is designed to empower creators to own the links between themselves and their community, forming a fully composable, user-owned social graph. The protocol is built from the ground up with modularity in mind, allowing new features and fixes to be added while ensuring immutable user-owned content and social relationships. - - -## How does the Lens Protocol compare to existing social networks and graphs? - -Lens Protocol seeks to solve major issues in existing social media networks. Namely, Web2 networks all read from their unique, centralized database. There is no portability. Your profile, friends, and content are locked to a specific network and owned by the network operator. This causes each network to fight a zero-sum game for your attention. - -Lens Protocol corrects this by being a user-owned, open social graph that any application can plug into. Since users own their data, they can bring it to any application built on top of Lens Protocol. As the true owners of their content, creators no longer need to worry about losing their content, audience, and livelihood based on the whims of an individual platform's algorithms and policies. Additionally, each application using Lens Protocol benefits the whole ecosystem, turning the zero-sum game into a collaborative one. Developers can design meaningful social experiences without needing to turn to feedback mechanisms to lock in a user's attention. \ No newline at end of file diff --git a/documents/Integrations/encrypted-dms.md b/documents/Integrations/encrypted-dms.md deleted file mode 100644 index 1cd965c..0000000 --- a/documents/Integrations/encrypted-dms.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -title: "Encrypted DMs" -slug: "encrypted-dms" -hidden: false -createdAt: "2023-01-24T21:13:51.294Z" -updatedAt: "2023-01-26T02:41:59.370Z" ---- -Lens apps use [XMTP](https://xmtp.org/) to provide secure, private messaging across different apps. - -XMTP is an open protocol and network for secure web3 messaging. It allows developers to quickly and easily get up and running with private, encrypted, real-time messaging in their applications. - -XMTP enables composability in that it is permissionless and anyone can easily integrate it into their application, inheriting the entire network and ecosystem of applications, similar to how Lens enables developers to inherit the entire ecosystem of users in the existing ecosystem. - -In this guide, you'll learn how to get up and running with private messages using Lens and XMTP. - -> To learn more about XMTP, check out [their docs.](https://xmtp.org/) - -## Getting started - -To get started interacting with XMTP, the user must sign a message with their wallet. Once they've signed and are successfully authenticated within the protocol, the messages for their wallet will be retrieved, and they will be decoded and decrypted. - -In order to do this, we'll use the XMTP JavaScript SDK and a library like `ethers.js`. - -First, install the libraries using **npm**, **yarn**, or your favorite package manager: - -```javascript -npm install @xmtp/xmtp-js ethers -``` - -In your JavaScript or TypeScript application, import XMTP and `ethers.js`: - -```javascript -import { Client } from '@xmtp/xmtp-js' -import { ethers } from 'ethers' -``` - -Next, create a function that allows a user to connect their wallet and sign in: - -```javascript -async function connect() { - await window.ethereum.send('eth_requestAccounts') - const provider = new ethers.providers.Web3Provider(window.ethereum) - const signer = provider.getSigner() - const xmtp = await Client.create(signer, { - env: 'production' - }) -} -``` - - - -Now, using the `xmtp` instance, we can interact with the protocol! - -### Reading conversations and messages - -For instance, if we'd like to get all of the user's conversations, we can do this: - -```javascript -const allConversations = await xmtp.conversations.list() -``` - - - -This does not get the messages themselves, only the conversations that a user has taken part in. - -In order to get the messages from a conversation, we can do this: - -```javascript -const messages = await conversations[0].messages() -``` - - - -### Creating messages - -To create a message, choose the conversation you'd like to send a message to and do this: - -```javascript -await conversation.send('gm') -``` - - - -As you can see, the API is pretty simple to get started with. - -### Real-time updates - -The XMTP service provides real-time message delivery and retrieval. - -Once you retrieve the conversations from the service, you listen for a stream of new conversations coming from the protocol. - -Here is some example code of how that would look: - -```javascript -async function streamConvos() { - const stream = await client.conversations.stream() - for await (const conversation of stream) { - console.log('new conversation in real time! :', conversation) - } -} -``` - - - -And for streaming messages from a conversation: - -```javascript -async function streamMessages(conversation) { - const stream = await conversation.streamMessages() - for await (const newMessage of stream) { - console.log('new message in real time! :', message) - } -} -``` - - - -## Integrating with Lens - -Because XMTP is an open protocol, anyone can build their messaging system using it. - -Different ecosystems can come together to form specifications that enable interoperability between the applications within their ecosystem. - -They do this by prefixing a certain namespace to their `conversationId`, like for example: - -```javascript -const conversationID = `myprotocolname/dm/${profileIdA}-${profileIdB}` -``` - - - -With Lens, there are many apps using the following namespace: - -``` -lens.dev/dm -``` - - - -With the following script, you can create a `conversationID` consistent with the rest of the Lens ecosystem: - -```javascript -const PREFIX = 'lens.dev/dm' -const buildConversationId = (profileIdA: string, profileIdB: string) => { - const profileIdAParsed = parseInt(profileIdA, 16) - const profileIdBParsed = parseInt(profileIdB, 16) - return profileIdAParsed < profileIdBParsed - ? `${PREFIX}/${profileIdA}-${profileIdB}` - : `${PREFIX}/${profileIdB}-${profileIdA}` -} -``` - - - -So when you create a new conversation, you would create the new conversation using this conversation ID in order to be interoperable with the other apps in the ecosystem. - -In practice, your function might look like this: - -```javascript -const conversation = await client.conversations.newConversation( - someLensProfileId, - { - conversationId: buildConversationId(profile1.id, profile2.id), - metadata: {}, - } -) -``` - - - -## Putting it all together - -In this guide we've covered most of the basics to get you up and running with XMTP in a Lens app. - -If you'd like to see a comprehensive full stack codebase, check out [this app ](https://github.com/dabit3/xmtp-chat-app-nextjs)using XMTP and Next.js - -If you'd like to learn more, check out the Lens tutorial from XMTP [here](https://xmtp.org/docs/client-sdk/javascript/tutorials/build-key-xmtp-chat-features-in-a-lens-app). \ No newline at end of file diff --git a/documents/Integrations/integrating-lens.md b/documents/Integrations/integrating-lens.md deleted file mode 100644 index d407c24..0000000 --- a/documents/Integrations/integrating-lens.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: "Embeds and custom links" -slug: "integrating-lens" -hidden: false -createdAt: "2023-01-12T20:55:32.629Z" -updatedAt: "2023-02-26T16:44:36.176Z" ---- -In addition to building applications directly on Lens, you may want to integrate Lens into other new or existing applications. Lens Protocol provides a variety of social features, including profiles, content, comments, and monetization, which can be easily integrated. With our API, you can quickly access a large user base and generate network effects with less effort. - -You can do this by providing features like **sharing** to Lens, **following** on Lens, or **signing in **with Lens in your application. - -## Share to Lens - -**Share to Lens** can help distributing your application and its content to a larger audience. You can create a "Share to Lens" button easily via [Lenster](https://lenster.xyz/) using HTML. - -``` -https://lenster.xyz/?text=Hello%20World! -``` - - - -The following url parameters are supported: - -``` -text -url -via -hashtags -``` - - - -So for example, let's say we have an app called "MyCoolApp" and we wanted to share some content from it to Lens, we could format a URL that looks like this: - -``` -https://lenster.xyz/?text=Hello%20World!&url=https://mycoolapp.xyz&via=MyCoolApp&hashtags=lens,web3 -``` - - - -We would get the following share modal on Lenster: - -![](https://files.readme.io/4e4d25f-Screen_Shot_2023-01-12_at_4.24.20_PM.png) - -### Video tutorial - share to Lens - - -[block:embed] -{ - "html": "", - "url": "https://www.youtube.com/watch?v=lUJs63xILR8", - "title": "How to integrate a Share to Lens button into your web application", - "favicon": "https://www.google.com/favicon.ico", - "provider": "youtube.com", - "href": "https://www.youtube.com/watch?v=lUJs63xILR8", - "typeOfEmbed": "youtube" -} -[/block] - - - - -## Follow on Lens - -Follow on Lens enables your app to display social connections. If you want to include a follow intent button on your website / web app, it’s super simple! - -Just copy/paste the code snippets from below and replace handle with the handle you want the button intent to follow. - -You can theme it with your own app color, or use our default color. - -```html - - - - - - - -``` - - - -### Visual example (follow on Lens) - -![](https://files.readme.io/1434b9f-Screen_Shot_2023-01-12_at_4.38.00_PM.png) - -### Video tutorial - Follow on Lens - - -[block:embed] -{ - "html": "", - "url": "https://www.youtube.com/watch?v=t2DbwnBqqhs", - "title": "How to integrate a Follow On Lens button into your web application", - "favicon": "https://www.google.com/favicon.ico", - "image": "https://i.ytimg.com/vi/t2DbwnBqqhs/hqdefault.jpg", - "provider": "youtube.com", - "href": "https://www.youtube.com/watch?v=t2DbwnBqqhs", - "typeOfEmbed": "youtube" -} -[/block] - - - - -## Sign in with Lens - -**Sign to Lens** lets you access user's information, such as name, bio, social URLs, pictures, interests, reputation, and activity. - -If you want to include a “Sign in with Lens” button in your web app to connect a wallet that contains a Lens profile, you can use the code below. - -You will have to connect it to your Web3 provider yourself - this is just a dummy themed button. - -```html - - - - - - -``` - - - -### Visual example (Sign in with Lens) - -![](https://files.readme.io/4c77635-Screen_Shot_2023-01-12_at_4.41.15_PM.png) \ No newline at end of file diff --git a/documents/Integrations/lens-widgets.md b/documents/Integrations/lens-widgets.md deleted file mode 100644 index 1885966..0000000 --- a/documents/Integrations/lens-widgets.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: "Lens Widgets" -slug: "lens-widgets" -hidden: false -createdAt: "2023-02-26T15:31:44.661Z" -updatedAt: "2023-02-26T15:48:26.262Z" ---- -[Lens Widgets](https://github.com/lens-protocol/lens-widgets) enable developers to easily integrate social features into their web applications with just a few lines of code. - -Lens Widgets support both [React](https://github.com/lens-protocol/lens-widgets/tree/main/lens-widgets-react) and [Svelte](https://github.com/lens-protocol/lens-widgets/tree/main/lens-widgets-svelte). - -## Lens Widgets React - -To view the library on GitHub click [here](https://github.com/lens-protocol/lens-widgets/tree/main/lens-widgets-react). - -### Installation - -```shell -npm install @lens-protocol/widgets-react -``` - - - -### Share to Lens - -```typescript -import { - ShareToLens, Theme, Size -} from '@lens-protocol/widgets-react' - - - -/* Optional parameters */ -url: string = "https://your-awesome-app.com" -hashtags: string = "web3,social,blockchain" -via: string = "YourAwesomeApp" -title: string = "Share your post on Lens 🌿" -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -``` - - - -### Follow on Lens - -```typescript -import { - FollowOnLens, Theme, Size -} from '@lens-protocol/widgets-react' - - - -/* Optional parameters */ -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -title: string = "Follow me on Lens" -``` - - - -### Sign in with Lens - -```typescript -import { - SignInWithLens, Theme, Size -} from '@lens-protocol/widgets-react' - -async function onSignIn(tokens, profile) { - console.log('tokens: ', tokens) - console.log('profile: ', profile) -} - - - -/* Optional parameters */ -provider: Provider -title: string -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -``` - - - -### Profile - -```typescript -import { - Profile, Theme -} from '@lens-protocol/widgets-react' - - - -/* Optional parameters */ -handle: string -ethereumAddress: string -profileId: string -theme: Theme (default, dark) -onClick: () => void -containerStyle: css style -``` - - - -## Lens Widgets Svelte - -To view the library on GitHub click [here](https://github.com/lens-protocol/lens-widgets/tree/main/lens-widgets-svelte). - -### Installation - -```shell -npm install @lens-protocol/widgets-svelte -``` - - - -### Share to Lens - -```typescript -import { - ShareToLens, Theme, Size -} from '@lens-protocol/widgets-svelte' - - - -/* Optional parameters */ -url: string = "https://your-awesome-app.com" -hashtags: string = "web3,social,blockchain" -via: string = "YourAwesomeApp" -title: string = "Share your post on Lens 🌿" -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -``` - - - -### Follow on Lens - -```typescript -import { - FollowOnLens, Theme, Size -} from '@lens-protocol/widgets-svelte' - - - -/* Optional parameters */ -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -title: string = "Follow me on Lens" -``` - - - -### Sign in with Lens - -```typescript -import { - SignInWithLens, Theme, Size -} from '@lens-protocol/widgets-svelte' - -async function onSignIn(tokens, profile) { - console.log('tokens: ', tokens) - console.log('profile: ', profile) -} - - - -/* Optional parameters */ -provider: Provider -title: string -theme: Theme (default, dark, light, mint, green, peach, lavender, blonde) -size: Size (small, medium, large) -``` - - - -### Profile - -```typescript -import { - Profile, Theme -} from '@lens-protocol/widgets-svelte' - - - -/* Optional parameters */ -handle: string -ethereumAddress: string -profileId: string -theme: Theme (default, dark) -onClick: () => void -containerStyle: css style -``` \ No newline at end of file diff --git a/documents/Lens API/api-links.md b/documents/Lens API/api-links.md deleted file mode 100644 index 04ad709..0000000 --- a/documents/Lens API/api-links.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "API links" -slug: "api-links" -hidden: false -createdAt: "2022-02-16T17:21:12.408Z" -updatedAt: "2022-12-22T23:40:14.797Z" ---- -# Public API - -## Mumbai Testnet - -Testnet is the protocol deployed to Mumbai but you _cannot_ whitelist any modules. - -This points to the [Deployed Testnet Contract Addresses](https://docs.lens.xyz/docs/deployed-contract-addresses#mumbai-testnet-addresses). - - - -## Mumbai Sandbox - -Sandbox is the protocol deployed to Mumbai but you _can_ whitelist any modules you want. The API supports this, and can be done using the `UnknownModules` properties. This allows you to test your modules out and still use the API. - - - -## Polygon Mainnet - -This points to the [Deployed Mainnet Contract Addresses](https://docs.lens.xyz/docs/deployed-contract-addresses#polygon-mainnet-addresses). - - - -# Playground - -If you want to just go and play around with the queries go and jump onto the playground and have some fun. This is a great way to learn about how the API has been structured. - -## Mumbai Testnet - - - -## Mumbai Sandbox - - - -## Polygon Mainnet - - \ No newline at end of file diff --git a/documents/Lens API/authentication.md b/documents/Lens API/authentication.md deleted file mode 100644 index b679659..0000000 --- a/documents/Lens API/authentication.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Authentication" -slug: "authentication" -hidden: false -createdAt: "2022-02-17T11:50:11.701Z" -updatedAt: "2023-04-11T16:40:09.375Z" ---- -## Endpoints - -Authentication is used on the API on some API endpoints. In the docs, we notify you when you're looking at an endpoint that needs authentication. We use JWT tokens as our authentication layer and use the user's Ethereum wallet to verify ownership. This token can also be used in your own server-side application if you wish as you can use the [Verify JWT](doc:verify-jwt) endpoint to make sure the JWT token is valid on your server itself, this is explained in greater detail below. - -Our authentication resolver contains: - -- [Login](doc:login) -- [Refresh JWT](doc:refresh-jwt) -- [Verify JWT](doc:verify-jwt) - -### - -### - -## Using LensClient SDK - -Example of how to authenticate a LensClient instance. - -```typescript TypeScript -import { LensClient, development } from "@lens-protocol/client"; -import { ethers } from "ethers"; - -const lensClient = new LensClient({ - environment: development, -}); - -const wallet = new ethers.Wallet(WALLET_PRIVATE_KEY); -const address = await wallet.getAddress(); - -const challenge = await lensClient.authentication.generateChallenge(address); -const signature = await wallet.signMessage(challenge); - -await lensClient.authentication.authenticate(address, signature); - -// check the state with -await lensClient.authentication.isAuthenticated() -``` \ No newline at end of file diff --git a/documents/Lens API/authentication/login.md b/documents/Lens API/authentication/login.md deleted file mode 100644 index dbdb8d6..0000000 --- a/documents/Lens API/authentication/login.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "Login" -slug: "login" -hidden: false -createdAt: "2022-02-18T07:09:55.578Z" -updatedAt: "2023-03-14T10:11:54.195Z" ---- -> 📘 Full code example -> -> - -To login it takes two server actions: the first is to generate a challenge from the server, and the second is to sign that challenge with your Ethereum wallet and send the signature to our server to generate a valid JWT access token, and refresh token. - -## Challenge - -To get a JWT token, you must first request a challenge from the server, which will return you some text to sign with the wallet to prove ownership. Please note the challenge will only last 5 minutes before it expires, if it expires you must generate a new challenge. Once you have used the challenge to generate a JWT token it will not work again. - -### API details - -```graphql Example operation -query Challenge { - challenge(request: { address: "0xdfd7D26fd33473F475b57556118F8251464a24eb" }) { - text - } -} -``` -```javascript Example response -{ - "data": { - "challenge": { - "text": "I want to authenticate with lens and generate a JWT token at timestamp - 1645102996447. Auth request id - 6a01ffa229be678f03d705eb9b4c454554e2cef4be2c273fc0c9ed5be8762625" - } - } -} -``` - - - -## Authenticate - -Once you get the challenge text from the server you need to sign the challenge with your ethereum wallet and then pass that signature to the `authentication` endpoint, this will generate you an `accessToken` and a `refreshToken`. - -- `accessToken` - This lasts 30 minutes before needed to be refreshed -- `refreshToken` - This lasts 7 days to allow you to keep them logged in and generate a new `accessToken` when they come back without them having to sign a challenge again. - -### API details - -```graphql Example operation -mutation Authenticate { - authenticate(request: { - address: "0xdfd7D26fd33473F475b57556118F8251464a24eb", - signature: "0x8f82e1a2c2cc35a2963c60eeb0a76aecc100686c4ffcb98fd522a90cba2f0b2642067c79cd6d0c9d239ed28a6882818f77bf546e774410236c730988bd14de5d1c" - }) { - accessToken - refreshToken - } -} -``` -```javascript Example response -{ - "data": { - "authenticate": { - "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJub3JtYWwiLCJpYXQiOjE2NDUxMDQyMzEsImV4cCI6MTY0NTEwNjAzMX0.lwLlo3UBxjNGn5D_W25oh2rg2I_ZS3KVuU9n7dctGIU", - "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJyZWZyZXNoIiwiaWF0IjoxNjQ1MTA0MjMxLCJleHAiOjE2NDUxOTA2MzF9.2Tdts-dLVWgTLXmah8cfzNx7sGLFtMBY7Z9VXcn2ZpE" - } - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/authentication/refresh-jwt.md b/documents/Lens API/authentication/refresh-jwt.md deleted file mode 100644 index 145fc60..0000000 --- a/documents/Lens API/authentication/refresh-jwt.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Refresh JWT" -slug: "refresh-jwt" -hidden: false -createdAt: "2022-02-18T07:15:33.542Z" -updatedAt: "2022-11-09T10:34:24.506Z" ---- -> 📘 Full code example -> -> - -Your `accessToken` expires every 30 minutes this means you have to refresh it with the `refreshToken` to get a new access token. It is up to your client to make sure that you refresh it before it expires. - -hint: use to decode your JWT token, when you do in the payload section you will see some claims showing. `exp` is the unix timestamp for when the token will expiry. - -## API details - -```graphql Example operation -mutation Refresh { - refresh(request: { - refreshToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJyZWZyZXNoIiwiaWF0IjoxNjQ1MTA0MjMxLCJleHAiOjE2NDUxOTA2MzF9.2Tdts-dLVWgTLXmah8cfzNx7sGLFtMBY7Z9VXcn2ZpE" - }) { - accessToken - refreshToken - } -} -``` -```javascript Example response -{ - "data": { - "refresh": { - "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJub3JtYWwiLCJpYXQiOjE2NDUxMDQyMzEsImV4cCI6MTY0NTEwNjAzMX0.lwLlo3UBxjNGn5D_W25oh2rg2I_ZS3KVuU9n7dctGIU", - "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJyZWZyZXNoIiwiaWF0IjoxNjQ1MTA0MjMxLCJleHAiOjE2NDUxOTA2MzF9.2Tdts-dLVWgTLXmah8cfzNx7sGLFtMBY7Z9VXcn2ZpE" - } - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/authentication/verify-jwt.md b/documents/Lens API/authentication/verify-jwt.md deleted file mode 100644 index 9226b18..0000000 --- a/documents/Lens API/authentication/verify-jwt.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Verify JWT" -slug: "verify-jwt" -hidden: false -createdAt: "2022-02-18T07:17:17.149Z" -updatedAt: "2023-01-18T11:26:19.444Z" ---- -> 📘 Full code example -> -> - -You may wish to use the same authentication on your server-side to save you having to do authentication yourself as the claims hold the Ethereum address in it; the issue you would face is verifying that token is actually signed by the server and the user or if it has just been generated and is not secure. This endpoint solves this for you. - -### API details - -```graphql Example operation -query Query { - verify(request: { - accessToken: "eyJhbGmiOiJIUzI1NiIsInR5cCI2IkpXVCJ9.eyJpZCI6IjB4RUVBMEMxZjVhYjAxNTlkYmE3NDlEYzBCQWVlNDYyRTVlMjkzZGFhRiIsInJvbGUiOiJub3JtYWwiLCJpYXQiOjE2NDUxODg5OTQsImV4cCI6MTY2MzE4ODk5NH0.dgO9L5NxlVG_8Mc7H-1VFTIYQDRm_I-KCe2nvkLpx5o" - }) -} -``` -```javascript Example response -{ - "data": { - "verify": false - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/e2ee-dms.md b/documents/Lens API/e2ee-dms.md deleted file mode 100644 index d6ba880..0000000 --- a/documents/Lens API/e2ee-dms.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "E2EE DMs" -slug: "e2ee-dms" -hidden: false -createdAt: "2022-11-03T16:13:37.451Z" -updatedAt: "2023-01-26T01:42:53.134Z" ---- -We have been working closely with the fantastic XMTP to get E2EE DMs into the lens. They have now applied it to lenster but the standards are set to allow any lens app to inherit it. - -We will expose this logic in our LENS SDK once an official one is supported. This will abstract all of this way for you and we will be building call features on top of XMTP core features. Stay tuned! - -If you wish to hook it into one of your lens powers apps today go and check out the guides [here](https://docs.lens.xyz/docs/encrypted-dms) and [here](https://xmtp.to/lens-quickstart) \ No newline at end of file diff --git a/documents/Lens API/explore.md b/documents/Lens API/explore.md deleted file mode 100644 index 82bf8bd..0000000 --- a/documents/Lens API/explore.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Explore" -slug: "explore" -hidden: false -createdAt: "2022-02-17T17:58:00.395Z" -updatedAt: "2022-05-30T08:47:20.583Z" ---- -The explore resolver API returns content which is trending on the Lens protocol. Over time we shall add more features into this resolver. - -Our explore resolver contains: - -- [Explore publications](doc:explore-publications) -- [Explore profiles](doc:explore-profiles) \ No newline at end of file diff --git a/documents/Lens API/explore/explore-profiles.md b/documents/Lens API/explore/explore-profiles.md deleted file mode 100644 index 99c7dd6..0000000 --- a/documents/Lens API/explore/explore-profiles.md +++ /dev/null @@ -1,1466 +0,0 @@ ---- -title: "Explore profiles" -slug: "explore-profiles" -hidden: false -createdAt: "2022-05-30T08:27:37.165Z" -updatedAt: "2023-03-14T10:18:47.727Z" ---- -> 📘 Full code example -> -> - -This query returns a list of profiles based on the profile sort criteria you pass in. - -# API Design - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is you have a schema that should explain how the request and response schema should look at what properties exist in that. In these docs we explore code examples and explain key concepts but we will not explain each property that exists in the response for example, as the schema already does that! - -The example below uses `MOST_FOLLOWERS` sort criteria but you have many other options which are explained below. - -```graphql Example operation -query ExploreProfiles { - exploreProfiles(request: { sortCriteria: MOST_FOLLOWERS }) { - items { - id - name - bio - isDefault - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - contractAddress - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "exploreProfiles": { - "items": [ - { - "id": "0x21d5", - "name": "Caio Vicentino", - "bio": "Caio Vicentino no YouTube\nEmbaixador do MakerDAO no Brasil.\nDo Ceará pro Mundo.\nYield Hacker 🔥\n#DeFi #MAYC 6899, KODA 3375.\nCaiov.eth\nlinktr.ee/caiovicentino\nFortaleza, Ceará, Brasil.\n", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Brazil" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://www.caioinveste.com.br/" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "caiovicentino" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "followNftAddress": null, - "handle": "caiovicentino.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmNVCUvjTGLqUoJ6Nqfwc434RtKx7EWvkLdSdAAEg5EwkQ", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qmcg3uAXMDGvPsLuT3zQ2A92fuPAPCFgWyt4oMFAuL5jZq", - "mimeType": null - } - }, - "ownedBy": "0xB6ad42D615759E50C8087849a2F6f0E2032f7085", - "dispatcher": null, - "stats": { - "totalFollowers": 1188, - "totalFollowing": 9, - "totalPosts": 23, - "totalComments": 14, - "totalMirrors": 6, - "totalPublications": 43, - "totalCollects": 161 - }, - "followModule": null - }, - { - "id": "0x10", - "name": "Daniel", - "bio": "Senior Software Developer | Blockchain enthusiast | working at \n@AaveAave & @LensProtocol & much more :D\n- My Roots are my own", - "isDefault": true, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "location", - "value": "Metaverse" - }, - { - "displayType": "string", - "traitType": null, - "key": "website", - "value": "https://damarnez.me" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "damarnez" - } - ], - "metadata": null, - "handle": "damarnez.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmR6913vGvoLHjqZ4BMtYDLSxD3p7iscSCYkQTPTL6vRv7", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmcYCCtSyQyQ8j39nKQfNiMbkLuC6C73dV5uQP7vpm9mj7", - "mimeType": null - } - }, - "ownedBy": "0x88a769db5055B046c9A45Db621978bbEC65c8c5b", - "dispatcher": null, - "stats": { - "totalFollowers": 1122, - "totalFollowing": 30, - "totalPosts": 6, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 7, - "totalCollects": 52 - }, - "followModule": null - }, - { - "id": "0x05", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "stani.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmcxGEZ1Qqiw4EHqJTee8tPZBesvppuy7swFnRFMoM1Ka9", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x2E21f5d32841cf8C7da805185A041400bF15f21A", - "dispatcher": null, - "stats": { - "totalFollowers": 1067, - "totalFollowing": 157, - "totalPosts": 30, - "totalComments": 31, - "totalMirrors": 2, - "totalPublications": 63, - "totalCollects": 1222 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0x27", - "name": "jim", - "bio": "experiments @ aave", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://0xjim.xyz" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "0xjim" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "0xjim.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmSJnNcdrPNvtaRnxsHBeMcVW6Q2NfBSDHs8bzJa9EaXoU", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x705A42EcC5dF243BF9298f1D091b89761522a796", - "dispatcher": null, - "stats": { - "totalFollowers": 821, - "totalFollowing": 7, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 19 - }, - "followModule": null - }, - { - "id": "0x01", - "name": "LensProtocol.eth 🌿", - "bio": "A permissionless, composable, & decentralized social graph that makes building a Web3 social platform easy.", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://lens.xyz" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "lensprotocol" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "lensprotocol", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS", - "mimeType": null - } - }, - "ownedBy": "0x6C77a5a88C0AE712BAeABE12FeA81532060dcBf5", - "dispatcher": null, - "stats": { - "totalFollowers": 788, - "totalFollowing": 0, - "totalPosts": 6, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 6, - "totalCollects": 267 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0x0d", - "name": "Yoginth", - "bio": "요기 • Creator of @lenster.lens 🌸 • Bullish on Ξ • BTS Fanboi ⟬⟭ • he/him 🌳", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "India" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://yogi.codes" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "yogicodes" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "yoginth.lens", - "picture": { - "contractAddress": "0x6466B863353851F2ae866167610449B31A385df7", - "tokenId": "26396376898576019325902668567942607247753500533935235934491478860533906538497", - "uri": "https://statics-polygon-lens.s3.eu-west-1.amazonaws.com/profile/nft-0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3_polygon_0x6466B863353851F2ae866167610449B31A385df7_26396376898576019325902668567942607247753500533935235934491478860533906538497.png", - "chainId": 137, - "verified": true - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmR7vBHZm78hsymxYFkQBV4UC42Y4iGyHgyFwisMu9S66B", - "mimeType": null - } - }, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": { - "address": "0x57B7bf6f792a6181Ec5aFB88cE7bcE330a9d1b67", - "canUseRelay": false - }, - "stats": { - "totalFollowers": 779, - "totalFollowing": 31, - "totalPosts": 16, - "totalComments": 89, - "totalMirrors": 31, - "totalPublications": 136, - "totalCollects": 257 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0xf5", - "name": "Miguel Piedrafita", - "bio": "20. Purple-haired developer @ Worldcoin, core ConstitutionDAO. I talk about crypto, code, privacy & more. he/him", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Madrid, Spain" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://miguelpiedrafita.com" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "m1guelpf" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "m1guelpf.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmaiB8mqrYnNTEnjEL4TCfrkBDjZv6QQ9uh5FjTHa7Prmq", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmXjPMWt5qC7yYtMCMRqpwwu6VgGdc4Qrapncw3xnGGpCh", - "mimeType": null - } - }, - "ownedBy": "0xE340b00B6B622C136fFA5CFf130eC8edCdDCb39D", - "dispatcher": { - "address": "0x57B7bf6f792a6181Ec5aFB88cE7bcE330a9d1b67", - "canUseRelay": false - }, - "stats": { - "totalFollowers": 450, - "totalFollowing": 28, - "totalPosts": 23, - "totalComments": 20, - "totalMirrors": 2, - "totalPublications": 45, - "totalCollects": 159 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0x0c", - "name": "Lenster", - "bio": "Lenster is a decentralized, and permissionless social media app built with @lensprotocol 🌿", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://lenster.xyz" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "lensterxyz" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "lenster.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmUGKJZDgiMtPs6D9QqtuVmFPw5DTzvz6Tyb3HQYy9L5A3", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmPWMh27K5J7pQphSyesrYjr1tm1fjqtU4x8h7QyqqSazw", - "mimeType": null - } - }, - "ownedBy": "0xd3B307753097430FaEdFdb89809610bF8e8f3203", - "dispatcher": null, - "stats": { - "totalFollowers": 447, - "totalFollowing": 1, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 4, - "totalPublications": 9, - "totalCollects": 110 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0x012c", - "name": "airdrop hunter", - "bio": "my best airdrops in the past few years, including:$UNI, $ENS, $dYdX,$BICO $INCH, $SNX, $ILV, $NOTE, $RSS3,$OP", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "creatorfundincubator.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmZvb1JKG2BA7mz39ieQEAvBD1T9nSc2sEgGj7d1p6UEGW", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x84c0430F3564520dCde45C3dFD7cEb79372e4fA3", - "dispatcher": null, - "stats": { - "totalFollowers": 441, - "totalFollowing": 1957, - "totalPosts": 76, - "totalComments": 469, - "totalMirrors": 0, - "totalPublications": 545, - "totalCollects": 14 - }, - "followModule": null - }, - { - "id": "0x0160", - "name": "ETHGlobal", - "bio": "Growing the Ethereum ecosystem.", - "isDefault": true, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "location", - "value": "Decentralized" - }, - { - "displayType": "string", - "traitType": null, - "key": "website", - "value": "https://ethglobal.com" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "ethglobal" - } - ], - "metadata": null, - "handle": "ethglobal.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmPhtJNJ29iADT4NqnvDJKiZR4ie3cx2oEhwJAcD7rMMC3", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xe993486B257Cd1481aef74b3B909A2627Fc8d305", - "dispatcher": null, - "stats": { - "totalFollowers": 390, - "totalFollowing": 9, - "totalPosts": 6, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 6, - "totalCollects": 15 - }, - "followModule": null - }, - { - "id": "0x011d", - "name": "Marc Zeller", - "bio": null, - "isDefault": true, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "location", - "value": "Gotchiverse" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "lemiscate" - } - ], - "metadata": null, - "handle": "aavechan.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmfZkcDnYtWwRgYtvpZWwNjwdn7ScP4AHnobu5w2EDf4ot", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x329c54289Ff5D6B7b7daE13592C6B1EDA1543eD4", - "dispatcher": null, - "stats": { - "totalFollowers": 333, - "totalFollowing": 8, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x0a20", - "name": "Jeremy", - "bio": "Entered the encryption industry in 2015, started mining Ethereum in 2016, and has been building; Web3.0 has come, let us join hands to build a better future!", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Singapore" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://www.fortunetree-sg.com/" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "FortuneTrees" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "fortunetrees.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTkcegVLUy7YL6Wqz5Gv4y9fDdb2T1yKB6VjtubJ481Vf", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTkcegVLUy7YL6Wqz5Gv4y9fDdb2T1yKB6VjtubJ481Vf", - "mimeType": null - } - }, - "ownedBy": "0x1A8167907256ECE255be4563c141C88EE16427CA", - "dispatcher": { - "address": "0x57B7bf6f792a6181Ec5aFB88cE7bcE330a9d1b67", - "canUseRelay": false - }, - "stats": { - "totalFollowers": 331, - "totalFollowing": 11, - "totalPosts": 700, - "totalComments": 10, - "totalMirrors": 8, - "totalPublications": 718, - "totalCollects": 49 - }, - "followModule": null - }, - { - "id": "0x1cef", - "name": "David Hoffman ", - "bio": "Just setting my lens profile ", - "isDefault": false, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensClaimingApp" - } - ], - "metadata": null, - "handle": "trustlessstate.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVqqiMiXCfbSHk43ufgTMcGQwmjBujiUmJDQdYbzZi7Ju", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x3555d1E058E971d48c4266bF2264ebFc553d3F90", - "dispatcher": null, - "stats": { - "totalFollowers": 296, - "totalFollowing": 7, - "totalPosts": 2, - "totalComments": 3, - "totalMirrors": 0, - "totalPublications": 5, - "totalCollects": 29 - }, - "followModule": null - }, - { - "id": "0x0193", - "name": "beautiful destinations", - "bio": "Inspiring people to connect and make a positive impact through travel. 🌏 We are a climate-positive company that advocates sustainable tourism. ♻️", - "isDefault": false, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "tiffanyatrump.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmakeGFkpkAvwbvoxApkFbpphJHvwzadcfKnjXJbQQRxWR", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmWxUijYK2bHBFFnPC26uG6N2xof2aXp1iKZAiCCMfAwQK", - "mimeType": null - } - }, - "ownedBy": "0xbd7B2C3E167A1FfbDa56917e13f0802aFFC326d5", - "dispatcher": null, - "stats": { - "totalFollowers": 296, - "totalFollowing": 811, - "totalPosts": 31, - "totalComments": 88, - "totalMirrors": 1, - "totalPublications": 120, - "totalCollects": 7 - }, - "followModule": null - }, - { - "id": "0x8e", - "name": "Christina", - "bio": "Stay curious 🌎 // Building the Future at Lens 🌿 / Head of Growth // Prev music + NFTs TikTok / Bytedance (before it was on your 📱) ", - "isDefault": false, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "0xchristina" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "christina.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmawgZknFmZpU97tKEfBJKxwYZpkvZLQRkddHwpsuU2Asn", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmW5CNz3r63hzfBhRzXpaP2R4HHqb4jXStut6DzmeycroL", - "mimeType": null - } - }, - "ownedBy": "0xA7d53695aF1FD11E0b75d37695290C102D59D743", - "dispatcher": null, - "stats": { - "totalFollowers": 248, - "totalFollowing": 98, - "totalPosts": 9, - "totalComments": 25, - "totalMirrors": 6, - "totalPublications": 40, - "totalCollects": 94 - }, - "followModule": null - }, - { - "id": "0x02", - "name": "Aave", - "bio": "We built Aave Protocol, an open source and non-custodial liquidity protocol. #DeFi #FlashLoans $AAVE http://aave.com/discord http://instagram.com/aave.aave", - "isDefault": true, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "location", - "value": "London, England" - }, - { - "displayType": "string", - "traitType": null, - "key": "website", - "value": "https://aave.com" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "aaveaave" - } - ], - "metadata": null, - "handle": "aaveaave.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmeG11YaqCAirSXPhiN6qLNDqMsnED8WLJLgv2bhtE3QaS", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmXCNuoC4CfttCefwU4y8HemdD39921DfFmJGFo9kAqwWc", - "mimeType": null - } - }, - "ownedBy": "0x0550730EDb1948d3170113FF4FA0e4770fA47401", - "dispatcher": null, - "stats": { - "totalFollowers": 246, - "totalFollowing": 1, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 19 - }, - "followModule": { - "type": "ProfileFollowModule" - } - }, - { - "id": "0x0143", - "name": "Fei", - "bio": "Biochemist. 🇦🇷\nCrypto Enthusiast. Going bankless. Researcher. \nCurrent state: +25 browser tabs open", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Buenos Aires, Argentina" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://app.poap.xyz/scan/feiwian.eth" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "Monocito_" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "feiwian.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qmd1dX3SBdFUxEJGfEBt3v2PB8NKvRwz2f4oz43ytBxhZP", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmUt8TcXx4QDEkW29uEhHqgYTRqE3DmGHXSrhukgkkUYLd", - "mimeType": null - } - }, - "ownedBy": "0xb00Cc766b7AdC1a34d72EA46a8d4bbdfBc5904F9", - "dispatcher": null, - "stats": { - "totalFollowers": 228, - "totalFollowing": 61, - "totalPosts": 12, - "totalComments": 41, - "totalMirrors": 8, - "totalPublications": 61, - "totalCollects": 226 - }, - "followModule": null - }, - { - "id": "0xf7", - "name": "链上达人", - "bio": "Hi,bro", - "isDefault": false, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "location", - "value": "China" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "@wenxue600" - } - ], - "metadata": null, - "handle": "wenxue600.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmdqdLCenhB97Enb4Us3ZBfQqQcyryGCJWciTA26ZB6Yaz", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x5b197E3eE6770518f6F2735274522F48aBd69864", - "dispatcher": null, - "stats": { - "totalFollowers": 225, - "totalFollowing": 7, - "totalPosts": 9, - "totalComments": 7, - "totalMirrors": 2, - "totalPublications": 18, - "totalCollects": 477 - }, - "followModule": null - }, - { - "id": "0x0210", - "name": "Paris Rouzati", - "bio": "GP at IDEO VC crypto. Doing things with We3 + rAAVE. Dog mom, pasta lover, CryptoToadz fan. 🐻‍❄️ 🍩 👩🏻‍💻 ☁️ ", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "🌌" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "parisrouz" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "paris.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmWn5CgWGR5A3oGATAPoamqb2QPyxPFeDnGpybG6ZdxpY9", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qmd3LNbqtyxhdmfZ6VU71vER7wrXFnoKAR6Fi2KV63yLPX", - "mimeType": null - } - }, - "ownedBy": "0xA83444576F86C8B59A542eC2F286a19aB12c2666", - "dispatcher": null, - "stats": { - "totalFollowers": 221, - "totalFollowing": 39, - "totalPosts": 7, - "totalComments": 21, - "totalMirrors": 0, - "totalPublications": 28, - "totalCollects": 60 - }, - "followModule": null - }, - { - "id": "0x26e5", - "name": "Sismo", - "bio": "We develop the Sismo Protocol issuing ZK attestations for reputation aggregation and privacy preserving access control.", - "isDefault": false, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "website", - "value": "https://sismo.io" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "Sismo_eth" - } - ], - "metadata": null, - "handle": "sismo.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVnR5v3tMuFfqDUmAKZAn4jhNcTgSwsj6jYTSN5aGow1Y", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmduXoXUTJ6q1LM2M4GeqQCBpB1zjLMMXJoHWsKUZAYU6Z", - "mimeType": null - } - }, - "ownedBy": "0xB0A179C459484885D1875009110F3cE3064867B9", - "dispatcher": null, - "stats": { - "totalFollowers": 210, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x28a2", - "name": "nader dabit", - "bio": "teacher, author, software developer building in web3", - "isDefault": false, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "dabit3" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "nader.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVBfhfgfhGsRVxTNURVUgceqyzjdVe11ic5rCghmePuKX", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTfwKddZeHTWyvjbBK6LwrTpLrHwvGxBa9QbgkAiH8S84", - "mimeType": null - } - }, - "ownedBy": "0xB2Ebc9b3a788aFB1E942eD65B59E9E49A1eE500D", - "dispatcher": null, - "stats": { - "totalFollowers": 204, - "totalFollowing": 67, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 2, - "totalPublications": 5, - "totalCollects": 16 - }, - "followModule": null - }, - { - "id": "0x28f2", - "name": "WOMEN IN WEB3", - "bio": "A DAO-2B that invests in womxn who simply wants to explore web3 rabbit holes, in order to find their dream careers.", - "isDefault": false, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensClaimingApp" - } - ], - "metadata": null, - "handle": "womeninweb3.lens", - "picture": null, - "coverPicture": null, - "ownedBy": "0x9b27cCf7ff2039Ca56fAC29C51519F08d5e87530", - "dispatcher": null, - "stats": { - "totalFollowers": 198, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x1c19", - "name": "Gabriel", - "bio": "GM CT", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "clipto.io" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "gabrielhaines" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "gabriel.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmWDVt7vNoYkFvYSyBk8pdu9xSKiqt5PtYE4kaYNxnCgdA", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xCFFE08BDf20918007f8Ab268C32f8756494fC8D8", - "dispatcher": null, - "stats": { - "totalFollowers": 194, - "totalFollowing": 57, - "totalPosts": 21, - "totalComments": 28, - "totalMirrors": 2, - "totalPublications": 51, - "totalCollects": 13 - }, - "followModule": null - }, - { - "id": "0x1a75", - "name": "cryptocurrency(🌿,🌿)", - "bio": "🦇🔊enthusiast WAGMI", - "isDefault": false, - "attributes": [ - { - "displayType": "string", - "traitType": null, - "key": "app", - "value": "LensFrens" - }, - { - "displayType": "string", - "traitType": null, - "key": "website", - "value": "https://twitter.com/monpmer" - }, - { - "displayType": "string", - "traitType": null, - "key": "twitter", - "value": "@monpmer" - } - ], - "metadata": null, - "handle": "monpmer.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVoyfh2vzpzzkkg8etVwEYi7AL4KFGJ4Ncse7fkWHdjA2", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVoyfh2vzpzzkkg8etVwEYi7AL4KFGJ4Ncse7fkWHdjA2", - "mimeType": null - } - }, - "ownedBy": "0x9eC6c8314b1F3c87b751852D515B05178d4A50B8", - "dispatcher": null, - "stats": { - "totalFollowers": 193, - "totalFollowing": 119, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x1f4f", - "name": "TonHor", - "bio": "Web3 Builder. #MWAD", - "isDefault": true, - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Web3" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://www.facebook.com/tonhor" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "tonhor" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": null, - "handle": "tonhor.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmNwSXkshxj95ezyZ7EKtvMy4A3d8giAJTnnDHaGvBbyLv", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xfb10EFE8d84E73061ABDfa5F87f26aFC1f0a98f5", - "dispatcher": null, - "stats": { - "totalFollowers": 186, - "totalFollowing": 2, - "totalPosts": 3, - "totalComments": 3, - "totalMirrors": 0, - "totalPublications": 6, - "totalCollects": 1 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":25}", - "totalCount": 12112 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -## Request - -Let's look at the query options we can use here to get a lot of data for different things. - -### sortCriteria - -You can filter the profiles using any of the below: - -```typescript -export enum ProfileSortCriteria { - CREATED_ON = 'CREATED_ON', - MOST_FOLLOWERS = 'MOST_FOLLOWERS', - LATEST_CREATED = 'LATEST_CREATED', - MOST_POSTS = 'MOST_POSTS', - MOST_COMMENTS = 'MOST_COMMENTS', - MOST_MIRRORS = 'MOST_MIRRORS', - MOST_PUBLICATION = 'MOST_PUBLICATION', - MOST_COLLECTS = 'MOST_COLLECTS', -} -``` - - - -## - -## - -## Using LensClient SDK - -```typescript -import { ProfileSortCriteria } from "@lens-protocol/client"; - -lensClient.explore.profiles({ - sortCriteria: ProfileSortCriteria.MostFollowers -}) -``` \ No newline at end of file diff --git a/documents/Lens API/explore/explore-publications.md b/documents/Lens API/explore/explore-publications.md deleted file mode 100644 index 33716d1..0000000 --- a/documents/Lens API/explore/explore-publications.md +++ /dev/null @@ -1,680 +0,0 @@ ---- -title: "Explore publications" -slug: "explore-publications" -hidden: false -createdAt: "2022-02-18T11:29:23.848Z" -updatedAt: "2023-03-14T10:19:13.211Z" ---- -> 📘 Full code example -> -> - -This query returns a list of publications based on the top collected or top comments. It randomizes it so it is never the same content you see twice similar to how Instagram works when you refresh their explore section. - -For now, this uses basic explore logic on basic data the protocol has. We will be greatly increasing this when we start doing AI on the explore feeds and endpoints. If you integrate this API into your application you will be inheriting all of these improvements with no code changes. - -# API Design - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is you have a schema that should explain how the request and response schema should look at what properties exist in that. In these docs we explore code examples and explain key concepts but we will not explain each property that exists in the response for example, as the schema already does that! - -```graphql Example operation -query ExplorePublications { - explorePublications(request: { - sortCriteria: TOP_COMMENTED, - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10 - }) { - items { - __typename - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - ... on Mirror { - ...MirrorFields - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - hasCollectedByMe -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} - - -``` -```javascript Example response -{ - "data": { - "explorePublications": { - "items": [ - { - "__typename": "Post", - "id": "0x03b0-0x01", - "profile": { - "id": "0x03b0", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": true, - "handle": "jojay", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmcKD5Zxic7JAum22jKRnT3ENY4tCCp7qQSPJTCLkHAApm", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x0c0E611A29b339D8c1048F2Edf9d4160A5fb8F22", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 4, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "10.0" - }, - "recipient": "0x0c0E611A29b339D8c1048F2Edf9d4160A5fb8F22" - } - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 3 - }, - "metadata": { - "name": "Post by @jojay", - "description": "Hello Josh :)", - "content": "Hello Josh :)", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "type", - "value": "post" - } - ] - }, - "createdAt": "2022-04-16T08:33:25.000Z", - "collectModule": { - "__typename": "RevertCollectModuleSettings", - "type": "RevertCollectModule" - }, - "referenceModule": null, - "appId": "Lenster", - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - { - "__typename": "Post", - "id": "0x0f-0xa0", - "profile": { - "id": "0x0f", - "name": null, - "bio": null, - "attributes": [], - "followNftAddress": "0x8A8bd1E37b099aE3386D13947b6a90d97675e9a1" - "metadata": null, - "isDefault": true, - "handle": "wagmi.lens", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": null, - "stats": { - "totalFollowers": 111, - "totalFollowing": 15, - "totalPosts": 89, - "totalComments": 64, - "totalMirrors": 15, - "totalPublications": 168, - "totalCollects": 215 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 6 - }, - "metadata": { - "name": "Post by @yoginth", - "description": "Testing hashflags\n\n#lenster #Lenster #LENSTER #lens #ethereum #Bitcoin", - "content": "Testing hashflags\n\n#lenster #Lenster #LENSTER #lens #ethereum #Bitcoin", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "string", - "value": "post" - } - ] - }, - "createdAt": "2022-04-20T06:26:56.000Z", - "collectModule": { - "__typename": "RevertCollectModuleSettings", - "type": "RevertCollectModule" - }, - "referenceModule": null, - "appId": "Lenster", - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - ], - "pageInfo": { - "prev": "{\"timestamp\":1649942608500,\"offset\":0,\"randomizer\":5}", - "next": "{\"timestamp\":1649942608500,\"offset\":10,\"randomizer\":5}", - "totalCount": 2 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -## Request - -Let's look at the query options we can use here to get a lot of data for different things. - -```json get explore by top comments -// This returns you a random array back of the top commented publications on -// the protocol. Each time you call it a new set of random publications will return -{ - "sortCriteria": "TOP_COMMENTED", - // you can filter by publication type - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - "limit": 10 - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - // you can also pass in from which date you wish to start the explore from - // if nothing is passed it will use a week before - // "timestamp": 1645469133705 - // if you do not want it to be random each time - // "noRandomize": true - // if you want to exclude certain profiles from appearing in results - // "excludeProfileIds": ["0x01"] - } -``` -```json get explore by top collected -// This returns you a random array back of the top collected publications on -// the protocol. Each time you call it a new set of random publications will return -{ - "sortCriteria": "TOP_COLLECTED", - // you can filter by publication type - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - "limit": 10 - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - // you can also pass in from which date you wish to start the explore from - // if nothing is passed it will use a week before - // "timestamp": 1645469133705 - // if you do not want it to be random each time - // "noRandomize": true - // if you want to exclude certain profiles from appearing in results - // "excludeProfileIds": ["0x01"] - } -``` -```javascript get explore by top mirrored -// This returns you a random array back of the top collected publications on -// the protocol. Each time you call it a new set of random publications will return -{ - "sortCriteria": "TOP_MIRRORED", - // you can filter by publication type - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - "limit": 10 - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - // you can also pass in from which date you wish to start the explore from - // if nothing is passed it will use a week before - // "timestamp": 1645469133705 - // if you do not want it to be random each time - // "noRandomize": true - // if you want to exclude certain profiles from appearing in results - // "excludeProfileIds": ["0x01"] - } -``` -```javascript get latest -// This returns you a random array back of the top collected publications on -// the protocol. Each time you call it a new set of random publications will return -{ - "sortCriteria": "LATEST", - // you can filter by publication type - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - "limit": 10 - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - // you can also pass in from which date you wish to start the explore from - // if nothing is passed it will use a week before - // "timestamp": 1645469133705 - // if you do not want it to be random each time - // "noRandomize": true - // if you want to exclude certain profiles from appearing in results - // "excludeProfileIds": ["0x01"] - } -``` -```Text get by curated profiles -// This returns you a random array back of the top curated profiles publications on -// the protocol. Each time you call it a new set of random publications will return -{ - "sortCriteria": "CURATED_PROFILES", - // you can filter by publication type - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - "limit": 10 - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - // you can also pass in from which date you wish to start the explore from - // if nothing is passed it will use a week before - // "timestamp": 1645469133705 - // if you do not want it to be random each time - // "noRandomize": true - // if you want to exclude certain profiles from appearing in results - // "excludeProfileIds": ["0x01"] - } -``` - - - -## - -## - -## Using LensClient SDK - -```typescript -import { PublicationSortCriteria } from "@lens-protocol/client"; - -lensClient.explore.publications({ - sortCriteria: PublicationSortCriteria.TopCommented -}) -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api.md b/documents/Lens API/follow-api.md deleted file mode 100644 index 99c8eb0..0000000 --- a/documents/Lens API/follow-api.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: "Follow" -slug: "follow-api" -hidden: false -createdAt: "2022-02-17T17:58:10.545Z" -updatedAt: "2022-03-09T16:55:24.310Z" ---- -Follow resolver contains anything relating with the profiles follow actions. Every time someone follows it mints an NFT, you can read more in-depth about how follows work [here](doc:follow). - -The follow resolver have these queries: - -- [Create follow typed data](doc:create-follow-typed-data) -- [Create unfollow typed data](doc:create-unfollow-typed-data) -- [Approve follow](doc:approve-follow) -- [Pending approval follows](doc:pending-approval-follows) -- [Does follow](doc:does-follow) -- [Following](doc:following) -- [Followers](doc:followers) \ No newline at end of file diff --git a/documents/Lens API/follow-api/approve-follow.md b/documents/Lens API/follow-api/approve-follow.md deleted file mode 100644 index 7b2ed3d..0000000 --- a/documents/Lens API/follow-api/approve-follow.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: "Approve follow" -slug: "approve-follow" -hidden: true -createdAt: "2022-02-18T11:28:21.409Z" -updatedAt: "2022-08-16T19:56:54.953Z" ---- -> 📘 full code repo - -> ❗️ open PR -> -> We have a PR to fix this contract side with events once that comes this will be swapped out for the contract change which will be supported in the API as well. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -To get around the issues with people being able to spam other people with a follower NFT we have brought in approval follows server-side logic. - -Look at this situation: - -- @josh follows @dodgy.profile -- @josh gets a follower NFT for @dodgy.profile -- @josh sends the follower NFT to @coolshoes wallet owner -- @coolshoes wallet owner now looks like they follow @dodgy.profile - -You can see from the above how this could be a huge issue and with spam already a major thing on cheap transaction chains we do see this being a problem from day 1. - -To solve this for now we have a server approach but we have an open PR to allow this to be traceable onchain with events which we hope to merge soon. - -The approach we are taking to solve this is: - -- @josh follows @dodgy.profile -- @josh gets a follower NFT for @dodgy.profile -- @josh sends the follower NFT to @coolshoes -- The server removes that @josh follows @dodgy.profile from the indexer -- The server moves @coolshoes follows @dodgy.profile in an approval list -- This now means @coolshoes needs to approve that they approve to follow this profile - -This mutation approves the follow and now on the API side, it looks like you follow this profile from your wallet. - -API Design -========== - -returns a `VoidScalar` which means no response is returned if you do look at the response data it will be data.approveFollow = null but you do not need to look at the response for anything which returns `void`. If it does not throw it is successful. - -```javascript Example operation -mutation ApproveFollow { - approveFollow(request: { profileId: "0x01" }) -} -``` -```javascript Query interface -type Mutation { - approveFollow(request: ApproveFollowsRequest!): Void -} -``` -```javascript Request -input ApproveFollowsRequest { - profileId: ProfileId! -} - -# ProfileId custom scalar type -scalar ProfileId -``` - -Full code example ------------------ - -```javascript approve-follow.js -// this is showing you how you use it with react for example -// if your using node or something else you can import using -// @apollo/client/core! -import { apolloClient } from './apollo-client'; -// this is showing you how you use it with react for example -// if your using node or something else you can import using -// @apollo/client/core! -import { gql } from '@apollo/client' - -const APPROVE_FOLLOW = ` - mutation($request: ApproveFollowsRequest!) { - approveFollow(request: $request) - } -` - -export const approveFollow = (profileId) => { - return apolloClient.mutate({ - mutation: gql(APPROVE_FOLLOW), - variables: { - request: { - profileId, - }, - }, - }) -} -``` -```javascript apollo-client.js -// this is showing you how you use it with react for example -// if your using node or something else you can import using -// @apollo/client/core! -import { ApolloClient, InMemoryCache, HttpLink, ApolloLink } from '@apollo/client' - -const httpLink = new HttpLink({ uri: 'https://api-mumbai.lens.dev/' }); - -// example how you can pass in the x-access-token into requests using `ApolloLink` -const authLink = new ApolloLink((operation, forward) => { - // Retrieve the authorization token from local storage. - // if your using node etc you have to handle your auth different - const token = localStorage.getItem('auth_token'); - - // Use the setContext method to set the HTTP headers. - operation.setContext({ - headers: { - 'x-access-token': token ? `Bearer ${token}` : '' - } - }); - - // Call the next link in the middleware chain. - return forward(operation); -}); - -export const apolloClient = new ApolloClient({ - link: authLink.concat(httpLink), - cache: new InMemoryCache(), -}) -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/create-follow-typed-data.md b/documents/Lens API/follow-api/create-follow-typed-data.md deleted file mode 100644 index 676e2ba..0000000 --- a/documents/Lens API/follow-api/create-follow-typed-data.md +++ /dev/null @@ -1,319 +0,0 @@ ---- -title: "follow" -slug: "create-follow-typed-data" -hidden: false -createdAt: "2022-02-18T11:27:38.984Z" -updatedAt: "2023-03-09T13:03:16.201Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to follow profiles on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -You can follow many people in a single contract call so the API interface is designed around that as well. - -```graphql Example operation -mutation CreateFollowTypedData { - createFollowTypedData(request:{ - follow: [ - { - profile: "0x01", - followModule: null - } - ] - }) { - id - expiresAt - typedData { - domain { - name - chainId - version - verifyingContract - } - types { - FollowWithSig { - name - type - } - } - value { - nonce - deadline - profileIds - datas - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createFollowTypedData": { - "id": "5211ef22-fc0a-4662-aebf-2b04ab3fa8c2", - "expiresAt": "2022-02-18T13:10:14.000Z", - "typedData": { - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "types": { - "FollowWithSig": [ - { - "name": "profileIds", - "type": "uint256[]" - }, - { - "name": "datas", - "type": "bytes[]" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "value": { - "nonce": 0, - "deadline": 1645189814, - "profileIds": [ - "0x01" - ], - "datas": [ - "0x" - ] - } - } - } - } -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### Profile - required - -You have to pass in a `profile` that is mandatory (this is the `profileId`). - -### FollowModule - -If you are following someone who has a follow module defined you must pass in the properties to redeem it. We make you pass in the properties from the client-side because if we read it from the server each time someone could front-run the request and make you sign something which your client was not seeing at the time of generating the signature. Follow modules can be changed at any time by the profile. If no follow module is setup for this profile you do not need to pass anything in. - -Defining the follow module to be redeemed is very easy with the schema we have created: - -#### No follow module setup - -If the person has no follow module setup you do not need to pass anything into the follow module - -```graphql -mutation CreateFollowTypedData { - createFollowTypedData(request:{ - follow: [ - { - profile: "0x01" - } - ] - }) { - id - expiresAt - typedData { - domain { - name - chainId - version - verifyingContract - } - types { - FollowWithSig { - name - type - } - } - value { - nonce - deadline - profileIds - datas - } - } - } -} -``` - - - -#### Profile follow module - -The person you want to follow requires you to have a profile to follow him. You have to pass your `profileId` into the request. That profile can only follow them once which stops spam. - -```graphql -mutation CreateFollowTypedData { - createFollowTypedData(request:{ - follow: [ - { - profile: "0x01", - followModule: { - profileFollowModule: { - profileId: "0x02" - } - } - } - ] - }) { - id - expiresAt - typedData { - domain { - name - chainId - version - verifyingContract - } - types { - FollowWithSig { - name - type - } - } - value { - nonce - deadline - profileIds - datas - } - } - } -} -``` - - - -#### Fee follow module - -The person your following has a fee follow module setup - -```graphql -mutation CreateFollowTypedData { - createFollowTypedData(request:{ - follow: [ - { - profile: "0x01", - followModule: { - feeFollowModule: { - amount: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "0.01" - } - } - } - } - ] - }) { - id - expiresAt - typedData { - domain { - name - chainId - version - verifyingContract - } - types { - FollowWithSig { - name - type - } - } - value { - nonce - deadline - profileIds - datas - } - } - } -} -``` - - - -As you see above we have mapped the `currency` the profile wants to be paid in alongside the `value` which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if the profile cost to follow is 1 WETH you would enter 1 as a value. - -You know all this information about a profile as the follow module is attached to the `Profile` schema itself [Get profiles](doc:get-profiles). - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -You can use LensClient SDK to follow a profile. - -```typescript -// lensClient is an authenticated instance of LensClient - -// get recommended profiles to follow -const recommendedProfiles = await lensClient.profile.allRecommended(); - -// request follow typed data -const followTypedDataResult = await lensClient.profile.createFollowTypedData({ - follow: [ - { - profile: recommendedProfiles[0].id, - }, - ], -}); - -// sign and broadcast the typed data -const data = followTypedDataResult.unwrap(); - -// sign with the wallet -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/create-set-follow-module-typed-data.md b/documents/Lens API/follow-api/create-set-follow-module-typed-data.md deleted file mode 100644 index 5c01f49..0000000 --- a/documents/Lens API/follow-api/create-set-follow-module-typed-data.md +++ /dev/null @@ -1,340 +0,0 @@ ---- -title: "Set follow module" -slug: "create-set-follow-module-typed-data" -hidden: false -createdAt: "2022-02-18T11:28:05.923Z" -updatedAt: "2023-03-14T10:26:25.443Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to set your follow module for your profile on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```graphql Example operation -mutation CreateSetFollowModuleTypedData { - createSetFollowModuleTypedData(request:{ - profileId: "0x03", - followModule: { - feeFollowModule: { - amount: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "0.01" - }, - recipient: "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - } - } - }) { - id - expiresAt - typedData { - types { - SetFollowModuleWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - followModule - followModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetFollowModuleTypedData": { - "id": "27313933-5a6d-4b9a-b5a7-64a77506c988", - "expiresAt": "2022-02-18T15:08:11.000Z", - "typedData": { - "types": { - "SetFollowModuleWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "followModule", - "type": "address" - }, - { - "name": "followModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645196891, - "profileId": "0x03", - "followModule": "0x2268063b81e7BDf4Bc681ef6d054Bbd1513aaE4A", - "followModuleInitData": "0x000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000d40282e050723ae26aeb0f77022db14470f4e011000000000000000000000000eea0c1f5ab0159dba749dc0baee462e5e293daaf" - } - } - } - } -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### ProfileId - required - -This is mandatory - -### FollowModule - -Defining the follow module is very easy with the schema we have created: - -#### Free follow module - -You can unset your follow module back to nothing by using the `freeFollowModule` - -```graphql -mutation CreateSetFollowModuleTypedData { - createSetFollowModuleTypedData(request:{ - profileId: "0x03", - followModule: { - freeFollowModule: true - } - }) { - id - expiresAt - typedData { - types { - SetFollowModuleWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - followModule - followModuleInitData - } - } - } -} -``` - - - -#### Fee follow module - -You can charge to have someone follow you; to set this up you can do: - -```js -mutation CreateSetFollowModuleTypedData { - createSetFollowModuleTypedData(request:{ - profileId: "0x03", - followModule: { - feeFollowModule: { - amount: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "0.01" - }, - recipient: "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - } - } - }) { - id - expiresAt - typedData { - types { - SetFollowModuleWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - followModule - followModuleInitData - } - } - } -} -``` - - - -As you see above we have mapped the `currency` we want to be paid in alongside the `value` which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. The final property defined is the `recipient` you want the funds to go to. - -#### Revert follow module - -You do not want anyone to follow you; to set this up you can do: - -```js -mutation CreateSetFollowModuleTypedData { - createSetFollowModuleTypedData(request:{ - profileId: "0x03", - followModule: { - revertFollowModule: true - } - }) { - id - expiresAt - typedData { - types { - SetFollowModuleWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - followModule - followModuleInitData - } - } - } -} -``` - - - -#### Profile follow module - -You only want people with profiles to be able to follow you and only once on that profile (avoiding spam); to set this up you can do: - -```js -mutation CreateSetFollowModuleTypedData { - createSetFollowModuleTypedData(request:{ - profileId: "0x03", - followModule: { - profileFollowModule: true - } - }) { - id - expiresAt - typedData { - types { - SetFollowModuleWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - followModule - followModuleInitData - } - } - } -} -``` - - - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -# - -# Using LensClient SDK - -```typescript -// lensClient is an authenticated instance of LensClient - -const typedDataResult = await lensClient.profile.createSetFollowModuleTypedData({ - followModule: FollowModuleParams; - profileId: Scalars['ProfileId']; -}); - -const data = typedDataResult.unwrap(); - -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/create-set-follow-nft-uri.md b/documents/Lens API/follow-api/create-set-follow-nft-uri.md deleted file mode 100644 index 4a24355..0000000 --- a/documents/Lens API/follow-api/create-set-follow-nft-uri.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: "Set follow NFT URI" -slug: "create-set-follow-nft-uri" -hidden: false -createdAt: "2022-02-24T11:07:47.300Z" -updatedAt: "2023-03-14T10:27:19.328Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to set your follow NFT for your profile on lens. This is what your users will mint and see on secondary marketplaces and in their wallets as the follower NFT. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```graphql Example operation -mutation CreateSetFollowNFTUriTypedData { - createSetFollowNFTUriTypedData(request: { - profileId: "0x02", - followNFTURI: "ipfs://LmTqN4LZ2G4QRrsS2y2QFMUH5K7dT2ix6P6TuL3pq9CShx" - }) { - id - expiresAt - typedData { - types { - SetFollowNFTURIWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - profileId - deadline - followNFTURI - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetFollowNFTUriTypedData": { - "id": "5ee5c6d5-4e54-4a32-b044-34b16bef3001", - "expiresAt": "2022-03-03T09:45:32.000Z", - "typedData": { - "types": { - "SetFollowNFTURIWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "followNFTURI", - "type": "string" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 11, - "profileId": "0x02", - "deadline": 1646300732, - "followNFTURI": "ipfs://QmTqN4LZ2G4QRrsS2y2QFMUH5K7dT2ix6P6TuL3pq9CShx" - } - } - } - } -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### ProfileId - required - -This is mandatory - -### followNFTURI - -The follow NFT URI is the NFT metadata your followers will mint when they follow you. This can be updated at all times. If you do not pass in anything it will create a super cool changing NFT which will show the last publication of your profile as the NFT which looks awesome! This means people do not have to worry about writing this logic but still have the ability to customize it for their followers. - -We do not enforce our standards on this metadata as it is purely to be showed on secondary marketplaces. We advise you follow opensea metadata spec for this - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -```typescript -// lensClient is an authenticated instance of LensClient - -const typedDataResult = await lensClient.profile.createSetFollowNFTUriTypedData({ - followNFTURI?: InputMaybe; - profileId: Scalars['ProfileId']; -}); - -const data = typedDataResult.unwrap(); - -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/create-unfollow-typed-data.md b/documents/Lens API/follow-api/create-unfollow-typed-data.md deleted file mode 100644 index de3575b..0000000 --- a/documents/Lens API/follow-api/create-unfollow-typed-data.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: "unfollow" -slug: "create-unfollow-typed-data" -hidden: false -createdAt: "2022-02-18T11:27:51.832Z" -updatedAt: "2023-03-14T10:23:03.545Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to unfollow someone on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -If you are not following this profile it will throw a validation error and not generate the types. - -```graphql Example operation -mutation CreateUnfollowTypedData { - createUnfollowTypedData(request:{ - profile: "0x1d" - }) { - id - expiresAt - typedData { - types { - BurnWithSig { - name - type - } - } - domain { - version - chainId - name - verifyingContract - } - value { - nonce - deadline - tokenId - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createUnfollowTypedData": { - "id": "db0c9892-f7c8-45d0-acd1-b9bdb005646c", - "expiresAt": "2022-02-18T14:29:40.000Z", - "typedData": { - "types": { - "BurnWithSig": [ - { - "name": "tokenId", - "type": "uint256" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "version": "1", - "chainId": 80001, - "name": "devjosh-Follower", - "verifyingContract": "0x1091303A2a13d8f171355920693C6D17aaF81a9B" - }, - "value": { - "nonce": 0, - "deadline": 1645195096, - "tokenId": "0x01" - } - } - } - } -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -## - -## - -# Using LensClient SDK - -You can use LensClient SDK to unfollow a profile. - -```typescript -// lensClient is an authenticated instance of LensClient - -// to unfollow you need to request unfollow typed data, sign and broadcast -// but also make sure that you follow that profile first -const unfollowTypedDataResult = await lensClient.profile.createUnfollowTypedData({ - profile: profileId, -}); - -const data = unfollowTypedDataResult.unwrap(); - -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/does-follow.md b/documents/Lens API/follow-api/does-follow.md deleted file mode 100644 index b8f54ea..0000000 --- a/documents/Lens API/follow-api/does-follow.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: "Does follow" -slug: "does-follow" -hidden: false -createdAt: "2022-02-18T11:28:40.226Z" -updatedAt: "2023-03-14T10:31:39.444Z" ---- -> 📘 Full code example -> -> - -This query returns to you if the Ethereum address follows a profile. It allows you to do a bulk request. - -We highly advise using [Is followed by me](doc:is-followed-by-me) and [Is following](doc:is-following) as it solves most of the cases when you want to use this. - -# API Design - -```javascript Example operation -query DoesFollow { - doesFollow(request: { - followInfos: [ - { - followerAddress: "0xD020E01C0c90Ab005A01482d34B808874345FD82", - profileId: "0x01" - }, - { - followerAddress: "0x248ba21F6ff51cf0CD4765C3Bc9fAD2030a591d5", - profileId: "0x01" - } - ] - }) { - followerAddress - profileId - follows - } -} -``` -```javascript Example response -{ - "data": { - "doesFollow": [ - { - "followerAddress": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "profileId": "0x01", - "follows": true - }, - { - "followerAddress": "0x248ba21F6ff51cf0CD4765C3Bc9fAD2030a591d5", - "profileId": "0x01", - "follows": false - } - ] - } -} -``` -```javascript Query interface -type Query { - doesFollow(request: DoesFollowRequest!): [DoesFollowResponse!]! -} -``` -```javascript Request -input DoesFollowRequest { - # The follower infos - followInfos: [DoesFollow!]! -} - -input DoesFollow { - # The follower address remember wallets follow profiles - followerAddress: EthereumAddress! - - # The profile id - profileId: ProfileId! -} - -# ProfileId custom scalar type -scalar ProfileId - -# Ethereum address custom scalar type -scalar EthereumAddress -``` -```javascript Response -# hint: it returns an array of this type -# The does follow response -type DoesFollowResponse { - # The follower address remember wallets follow profiles - followerAddress: EthereumAddress! - - # The profile id - profileId: ProfileId! - - # If the user does follow - follows: Boolean! -} - -# ProfileId custom scalar type -scalar ProfileId - -# Ethereum address custom scalar type -scalar EthereumAddress -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.profile.doesFollow({ - followInfos: [ - { - followerAddress: "", - profileId, - }, - ], -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/follower-nft-owned-token-ids.md b/documents/Lens API/follow-api/follower-nft-owned-token-ids.md deleted file mode 100644 index 9eef09d..0000000 --- a/documents/Lens API/follow-api/follower-nft-owned-token-ids.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "Follower NFT owned token ids" -slug: "follower-nft-owned-token-ids" -hidden: false -createdAt: "2022-03-04T21:39:07.383Z" -updatedAt: "2023-03-14T10:34:37.732Z" ---- -> 📘 Full code example -> -> - -This query returns the follower NFT for a profile token ids that the wallet address owns. Remember a wallet can follow a profile as many times as they wish. - -# API Design - -```javascript Example operation -query FollowerNftOwnedTokenIds { - followerNftOwnedTokenIds(request: { - address: "0xD020E01C0c90Ab005A01482d34B808874345FD82", - profileId: "0x01" - }) { - followerNftAddress - tokensIds - } -} -``` -```javascript Example response -{ - "data": { - "followerNftOwnedTokenIds": { - "followerNftAddress": "0x3471422cf7340ff2cC3608BCbc4B247F41F144d5", - "tokensIds": [ - "0x01", - "0x02", - "0x03", - "0x04", - "0x05", - "0x06", - "0x07" - ] - } - } -} -``` -```javascript Query interface -type Query { - followerNftOwnedTokenIds(request: FollowerNftOwnedTokenIdsRequest!): FollowerNftOwnedTokenIds! -} -``` -```javascript Request -input FollowerNftOwnedTokenIdsRequest { - address: EthereumAddress! - profileId: ProfileId! -} - -# Ethereum address custom scalar type -scalar EthereumAddress - -# ProfileId custom scalar type -scalar ProfileId -``` -```javascript Response -type FollowerNftOwnedTokenIds { - followerNftAddress: ContractAddress! - tokensIds: [Int!]! -} - -# Contract address custom scalar type -scalar ContractAddress -``` - - - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.profile.followerNftOwnedTokenIds({ - address: "", - profileId: "", -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/followers.md b/documents/Lens API/follow-api/followers.md deleted file mode 100644 index 3667a12..0000000 --- a/documents/Lens API/follow-api/followers.md +++ /dev/null @@ -1,323 +0,0 @@ ---- -title: "Followers" -slug: "followers" -hidden: false -createdAt: "2022-02-18T11:29:07.989Z" -updatedAt: "2023-03-14T10:33:41.716Z" ---- -> 📘 Full code example -> -> - -This query returns the wallet addresses which are following a profile - -# API Design - -```javascript Example operation -query Followers { - followers(request: { - profileId: "0x01", - limit: 10 - }) { - items { - wallet { - address - defaultProfile { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - contractAddress - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - } - totalAmountOfTimesFollowed - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "followers": { - "items": [ - { - "wallet": { - "address": "0x2376e9C7C604D1827bA9aCb1293Dc8b4DA2f0DB3", - "defaultProfile": { - "id": "0x14", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": true, - "handle": "no12", - "picture": null, - "coverPicture": null, - "ownedBy": "0x2376e9C7C604D1827bA9aCb1293Dc8b4DA2f0DB3", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 4, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - } - }, - "totalAmountOfTimesFollowed": 1 - }, - { - "wallet": { - "address": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "defaultProfile": null, - "totalAmountOfProfiles": 0 - }, - "totalAmountOfTimesFollowed": 2 - }, - { - "wallet": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "defaultProfile": { - "id": "0x032f1a", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": true, - "handle": "foobar222", - "picture": null, - "coverPicture": null, - "ownedBy": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "canUseRelay": false - }, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 4, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": { - "type": "FeeFollowModule", - "contractAddress": "0xBc20957342419BE3449DB77f89DEAdcb95cb32f5", - "amount": { - "asset": { - "name": "WETH", - "symbol": "WETH", - "decimals": 18, - "address": "0x3C68CE8504087f89c640D02d133646d98e64ddd9" - }, - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - } - } - }, - "totalAmountOfTimesFollowed": 3 - }, - { - "wallet": { - "address": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "defaultProfile": { - "id": "0x02b047", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": true, - "handle": "yoginth", - "picture": null, - "coverPicture": null, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": null, - "stats": { - "totalFollowers": 3, - "totalFollowing": 3, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 2, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - } - }, - "totalAmountOfTimesFollowed": 3 - }, - { - "wallet": { - "address": "0x9260363c60A6782c2B6a702594B75F6e7CC096aC", - "defaultProfile": { - "id": "0x032e41", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": true, - "handle": "gaming", - "picture": null, - "coverPicture": null, - "ownedBy": "0x9260363c60A6782c2B6a702594B75F6e7CC096aC", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 4, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - } - }, - "totalAmountOfTimesFollowed": 1 - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":5}", - "totalCount": 5 - } - } - } -} -``` -```javascript Query interface -type Query { - followers(request: FollowersRequest!): PaginatedFollowersResult! -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass the previous and next cursor in the request cursor property. - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.profile.allFollowers({ - profileId: "", -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/following.md b/documents/Lens API/follow-api/following.md deleted file mode 100644 index 153b025..0000000 --- a/documents/Lens API/follow-api/following.md +++ /dev/null @@ -1,247 +0,0 @@ ---- -title: "Following" -slug: "following" -hidden: false -createdAt: "2022-02-18T11:28:52.724Z" -updatedAt: "2023-03-14T10:32:40.835Z" ---- -> 📘 Full code example -> -> - -This query returns all the profiles an Ethereum address is following - -# API Design - -```javascript Example operation -query Following { - following(request: { - address: "0xD020E01C0c90Ab005A01482d34B808874345FD82", - limit: 10 - }) { - items { - profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - width - height - mimeType - } - medium { - url - width - height - mimeType - } - small { - url - width - height - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - width - height - mimeType - } - small { - width - url - height - mimeType - } - medium { - url - width - height - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - totalAmountOfTimesFollowing - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "following": { - "items": [ - { - "profile": { - "id": "0x09", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "keyboard", - "picture": null, - "coverPicture": null, - "ownedBy": "0xFC88582d42a377cc0055660f86f6FEFe333cCC89", - "dispatcher": null, - "stats": { - "totalFollowers": 10, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - "totalAmountOfTimesFollowing": 2 - }, - { - "profile": { - "id": "0x032f1a", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "foobar222", - "picture": null, - "coverPicture": null, - "ownedBy": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "canUseRelay": false - }, - "stats": { - "totalFollowers": 6, - "totalFollowing": 3, - "totalPosts": 9, - "totalComments": 0, - "totalMirrors": 1, - "totalPublications": 10, - "totalCollects": 3 - }, - "followModule": null - }, - "totalAmountOfTimesFollowing": 1 - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":2}", - "totalCount": 2 - } - } - } -} -``` -```javascript Query interface -type Query { - following(request: FollowingRequest!): PaginatedFollowingResult! -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - - - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.profile.allFollowing({ - address: "", -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/is-followed-by-me.md b/documents/Lens API/follow-api/is-followed-by-me.md deleted file mode 100644 index d692f70..0000000 --- a/documents/Lens API/follow-api/is-followed-by-me.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Is followed by me" -slug: "is-followed-by-me" -hidden: false -createdAt: "2022-06-20T16:32:25.762Z" -updatedAt: "2022-06-20T16:33:12.472Z" ---- -You need to know if the logged-in user is following the profile it's viewing, to do this you need to look at the `isFollowingByMe` property on the profile response. This is shown in the examples when fetching back a profile. It will always be false if calling when not logged in but when passing in the auth header it will work out if that wallet has is following the profile. - -# API Design basic - -please note the example below doesn't pick all the content out of the profile it just shows you the field used to get that back. -[block:code] -{ - "codes": [ - { - "code": "query Profile {\n profile(request: { profileId: \"0x01\" }) {\n isFollowedByMe\n }\n}", - "language": "javascript", - "name": "Example operation" - } - ] -} -[/block] \ No newline at end of file diff --git a/documents/Lens API/follow-api/is-following.md b/documents/Lens API/follow-api/is-following.md deleted file mode 100644 index 0141a4d..0000000 --- a/documents/Lens API/follow-api/is-following.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Is following" -slug: "is-following" -hidden: false -createdAt: "2022-06-20T16:34:57.428Z" -updatedAt: "2023-02-23T00:16:45.108Z" ---- -You need to know if a user is following another user, to do this you need to look at the `isFollowing` property on the profile response. - -This is shown in the examples when fetching back a profile. In the `isFollowing` field resolver you can pass in a `profileId` you wish to know if the owner of this profile is following, most apps would use the logged in users selected profile they are browsing on. - -# API design basic - -please note the example below doesn't pick all the content out of the profile it just shows you the field used to get that back. - -```javascript Example operation -query Profile { - profile(request: { profileId: "0x01" }) { - isFollowing(who: "0x08") - } -} -``` - - - -The profile id passed in for `isFollowing` can pass in as a variable easily enough as well. You can imagine passing the logged-in users profile they are browsing on to see if you should render a `follows back` label. This can be hooked in like this for every query which returns a profile type. - -```javascript Example operation -query Profile($profileId: ProfileId) { - profile(request: { profileId: "0x01" }) { - isFollowing(who: $profileId) - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/follow-api/pending-approval-follows.md b/documents/Lens API/follow-api/pending-approval-follows.md deleted file mode 100644 index b995cb3..0000000 --- a/documents/Lens API/follow-api/pending-approval-follows.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: "Pending approval follows" -slug: "pending-approval-follows" -hidden: false -createdAt: "2022-02-18T11:28:31.800Z" -updatedAt: "2023-03-14T10:29:40.830Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -To get around the issues with people being able to spam other people will a follower NFT we have brought in approval follows. Look at this situation: - -- @josh follows @dodgy.profile -- @josh gets a follower NFT for @dodgy.profile -- @josh sends the follower NFT to @coolshoes wallet owner -- @coolshoes wallet owner now looks like they follow @dodgy.profile - -You can see from the above how this could be a huge issue and with spam already a major thing on cheap transaction chains we do see this being a problem from day 1. - -To solve this we have a contract call called toggleFollow allowing you to move these from pending approvals to approved follows. - -- @josh follows @dodgy.profile -- @josh gets a follower NFT for @dodgy.profile -- @josh sends the follower NFT to @coolshoes -- The server removes that @josh follows @dodgy.profile from the indexer -- The server moves @coolshoes follows @dodgy.profile in an approval list -- This now means @coolshoes needs to approve that they approve to follow this profile - -This query returns all the pending approval follow NFT you have been sent and a way to show the user these so they can approve them. - -# API Design - -```javascript Example operation -query Followers { - pendingApprovalFollows(request: { - limit: 10 - }) { - items { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - mimeType - height - width - url - } - small { - url - width - height - mimeType - } - medium { - url - width - height - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - width - url - height - mimeType - } - small { - height - width - url - mimeType - } - medium { - url - width - height - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "pendingApprovalFollows": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "location": "UK", - "website": "https://mumbai.polygonscan.com/", - "twitter": "devjoshstevens", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.dev", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "depatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":0}", - "totalCount": 1 - } - } - } -} -``` -```javascript Query interface -type Query { - pendingApprovalFollows( - request: PendingApprovalFollowsRequest! - ): PendingApproveFollowsResult! -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -# - -# Using LensClient SDK - -```typescript -// lensClient is an authenticated instance of LensClient - -// paginatedResult is a Result type -const paginatedResult = await lensClient.profile.pendingApprovalFollows(); - -``` \ No newline at end of file diff --git a/documents/Lens API/gasless.md b/documents/Lens API/gasless.md deleted file mode 100644 index 6bc62b8..0000000 --- a/documents/Lens API/gasless.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Gasless" -slug: "gasless" -hidden: false -createdAt: "2023-02-17T18:32:56.179Z" -updatedAt: "2023-05-24T14:51:44.314Z" ---- -## Eligibility requirements - -LENS believes in supporting content creators and followers who create an engaging environment for everyone. Currently, we use machine learning algorithms to identify high-signal accounts and curated profiles based on factors such as follower graphs, content and other factors. Unfortunately, low-signal, pesty profiles diminish everyone's experience and waste gas. As a way of curtailing flagged, low-signal profiles, we have decided to stop paying gas fees for profiles that do not meet a certain signal threshold and create a nuisance. The protocol will remain open to anyone to do any actions; however, going forward, low-signal accounts must pay their own way. - -## How to use it - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -When to use each solution: - -- Broadcast is for gasless -- Dispatcher is for signless post, comment, mirror -- Proxy is for signless free follow, collect - -## Whitelisting your app - - To get your app whitelisted for gasless transactions through our API, submit your information to the following form: - -https\://www.lens.xyz/whitelist \ No newline at end of file diff --git a/documents/Lens API/gasless/broadcast-data-availability-transaction.md b/documents/Lens API/gasless/broadcast-data-availability-transaction.md deleted file mode 100644 index adc162d..0000000 --- a/documents/Lens API/gasless/broadcast-data-availability-transaction.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Broadcast Data Availability Transaction" -slug: "broadcast-data-availability-transaction" -hidden: false -createdAt: "2023-04-26T14:41:19.528Z" -updatedAt: "2023-04-26T16:31:44.885Z" ---- -Any time you do any typed data signing for DA, you need to use `broadcastDataAvailability` , which will broadcast the transaction for you. - -### Response - -The response from the API is `CreateDataAvailabilityPublicationResult` which holds the following properties: - -### id - -This is the publication ID, it is unique and can be used in all the same queries as before when using the publication ID to search. The format is: - -`profileId-publicationId-DA-FIRST_8_CHARS_OF_DATA_AVAILABILTY-ID` - -example: - -`0x01-0x01-DA-12345678` - -Publications are not submitted on-chain to Polygon, so the state does not change. If they do many DA publications without an on-chain action will always be that all the time and the only change will be the last 8 chars at the end. - -### proofs - -The arweave txId which is the proof string you can run checks on. - -### dataAvailabilityId - -This is not that useful for much, but the proof itself has an ID. \ No newline at end of file diff --git a/documents/Lens API/gasless/broadcast-transaction.md b/documents/Lens API/gasless/broadcast-transaction.md deleted file mode 100644 index f965118..0000000 --- a/documents/Lens API/gasless/broadcast-transaction.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: "Broadcast transaction" -slug: "broadcast-transaction" -hidden: false -createdAt: "2022-09-23T12:04:57.484Z" -updatedAt: "2023-05-24T15:06:57.118Z" ---- -> 🚧 Please note you can use broadcast freely on mumbai but if you want to use it on polygon you need to be whitelisted. - -> 📘 Full code example -> -> - -Using `broadcast`, you can enable gasless transactions in your Lens application. - -You should only call `broadcast` if you are using the typed data logic. If you are using the [dispatcher](https://docs.lens.xyz/docs/dispatcher) you don't need to broadcast it. If the user does not have a dispatcher on this is the way you can relay the transaction allowing the user not to pay gas. - -If you look at the schema you will see a broadcast mutation: - -```graphql request -mutation Broadcast($request: BroadcastRequest!) { - broadcast(request: $request) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` - -## Request - -### id - `broadcastId` - required - -This is the ID that is given back to you when you call any of the typed data calls example: - - - -![](https://files.readme.io/0b9a30c-image.png) - -please note you will be given an `expiresAt` date if you try to send the broadcast after that has expired it will be rejected. It is worth checking that for edge cases if someone takes a long time accepting the approval modal. - -### signature - `Signature` - required - -This is the signature without it being split so after your call `ethers _signTypedData` as you must do now if using the typed data methods instead of calling ethers `utils.splitSignature` you just pass in the full hex string of the signature. - -The response will either give you back a RelayerResult which holds the `txHash` and a `txId` (this is explained more below) or a RelayError which will give you a reason: - -```typescript -export enum RelayErrorReasons { - REJECTED = 'REJECTED', - EXPIRED = 'EXPIRED', - WRONG_WALLET_SIGNED = 'WRONG_WALLET_SIGNED', - NOT_ALLOWED = 'NOT_ALLOWED', -} -``` - -If you see a rejection it is worth allowing them to pay for it themselves so if the error happens use the normal `withSig` methods so you can handle gasless and if gasless is ever turned off without your code-breaking. `REJECTED` can mean they have used the max allowance in the hour. - -## Querying when it has been indexed - -You need to use endpoint to know when it's been indexed. This should be your source of truth and the only thing you call to watch for it to be successful. The main difference between what you should do with this call when using the relay and what you should call when not using the relay is instead of passing in the `txHash` into the `hasTxHashBeenIndexed` pass in the `txId` returned in `RelayerResult` this is because our relay will speed up gas on the transactions if the gas prices move or if it's taking too long to be picked up, this, of course, generates a new `txHash` and the old one would be dropped. So this is to make sure your client is never stuck in a loop forever. Also because we have to do an extra HTTP call here to find out the status from the transaction id when using txId it will be longer response times than using `txHash` so we recommend only calling it once every 1 second. - -## Using LensClient SDK - -You can use the `Transaction` module of LensClient SDK to broadcast typed data that were signed by your wallet. See the example below. - -```typescript -import { isRelayerResult } from "@lens-protocol/client"; - -// lensClient is an authenticated instance of LensClient - -// we need some typedData to sign and broadcast so let's set the dispatcher as an example -const typedDataResult = await lensClient.profile.createSetDispatcherTypedData({ - profileId: activeProfile.id, -}); - -// typedDataResult is a Result object -const data = typedDataResult.unwrap(); - -// sign with the wallet -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -// broadcast -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); - -// broadcastResult is a Result object -const broadcastResultValue = broadcastResult.unwrap(); - -if (!isRelayerResult(broadcastResultValue)) { - console.log(`Something went wrong`, broadcastResultValue); - return; -} - -console.log( - `Transaction was successfuly broadcasted with txId ${broadcastResultValue.txId}` -); - -``` - -You can also check the status of the transaction with - -```typescript -// result is a Result object -const result = await lensClient.transaction.wasIndexed(txId); - -// or wait till transaction is indexed -await lensClient.transaction.waitForIsIndexed(txId); -``` - -Read here about the returned [Result type](doc:client-sdk-types). - -## \ No newline at end of file diff --git a/documents/Lens API/gasless/dispatcher.md b/documents/Lens API/gasless/dispatcher.md deleted file mode 100644 index 9bf4c07..0000000 --- a/documents/Lens API/gasless/dispatcher.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Dispatcher" -slug: "dispatcher" -hidden: false -createdAt: "2022-02-17T17:57:00.438Z" -updatedAt: "2023-05-24T15:07:21.106Z" ---- -# Dispatcher - -The **Dispatcher** enables gasless and signless transactions (transactions without signing any approval modals) in your Lens app. - -Blockchain technology introduced many drawbacks like wallet popups, seed phrases, passwords, funds, and multi-network (blockchain) dynamics. These are fundamental for securing cryptographic transactions but present many UX challenges. So, are we doomed, or should we be optimistic? - -In blockchain terms, Optimistic means that we assume the transaction will come through so we don't need to wait for validators to reach a consensus. This wouldn't be acceptable for financial transactions because of the double spending problem but can be helpful for social media interactions. - -Social media is about great frontend experiences so having wallet prompts for every share or follow is not ideal. The challenge is that being optimistic in a front-end experience is possible but still, every action must be approved by the user wallet. - -To solve this issue, we created the ** Dispatcher**. Basically, it is an intermediate wallet with funds that act as the signer for every transaction. We only have to delegate signing privileges to this dispatcher wallet which operates hidden in the backend. This combined with an optimistic UI creates a seamless experience identical to what we are used to today. - -![](https://files.readme.io/e4b6d72-LENS_CHART_copy_1.png) - -![](https://files.readme.io/834df82-LENS_CHART_1.png) - -**Security** - -Dispatcher only works for post, comment, mirror, set profile metadata and set profile image. - -## Dispatcher examples - -Post - - -Comment - - -Mirror - - -Profile metadata - - -Profile image - - -## How to know if a user has a dispatcher on - -You can use the `withSig` methods and go through the `broadcast` logic to keep transactions gasless but that still requires a signature. The dispatcher is an opt-in step so you can check if a profile has a dispatcher on by doing: - -```graphql example operation -query Profile { - profile(request: { profileId: "0x18" }) { - dispatcher { - address - canUseRelay - } - } -} -``` -```javascript example response -{ - "data": { - "profile": { - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F", - "canUseRelay": true - } - } - } -} -``` - -If the `canUseRelay` is true this means they can use the built-in dispatcher on the API. Remember profiles could have mapped to another dispatcher which is not the lens API one so if it is false you can not do dispatcher transactions through the API. You would have to prompt the user to move over to ours which is described below. Also, note that dispatcher can not be set at all if so it will be `dispatcher: null` - -## WithSig methods - -As a dispatcher can only use a subset of methods this doesn't mean you can not be gasless for everything. Any `withSig` methods can go through the relay. On each document, if that logic can go through the `broadcast` it will state it to make it very clear for you. - -## Set dispatcher - -> 📘 Full code example -> -> Disable - -> -> Enable - - -This API call allows you to get the typed data to then call the `withSig` method to set a dispatcher for your Lens profile. - -Dispatcher allows another address to post, comment, mirror, set follow module and change the profile picture on behalf of you using their wallet - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```graphql Example operation -mutation CreateSetDispatcherTypedData { - createSetDispatcherTypedData(request:{ - profileId: "0x1d", - dispatcher: "0xdfd7D26fd33473F475b57556118F8251464a24eb" - }) { - id - expiresAt - typedData { - types { - SetDispatcherWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - dispatcher - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetDispatcherTypedData": { - "id": "1c0829c0-94d9-4ca8-938e-61f87a73c811", - "expiresAt": "2022-02-18T15:45:17.000Z", - "typedData": { - "types": { - "SetDispatcherWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "dispatcher", - "type": "address" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645199117, - "profileId": "0x1d", - "dispatcher": "0xdfd7D26fd33473F475b57556118F8251464a24eb" - } - } - } - } -} -``` - -## Request - -Let's touch on this request so it's super clear. - -### profiled - required - -You must pass in a `profileId` that is mandatory. - -### dispatcher - -You can pass in the `dispatcher` as per the above to set a dispatcher. - -### enabled - -You can remove the dispatcher by setting `enabled: false`. - -Example in the request as below: - -```js -mutation CreateSetDispatcherTypedData { - createSetDispatcherTypedData(request:{ - profileId: "0x1d", - enabled: false - }) { - id - expiresAt - typedData { - types { - SetDispatcherWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - dispatcher - } - } - } -} -``` - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -Our dispatcher resolver contains: - -- [Create set dispatcher typed data](doc:create-set-dispatcher-typed-data) - -# Using LensClient SDK - -You can use LensClient SDK to set the dispatcher. See the example below. - -```typescript -import { isRelayerResult } from "@lens-protocol/client"; - -// lensClient is an authenticated instance of LensClient - -const typedDataResult = await lensClient.profile.createSetDispatcherTypedData({ - profileId: activeProfile.id, -}); - -// typedDataResult is a Result object -const data = typedDataResult.unwrap(); - -// sign with the wallet -const signedTypedData = await wallet._signTypedData( - data.typedData.domain, - data.typedData.types, - data.typedData.value -); - -// broadcast -const broadcastResult = await lensClient.transaction.broadcast({ - id: data.id, - signature: signedTypedData, -}); - -// broadcastResult is a Result object -const broadcastResultValue = broadcastResult.unwrap(); - -if (!isRelayerResult(broadcastResultValue)) { - console.log(`Something went wrong`, broadcastResultValue); - return; -} - -console.log( - `Transaction was successfuly broadcasted with txId ${broadcastResultValue.txId}` -); - -``` - -### Reference - -```typescript -async createSetDispatcherTypedData( - request: SetDispatcherRequest, - options?: TypedDataOptions, -): PromiseResult< - InferResultType, - CredentialsExpiredError | NotAuthenticatedError -> - -type SetDispatcherRequest = { - /** The dispatcher address - they can post, comment, mirror, set follow module, change your profile picture on your behalf, if left as none it will use the built in dispatcher address. */ - dispatcher?: InputMaybe; - /** If you want to enable or disable it */ - enable?: InputMaybe; - /** The profile id */ - profileId: Scalars['ProfileId']; -}; - -type TypedDataOptions = { - /** You can override the nonce for the sig if you want to do some clever stuff in the client */ - overrideSigNonce: Scalars['Nonce']; -}; -``` \ No newline at end of file diff --git a/documents/Lens API/gasless/proxy-action-gasless.md b/documents/Lens API/gasless/proxy-action-gasless.md deleted file mode 100644 index a22adf9..0000000 --- a/documents/Lens API/gasless/proxy-action-gasless.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: "Proxy action" -slug: "proxy-action-gasless" -hidden: false -createdAt: "2022-09-23T12:34:31.525Z" -updatedAt: "2023-05-24T15:07:35.465Z" ---- -> 🚧 Please note you can use broadcast freely on mumbai but if you want to use it on polygon you need to be whitelisted. - -While the dispatcher will allow you to do actions like `post`, `comment`, and `mirror` without signing any approval modals, this endpoint allows you to do actions like `follow` and `collect` without having to sign any approval modals. - -_This only works if the modules assigned to those actions are free and have no cost to them, ie. FreeCollectModule and SimpleCollectModule._ - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -> 📘 Full code example -> -> Free collect - -> -> Free follow - - -> 👍 SimpleCollectModule support -> -> You can use Proxy actions to collect posts made with the new SimpleCollectModule. Keep in mind, posts still need to be free of charge and not require the collector to follow the post creator. -> -> In these cases, the [request](proxy-action-gasless#free-collect) to the API remains the same as with FreeCollectModule. - -# API Design - -## Free follow - -```javascript Example operation -mutation ProxyAction { - proxyAction(request: { - follow: { - freeFollow: { - profileId: "0x01" - } - } - }) -} -``` -```javascript Example response -{ - "data": { - "proxyAction": "7624f076-446d-4f38-8277-326b269fe8d8" - } -} -``` - -## Free collect - -```javascript Example operation -mutation ProxyAction { - proxyAction(request: { - collect: { - freeCollect: { - publicationId: "0x01-0x01" - } - } - }) -} -``` -```javascript Example response -{ - "data": { - "proxyAction": "7624f076-446d-4f38-8277-326b269fe8d8" - } -} -``` - -## Response - -This returns a `proxyActionId` which is a new id linked to that event, this is important to keep as you need it to track the status of the action. You should track this behind the scenes so the user does not need to be blocked, requesting it every 1-2 minutes is enough. To them, it should look like it's done. - -The API uses optimistic updates so when you click that button on the user it is complete and they inherit all the stuff instantly. You do not need to worry about optimistic UI caching on your end even though of course it's best practice. - -## Tracking the proxy action status - -Once you got the proxy action id you should track its status to make sure it goes all the way through. - -```Text Example operation -query ProxyActionStatus { - proxyActionStatus(proxyActionId: "7624f076-446d-4f38-8277-326b269fe8d8") { - ... on ProxyActionStatusResult { - txHash - txId - status - } - ... on ProxyActionError { - reason - lastKnownTxId - } - ... on ProxyActionQueued { - queuedAt - } - } -} -``` - -### Response - -These are all the points a proxy action can go through: - -- queued = it is waiting to be picked up by the cron -- minting = the process has started (bare in mind it may need to do > 1 tx to complete the action) -- complete = it's all done -- failed = something went wrong with the process (you should alert the user that the follow failed). - -```Text when queued -{ - "data": { - "result": { - "queuedAt": "2022-09-23T12:45:58.790Z", - "__typename": "ProxyActionQueued" - } - } -} -``` -```Text when minting -{ - "data": { - "result": { - "txHash": "0xf73a981bda4fef5dda24cf62225a3cc0807ff4d8ecbe0e0fbdf8f8470d17a751", - "txId": "0d7f6211-a72c-4c17-a856-a1211d7bb060", - "status": "MINTING", - "__typename": "ProxyActionStatusResult" - } - } -} -``` -```Text when complete -{ - "data": { - "result": { - "txHash": "0x0ef4bd411258518da45a84ed3484bbaaac48afcc20ad1d5acf6ee025df86cb6b", - "txId": "76bb7b84-0a66-45a9-a834-a21e1a8a07c6", - "status": "COMPLETE", - "__typename": "ProxyActionStatusResult" - } - } -} -``` -```Text when fails -{ - "data": { - "result": { - "reason": "bad things happened", - "lastKnownTxId": "0x0ef4bd411258518da45a84ed3484bbaaac48afcc20ad1d5acf6ee025df86cb6b" - "__typename": "ProxyActionError" - } - } -} -``` -```Text when transferring -{ - "data": { - "result": { - "txHash": "0x0ef4bd411258518da45a84ed3484bbaaac48afcc20ad1d5acf6ee025df86cb6b", - "txId": "76bb7b84-0a66-45a9-a834-a21e1a8a07c6", - "status": "TRANSFERRING", - "__typename": "ProxyActionStatusResult" - } - } -} -``` - - - -## Using LensClient SDK - -You can use LensClient SDK to trigger proxy actions. See the examples below. - -```typescript -// lensClient is an authenticated instance of LensClient - -// follow -const followResult = await lensClient.proxyAction.freeFollow(profileId); - -// collect -const collectResult = await lensClient.proxyAction.freeCollect(publicationId); - -// check status of a proxy action -const actionId = collectResult.unwrap(); -const checkStatusResult = await lensClient.proxyAction.checkStatus(actionId); -``` \ No newline at end of file diff --git a/documents/Lens API/gasless/relay-queues.md b/documents/Lens API/gasless/relay-queues.md deleted file mode 100644 index fe48b0b..0000000 --- a/documents/Lens API/gasless/relay-queues.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -title: "Relay queues tracking" -slug: "relay-queues" -hidden: false -createdAt: "2023-04-12T13:04:22.684Z" -updatedAt: "2023-04-13T12:57:53.955Z" ---- -The relay can sometimes get very busy as we scale. We will keep adding new relays to load and balance them out. This query is great for debugging to see the size of each queue if you ever see any delays in it being submitted on-chain. - -This API call can sometimes take 10-20 seconds if you are not using the cache, as it has to speak to the defender, which is not fast. It will respond instantly if you are saved the cache. This data is cached for 5 minutes at a time. - -If this fails due to Defender DB being unable to work it out, you can just retry. We do not suggest anyone to use this for any production code, it purely exists to get visibility for queues. - -# API Design - -```graphql Example operation -query RelayQueues { - relayQueues { - relayer - address - queue - } -} -``` -```javascript Example response -{ - "data": { - "relayQueues": [ - { - "relayer": "CREATE_PROFILE", - "address": "0xe7Af8325aA443F7678B651d4f0De23663E818691", - "queue": 0 - }, - { - "relayer": "DISPATCHER_1", - "address": "0xD1FecCF6881970105dfb2b654054174007f0e07E", - "queue": 17 - }, - { - "relayer": "DISPATCHER_10", - "address": "0x761010EFc8826fFdcb8Ad005BD935698ed38DfE7", - "queue": 5 - }, - { - "relayer": "DISPATCHER_2", - "address": "0xC9FA5F824530b0DB3Df97820ded190F849b9bc0d", - "queue": 5 - }, - { - "relayer": "DISPATCHER_3", - "address": "0xca674628a04dA98D12147EF8bE7c3663bc0820Ff", - "queue": 2 - }, - { - "relayer": "DISPATCHER_4", - "address": "0x999119915b0d11aE86087F03E312aCC1C2aC750E", - "queue": 2 - }, - { - "relayer": "DISPATCHER_5", - "address": "0x3530c7CAc2E47F27bA82a5d0D3671181171292DB", - "queue": 4 - }, - { - "relayer": "DISPATCHER_6", - "address": "0x112b57A293d99b79Fe360Af042bb3bfFc824Ab3a", - "queue": 4 - }, - { - "relayer": "DISPATCHER_7", - "address": "0x25418Bcf53dAe1167cD5d0cad34Eec31C0C37E41", - "queue": 6 - }, - { - "relayer": "DISPATCHER_8", - "address": "0xeCE7edDc02FB8F0010420D0d76911826b1536655", - "queue": 4 - }, - { - "relayer": "DISPATCHER_9", - "address": "0x76D4fFdA8c66864FA07f0a285B8E01E11b4Bb7b3", - "queue": 2 - }, - { - "relayer": "PROXY_ACTION_COLLECT_1", - "address": "0xBa4ae59edF4b34974dD6b19c89646b09AB1E044d", - "queue": 1 - }, - { - "relayer": "PROXY_ACTION_COLLECT_2", - "address": "0x77582a98132c2BE11a6C0F85Ca6361555A030A68", - "queue": 1 - }, - { - "relayer": "PROXY_ACTION_COLLECT_3", - "address": "0x75fAe78Ce542DE64824DF2e60e2828bC2A2d953c", - "queue": 4 - }, - { - "relayer": "PROXY_ACTION_COLLECT_4", - "address": "0x765F899Cc972768cd0440e7aaB112C26afbEE7cA", - "queue": 5 - }, - { - "relayer": "PROXY_ACTION_COLLECT_5", - "address": "0x479b18C5c5cd07777D97c523983779Bb6b4f8312", - "queue": 6 - }, - { - "relayer": "PROXY_ACTION_COLLECT_6", - "address": "0x9FE3c6449Dd952b16FD452B096EFb7f50a895ADc", - "queue": 7 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_1", - "address": "0x900caB7bB11Ae04B943496FD6Ae686Fb15f4d98E", - "queue": 0 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_10", - "address": "0xB2989c99C673510d04b9A7202108164DC03e89c7", - "queue": 2 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_2", - "address": "0x6204BFAa0f5be46F0D3DeA4334E66523a973086b", - "queue": 1 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_3", - "address": "0xaC5314FC0cD30064C6BD143f74aA724c0C69FD40", - "queue": 1 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_4", - "address": "0xdB400AbFa13E11a93a6b631Ebad2F15BA4bC43DA", - "queue": 3 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_5", - "address": "0x9A286e7f4c3245b812fadCD2c00bC818b9a754a0", - "queue": 3 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_6", - "address": "0xD209b5957a3eaB13008a18179E44f97ab34269d2", - "queue": 3 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_7", - "address": "0x9C8297dfDBD09330cF6AA458639aAEC29090d9c5", - "queue": 3 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_8", - "address": "0xf1a42d1975826b6beCBCaF6Cd105eecE26bc5C76", - "queue": 3 - }, - { - "relayer": "PROXY_ACTION_FOLLOW_9", - "address": "0x886E88c733AbBf5400b54766569b077088348ffE", - "queue": 3 - }, - { - "relayer": "WITH_SIG_1", - "address": "0x10773553e2144379c63fc69Ad357217acc79917e", - "queue": 9 - }, - { - "relayer": "WITH_SIG_2", - "address": "0x5B24683d4AD155EDA4782C8b6930B2C065014c32", - "queue": 17 - }, - { - "relayer": "WITH_SIG_3", - "address": "0xe6aB66Ca47b9c6CF5a0269786E6aF86a44FF8c49", - "queue": 27 - } - ] - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/general-information.md b/documents/Lens API/general-information.md deleted file mode 100644 index 2e1ef14..0000000 --- a/documents/Lens API/general-information.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "General information" -slug: "general-information" -hidden: false -createdAt: "2022-02-18T10:43:51.197Z" -updatedAt: "2022-02-21T09:33:27.857Z" ---- -- [Why our own indexer?](doc:why-our-own-indexer) -- [How do we index?](doc:how-do-we-index) -- [How do we cache?](doc:how-do-we-cache) -- [What database do we use?](doc:what-database-do-we-use) -- [What is the backend code ?](doc:what-is-the-backend-code) -- [Why GraphQL?](doc:why-graphql) \ No newline at end of file diff --git a/documents/Lens API/general-information/how-do-we-cache.md b/documents/Lens API/general-information/how-do-we-cache.md deleted file mode 100644 index 3930697..0000000 --- a/documents/Lens API/general-information/how-do-we-cache.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "How do we cache?" -slug: "how-do-we-cache" -hidden: false -createdAt: "2022-02-18T10:44:14.715Z" -updatedAt: "2022-03-09T19:24:42.338Z" ---- -We use Redis for caching everything. The issue you face with caching with a social media site is that you want data to be broadcasted as fast as possible but you want to also keep the speed impact of getting it. Our cache policy caches the generic data -- that is, if a user queries their timeline, they will always get back the latest stuff because the initial lightweight query of bringing back all the ids but the publication themselves have heavy caching on it. This allows us to still broadcast the latest data as soon as it is available but also have super fast queries for every API endpoint. The busier we are the faster we become. Speed is super important and improving this all the time will be something we constantly keep looking at. \ No newline at end of file diff --git a/documents/Lens API/general-information/how-do-we-index.md b/documents/Lens API/general-information/how-do-we-index.md deleted file mode 100644 index 204d645..0000000 --- a/documents/Lens API/general-information/how-do-we-index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "How do we index?" -slug: "how-do-we-index" -hidden: false -createdAt: "2022-02-18T10:44:08.161Z" -updatedAt: "2022-05-11T12:03:24.982Z" ---- -# Top level overview - -The backend server has many cron jobs which run individually; they all have a job to do, and to do it well they do. With the crons, we have a shared Redis cache to share states between them if they need to talk to each other. One cron is in charge of getting the latest block number and pushing changing state of that block number to Redis and another is in charge of reacting when the block number changes to access if anything in that block has changed for the lens protocol itself. - -We heavily use `bloomFilters` to check without any JSON RPC calls if the event and the lens contract are present in that block, if it is not we do nothing if it is we then get the logs for those events based on the topic and index it into our database. Our indexer also turns the data into a relational state, we do not just index the raw events we turn this data into already pre-formatted ready-to-go data, and save it in a structured highly relational database structure. This then means we can achieve super-fast queries with all the decoding already done for us within the indexer itself. Every event runs independently of itself allowing them all to access the block at the same time without blocking each other which increases the speed of broadcasting to anyone using our API. Alongside this we do not save as we see either. The server will generate everything which has changed in this block and then save in 1 database transaction meaning debugging is very easy and everything is transactional like how the blockchain is in theory. - -These tech decisions allow us to index super fast and only hit our node provider when we need to due to highly using blooms. Alongside super-fast queries and everything formatted and saved in the database in a relational optimized manner. - -# Reorgs - -As everyone knows reorgs can happen and they can happen many blocks in the future. Even though our node provider alchemy is a rockstar and protects us as much as they can sometimes it's out of their control if a reorg happens. Every part of the data saved on the database level which came from the protocol is attached next to a `blockHash` and `blockNumber`. Alongside this, we also have a block safe table that inserts any blocks we index with the block hash and block number as well. Our reorg cron checks the `blockHash` still exists after 300 blocks which are 3x the highest alchemy has ever seen a reorg happen on Polygon. If the `blockHash` does not exist anymore we revert the data inserted/updated in our database and use the old values if they existed before. If the `blockHash` still exists we mark this `block` as safe and do not re-evaluate the data again. - -# Your metadata - -Like OpenSea when the indexer sees your publication content come in we move it to our own storage and index the data at that time like a snapshot. Say you publish a post and the content points to your s3 box once the indexer picks it up it snapshots it and then going forward we read it from our own storage due to speed but also due to links being taken down and loads more reasons. This means if you did change that s3 link you used to point the publication to then it would not change on our API. \ No newline at end of file diff --git a/documents/Lens API/general-information/what-database-do-we-use.md b/documents/Lens API/general-information/what-database-do-we-use.md deleted file mode 100644 index e522172..0000000 --- a/documents/Lens API/general-information/what-database-do-we-use.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "What database do we use?" -slug: "what-database-do-we-use" -hidden: false -createdAt: "2022-02-18T10:44:22.322Z" -updatedAt: "2022-03-09T19:25:09.632Z" ---- -We use `postgres` database to store all our data. We wanted to ensure certainty in every aspect of how the data can be queried and how fast it can be queried. With speed in our minds, we had to go for the more low-level database over for example `NoSql` databases. \ No newline at end of file diff --git a/documents/Lens API/general-information/what-is-the-backend-code.md b/documents/Lens API/general-information/what-is-the-backend-code.md deleted file mode 100644 index ee643ed..0000000 --- a/documents/Lens API/general-information/what-is-the-backend-code.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "What is the backend code ?" -slug: "what-is-the-backend-code" -hidden: false -createdAt: "2022-02-18T10:44:35.768Z" -updatedAt: "2022-10-12T11:40:06.448Z" ---- -The main API backend stack is written in `node` and uses `TypeScript`. We also have crons which run in `rust` and we migrating more of our crons into `rust` as we continue developing the solutions. \ No newline at end of file diff --git a/documents/Lens API/general-information/why-graphql.md b/documents/Lens API/general-information/why-graphql.md deleted file mode 100644 index da60fc3..0000000 --- a/documents/Lens API/general-information/why-graphql.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Why GraphQL?" -slug: "why-graphql" -hidden: false -createdAt: "2022-02-18T10:44:48.797Z" -updatedAt: "2022-03-09T13:54:50.621Z" ---- -There are several major reasons we have decided to use GraphQL over a REST architecture: - -# Strongly-typed schema - -All the types (such as Boolean, String, Int, Float, ID, Scalar) supported by the API are specified in the schema in GraphQL Schema Definition Language (SDL), which helps determine the data that is available and the form it exists in. This, consequently, makes GraphQL less error-prone, and more validated, and provides auto-completion for supported IDE/editors. With a protocol that holds a lot of complexity, this really empowers the developer to understand the protocol just by looking at the schema which is super powerful. - -# Saves Time and Bandwidth - -GraphQL allows making multiple resources request in a single query call, which saves a lot of time and bandwidth by reducing the number of network round trips to the server. It also helps to save waterfall network requests, where you need to resolve dependent resources on previous requests - -# Versioning Is Not Required - -In REST architecture, developers create new versions (e.g., api.domain.com/v1/, api.domain.com/v2/) due to changes in resources or the request/response structure of the resources over time. Hence, maintaining versions is a common practice. With GraphQL, there is no need to maintain versions. The resource URL or address remains the same. You can add new fields and deprecate older fields. This approach is intuitive as the client receives a deprecation warning when querying a deprecated field. - -# No Over-Fetching or Under-Fetching - -With GraphQL, developers can fetch only what is required. Nothing less, nothing more. This solves the issues that arise due to over-fetching and under-fetching. You define how big your payload response should be! - -# The blockchain space people are used to GraphQL APIs - -The main reason is that we know the community use subgraphs on The Graph a lot and know how the syntax works so we think it will not be a learning curve at all for a lot of people who want to build on top of lens. - -We have loads and loads more reasons but yeah we love `GraphQL` and works perfectly for our need here. \ No newline at end of file diff --git a/documents/Lens API/general-information/why-our-own-indexer.md b/documents/Lens API/general-information/why-our-own-indexer.md deleted file mode 100644 index dae46f6..0000000 --- a/documents/Lens API/general-information/why-our-own-indexer.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Why our own indexer?" -slug: "why-our-own-indexer" -hidden: false -createdAt: "2022-02-21T09:33:07.001Z" -updatedAt: "2022-03-18T17:59:27.936Z" ---- -We are huge fans of `The Graph` and the ability to spin up subgraphs is amazing. As a team experienced working on subgraphs, we wanted to ensure smooth and efficient functioning for the Lens Protocol API. - -1) The subgraph sometimes takes a while to broadcast the indexed event. Now when we are building a social protocol we need the data to be ready at the second it has been mined in the block. Having this big dependency over our heads and not being able to control it would deeply ruin the whole network effect of the API. Speed is critical. - -2) We slightly touched on this above but we want to be able to be in control if things go wrong and have the ability to fix it. Having our own in-house indexer allows us to fine-tune it and fix any bugs which arise. Additionally, having all the code in-house allows us to have higher uptime and fix any issues fast, without a third-party dependency. - -3) This data is highly relational. With social data and unlimited pointers, the data becomes highly relational very fast, especially when a publication starts getting attention. This means we need to structure this data in a relational manner to allow it to be fast and scale well. Having Postgres as our database allows us to do this really nicely. - -There are many more reasons why we went down the path of creating an indexer, but our main goal was to give Lens developers the best infrastructure possible, and to allow developers to be able to build applications that can scale and compete with the largest networks today. \ No newline at end of file diff --git a/documents/Lens API/getting-started-with-your-api.md b/documents/Lens API/getting-started-with-your-api.md deleted file mode 100644 index a3eab01..0000000 --- a/documents/Lens API/getting-started-with-your-api.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Getting Started With Your API" -slug: "getting-started-with-your-api" -excerpt: "This page will help you get started with LENS API." -hidden: false -createdAt: "2022-09-02T21:11:46.722Z" -updatedAt: "2022-09-02T21:15:07.014Z" ---- -This is where you show your users how to set it up. You can use code samples, like this: - -```graphql gr -query ping { - ping -} -``` - - - -Try dragging a block from the right to see how easy it is to add more content! \ No newline at end of file diff --git a/documents/Lens API/health.md b/documents/Lens API/health.md deleted file mode 100644 index 5c2f7aa..0000000 --- a/documents/Lens API/health.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Health" -slug: "health" -hidden: false -createdAt: "2022-02-17T17:58:17.423Z" -updatedAt: "2022-03-09T15:14:01.255Z" ---- -The health status of our API is important to know the state of the API at a given time. - -Our health resolver contains: - -- [Ping](doc:ping) \ No newline at end of file diff --git a/documents/Lens API/health/ping.md b/documents/Lens API/health/ping.md deleted file mode 100644 index b9830c8..0000000 --- a/documents/Lens API/health/ping.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Ping" -slug: "ping" -hidden: false -createdAt: "2022-02-18T08:35:45.162Z" -updatedAt: "2022-09-23T15:13:49.719Z" ---- -> 📘 Full code example -> -> - -This returns if the API is online. - -# API details - -```javascript Example operation -query Query { - ping -} -``` -```javascript Example response -{ - "data": { - "ping": "pong" - } -} -``` -```javascript Query interface -ping: String! -``` -```text Response -String! -``` \ No newline at end of file diff --git a/documents/Lens API/indexer.md b/documents/Lens API/indexer.md deleted file mode 100644 index 7205419..0000000 --- a/documents/Lens API/indexer.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Indexer" -slug: "indexer" -hidden: false -createdAt: "2022-02-17T17:58:24.844Z" -updatedAt: "2022-02-25T09:54:06.942Z" ---- -The indexer resolver holds states about what the API knows about. Nothing is broadcasted on our API until it has been minted and indexed by us. Our indexer runs on every block so is very fast and broadcasting this data to the API once indexed. - -Our indexer resolver contains: - -- [Has transaction been indexed](doc:has-transaction-been-indexed) \ No newline at end of file diff --git a/documents/Lens API/indexer/has-transaction-been-indexed.md b/documents/Lens API/indexer/has-transaction-been-indexed.md deleted file mode 100644 index 64e1a05..0000000 --- a/documents/Lens API/indexer/has-transaction-been-indexed.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: "Has transaction been indexed" -slug: "has-transaction-been-indexed" -hidden: false -createdAt: "2022-02-18T08:42:28.223Z" -updatedAt: "2023-03-14T10:21:56.884Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Normally when you broadcast transactions to the blockchain you wait for the receipt to know the transaction has been completed fully. The transaction is in a pending state until you have a receipt. If you use `ethers.js` you normally use their method to wait to get the receipt. - -```js -await tx.wait(); -``` - - - -As this is slightly different your source of truth is actually the API's indexer and database. So this method allows you to swap out the wait method from `ethers.js` and use this API query as a source of truth for when it is complete. - -The indexer tracks all transaction hashes to allow you to easily query to work out if the indexer has now broadcasted it. Please note there is a 2 stage process when you do a publication: - -1. The indexer indexes it and this will be field `indexed` -2. The server then validates the metadata conforms to standards and processes it to internal storage. This is description in `metadataStatus`. This contains the `status` of the processing and also the `reason` if it fails. This field can be ignored if you are not waiting on a publication to be indexed. - -# API details - -> 📘 If your using gasless -> -> When using gasless you must use the `txId` over the `txHash` as the gasless would bump up the transaction if the gas prices move meaning a new `txHash` will be generated. - -```javascript Example operation -query HasTxHashBeenIndexed { - hasTxHashBeenIndexed(request: { txHash: "0x64464dc0de5aac614a82dfd946fc0e17105ff6ed177b7d677ddb88ec772c52d3" }) { - ... on TransactionIndexedResult { - indexed - txReceipt { - to - from - contractAddress - transactionIndex - root - gasUsed - logsBloom - blockHash - transactionHash - blockNumber - confirmations - cumulativeGasUsed - effectiveGasPrice - byzantium - type - status - logs { - blockNumber - blockHash - transactionIndex - removed - address - data - topics - transactionHash - logIndex - } - } - metadataStatus { - status - reason - } - } - ... on TransactionError { - reason - txReceipt { - to - from - contractAddress - transactionIndex - root - gasUsed - logsBloom - blockHash - transactionHash - blockNumber - confirmations - cumulativeGasUsed - effectiveGasPrice - byzantium - type - status - logs { - blockNumber - blockHash - transactionIndex - removed - address - data - topics - transactionHash - logIndex - } - } - }, - __typename - } -} -``` -```javascript Example response success -{ - "data": { - "hasTxHashBeenIndexed": { - "indexed": true, - "txReceipt": { - "to": "0xF6BF84E5df229029C9D36dC7ABaCDBE9c0bd7b4F", - "from": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F", - "contractAddress": null, - "transactionIndex": 1, - "root": null, - "gasUsed": "0x028545", - "logsBloom": "0x04000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000800000000000000000000100000000004000000000000010000008000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000200004000000000000000100000000100000000000000200000000000000004000000000000100000001000000000000000000000010000000100040000000000000000000000100000000000000000000000000008000000040000000100001", - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "blockNumber": 25427445, - "confirmations": 88, - "cumulativeGasUsed": "0x03d110", - "effectiveGasPrice": "0x06fc23ac00", - "byzantium": true, - "type": 0, - "status": 1, - "logs": [ - { - "blockNumber": 25427445, - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionIndex": 1, - "removed": false, - "address": "0xF6BF84E5df229029C9D36dC7ABaCDBE9c0bd7b4F", - "data": "0x00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000edeb556d916d9e6e154a083ac18da52cc5ed8b1c0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000062271ad4000000000000000000000000000000000000000000000000000000000000003a697066733a2f2f516d646e3566674b7750516b684b78446f35514643584559767178737965445050435644367a727975775631526f2e6a736f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "topics": [ - "0xc672c38b4d26c3c978228e99164105280410b144af24dd3ed8e4f9d211d96a50", - "0x0000000000000000000000000000000000000000000000000000000000032f1a", - "0x0000000000000000000000000000000000000000000000000000000000000002" - ], - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "logIndex": 2 - }, - { - "blockNumber": 25427445, - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionIndex": 1, - "removed": false, - "address": "0x0000000000000000000000000000000000001010", - "data": "0x000000000000000000000000000000000000000000000000000f4c2f5f77af5500000000000000000000000000000000000000000000000035d05225576c9b000000000000000000000000000000000000000000000008fce4cf8ae2602de1b800000000000000000000000000000000000000000000000035c105f5f7f4ebab0000000000000000000000000000000000000000000008fce4ded711bfa5910d", - "topics": [ - "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000006c1e1bc39b13f9e0af9424d76de899203f47755f", - "0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f" - ], - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "logIndex": 3 - } - ] - }, - "metadataStatus": { - "status": "SUCCESS", - "reason": null - } - } - } -} -``` -```javascript Example response revert -{ - "data": { - "hasTxHashBeenIndexed": { - "reason": "REVERTED" - "txReceipt": { - "to": "0xF6BF84E5df229029C9D36dC7ABaCDBE9c0bd7b4F", - "from": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F", - "contractAddress": null, - "transactionIndex": 1, - "root": null, - "gasUsed": "0x028545", - "logsBloom": "0x04000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000800000000000000000000100000000004000000000000010000008000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000200004000000000000000100000000100000000000000200000000000000004000000000000100000001000000000000000000000010000000100040000000000000000000000100000000000000000000000000008000000040000000100001", - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "blockNumber": 25427445, - "confirmations": 88, - "cumulativeGasUsed": "0x03d110", - "effectiveGasPrice": "0x06fc23ac00", - "byzantium": true, - "type": 0, - "status": 0, - "logs": [ - { - "blockNumber": 25427445, - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionIndex": 1, - "removed": false, - "address": "0xF6BF84E5df229029C9D36dC7ABaCDBE9c0bd7b4F", - "data": "0x00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000edeb556d916d9e6e154a083ac18da52cc5ed8b1c0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000062271ad4000000000000000000000000000000000000000000000000000000000000003a697066733a2f2f516d646e3566674b7750516b684b78446f35514643584559767178737965445050435644367a727975775631526f2e6a736f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "topics": [ - "0xc672c38b4d26c3c978228e99164105280410b144af24dd3ed8e4f9d211d96a50", - "0x0000000000000000000000000000000000000000000000000000000000032f1a", - "0x0000000000000000000000000000000000000000000000000000000000000002" - ], - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "logIndex": 2 - }, - { - "blockNumber": 25427445, - "blockHash": "0x4da3491fe338c2a5b4c7ee6d0388be4f07481f69fd7a6d78f8d9f11e36697bae", - "transactionIndex": 1, - "removed": false, - "address": "0x0000000000000000000000000000000000001010", - "data": "0x000000000000000000000000000000000000000000000000000f4c2f5f77af5500000000000000000000000000000000000000000000000035d05225576c9b000000000000000000000000000000000000000000000008fce4cf8ae2602de1b800000000000000000000000000000000000000000000000035c105f5f7f4ebab0000000000000000000000000000000000000000000008fce4ded711bfa5910d", - "topics": [ - "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000006c1e1bc39b13f9e0af9424d76de899203f47755f", - "0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f" - ], - "transactionHash": "0xc896c44a3d39ad07922f6d7e915b555b2f327b651b636c197a987b3f921e987d", - "logIndex": 3 - } - ] - } - } - } -} -``` - - - -## Request - -you may see that the request takes in a nullable `txHash` or a nullable `txId` if you are not using the server relay `txHash` you should always use the `txHash` when doing this query. Please note if the user upgrades the gas price the `txHash` changes so your client should handle that on those edge cases to avoid being stuck in a loop until that `txHash` is dropped (sometimes can take a long time). - - - - - -## - -## - -## Using LensClient SDK - -Check the status of a transaction. Read here about the returned [Result type](doc:client-sdk-types). - -```typescript -// result is a Result object -const result = await lensClient.transaction.wasIndexed(txId); - -// or wait till transaction is indexed -await lensClient.transaction.waitForIsIndexed(txId); -``` \ No newline at end of file diff --git a/documents/Lens API/introduction.md b/documents/Lens API/introduction.md deleted file mode 100644 index d3ce297..0000000 --- a/documents/Lens API/introduction.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Introduction" -slug: "introduction" -hidden: false -createdAt: "2022-02-18T17:07:36.350Z" -updatedAt: "2022-11-09T16:41:20.971Z" ---- -> 🚧 This is a beta API -> -> This API is beta and not production complete yet, which means that we could change schemas and endpoints at any time without warning or notice to you. When this API is production ready, we will remove this beta warning and will endeavor to ensure that there are no changes going forward unless a major change to the protocol itself is required. - -Welcome to the API docs for Lens Protocol. We aim to highlight all the endpoints which are exposed on the public API and explain how to use them and what they return. - -The API is a GraphQL API which is very similar to how a lot of people use the subgraph when using The Graph so it should be very familiar for many developers. If you have come from a REST backend we will explain how you can easily get up and running with this on your client. - -GraphQL gives us a lot of benefits but the main one is a schema first approach. We believe for mass adoption and building of Lens we need the tools to be super easy and abstract away as much as the blockchain stuff as we can. You will see how we did this with our schema, everything should just make sense without having a deep technical understanding of how the protocol works or having to understand Solidity. - -As the protocol data on the blockchain is very relational, our indexer does all the work for you. Mapping it into our Postgres database decoded and in a relational manner optimized for fast fetching. This allows you to query us with the same speed as if you were querying Twitter for example. - -We have packed the API with a lot of features and will be continuing to develop and improve it. By using this API in your application you automatically inherit many of these improvements. - -We hope you like it and any feedback you have is extremely welcomed. - - -[block:embed] -{ - "html": "", - "url": "https://www.youtube.com/watch?v=mIJKa2-2p8w", - "title": "The Lens GraphQL API", - "favicon": "http://www.google.com/favicon.ico", - "provider": "youtube.com", - "href": "https://www.youtube.com/watch?v=mIJKa2-2p8w", - "typeOfEmbed": "youtube" -} -[/block] \ No newline at end of file diff --git a/documents/Lens API/media-snapshots.md b/documents/Lens API/media-snapshots.md deleted file mode 100644 index 8b9b3d4..0000000 --- a/documents/Lens API/media-snapshots.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: "Media Snapshots" -slug: "media-snapshots" -hidden: false -createdAt: "2023-05-25T10:44:00.330Z" -updatedAt: "2023-05-26T16:33:51.252Z" ---- -The Lens API now snapshots the media content from profiles and publications. Our goal is to provide a seamless experience to users, on par with web2, so that content delivery is quick, responsive and adjustable to your application's needs. - -This new feature is implemented by adding 2 new fields on the `MediaSet` type, called `onChain` and `optimized`, which will contain the originally uploaded content and the snapshotted content respectively. The `original` field will now dynamically return snapshotted content if available, otherwise the original url uploaded by the user. This way, applications can enjoy faster loading times with zero changes on their side, and if it's crucial for a business case to include the on-chain content, that also remains available. - -The type of content being snapshotted is: - -- Profile pictures (not NFT PFPs) -- Profile cover photos -- Publication content under `metadata.media` (including covers) - -> 📘 My content is not being snapshotted, why? -> -> While most media snapshots will happen almost instantaneously, some might take some time to complete especially for typically larger types of content like audio and video, in these cases, the `original` field will resolve to the onChain url, and will point to the snapshot once it's complete. -> -> The current limits for snapshots are 50MB for images, 200MB for audio and 1GB for video content. -> -> Also, please note that the `metadata.image` and `metadata.animation_url` fields are _not_ snapshotted right now. - -### Images - -Image content will be snapshotted on [ImageKit](https://imagekit.io) as well as S3 for redundancy, and will always be served from ImageKit CDN. This applies to images up to 50MB in size, larger ones will _not_ be snapshotted at this point. - -#### Image transformations - -One common usecase is to serve image content in various sizes for different purposes. eg. A profile picture can be served as part of a post in a small format, or in the profile page in a medium format, or even in full resolution if needed. The now deprecated `small` and `medium` media formats were allowing this but not in a customizable way. To support these usecases, `MediaSet` now has a `transform` field resolver that will serve images in custom resolutions harnessing ImageKit's on-the-fly transformation feature. - -The new field resolver takes a single input object with 3 properties `width`, `height` and `keepAspectRatio`. `width` and `height` accept string values in the following forms: `'500px'` for pixel-based transformations, `'50%'` for transformations based on the percentage of the original image size and `'auto'` in cases you only want to supply one dimension and auto-compute the other. `keepAspectRatio` is set to true by default, and you can set it as false in case you explicitly want the image to be stretched. - -Here is a few GraphQL snippets using the `transform` field resolver: - -```gql -... on Post { - metadata { - media { - original { - url - } - transform(params:{ - width: "200px" - height: "10%" - keepAspectRatio:false - }) - } - } -} - -``` - -```gql -... on Post { - metadata { - media { - original { - url - } - transform(params:{ - height: "100px" - width: "auto" - }) - - } - } -} -``` - -### Audio - -Audio content up to 200MBs in size will be snapshotted on an S3 bucket. The audio will be intact, no transcoding will be made, it will be a direct copy of the original. - -### Video content - -Video content up to 1GB will be snapshotted on [Livepeer](https://livepeer.org). Snapshotting on Livepeer involves transcoding the video, so it's a lengthier process, that should take up to a few minutes. - -Also, Livepeer-snapshotted videos will be served in the m3u8 format, and that might need some additional handling from your side. \ No newline at end of file diff --git a/documents/Lens API/modules-api.md b/documents/Lens API/modules-api.md deleted file mode 100644 index 5d005af..0000000 --- a/documents/Lens API/modules-api.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Modules" -slug: "modules-api" -hidden: false -createdAt: "2022-02-17T17:58:33.969Z" -updatedAt: "2023-02-17T18:51:47.095Z" ---- -Modules are an integral part of the Lens Protocol: they allow profile owners to include unique, custom functionality on follow, collect and reference. You can read more about modules [here](doc:module-interfaces) and what they do. - -The module resolver has these queries: - -- [Create collected typed data](doc:create-collected-typed-data) -- [Enabled modules currencies](doc:enabled-modules-currencies) -- [Enabled modules](doc:enabled-modules) -- [Approved allowance of modules](doc:approved-allowance-of-modules) -- [Generate module currency approval data](doc:generate-module-currency-approval-data) \ No newline at end of file diff --git a/documents/Lens API/modules-api/approved-allowance-of-modules.md b/documents/Lens API/modules-api/approved-allowance-of-modules.md deleted file mode 100644 index 944da0c..0000000 --- a/documents/Lens API/modules-api/approved-allowance-of-modules.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: "Approved allowance of modules" -slug: "approved-allowance-of-modules" -hidden: false -createdAt: "2022-02-24T12:32:51.716Z" -updatedAt: "2023-03-14T12:42:33.952Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Each [Enabled modules currencies](doc:enabled-modules-currencies) needs to have approval greater than the amount of the collect module. If it is not then an API request will throw an error as the module will not be able to move funds on your behalf. - -This query returns you the amount approved that the modules can move on your behalf for the array of currencies you supply. - -# API Design - -```javascript Example operation -query ApprovedModuleAllowanceAmount { - approvedModuleAllowanceAmount(request: { - currencies: ["0x3C68CE8504087f89c640D02d133646d98e64ddd9"], - collectModules: [LimitedFeeCollectModule, FeeCollectModule, LimitedTimedFeeCollectModule, TimedFeeCollectModule, FreeCollectModule, RevertCollectModule], - followModules: [FeeFollowModule, RevertFollowModule, ProfileFollowModule], - referenceModules: [FollowerOnlyReferenceModule] - }) { - currency - module - contractAddress - allowance - } -} -``` -```javascript Example response -{ - "data": { - "approvedModuleAllowanceAmount": [ - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "LimitedFeeCollectModule", - "contractAddress": "0x25DC6498A9d6Bb8eDE2A4Fd96276aEb9256a60b7", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "FeeCollectModule", - "contractAddress": "0x171c49f4e5Ef41e9c5731a35ed42487d168CF8Db", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "TimedFeeCollectModule", - "contractAddress": "0x1c8E432C93276370fBfceD16d842670eEEc06B67", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "EmptyCollectModule", - "contractAddress": "0x2732FfD7f7352c9492089C40A0C3368220a438D4", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "RevertCollectModule", - "contractAddress": "0x45B7907d5c5d2aF9157898601B7B3e18670891c3", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "FeeFollowModule", - "contractAddress": "0x2268063b81e7BDf4Bc681ef6d054Bbd1513aaE4A", - "allowance": "0x00" - }, - { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "module": "FollowerOnlyReferenceModule", - "contractAddress": "0x1F5a47fE69e09397D5386FfdA9134afDF6555498", - "allowance": "0x00" - } - ] - } -} -``` -```javascript Query interface -type Query { - approvedModuleAllowanceAmount( - request: ApprovedModuleAllowanceAmountRequest! - ): [ApprovedAllowanceAmount!]! -} -``` -```javascript Request -input ApprovedModuleAllowanceAmountRequest { - # The contract addresses for the module approved currencies you want to find information on about the user - currencies: [ContractAddress!]! - collectModules: [CollectModules!]! - followModules: [FollowModules!]! - referenceModules: [ReferenceModules!]! -} - -# The collect module types -enum CollectModules { - LimitedFeeCollectModule - FeeCollectModule - LimitedTimedFeeCollectModule - TimedFeeCollectModule - RevertCollectModule - EmptyCollectModule -} - -# The follow module types -enum FollowModules { - FeeFollowModule -} - -# The reference module types -enum ReferenceModules { - FollowerOnlyReferenceModule -} - -# Contract address custom scalar type -scalar ContractAddress -``` -```javascript Response -# remember it returns an array of this -type ApprovedAllowanceAmount { - currency: ContractAddress! - module: String! - contractAddress: ContractAddress! - allowance: String! -} - -# Contract address custom scalar type -scalar ContractAddress -``` - - - -# - -# Using LensClient SDK - -Example use. - -```typescript -import { CollectModules, FollowModules, ReferenceModules } from "@lens-protocol/client"; - -const result = await lensClient.modules.approvedAllowanceAmount({ - currencies: ['0x3C68CE8504087f89c640D02d133646d98e64ddd9'], - collectModules: [CollectModules.LimitedFeeCollectModule], - followModules: [FollowModules.FeeFollowModule], - referenceModules: [ReferenceModules.FollowerOnlyReferenceModule], -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/modules-api/enabled-modules-currencies.md b/documents/Lens API/modules-api/enabled-modules-currencies.md deleted file mode 100644 index c0d6fdd..0000000 --- a/documents/Lens API/modules-api/enabled-modules-currencies.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: "Enabled modules currencies" -slug: "enabled-modules-currencies" -hidden: false -createdAt: "2022-02-18T11:26:39.765Z" -updatedAt: "2023-03-14T10:36:58.058Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Modules currencies are whitelisted tokens that can be used as the currency for charged modules. All module currencies must be whitelisted by the governance, if you try to use a none whitelisted currency when setting the module it will throw an error. - - This query returns to you all the enabled module currencies - -# API Design - -```javascript Example operation -query EnabledModuleCurrencies { - enabledModuleCurrencies { - name - symbol - decimals - address - } -} -``` -```javascript Example response -{ - "data": { - "enabledModuleCurrencies": [ - { - "name": "Currency", - "symbol": "CRNC", - "decimals": 18, - "address": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011" - } - ] - } -} -``` -```javascript Query interface -type Query { - enabledModuleCurrencies: [Erc20!]! -} -``` -```javascript Response -# The erc20 type -type Erc20 { - # Name of the symbol - name: String! - - # Symbol for the token - symbol: String! - - # Decimal places for the token - decimals: Int! - - # The erc20 address - address: ContractAddress! -} - -# Contract address custom scalar type -scalar ContractAddress -``` - - - -> 👍 You can check current list [here](https://github.com/lens-protocol/token-list/blob/main/testnet-token-list.json) -> -> WMATIC -> 0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889 - - - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.modules.fetchEnabledCurrencies() - -``` \ No newline at end of file diff --git a/documents/Lens API/modules-api/enabled-modules.md b/documents/Lens API/modules-api/enabled-modules.md deleted file mode 100644 index dcc4825..0000000 --- a/documents/Lens API/modules-api/enabled-modules.md +++ /dev/null @@ -1,474 +0,0 @@ ---- -title: "Enabled modules" -slug: "enabled-modules" -hidden: false -createdAt: "2022-02-18T11:36:27.090Z" -updatedAt: "2023-03-14T12:42:21.693Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -This query returns to you all the modules that the server knows about and information about those modules. - -# API Design - -```javascript Example operation -query CollectModules { - enabledModules { - collectModules { - moduleName - contractAddress - inputParams { - name - type - } - redeemParams { - name - type - } - returnDataParms { - name - type - } - } - followModules { - moduleName - contractAddress - inputParams { - name - type - } - redeemParams { - name - type - } - returnDataParms { - name - type - } - } - referenceModules { - moduleName - contractAddress - inputParams { - name - type - } - redeemParams { - name - type - } - returnDataParms { - name - type - } - } - } -} -``` -```javascript Example response -{ - "data": { - "enabledModules": { - "collectModules": [ - { - "moduleName": "FeeCollectModule", - "contractAddress": "0xeb4f3EC9d01856Cec2413bA5338bF35CeF932D82", - "inputParams": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ], - "redeemParams": [ - { - "name": "currency", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "returnDataParms": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ] - }, - { - "moduleName": "LimitedFeeCollectModule", - "contractAddress": "0xFCDA2801a31ba70dfe542793020a934F880D54aB", - "inputParams": [ - { - "name": "collectLimit", - "type": "uint256" - }, - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ], - "redeemParams": [ - { - "name": "currency", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "returnDataParms": [ - { - "name": "collectLimit", - "type": "uint256" - }, - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ] - }, - { - "moduleName": "LimitedTimedFeeCollectModule", - "contractAddress": "0xDa76E44775C441eF53B9c769d175fB2948F15e1C", - "inputParams": [ - { - "name": "collectLimit", - "type": "uint256" - }, - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ], - "redeemParams": [ - { - "name": "currency", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "returnDataParms": [ - { - "name": "collectLimit", - "type": "uint256" - }, - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - }, - { - "name": "endTimestamp", - "type": "uint40" - } - ] - }, - { - "moduleName": "RevertCollectModule", - "contractAddress": "0x5E70fFD2C6D04d65C3abeBa64E93082cfA348dF8", - "inputParams": [], - "redeemParams": [], - "returnDataParms": [] - }, - { - "moduleName": "TimedFeeCollectModule", - "contractAddress": "0x36447b496ebc97DDA6d8c8113Fe30A30dC0126Db", - "inputParams": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - } - ], - "redeemParams": [ - { - "name": "currency", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "returnDataParms": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - }, - { - "name": "referralFee", - "type": "uint16" - }, - { - "name": "followerOnly", - "type": "bool" - }, - { - "name": "endTimestamp", - "type": "uint40" - } - ] - }, - { - "moduleName": "FreeCollectModule", - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c", - "inputParams": [ - { - "name": "followerOnly", - "type": "bool" - } - ], - "redeemParams": [], - "returnDataParms": [ - { - "name": "followerOnly", - "type": "bool" - } - ] - } - ], - "followModules": [ - { - "moduleName": "FeeFollowModule", - "contractAddress": "0xe7AB9BA11b97EAC820DbCc861869092b52B65C06", - "inputParams": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - } - ], - "redeemParams": [ - { - "name": "currency", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "returnDataParms": [ - { - "name": "amount", - "type": "uint256" - }, - { - "name": "currency", - "type": "address" - }, - { - "name": "recipient", - "type": "address" - } - ] - }, - { - "moduleName": "RevertFollowModule", - "contractAddress": "0x8c822Fc029EBdE62Da1Ed1072534c5e112dAE48c", - "inputParams": [], - "redeemParams": [], - "returnDataParms": [] - }, - { - "moduleName": "ProfileFollowModule", - "contractAddress": "0x8c32203df6b1A04E25145346e2DaAD0B4712C20D", - "inputParams": [], - "redeemParams": [ - { - "name": "followerProfileId", - "type": "uint256" - } - ], - "returnDataParms": [] - } - ], - "referenceModules": [ - { - "moduleName": "FollowerOnlyReferenceModule", - "contractAddress": "0x7Ea109eC988a0200A1F79Ae9b78590F92D357a16", - "inputParams": [], - "redeemParams": [], - "returnDataParms": [] - } - ] - } - } -} -``` -```javascript Query interface -type Query { - enabledModules: EnabledModules! -} -``` -```javascript Response -type EnabledModules { - collectModules: [EnabledModule!]! - followModules: [EnabledModule!]! - referenceModules: [EnabledModule!]! -} - -type EnabledModule { - moduleName: String! - contractAddress: ContractAddress! - inputParams: [ModuleInfo!]! - redeemParams: [ModuleInfo!]! - returnDataParms: [ModuleInfo!]! -} - -type ModuleInfo { - name: String! - type: String! -} - -# Contract address custom scalar type -scalar ContractAddress -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.modules.fetchEnabled() - -``` \ No newline at end of file diff --git a/documents/Lens API/modules-api/generate-module-currency-approval-data.md b/documents/Lens API/modules-api/generate-module-currency-approval-data.md deleted file mode 100644 index 3ec8308..0000000 --- a/documents/Lens API/modules-api/generate-module-currency-approval-data.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: "Module currency approval data" -slug: "generate-module-currency-approval-data" -hidden: false -createdAt: "2022-02-24T15:16:55.820Z" -updatedAt: "2023-03-14T12:38:55.132Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -This query encodes the `allowance` ERC-20 data for you for the module. This allows you to just call this without any context of the modules contracts or how to construct the approval and it will return you the partial transaction you just need to give it a gas price, estimate the gas and send it. - -# API Design - -```javascript Example operation -query GenerateModuleCurrencyApprovalData { - generateModuleCurrencyApprovalData(request: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "10", - collectModule: LimitedFeeCollectModule - }) { - to - from - data - } -} -``` -```javascript Example response -{ - "data": { - "generateModuleCurrencyApprovalData": { - "to": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "from": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "data": "0x095ea7b300000000000000000000000025dc6498a9d6bb8ede2a4fd96276aeb9256a60b70000000000000000000000000000000000000000000000008ac7230489e80000" - } - } -} -``` -```javascript Query interface -type Query { - generateModuleCurrencyApprovalData( - request: GenerateModuleCurrencyApprovalDataRequest! - ): GenerateModuleCurrencyApproval! -} -``` -```javascript Request -input GenerateModuleCurrencyApprovalDataRequest { - currency: ContractAddress! - - # Floating point number as string (e.g. 42.009837). The server will move its decimal places for you - value: String! - collectModule: CollectModules - followModule: FollowModules - referenceModule: ReferenceModules -} - -# The collect module types -enum CollectModules { - LimitedFeeCollectModule - FeeCollectModule - LimitedTimedFeeCollectModule - TimedFeeCollectModule - RevertCollectModule - EmptyCollectModule -} - -# The follow module types -enum FollowModules { - FeeFollowModule -} - -# The reference module types -enum ReferenceModules { - FollowerOnlyReferenceModule -} - -# Contract address custom scalar type -scalar ContractAddress -``` -```javascript Response -type GenerateModuleCurrencyApproval { - to: ContractAddress! - from: EthereumAddress! - data: BlockchainData! -} - -# Contract address custom scalar type -scalar ContractAddress - -# Ethereum address custom scalar type -scalar EthereumAddress - -# Blockchain data scalar type -scalar BlockchainData -``` - - - -## Request - -Let's dig in the request to make sure its super clear - -#### currency - required - -This is the module currency you wish to approve for the user - -#### value - required - -This is the value you want the user to approve this module with. It can be a high amount if you do not want them to keep approving it, but that tends to be up to the user to pick. It should be supplied in the normal formatted UI amount so if you want to approve 10 ETH you pass in "10" not the wei equivalent. It is a string number because of the overflows a JS number can have. - -#### collectModule - you must give a collect module or a followModule or a referenceModule - -This is the collect module you wish to approve. You can just pass in the enum value and the server will map the rest for you. This can not be used alongside the other modules it should only be supplied by itself. - -```js -query GenerateModuleCurrencyApprovalData { - generateModuleCurrencyApprovalData(request: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "10", - collectModule: LimitedFeeCollectModule - }) { - to - from - data - } -} -``` - - - -#### followModule - you must give a collect module or a collectModule or a referenceModule - -This is the follow module you wish to approve. You can just pass in the enum value and the server will map the rest for you. This can not be used alongside the other modules it should only be supplied by itself. - -```js -query GenerateModuleCurrencyApprovalData { - generateModuleCurrencyApprovalData(request: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "10", - followModule: FeeFollowModule - }) { - to - from - data - } -} -``` - - - -#### referenceModule - you must give a collect module or a collectModule or a followModule - -This is the reference module you wish to approve. You can just pass in the enum value and the server will map the rest for you. This can not be used alongside the other modules it should only be supplied by itself. - -```js -query GenerateModuleCurrencyApprovalData { - generateModuleCurrencyApprovalData(request: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "10", - referenceModule: FollowerOnlyReferenceModule - }) { - to - from - data - } -} -``` - - - -# - -# Using LensClient SDK - -Example use. - -```typescript -import { CollectModules } from "@lens-protocol/client"; - -const result = await lensClient.modules.generateCurrencyApprovalData({ - currency: '0xD40282e050723Ae26Aeb0F77022dB14470f4e011', - value: '10', - collectModule: CollectModules.LimitedFeeCollectModule, -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/nfts.md b/documents/Lens API/nfts.md deleted file mode 100644 index b3fb42f..0000000 --- a/documents/Lens API/nfts.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "NFTs" -slug: "nfts" -hidden: false -createdAt: "2022-02-17T17:58:41.479Z" -updatedAt: "2022-03-09T15:07:36.540Z" ---- -We have seen the NFT space explode over the past year and expect many developers to integrate NFTs into their applications. We have NFT lookups exposed for you so you can query NFTs on both Polygon and Ethereum, with more networks being supported in the future. -[block:callout] -{ - "type": "info", - "title": "Did you know..", - "body": "You can set NFT images as profile pictures and the server will track if they still own it every few hours. If they do not it will be removed from their profile picture." -} -[/block] -Our NFT resolver has these queries: - -- [Get Users NFTs](doc:get-users-nfts) -- [NFT ownership challenge](doc:nft-ownership-challenge) \ No newline at end of file diff --git a/documents/Lens API/nfts/get-users-nfts.md b/documents/Lens API/nfts/get-users-nfts.md deleted file mode 100644 index 6b145e9..0000000 --- a/documents/Lens API/nfts/get-users-nfts.md +++ /dev/null @@ -1,946 +0,0 @@ ---- -title: "Get Users NFTs" -slug: "get-users-nfts" -hidden: false -createdAt: "2022-02-18T11:25:35.980Z" -updatedAt: "2023-03-14T12:41:27.671Z" ---- -> 📘 Full code example -> -> - -This query allows you to find what NFTs a user owns. It also allows you to query what they own by contract address to sees which specific NFTs a user owns in a given collection. We use Moralis API to get the NFT data. - -# API details - -- If you are using testnet this endpoint will only allow you to query `polygon Mumbai (chainId: 80001)` -- If you are using mainnet this endpoint will only allow you to query `ethereum mainnet (chainId: 1)` and `polygon mainnet (chainId: 137)` - -Below is the overview of the entire interface but we dig into specific queries below. - -```javascript Example response -{ - "data": { - "nfts": { - "items": [ - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5742", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5741", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5740", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5739", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5738", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5737", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Tubby Cats", - "contractAddress": "0xCa7cA7BcC765F77339bE2d648BA53ce9c8a262bD", - "symbol": "TUBBY", - "tokenId": "4193", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Tubby Cats", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmWEsF23zM2C1afa6G9XwgBhqJsPH9CyQTDpToap1MD4Un", - "originalContent": { - "uri": "ipfs://QmXRJbXFUHPbHy6hLcVtrcUiEiWyPtXSGjgsH5RexMwMmd", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Tubby Cats", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "6518", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/6518", - "originalContent": { - "uri": "ipfs://QmTL41cWQGXXVEfvy9YiRfmx9NmEoQoiQVtVoSeWrrVDwS", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "3Landers", - "contractAddress": "0xb4d06d46A8285F4EC79Fd294F78a881799d8cEd9", - "symbol": "3L", - "tokenId": "4766", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "3Landers", - "description": "3Landers is a collectible NFT project centered around community, adventure, and collaboration.", - "contentURI": "https://ipfs.io/ipfs/QmNWziXfkdZRTY6ZQHkHGUe8smUCNGPT4umrpQ8KVjqNDB/", - "originalContent": { - "uri": "https://ipfs.io/ipfs/Qmb2t58xgmTFaZUxgPV1tfBkD1zP4avYf55RKevdCAHGSH/", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "3Landers", - "ercType": "ERC721" - }, - { - "contractName": "3Landers", - "contractAddress": "0xb4d06d46A8285F4EC79Fd294F78a881799d8cEd9", - "symbol": "3L", - "tokenId": "4765", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "3Landers", - "description": "3Landers is a collectible NFT project centered around community, adventure, and collaboration.", - "contentURI": "https://ipfs.io/ipfs/QmNWziXfkdZRTY6ZQHkHGUe8smUCNGPT4umrpQ8KVjqNDB/", - "originalContent": { - "uri": "https://ipfs.io/ipfs/Qmb2t58xgmTFaZUxgPV1tfBkD1zP4avYf55RKevdCAHGSH/", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "3Landers", - "ercType": "ERC721" - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":10}", - "totalCount": 4023 - } - } - } -} -``` -```javascript Query interface -type Query { - nfts(request: NFTsRequest!): NFTsResult! -} -``` -```javascript Request -input NFTsRequest { - limit: Int - - cursor: Cursor - - # Filter by owner address - ownerAddress: EthereumAddress! - - # Filter by contract address - contractAddress: ContractAddress - - # Chain Ids - chainIds: [ChainId!]! -} - -# ChainId custom scalar type -scalar ChainId - -# Ethereum address custom scalar type -scalar EthereumAddress - -# Contract address custom scalar type -scalar ContractAddress - -# Cursor custom scalar type -scalar Cursor -``` -```javascript Response -# Paginated nft results -type NFTsResult { - items: [NFT!]! - pageInfo: PaginatedResultInfo! -} - -# The nft type -type NFT { - # aka us CryptoKitties - contractName: String! - - # aka 0x057Ec652A4F150f7FF94f089A38008f49a0DF88e - contractAddress: ContractAddress! - - # aka RARI - symbol: String! - - # aka "13" - tokenId: String! - - # aka { address: 0x057Ec652A4F150f7FF94f089A38008f49a0DF88e, amount:"2" } - owners: [Owner!]! - - # aka "Beard Coffee" - name: String! - - # aka "Hey cutie! I m Beard Coffee. .... - description: String! - - # aka "https://api.criptokitt..." - contentURI: String! - - # aka "{ uri:"https://ipfs....", metaType:"image/png" }" - originalContent: NFTContent! - - # aka "1" - chainId: ChainId! - - # aka "CryptoKitties" - collectionName: String! - - # aka "ERC721" - ercType: String! -} - -# The nft type -type Owner { - # number of tokens owner - amount: Float! - - # aka 0x057Ec652A4F150f7FF94f089A38008f49a0DF88e - address: EthereumAddress! -} - -# The NFT content uri -type NFTContent { - # The token uri nft - uri: String! - - # The meta type content - metaType: String! -} - -# The paginated result info -type PaginatedResultInfo { - # Cursor to query the actual results - prev: Cursor - - # Cursor to query next results - next: Cursor - - # The total number of entities the pagination iterates over. e.g. For a query that requests all nfts with more than 10 likes, this field gives the total amount of nfts with more than 10 likes, not the total amount of nfts - totalCount: Int! -} - -# Cursor custom scalar type -scalar Cursor - -# ChainId custom scalar type -scalar ChainId -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -Now you see the base query let's look at how we can use different request parameters to request different NFTs for the user. - -## Get all NFTs a wallet address owns - -To do this just set the `ownerAddress` to the ethereum address you want to query for their NFTs. - -```javascript Example operation -query Nfts($request: NFTsRequest!) { - nfts(request: { - ownerAddress: "0x54be3a794282c030b15e43ae2bb182e14c409c5e", - limit: 10, - chainIds: [1] - }) { - items { - contractName - contractAddress - symbol - tokenId - owners { - amount - address - } - name - description - contentURI - originalContent { - uri - metaType - } - chainId - collectionName - ercType - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "nfts": { - "items": [ - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5742", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5741", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5740", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5739", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5738", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Origin Stories 1", - "contractAddress": "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - "symbol": "ORIGIN1", - "tokenId": "5737", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Origin Stories 1: Mad Clown, Sad Town", - "description": "Before she was a tough-as-nails lead member of the PUNKS crew, Courtney had humble beginnings. Okay, she was always tough as nails, but to follow her dreams she had to carve her own path. Coming from a small town, Courtney had to go it alone, overcome major fears and doubts, and finally take a major leap of faith to make it in… ORIGIN CITY.", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmRpVH1xubDpNJ5RUqjnhE9DLU99R44NtZqs1s59pH7qBB", - "originalContent": { - "uri": "ipfs://QmP7vzEULM45qZkYnTdejrDhprEM9xmCNHztaNgffEZvcm", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Origin Stories 1", - "ercType": "ERC721" - }, - { - "contractName": "Tubby Cats", - "contractAddress": "0xCa7cA7BcC765F77339bE2d648BA53ce9c8a262bD", - "symbol": "TUBBY", - "tokenId": "4193", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "Tubby Cats", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmWEsF23zM2C1afa6G9XwgBhqJsPH9CyQTDpToap1MD4Un", - "originalContent": { - "uri": "ipfs://QmXRJbXFUHPbHy6hLcVtrcUiEiWyPtXSGjgsH5RexMwMmd", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "Tubby Cats", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "6518", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/6518", - "originalContent": { - "uri": "ipfs://QmTL41cWQGXXVEfvy9YiRfmx9NmEoQoiQVtVoSeWrrVDwS", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "3Landers", - "contractAddress": "0xb4d06d46A8285F4EC79Fd294F78a881799d8cEd9", - "symbol": "3L", - "tokenId": "4766", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "3Landers", - "description": "3Landers is a collectible NFT project centered around community, adventure, and collaboration.", - "contentURI": "https://ipfs.io/ipfs/QmNWziXfkdZRTY6ZQHkHGUe8smUCNGPT4umrpQ8KVjqNDB/", - "originalContent": { - "uri": "https://ipfs.io/ipfs/Qmb2t58xgmTFaZUxgPV1tfBkD1zP4avYf55RKevdCAHGSH/", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "3Landers", - "ercType": "ERC721" - }, - { - "contractName": "3Landers", - "contractAddress": "0xb4d06d46A8285F4EC79Fd294F78a881799d8cEd9", - "symbol": "3L", - "tokenId": "4765", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "3Landers", - "description": "3Landers is a collectible NFT project centered around community, adventure, and collaboration.", - "contentURI": "https://ipfs.io/ipfs/QmNWziXfkdZRTY6ZQHkHGUe8smUCNGPT4umrpQ8KVjqNDB/", - "originalContent": { - "uri": "https://ipfs.io/ipfs/Qmb2t58xgmTFaZUxgPV1tfBkD1zP4avYf55RKevdCAHGSH/", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "3Landers", - "ercType": "ERC721" - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":10}", - "totalCount": 4023 - } - } - } -} -``` - - - -## Get NFTs of a collection a wallet address owns - -To do this just set the `ownerAddress` to the ethereum address you want to query for their NFTs and set the `contractAddress` of the NFT you wish to filter it on. - -```javascript Example operation -query Nfts($request: NFTsRequest!) { - nfts(request: { - ownerAddress: "0x54be3a794282c030b15e43ae2bb182e14c409c5e", - contractAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - limit: 10, - chainIds: [1] - }) { - items { - contractName - contractAddress - symbol - tokenId - owners { - amount - address - } - name - description - contentURI - originalContent { - uri - metaType - } - chainId - collectionName - ercType - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "nfts": { - "items": [ - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "6518", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/6518", - "originalContent": { - "uri": "ipfs://QmTL41cWQGXXVEfvy9YiRfmx9NmEoQoiQVtVoSeWrrVDwS", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "2368", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/2368", - "originalContent": { - "uri": "ipfs://QmbViGww8GWBHc1RnM4RgSCKavU1Ukh87X4dYFG9zhD9cY", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "5152", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/5152", - "originalContent": { - "uri": "ipfs://QmbTXzuujmgoAJAXTffnqybGVM6rxRsph3T2Hwi299X3h5", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "3531", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/3531", - "originalContent": { - "uri": "ipfs://QmNmhacgx7MZEtunTQTGZHYADREpQM4EJ3GmdkrbjwqTAJ", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "1044", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1044", - "originalContent": { - "uri": "ipfs://QmS3mcnRtjeUX7a1HAG5hMbPetQMjWSWhmD57AiPm4wPFo", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "188", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/188", - "originalContent": { - "uri": "ipfs://QmPnPEAdMUovvZTCPpyZJJhyGuVLq6YVyZj88tJbjqQiwn", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "1212", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1212", - "originalContent": { - "uri": "ipfs://QmNRKUobxikfymw5386TRysoFyNUJpr4D4EatoTiiJftJc", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "809", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/809", - "originalContent": { - "uri": "ipfs://QmV7G7p1sxv8Udzouo8qacBVMmPEWrMMb5JVsSRZSRyzkp", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "6865", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/6865", - "originalContent": { - "uri": "ipfs://QmU8ebqh7qL2WFBkoKAdAkNEzTEHuZfAcU5FMeJb3Nn3Jq", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - }, - { - "contractName": "BoredApeYachtClub", - "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", - "symbol": "BAYC", - "tokenId": "865", - "owners": [ - { - "amount": 1, - "address": "0x54BE3a794282C030b15E43aE2bB182E14c409C5e" - } - ], - "name": "BoredApeYachtClub", - "description": "", - "contentURI": "https://ipfs.moralis.io:2053/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/865", - "originalContent": { - "uri": "ipfs://QmQ2AJzdeXXBTBdxNaT4wHDXymekcGMZBrQaXd7gHKhUrp", - "metaType": "unknown" - }, - "chainId": 1, - "collectionName": "BoredApeYachtClub", - "ercType": "ERC721" - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":10}", - "totalCount": 109 - } - } - } -} -``` - - - -# - -# Using LensClient SDK - -Example use. - -```typescript -const result = await lensClient.nfts.fetch({ - chainIds: [80001], - ownerAddress: '0xa5653e88D9c352387deDdC79bcf99f0ada62e9c6', - limit: 10, -}), - -``` \ No newline at end of file diff --git a/documents/Lens API/nfts/nft-galleries.md b/documents/Lens API/nfts/nft-galleries.md deleted file mode 100644 index 2ebb480..0000000 --- a/documents/Lens API/nfts/nft-galleries.md +++ /dev/null @@ -1,318 +0,0 @@ ---- -title: "NFT Galleries" -slug: "nft-galleries" -hidden: false -createdAt: "2023-01-18T09:56:04.753Z" -updatedAt: "2023-03-14T12:53:30.677Z" ---- -# NFT Galleries - -This new Lens API feature allows profiles to own curated NFT galleries. This is all off-chain, and helps you showcase your favorite NFTs to other Lens users. - -## Get a user's NFT galleries - -This endpoint is public and does not require any authentication - -```graphql Example query -query GetUserGalleries { - nftGalleries(request: { - profileId: "0x01" - }) { - id - name - profileId - items { - contractName - contractAddress - symbol - tokenId - owners { - address - amount - } - name - description - originalContent { - uri - metaType - animatedUrl - } - chainId - collectionName - ercType - } - } -} -``` -```json Example response -{ - items: [ - { - id: "some uuid", - name: "my favorite NFTs", - profileId: "0x01", - items: [ - { - contractName: "NFT Collection contract", - contractAddress: "0x1234123412341234123412341234123412341234", - symbol: "FUN", - tokenId: "1", - owners: [{ - address: "0x0101010101010101010101010101010101010101", - amount: 1 - }], - name: "FUN NFTs #1", - description: "A collection of fun NFTs", - contentURI: "http://example.com/image.png", - originalContent: { - uri: "http://example.com/image.png", - metaType: "image/png", - animatedUrl: null - }, - chainId: "137", - collectionName: "FUN NFTs", - ercType: "ERC721" - } - ], - createdAt: "2023-01-01T00:00:00", - updatedAt: "2023-01-01T00:00:00", - } - ] -} -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.fetchGalleries({ - profileId: '0x0185', -}); -``` - - - -## Create a new NFT Gallery - -This endpoint creates a new NFT gallery for a given profile, with its name and contents. -NFTs are uniquely identified with a combination of `contractAddress`, `tokenId` and `chainId`. These are the minimum information required to fetch and populate the NFT information. You can find items by using the `nfts` query [here](doc:get-users-nfts). This mutation returns the `NftGalleryId` scalar upon completion. - -_Note_: NFT Gallery creation will fail if you try to add NFTs you do not own. - -```graphql Example query -mutation CreateNFTGallery { - createNftGallery(request: { - profileId: "0x01", - name: "my favorite NFTs", - items: [ - { - contractAddress: "0x1234123412341234123412341234123412341234" - tokenId: "1", - chainId: 137 - } - ] - }) -} -``` -```json Example response -{ - id: "some uuid", - name: "my favorite NFTs", - profileId: "0x01", - items: [ - { - contractName: "NFT Collection contract", - contractAddress: "0x1234123412341234123412341234123412341234", - symbol: "FUN", - tokenId: "1", - owners: [{ - address: "0x0101010101010101010101010101010101010101", - amount: 1 - }], - name: "FUN NFTs #1", - description: "A collection of fun NFTs", - contentURI: "http://example.com/image.png", - originalContent: { - uri: "http://example.com/image.png", - metaType: "image/png", - animatedUrl: null - }, - chainId: "137", - collectionName: "FUN NFTs", - ercType: "ERC721" - } - ], - createdAt: "2023-01-01T00:00:00", - updatedAt: "2023-01-01T00:00:00", -} -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.createGallery({ - profileId: "0x01", - name: "my favorite NFTs", - items: [ - { - contractAddress: "0x1234123412341234123412341234123412341234" - tokenId: "1", - chainId: 137 - } - ] -}); -``` - - - -## Update NFT gallery name - -Only the owning profile can change an NFT Gallery name - -```graphql Example mutation -mutation UpdateNFTGalleryInfo { - updateNftGalleryInfo(request: { - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - name: "new name" - }) -} - -``` -```graphql Example response -// returns null -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.updateGalleryInfo({ - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - name: "new name" -}); -``` - - - -## Update NFT Gallery items - -Owning profiles can add and/or remove items to an NFT gallery using the following mutation. All added items will be added to the end of the gallery content list. - -```graphql Example mutation -mutation UpdateNFTGalleryItems { - updateNftGalleryItems(request: { - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - toAdd: [{ - contractAddress: "0x1234123412341234123412341234123412341234" - tokenId: "1", - chainId: 137 - }], - toRemove: [{ - contractAddress: "0x0001000100010001000100010001000100010001" - tokenId: "2", - chainId: 137 - }] - }) -} -``` -```graphql Example response -// returns null -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.updateGalleryItems({ - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - toAdd: [{ - contractAddress: "0x1234123412341234123412341234123412341234" - tokenId: "1", - chainId: 137 - }], - toRemove: [{ - contractAddress: "0x0001000100010001000100010001000100010001" - tokenId: "2", - chainId: 137 - }] -}); -``` - - - -## Update NFT gallery item order - -You can also rearrange the order of NFT gallery contents in any frontend by using the following endpoint. It supports single or multiple updates in every call. Every update places the given NFT at the `newOrder` position by shifting items before and after it accordingly. - -```graphql Example mutation -mutation UpdateNFTGalleryOrder { - updateNftGalleryOrder(request: { - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - updates: [{ - contractAddress: "0x1234123412341234123412341234123412341234", - tokenId: "1", - chainId: 137, - newOrder: 1 - }] - }) -} -``` -```graphql Example response -// returns null -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.updateGalleryOrder({ - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148", - updates: [{ - contractAddress: "0x1234123412341234123412341234123412341234", - tokenId: "1", - chainId: 137, - newOrder: 1 - }] -}); -``` - - - -## Delete a gallery - -Deletes the given gallery from your profile - -```graphql Example mutation -mutation DeleteNFTGallery { - deleteNftGallery(request: { - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148" - }) -} -``` -```graphql Example response -// returns null -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.nfts.deleteGallery({ - profileId: "0x01", - galleryId: "9aeb66b2-0d8f-4c33-951c-feedbb171148" -}); -``` \ No newline at end of file diff --git a/documents/Lens API/nfts/nft-ownership-challenge.md b/documents/Lens API/nfts/nft-ownership-challenge.md deleted file mode 100644 index be4e3ad..0000000 --- a/documents/Lens API/nfts/nft-ownership-challenge.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: "NFT ownership challenge" -slug: "nft-ownership-challenge" -hidden: false -createdAt: "2022-02-18T11:26:13.921Z" -updatedAt: "2023-03-14T12:44:14.500Z" ---- -> 📘 Full code example -> -> This is an example of it hooked into the profile image -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -This endpoint allows you to sign some text to prove you own an NFT. This is then used in setting your profile picture to an NFT image which then gets brought back on the `Profile` entity. - -This endpoint goes hand in hand with [Set profile image URI](doc:set-profile-image-uri). - -# API details - -Note: the challenge will last 20 minutes if it expires you will need to generate a new challenge. - -> 🚧 Note when using this for Set profile image URI.. -> -> As this is a generic API challenge for NFTs to make sure people do not get confused if you are using this to set a user's profile picture to the NFT then you must only pass in one NFT in the array. If you pass in more than one when you come to calling `createSetProfileImageURITypedData` it will throw. - -```javascript Example operation -query NftOwnershipChallenge { - nftOwnershipChallenge(request: { - ethereumAddress: "0xdfd7D26fd33473F475b57556118F8251464a24eb", - nfts: [ - { - contractAddress: "0x54439D4908A3E19356F876aa6022D67d0b3B12d6", - tokenId: "5742", - chainId: 1 - } - ] - }) { - id - text - } -} -``` -```javascript Example response -{ - "data": { - "nftOwnershipChallenge": { - "id": "46393b78-4bfa-4830-8f5f-badca8b06e42", - "text": "I approve i own these nfts. Nft ownership request id - 46393b78-4bfa-4830-8f5f-badca8b06e42" - } - } -} -``` -```javascript Query interface -type Query { - nftOwnershipChallenge( - request: NftOwnershipChallengeRequest! - ): NftOwnershipChallengeResult! -} -``` -```javascript Request -input NftOwnershipChallengeRequest { - # ContractAddress for nft - ethereumAddress: EthereumAddress! - nfts: [NftOwnershipChallenge!]! -} - -input NftOwnershipChallenge { - # ContractAddress for nft - contractAddress: ContractAddress! - - # Token id for NFT - tokenId: String! - - # Chain Id - chainId: ChainId! -} - -# Ethereum address custom scalar type -scalar EthereumAddress - -# Contract address custom scalar type -scalar ContractAddress - -# ChainId custom scalar type -scalar ChainId -``` -```javascript Response -# NFT ownership challenge result -type NftOwnershipChallengeResult { - # Id of the nft ownership challenge - id: NftOwnershipId! - text: String! -} - -# Nft ownership id type -scalar NftOwnershipId -``` - - - -## Request - -let's dig into the request a little more so its clear what is going on here - -### ethereumAddress - required - -The wallet address which owns the NFTs. - -Even though this is an authenticated endpoint you could own this NFT on a different wallet and want to sign it through your ledger etc. - -### nfts - required - -You can pass in an array of NFTs to verify ownership, but for now, the API does not allow you to just prove generic ownership to flex. The API only support setting your profile picture with your NFTs. A generic way of just proving ownership to flex NFT will be coming to the API soon. So for now most people will only be passing in 1 item here but the request was written to handle the other cases without a schema change. This endpoint was written to be used in a few places once we extend. - -#### contractAddress - required - -The contract address of the NFT you want to prove ownership of. - -#### tokenId - required - -The tokenId you own of this NFT. - -#### chainId - required - -The chain id it is on. - -- If you are using testnet this endpoint will only allow you to pass in chainId `ethereum kovan (chainId: 42)` or `polygon Mumbai (chainId: 80001)` -- If you are using mainnet this endpoint will only allow you to pass in `ethereum mainnet (chainId: 1)` or `polygon mainnet (chainId: 137)` - - - -# - -# Using LensClient SDK - -Example use. - -```typescript -const result = await lensClient.nfts.ownershipChallenge({ - ethereumAddress: '0xa5653e88D9c352387deDdC79bcf99f0ada62e9c6', - nfts: [ - { - tokenId: '411', - contractAddress: '0x7582177F9E536aB0b6c721e11f383C326F2Ad1D5', - chainId: 80001, - }, - ], -}); - -``` \ No newline at end of file diff --git a/documents/Lens API/notifications.md b/documents/Lens API/notifications.md deleted file mode 100644 index 7066dcd..0000000 --- a/documents/Lens API/notifications.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Notification" -slug: "notifications" -hidden: false -createdAt: "2022-02-17T17:58:52.156Z" -updatedAt: "2022-03-09T15:02:20.536Z" ---- -With any social platform, notifications are super important. Our API returns notifications on activity for your profile including collects, comment, new followers, and mirrors. - -Our notification resolver has these queries: - -- [Users notifications](doc:users-notifications) \ No newline at end of file diff --git a/documents/Lens API/notifications/users-notifications.md b/documents/Lens API/notifications/users-notifications.md deleted file mode 100644 index 1a7974e..0000000 --- a/documents/Lens API/notifications/users-notifications.md +++ /dev/null @@ -1,849 +0,0 @@ ---- -title: "Users notifications" -slug: "users-notifications" -hidden: false -createdAt: "2022-02-18T11:29:40.844Z" -updatedAt: "2023-04-11T17:54:17.809Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Get notifications of actions occurring on Lens Protocol. - -The notifications bring back: - -- mirrored posts on your publication (post/comments) -- mirrored comments on your publication (post/comments) -- comments on your publication (post/comments) -- collects on your publications (post/comments) -- new followers -- mentions on publications (post/comment/mirrors) -- reactions on publications (post/comment/mirrors) - -# API details - -Notifications can be spammy if you do not have control of them. For this sake, we default the filter, which is called `highSignalFilter` on which will only bring back likes, mirrors, collects, follows, and comments if you follow these users or they are on the curated list. Mentions will always come back. You can turn this off by passing in false on the`highSignalFilter` notification object. - -You can also filter by the exact notification type this can be passed into`notificationTypes` request object to only bring back the notifications you care about. If you do not supply it, it brings them all back for you. - -```typescript notification type filters -export enum NotificationTypes { - MIRRORED_POST = 'MIRRORED_POST', - MIRRORED_COMMENT = 'MIRRORED_COMMENT', - MENTION_POST = 'MENTION_POST', - MENTION_COMMENT = 'MENTION_COMMENT', - COMMENTED_COMMENT = 'COMMENTED_COMMENT', - COMMENTED_POST = 'COMMENTED_POST', - COLLECTED_POST = 'COLLECTED_POST', - COLLECTED_COMMENT = 'COLLECTED_COMMENT', - FOLLOWED = 'FOLLOWED', - REACTION_POST = 'REACTION_POST', - REACTION_COMMENT = 'REACTION_COMMENT', -} - -``` - - - -```javascript Example operation -query Notifications { - result: notifications(request: { profileId: "0x0f", limit: 10 }) { - items { - ... on NewFollowerNotification { - notificationId - ...NewFollowerNotificationFields - } - - ... on NewMirrorNotification { - notificationId - ...NewMirrorNotificationFields - } - - ... on NewCollectNotification { - notificationId - ...NewCollectNotificationFields - } - - ... on NewCommentNotification { - notificationId - ...NewCommentNotificationFields - } - - ... on NewMentionNotification { - notificationId - ...NewMentionNotificationFields - } - ... on NewReactionNotification { - notificationId - ...NewReactionNotificationFields - } - } - pageInfo { - ...CommonPaginatedResultInfo - } - } -} - -fragment CommentWithCommentedPublicationFields on Comment { - ...CompactComment - commentOn { - ... on Post { - ...CompactPost - } - ... on Mirror { - ...CompactMirror - } - ... on Comment { - ...CompactComment - } - } -} - -fragment NewFollowerNotificationFields on NewFollowerNotification { - __typename - createdAt - isFollowedByMe - wallet { - ...Wallet - } -} - -fragment NewCollectNotificationFields on NewCollectNotification { - __typename - createdAt - wallet { - ...Wallet - } - collectedPublication { - __typename - ... on Post { - ...CompactPost - } - - ... on Mirror { - ...CompactMirror - } - - ... on Comment { - ...CompactComment - } - } -} - -fragment NewMirrorNotificationFields on NewMirrorNotification { - __typename - createdAt - profile { - ...CompactProfile - } - publication { - ... on Post { - ...CompactPost - } - ... on Comment { - ...CompactComment - } - } -} - -fragment NewCommentNotificationFields on NewCommentNotification { - __typename - createdAt - profile { - ...CompactProfile - } - comment { - ...CommentWithCommentedPublicationFields - } -} - -fragment NewMentionNotificationFields on NewMentionNotification { - __typename - mentionPublication { - ... on Post { - ...CompactPost - } - ... on Comment { - ...CompactComment - } - } - createdAt -} - -fragment NewReactionNotificationFields on NewReactionNotification { - __typename - createdAt - profile { - ...CompactProfile - } - reaction - publication { - ... on Post { - ...CompactPost - } - ... on Mirror { - ...CompactMirror - } - ... on Comment { - ...CompactComment - } - } -} - -fragment CompactPublicationStats on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment CompactMetadata on MetadataOutput { - name - description - content - media { - ...ProfileMediaFields - } -} - -fragment CompactPost on Post { - id - stats { - ...CompactPublicationStats - } - metadata { - ...CompactMetadata - } - profile { - ...CompactProfile - } - collectedBy { - ...Wallet - } - createdAt -} - -fragment CompactMirror on Mirror { - id - stats { - ...CompactPublicationStats - } - metadata { - ...CompactMetadata - } - profile { - ...CompactProfile - } - createdAt -} - -fragment CompactComment on Comment { - id - stats { - ...CompactPublicationStats - } - metadata { - ...CompactMetadata - } - profile { - ...CompactProfile - } - collectedBy { - ...Wallet - } - createdAt -} - -fragment CommonPaginatedResultInfo on PaginatedResultInfo { - prev - next - totalCount -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - -fragment ProfileMediaFields on ProfileMedia { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - - ... on MediaSet { - original { - ...MediaFields - } - - small { - ...MediaFields - } - - medium { - ...MediaFields - } - } -} - -fragment Wallet on Wallet { - address - defaultProfile { - ...CompactProfile - } -} - -fragment CompactProfile on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } -} -``` -```javascript Example response -{ - "data": { - "result": { - "items": [ - { - "__typename": "NewCommentNotification", - "createdAt": "2022-04-20T21:33:08.000Z", - "profile": { - "id": "0x02aa", - "name": null, - "handle": "fommes", - "picture": { - "original": { - "url": "https://ik.imagekit.io/lensterimg/https://ipfs.infura.io/ipfs/QmVrUurkhodoPexGzQT1bayx2Fz9mxsKJyqVNsXwcBMzdY", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "comment": { - "id": "0x02aa-0x0d", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 1 - }, - "metadata": { - "name": "Comment by @fommes", - "description": "upvote is missing! oh yeah and downvote would be cool, no social has that afaik", - "content": "upvote is missing! oh yeah and downvote would be cool, no social has that afaik", - "media": [] - }, - "profile": { - "id": "0x02aa", - "name": null, - "handle": "fommes", - "picture": { - "original": { - "url": "https://ik.imagekit.io/lensterimg/https://ipfs.infura.io/ipfs/QmVrUurkhodoPexGzQT1bayx2Fz9mxsKJyqVNsXwcBMzdY", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T21:33:08.000Z", - "commentOn": { - "id": "0x0f-0xa2", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 2 - }, - "metadata": { - "name": "Comment by @yoginth", - "description": "how about #lensterdev and #lenster-fam", - "content": "how about #lensterdev and #lenster-fam", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T07:20:47.000Z" - } - } - }, - { - "__typename": "NewCollectNotification", - "createdAt": "2022-04-20T17:17:26.000Z", - "wallet": { - "address": "0x067F2Bef6A1f929544253B9fb95F99BaE77B2518", - "defaultProfile": null - }, - "collectedPublication": { - "__typename": "Post", - "id": "0x0f-0x97", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 3, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "Post by @yoginth", - "description": "gm lens 🌿 and lenster 🌸", - "content": "gm lens 🌿 and lenster 🌸", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": { - "address": "0x067F2Bef6A1f929544253B9fb95F99BaE77B2518", - "defaultProfile": null - }, - "createdAt": "2022-04-18T03:35:01.000Z" - } - }, - { - "__typename": "NewCollectNotification", - "createdAt": "2022-04-20T17:17:06.000Z", - "wallet": { - "address": "0x067F2Bef6A1f929544253B9fb95F99BaE77B2518", - "defaultProfile": null - }, - "collectedPublication": { - "__typename": "Post", - "id": "0x0f-0x97", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 3, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "Post by @yoginth", - "description": "gm lens 🌿 and lenster 🌸", - "content": "gm lens 🌿 and lenster 🌸", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": { - "address": "0x067F2Bef6A1f929544253B9fb95F99BaE77B2518", - "defaultProfile": null - }, - "createdAt": "2022-04-18T03:35:01.000Z" - } - }, - { - "__typename": "NewFollowerNotification", - "createdAt": "2022-04-20T17:16:11.000Z", - "isFollowedByMe": false, - "wallet": { - "address": "0x067F2Bef6A1f929544253B9fb95F99BaE77B2518", - "defaultProfile": null - } - }, - { - "__typename": "NewCommentNotification", - "createdAt": "2022-04-20T16:52:13.000Z", - "profile": { - "id": "0x050f", - "name": null, - "handle": "khatia", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmNjaGcxcxVvHV78NANLqgaHKtEgKD8my9He9MoEFuBNbo", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "comment": { - "id": "0x050f-0x02", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "Comment by @khatia", - "description": "gm", - "content": "gm", - "media": [] - }, - "profile": { - "id": "0x050f", - "name": null, - "handle": "khatia", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmNjaGcxcxVvHV78NANLqgaHKtEgKD8my9He9MoEFuBNbo", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T16:52:13.000Z", - "commentOn": { - "id": "0x0f-0xa2", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 2 - }, - "metadata": { - "name": "Comment by @yoginth", - "description": "how about #lensterdev and #lenster-fam", - "content": "how about #lensterdev and #lenster-fam", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T07:20:47.000Z" - } - } - }, - { - "__typename": "NewFollowerNotification", - "createdAt": "2022-04-20T16:37:41.000Z", - "isFollowedByMe": false, - "wallet": { - "address": "0xA1F36EB2f8bAAA3d700bB0708E6c2B0741bED6fA", - "defaultProfile": null - } - }, - { - "__typename": "NewCommentNotification", - "createdAt": "2022-04-20T12:34:00.000Z", - "profile": { - "id": "0x73", - "name": null, - "handle": "jensei", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmWwgPpqtGE9VEHba26ahNqaY9wi8KxQfce1E78zLufuHX", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "comment": { - "id": "0x73-0x08", - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "Comment by @jensei", - "description": "!gm", - "content": "!gm", - "media": [] - }, - "profile": { - "id": "0x73", - "name": null, - "handle": "jensei", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmWwgPpqtGE9VEHba26ahNqaY9wi8KxQfce1E78zLufuHX", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T12:34:00.000Z", - "commentOn": { - "id": "0x0f-0x9c", - "stats": { - "totalAmountOfMirrors": 2, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 6 - }, - "metadata": { - "name": "Post by @yoginth", - "description": "#gm #gm lens fam 🌿", - "content": "#gm #gm lens fam 🌿", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-18T07:45:57.000Z" - } - } - }, - { - "__typename": "NewMirrorNotification", - "createdAt": "2022-04-20T06:26:56.000Z", - "profile": { - "id": "0x056e", - "name": null, - "handle": "handl3", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmYfsQjEfR7JGqbCRgZ1SkEANTY8wcUcccTTQt6jxm5q23", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "publication": { - "id": "0x0f-0xa0", - "stats": { - "totalAmountOfMirrors": 1, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 6 - }, - "metadata": { - "name": "Post by @yoginth", - "description": "Testing hashflags\n\n#lenster #Lenster #LENSTER #lens #ethereum #Bitcoin", - "content": "Testing hashflags\n\n#lenster #Lenster #LENSTER #lens #ethereum #Bitcoin", - "media": [] - }, - "profile": { - "id": "0x0f", - "name": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - }, - "collectedBy": null, - "createdAt": "2022-04-20T06:26:56.000Z" - } - }, - { - "__typename": "NewFollowerNotification", - "createdAt": "2022-04-19T17:58:35.000Z", - "isFollowedByMe": false, - "wallet": { - "address": "0x6ea7c12CbB8480236716d1EEB0B31C2950166F3B", - "defaultProfile": null - } - }, - { - "__typename": "NewFollowerNotification", - "createdAt": "2022-04-19T17:55:05.000Z", - "isFollowedByMe": false, - "wallet": { - "address": "0x0bCcE7961ecd2a667fEc4DE78a6b7407b28eFc1e", - "defaultProfile": { - "id": "0x0166", - "name": null, - "handle": "elonmux", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/elonmux.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - } - } - } - } - ], - "pageInfo": { - "prev": "{\"timestamp\":1650490388,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"timestamp\":1650390905,\"cursorDirection\":\"AFTER\"}", - "totalCount": 456 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API. This is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass the previous and next cursor in the request cursor property. - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.notifications.fetch({ - profileId: '0x0185', - limit: 10, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles.md b/documents/Lens API/profiles.md deleted file mode 100644 index 9480565..0000000 --- a/documents/Lens API/profiles.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Profile" -slug: "profiles" -excerpt: "This will show the queries exposed to get anything related to profiles back from the public API" -hidden: false -createdAt: "2022-02-17T11:36:58.036Z" -updatedAt: "2022-06-20T10:58:17.461Z" ---- -Profiles are the accounts that create publications and are owned by wallets. You can read more in-depth about what profiles are [here](doc:profile). - -Our profile resolver have these queries: - -- [Create profile](doc:create-profile) NOTE: Testnet Only -- [Get default profile](doc:get-default-profile) -- [Get profiles](doc:get-profiles) -- [Get profile](doc:get-profile) -- [Recommended profiles](doc:recommended-profiles) -- [Create set update profile metadata typed data](doc:create-set-update-profile-metadata-typed-data) -- [Create set profile image URI typed data](doc:create-set-profile-image-uri-typed-data) -- [Create burn profile typed data](doc:create-burn-profile-typed-data) -- [Create set default profile typed data](doc:create-set-default-profile-typed-data) \ No newline at end of file diff --git a/documents/Lens API/profiles/app-comment-total-1.md b/documents/Lens API/profiles/app-comment-total-1.md deleted file mode 100644 index 13f1b7e..0000000 --- a/documents/Lens API/profiles/app-comment-total-1.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "App profile stats total" -slug: "app-comment-total-1" -hidden: false -createdAt: "2022-09-26T15:22:25.817Z" -updatedAt: "2023-04-27T23:15:01.665Z" ---- -As you attach an appId to the publications you post the number of publications you did on profile Y on app Z can be different from app H numbers, this allows you to query by sources to get the correct stats if you're building an app that only cares about the content of the app. - -# API design - -```javascript Example operation -query Profile { - profile(request: { profileId: "0x18" }) { - stats { - publicationsTotal(forSources: ["your_app_id"]) - postsTotal(forSources: ["your_app_id"]) - mirrorsTotal(forSources: ["your_app_id"]) - commentsTotal(forSources: ["your_app_id"]) - totalPublications - totalPosts - totalMirrors - totalComments - } - } -} -``` -```javascript Example response -{ - "data": { - "profile": { - "stats": { - "publicationsTotal": 0, - "postsTotal": 0, - "mirrorsTotal": 0, - "commentsTotal": 0, - "totalPublications": 91, - "totalPosts": 52, - "totalMirrors": 11, - "totalComments": 28 - } - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const profileById = await lensClient.profile.stats( - { - handle: "pukkynext.test", - }, - ["your_app_id"] // array of sources -> appIds you want the stats to be calculated for -); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/create-burn-profile-typed-data.md b/documents/Lens API/profiles/create-burn-profile-typed-data.md deleted file mode 100644 index 9f8fbf2..0000000 --- a/documents/Lens API/profiles/create-burn-profile-typed-data.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: "Delete profile" -slug: "create-burn-profile-typed-data" -excerpt: "This please you are burning your profile, all your content still lives on." -hidden: false -createdAt: "2022-04-21T13:47:30.230Z" -updatedAt: "2023-03-15T18:13:55.413Z" ---- -> 📘 Full code example -> -> - -This API call allows you to get the typed data to then call the `withSig` method to burn your lens profile. This please you are burning your profile, all your content still lives on.This request is protected by authentication - -> 🚧 hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API, the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always-failing transaction, the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```javascript Example operation -mutation CreateBurnProfileTypedData { - createBurnProfileTypedData(request: { profileId: "0x01"}) { - id - expiresAt - typedData { - domain { - name - chainId - version - verifyingContract - } - types { - BurnWithSig { - name - type - } - } - value { - nonce - deadline - tokenId - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createBurnProfileTypedData": { - "id": "ced2635e-2d5f-43b6-bb90-a45289be763d", - "expiresAt": "2022-04-21T14:05:16.000Z", - "typedData": { - "domain": { - "name": "Lens Protocol Profiles", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x4BF0c7AD32Fd2d32089790a54485e23f5C7736C0" - }, - "types": { - "BurnWithSig": [ - { - "name": "tokenId", - "type": "uint256" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "value": { - "nonce": 26, - "deadline": 1650549916, - "tokenId": "0x01" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createBurnProfileTypedData( - options: TypedDataOptions - request: BurnProfileRequest! - ): CreateBurnProfileBroadcastItemResult! -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -```typescript -const burnProfileTypedDataResult = await lensClient.profile.createBurnProfileTypedData({ - profileId, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/create-profile.md b/documents/Lens API/profiles/create-profile.md deleted file mode 100644 index d3af1ca..0000000 --- a/documents/Lens API/profiles/create-profile.md +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: "Create profile" -slug: "create-profile" -hidden: false -createdAt: "2022-02-17T11:38:47.107Z" -updatedAt: "2023-05-13T05:44:54.092Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Creating a profile on `MAINNET` is only allowed by trusted whitelisted addresses for now. This endpoint can be used on `TESTNET` to allow you to create profiles easily through your UI without worrying about the gas. This will only be exposed on the `TESTNET` public API. This is great for when you building some cool stuff against the `TESTNET` contracts. - -# API Design - -```javascript Example operation -mutation CreateProfile { - createProfile(request: { - handle: "devjoshstevens", - profilePictureUri: null, - followNFTURI: null, - followModule: null - }) { - ... on RelayerResult { - txHash - } - ... on RelayError { - reason - } - __typename - } -} -``` -```javascript Example response -{ - "data": { - "txHash": "0xd771b9b8fd558eda20598e8a464cc9cc9e28f4bd75e823d30ee276dd590cd67e" - } -} -``` -```javascript Query interface -type Mutation { - createProfile(request: CreateProfileRequest!): RelayResult! -} -``` -```javascript Request -input CreateProfileRequest { - handle: Handle! - - # The profile picture uri - profilePictureUri: Url - - # The follow module - followModule: FollowModuleParams - - # The follow NFT URI is the NFT metadata your followers will mint when they follow you. This can be updated at all times. If you do not pass in anything it will create a super cool changing NFT which will show the last publication of your profile as the NFT which looks awesome! This means people do not have to worry about writing this logic but still have the ability to customise it for their followers - followNFTURI: Url -} - -input FollowModuleParams { - # The follower fee follower module - feeFollowModule: FeeFollowModuleParams - - # The empty follow module - emptyFollowModule: Boolean -} - -input FeeFollowModuleParams { - # The follow module amount info - amount: ModuleFeeAmountParams! - - # The follow module recipient address - recipient: EthereumAddress! -} -``` -```javascript Response -union RelayResult = RelayerResult | RelayError - -# The relayer result -type RelayerResult { - # The tx hash - txHash: TxHash! -} - -type RelayError { - reason: RelayErrorReasons! -} - -# Relay error reason -enum RelayErrorReasons { - REJECTED - HANDLE_TAKEN - EXPIRED - WRONG_WALLET_SIGNED -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### Handle - required - -You must define the handle you wish to have for the profile which will be created. This is mandatory. - -### profilePictureUri - -You can pass in a `profilePictureUri` which is a link to any kind of storage that points to an image. You can leave this out the request if you do not want to supply a default image for the profile. - -### followNFTURI - -The follow NFT URI is the NFT metadata your followers will mint when they follow you. This can be updated at all times. If you do not pass in anything it will default to a dynamic NFT which will show the last publication of your profile as the NFT image. - -We do not enforce our standards on this metadata as it is purely to be showed on secondary marketplaces. We advise you follow opensea metadata spec for this - -### followModule - -Defining the follow module is very easy with the schema we have created: - -#### Free follow module - -As the example above shows, you can leave this as null or not pass it in; if you do that it will point to the free follow module which basically means no modules are fired when someone follows you (free). We promote not passing it in the request if you do not want to set a follow module. - -This can also be defined explicitly in the request by doing: - -```js -mutation CreateProfile { - createProfile(request:{ - handle: "devjoshstevens", - profilePictureUri: null, - followModule: { - freeFollowModule: true - } - }) { - ... on RelayerResult { - txHash - } - ... on RelayError { - reason - } - __typename - } -} -``` - - - -#### Revert follow module - -You do not want anyone to follow you; to set this up you can do: - -```js -mutation CreateProfile { - createProfile(request:{ - handle: "devjoshstevens", - profilePictureUri: null, - followModule: { - revertFollowModule: true - } - }) { - ... on RelayerResult { - txHash - } - ... on RelayError { - reason - } - __typename - } -} -``` - - - -#### Fee follow module - -You can charge a fee when someone follows you, to set this up when you create a profile you can do: - -```js -mutation CreateProfile { - createProfile(request:{ - handle: "devjoshstevens", - profilePictureUri: null, - followModule: { - feeFollowModule: { - amount: { - currency: "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - value: "0.01" - }, - recipient: "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - } - } - }) { - ... on RelayerResult { - txHash - } - ... on RelayError { - reason - } - __typename - } -} -``` - - - -As you see above we have mapped the `currency` we want to be paid in alongside the `value` which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. The final property defined is the `recipient` you want the funds to go to. - -You can update the follow module for your profile at any time, the resolver endpoints to generate the typed data for them are explained on the [Create set follow module typed data](doc:create-set-follow-module-typed-data) - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. - -When calling the `createProfile()` function, the contract will add the `.test` or `.lens` extension to your handle. The best way to check all the profiles you have created is to send a `getProfiles()` request filtered with `ownedBy` and your account address as the value. - - - -# - -# Using LensClient SDK - -You can use LensClient SDK to create a new profile. - -```typescript -import { isRelayerResult } from "@lens-protocol/client"; - -// lensClient is an authenticated instance of LensClient - -const profileCreateResult = await lensClient.profile.create({ - handle: 'profilehandle', - // other request args -}); - -// profileCreateResult is a Result object -const profileCreateResultValue = profileCreateResult.unwrap(); - -if (!isRelayerResult(profileCreateResultValue)) { - console.log(`Something went wrong`, profileCreateResultValue); - return; -} - -console.log( - `Transaction was successfuly broadcasted with txId ${profileCreateResultValue.txId}` -); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/create-set-default-profile-typed-data.md b/documents/Lens API/profiles/create-set-default-profile-typed-data.md deleted file mode 100644 index 0ce6451..0000000 --- a/documents/Lens API/profiles/create-set-default-profile-typed-data.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: "Set default profile" -slug: "create-set-default-profile-typed-data" -hidden: false -createdAt: "2022-04-21T14:33:17.153Z" -updatedAt: "2023-03-15T18:15:55.175Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to set your default lens profile. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API, the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always-failing transaction, the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```javascript Example operation -mutation CreateSetDefaultProfileTypedData { - createSetDefaultProfileTypedData(request: { profileId: "0x01"}) { - id - expiresAt - typedData { - types { - SetDefaultProfileWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - wallet - profileId - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetDefaultProfileTypedData": { - "id": "7a83b5df-777c-469c-be31-53a59c9a61a8", - "expiresAt": "2022-04-21T14:50:21.000Z", - "typedData": { - "types": { - "SetDefaultProfileWithSig": [ - { - "name": "wallet", - "type": "address" - }, - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profiles", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x4BF0c7AD32Fd2d32089790a54485e23f5C7736C0" - }, - "value": { - "nonce": 26, - "deadline": 1650552621, - "wallet": "0xD8c789626CDb461ec9347f26DDbA98F9383aa457", - "profileId": "0x01" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createSetDefaultProfileTypedData( - request: CreateSetDefaultProfileRequest! - ): SetDefaultProfileBroadcastItemResult! -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -```typescript -// lensClient is authenticated - -const typedDataResult = await lensClient.profile.createSetDefaultProfileTypedData({ - profileId: "0x0635", // must be a profile that authenticated address owns -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/create-set-profile-image-uri-typed-data.md b/documents/Lens API/profiles/create-set-profile-image-uri-typed-data.md deleted file mode 100644 index 6f172d4..0000000 --- a/documents/Lens API/profiles/create-set-profile-image-uri-typed-data.md +++ /dev/null @@ -1,395 +0,0 @@ ---- -title: "Set profile image" -slug: "create-set-profile-image-uri-typed-data" -hidden: false -createdAt: "2022-02-17T11:39:58.683Z" -updatedAt: "2023-03-15T18:12:35.115Z" ---- -This API call allows you to get the typed data to then call the `withSig` method to set your profile picture for your profile on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API, the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always-failing transaction, the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -You can attach a normal link in the `uri`, this can be any image location you wish, our example shows the IPFS link. You can also attach the NFT data to link your profile NFT and prove ownership which you would have done using these docs [NFT ownership challenge](doc:nft-ownership-challenge). - -```javascript Example operation -mutation CreateSetProfileImageURITypedData { - createSetProfileImageURITypedData(request: { - profileId: "0x03", - url: "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP" - }) { - id - expiresAt - typedData { - types { - SetProfileImageURIWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - imageURI - profileId - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetProfileImageURITypedData": { - "id": "745d18ea-73fa-432e-aa1f-72e143ea3c10", - "expiresAt": "2022-02-22T16:48:52.000Z", - "typedData": { - "types": { - "SetProfileImageURIWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "imageURI", - "type": "string" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645548532, - "imageURI": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "profileId": "0x03" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createSetProfileImageURITypedData( - request: UpdateProfileImageRequest! - ): CreateSetProfileImageUriBroadcastItemResult! -} -``` -```javascript Request -input UpdateProfileImageRequest { - profileId: ProfileId! - - # The url to the image if offline - url: Url - - # The nft data - NFTData: NFTData -} - -input NFTData { - # Id of the nft ownership challenge - id: NftOwnershipId! - - # Address owner - address: EthereumAddress! - - # The signature - signature: Signature! - - # The chain id - chainId: ChainId! - - # The contract address - contract: ContractAddress! - - # The token id - tokenId: String! -} - -# Contract address custom scalar type -scalar ContractAddress - -# Ethereum address custom scalar type -scalar EthereumAddress - -# ChainId custom scalar type -scalar ChainId - -scalar Signature - -# Nft ownership id type -scalar NftOwnershipId - -# Url scalar type -scalar Url - -# ProfileId custom scalar type -scalar ProfileId -``` -```javascript Response -The broadcast item -type CreateSetProfileImageUriBroadcastItemResult { - # This broadcast item ID - id: BroadcastId! - - # The date the broadcast item expiries - expiresAt: DateTime! - - # The typed data - typedData: CreateSetProfileImageUriEIP712TypedData! -} - -# The eip 712 typed data field -type EIP712TypedDataField { - # The name of the typed data field - name: String! - - # The type of the typed data field - type: String! -} - -# The eip 712 typed data domain -type EIP712TypedDataDomain { - # The name of the typed data domain - name: String! - - # The chainId - chainId: ChainId! - - # The version - version: String! - - # The verifying contract - verifyingContract: ContractAddress! -} - -# The set profile uri eip 712 typed data -type CreateSetProfileImageUriEIP712TypedData { - # The types - types: CreateSetProfileImageUriEIP712TypedDataTypes! - - # The typed data domain - domain: EIP712TypedDataDomain! - - # The values - value: CreateSetProfileImageUriEIP712TypedDataValue! -} - -# The set profile image uri eip 712 typed data types -type CreateSetProfileImageUriEIP712TypedDataTypes { - SetProfileImageURIWithSig: [EIP712TypedDataField!]! -} - -# The set profile uri eip 712 typed data value -type CreateSetProfileImageUriEIP712TypedDataValue { - nonce: Nonce! - deadline: UnixTimestamp! - profileId: ProfileId! - imageURI: Url! -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### profiled - required - -This is mandatory. - -### url - optional if not supplied you need to supply `nftData` - -This can be any image link you wish. - -### nftData- optional if not supplied you need to supply the `url` - -- `id` - The id given back to you from [NFT ownership challenge](doc:nft-ownership-challenge) -- `signature` - The signature result after signing the text returned from [NFT ownership challenge](doc:nft-ownership-challenge) - -Example using `nftData` to set the profile picture: - -```javascript Example operation -mutation CreateSetProfileImageURITypedData { - createSetProfileImageURITypedData(request: { - profileId: "0x03", - nftData: { - id: "46393b78-4bfa-4830-8f5f-badca8b06e42", - signature: "0x8f82e1a2c2cc35a2963c60eeb0a76aecc100686c4ffcb98fd522a90cba2f0b2642067c79cd6d0c9d239ed28a6882818f77bf546e774410236c730988bd14de5d1c" - } - }) { - id - expiresAt - typedData { - types { - SetProfileImageURIWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - imageURI - profileId - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetProfileImageURITypedData": { - "id": "745d18ea-73fa-432e-aa1f-72e143ea3c10", - "expiresAt": "2022-02-22T16:48:52.000Z", - "typedData": { - "types": { - "SetProfileImageURIWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "imageURI", - "type": "string" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645548532, - "imageURI": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "profileId": "0x03" - } - } - } - } -} -``` - - - -## Putting it together - - shows you a live running example of how you would generate the signed typed data from the API and send it through the `withSig` methods. - -# Gasless - -> 🚧 If you are on mumbai anyone can use gasless but if your on polygon only whitelisted apps can currently use this - -You have 2 options when doing gasless you have `broadcast` and also the `dispatcher`. The dispatcher supports a subset of methods that allows you to do actions without signing, these actions are protocol calls that can not drain funds from any wallet making them classed as safe actions, not all methods are supported by the dispatcher. Posting is one of those allowed dispatcher methods. You can set up a dispatcher for the user using and then broadcast that transaction which is described in that document. - -> 📘 Full code example of gasless -> -> - -## Broadcast - -This doc explains how you would broadcast a transaction with the demo example in there. You basically use all of the examples in the GitHub code snippet but instead of calling the `withSig` methods on the hub directly, you pass the signature into the broadcast call. This is all shown in the full code GitHub example above. - -## Using dispatcher - -This takes in the same request as the `withSig` method so nothing needs to change in that regard. You then can track the `txId` to see what it is indexed. Look at the code examples for more low-level detail. - -```javascript Example operation -mutation CreateSetProfileImageURIViaDispatcher { - createSetProfileImageURIViaDispatcher(request: { - profileId: "0x03", - url: "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP" - }) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example result -{ - "data": { - "createPostViaDispatcher": { - "txHash": "0xc37eed339fb06320906fdb0a0078ae8e5e7d6f1496e01084489180cd3cb3abe6", - "txId": "83ae3af8-220c-4e9d-be7c-6cdf3b50fa44" - } - } -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -# - -# Using LensClient SDK - -```typescript -const typedDataResult = await lensClient.profile.createSetProfileImageURITypedData({ - url: "https://arweave.net/dOKOqiZVvSs14n54GIRH9nkSlLKArzK7-SPc2sBVmAM", - profileId: "0x0635", -}); - -// or - -const relayerResult = await lensClient.profile.createSetProfileImageURIViaDispatcher({ - url: "https://arweave.net/dOKOqiZVvSs14n54GIRH9nkSlLKArzK7-SPc2sBVmAM", - profileId: "0x0635", -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/create-set-update-profile-metadata-typed-data.md b/documents/Lens API/profiles/create-set-update-profile-metadata-typed-data.md deleted file mode 100644 index bf7bfd9..0000000 --- a/documents/Lens API/profiles/create-set-update-profile-metadata-typed-data.md +++ /dev/null @@ -1,322 +0,0 @@ ---- -title: "Set profile metadata" -slug: "create-set-update-profile-metadata-typed-data" -hidden: false -createdAt: "2022-02-17T11:39:09.059Z" -updatedAt: "2023-03-15T18:08:04.628Z" ---- -This API call allows you to get the typed data to then call the `withSig` method to set your profile metadata for your profile on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API, the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always-failing transaction, the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -All the metadata of the profile is stored on-chain in a URL/IPFS link that points to the metadata just how NFTs work. This means updating profile details is a transaction. - -# Profile Metadata Structure - -```ts -export enum MetadataDisplayType { - number = 'number', - string = 'string', - date = 'date', -} - -export enum MetadataVersions { - one = '1.0.0', -} - -export interface AttributeData { - displayType?: MetadataDisplayType; - traitType?: string; - value: string; - key: string; -} - -export interface ProfileMetadata { - /** - * The metadata version. - */ - version: MetadataVersions; - - /** - * The metadata id can be anything but if your uploading to ipfs - * you will want it to be random.. using uuid could be an option! - */ - metadata_id: string; - - /** - * The display name for the profile - */ - name: string | null; - - /** - * The bio for the profile - */ - bio: string | null; - - /** - * Cover picture - */ - cover_picture: string | null; - - /** - * Any custom attributes can be added here to save state for a profile - */ - attributes: AttributeData[]; -} -``` - - - -anything you put in `attributes` will be extracted out of the metadata and put into the profile schema under `attributes` - -# API Design - -```javascript Example operation -mutation CreateSetProfileMetadataTypedData { - createSetProfileMetadataTypedData(request: { - profileId: "0x01", - metadata: "ipfs://Qmeu6u6Ta5qeCf6mw3zVoe9pMus96cX6eZT6dnRQKDStBL" - }) { - id - expiresAt - typedData { - types { - SetProfileMetadataURIWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - metadata - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createSetProfileMetadataTypedData": { - "id": "015c12ab-b9b3-4cec-8d43-35b186565542", - "expiresAt": "2022-04-21T09:13:58.000Z", - "typedData": { - "types": { - "SetProfileMetadataURIWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "metadata", - "type": "string" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "LensPeriphery", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x702C22BFCD705c42B46Df8512b51311a2B5e6036" - }, - "value": { - "nonce": 0, - "deadline": 1650532438, - "profileId": "0x01", - "metadata": "ipfs://Qmeu6u6Ta5qeCf6mw3zVoe9pMus96cX6eZT6dnRQKDStBL" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createSetProfileMetadataTypedData(request: CreatePublicSetProfileMetadataURIRequest!): CreateSetProfileMetadataURIBroadcastItemResult! -} -``` -```javascript Request -input CreatePublicSetProfileMetadataURIRequest { - # Profile id - profileId: ProfileId! - - # The metadata uploaded somewhere passing in the url to reach it - metadata: Url! -} -``` -```javascript Response -# The eip 712 typed data domain -type EIP712TypedDataDomain { - # The name of the typed data domain - name: String! - - # The chainId - chainId: ChainId! - - # The version - version: String! - - # The verifying contract - verifyingContract: ContractAddress! -} - -# The broadcast item -type CreateSetProfileMetadataURIBroadcastItemResult { - # This broadcast item ID - id: BroadcastId! - - # The date the broadcast item expiries - expiresAt: DateTime! - - # The typed data - typedData: CreateSetProfileMetadataURIEIP712TypedData! -} - -# The set follow nft uri eip 712 typed data -type CreateSetProfileMetadataURIEIP712TypedData { - # The types - types: CreateSetProfileMetadataURIEIP712TypedDataTypes! - - # The typed data domain - domain: EIP712TypedDataDomain! - - # The values - value: CreateSetProfileMetadataURIEIP712TypedDataValue! -} - -# The set follow nft uri eip 712 typed data types -type CreateSetProfileMetadataURIEIP712TypedDataTypes { - SetProfileMetadataURIWithSig: [EIP712TypedDataField!]! -} - -# The set follow nft uri eip 712 typed data value -type CreateSetProfileMetadataURIEIP712TypedDataValue { - nonce: Nonce! - deadline: UnixTimestamp! - profileId: ProfileId! - metadata: Url! -} - -input CreatePublicSetProfileMetadataURIRequest { - # Profile id - profileId: ProfileId! - - # The metadata uploaded somewhere passing in the url to reach it - metadata: Url! -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### profiled - required - -This is mandatory. - -### metadata - -This is where your new metadata for your profile is stored - -## Putting it together - - shows you a live running example of how you would generate the signed typed data from the API and send it through the `withSig` methods. - -# Gasless - -> 🚧 If you are on mumbai anyone can use gasless but if your on polygon only whitelisted apps can currently use this - -You have 2 options when doing gasless you have `broadcast` and also the `dispatcher`. The dispatcher supports a subset of methods that allows you to do actions without signing, these actions are protocol calls that can not drain funds from any wallet making them classed as safe actions, not all methods are supported by the dispatcher. Posting is one of those allowed dispatcher methods. You can set up a dispatcher for the user using and then broadcast that transaction which is described in that document. - -> 📘 Full code example of gasless -> -> - -## Broadcast - -This doc explains how you would broadcast a transaction with the demo example in there. You basically use all of the examples in the GitHub code snippet but instead of calling the `withSig` methods on the hub directly, you pass the signature into the broadcast call. This is all shown in the full code GitHub example above. - -## Using dispatcher - -This takes in the same request as the `withSig` method so nothing needs to change in that regard. You then can track the `txId` to see what it is indexed. Look at the code examples for more low-level detail. - -```javascript Example operation -mutation CreateSetProfileMetadataViaDispatcher { - createSetProfileMetadataViaDispatcher(request: { - profileId: "0x01", - metadata: "ipfs://Qmeu6u6Ta5qeCf6mw3zVoe9pMus96cX6eZT6dnRQKDStBL" - }) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example result -{ - "data": { - "createSetProfileMetadataViaDispatcher": { - "txHash": "0xc37eed339fb06320906fdb0a0078ae8e5e7d6f1496e01084489180cd3cb3abe6", - "txId": "83ae3af8-220c-4e9d-be7c-6cdf3b50fa44" - } - } -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -```typescript -const typedDataResult = await lensClient.profile.createSetProfileMetadataTypedData({ - metadata: "urlToMetadataFile", - profileId: "0x0635", -}); - -// or - -const relayerResult = await lensClient.profile.createSetProfileMetadataViaDispatcher({ - metadata: "urlToMetadataFile", - profileId: "0x0635", -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/get-default-profile.md b/documents/Lens API/profiles/get-default-profile.md deleted file mode 100644 index 8086232..0000000 --- a/documents/Lens API/profiles/get-default-profile.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: "Get default profile" -slug: "get-default-profile" -hidden: false -createdAt: "2022-04-21T11:23:51.427Z" -updatedAt: "2023-03-15T17:48:03.772Z" ---- -> 📘 Full code example -> -> - -This query returns to you the default profile for the wallet. A wallet can own many profiles but can set a default similar to how ens works with its resolvers. - -# API Design - -```javascript Example operation -query DefaultProfile { - defaultProfile(request: { ethereumAddress: "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3"}) { - id - name - bio - isDefault - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - contractAddress - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } -} -``` -```javascript Example response -{ - "data": { - "defaultProfile": { - "id": "0x0f", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "followNftAddress": null, - "metadata": null, - "handle": "yoooo1", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": null, - "stats": { - "totalFollowers": 111, - "totalFollowing": 15, - "totalPosts": 89, - "totalComments": 64, - "totalMirrors": 15, - "totalPublications": 168, - "totalCollects": 215 - }, - "followModule": null - } - } -} -``` -```javascript Query interface -type Query { - defaultProfile(request: DefaultProfileRequest!): Profile! -} -``` - - - -# - -# Using LensClient SDK - -Despite that we offer the `defaultProfile` query, we recommend using `profiles` query with `ownedBy`argument. Using LensClient SDK you can achieve it easily as in the example below. - -```typescript -const address = "0xe3D871d389BF78c091E29deCe83200E9d6B2B0C2"; -const allOwnedProfiles = await lensClient.profile.fetchAll({ - ownedBy: [address], - limit: 1, -}); - -// defaultProfile is a ProfileFragment -const defaultProfile = allOwnedProfiles.items[0]; -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/get-profile.md b/documents/Lens API/profiles/get-profile.md deleted file mode 100644 index e2d5712..0000000 --- a/documents/Lens API/profiles/get-profile.md +++ /dev/null @@ -1,447 +0,0 @@ ---- -title: "Get profile" -slug: "get-profile" -hidden: false -createdAt: "2022-06-20T10:43:22.328Z" -updatedAt: "2023-03-15T17:50:01.376Z" ---- -> 📘 Full code example -> -> - -Get a single profile by `id` or `handle` - -# API details - -> 📘 Hot tip -> -> If you do not know GraphQL that well remember things can be nullable if defined. In the schema how GraphQL knows it's nullable is without the `!` at the end here is an example: -> -> Not nullable: -> -> ownedBy: EthereumAddress! -> -> Nullable: -> -> ownedBy: EthereumAddress -> -> It's always worth generating the TypeScript types for the schema if your application is TypeScript here is a reference to how you would do that - - -```javascript Example response -{ - "data": { - "profile": { - "id": "0x01", - "name": "LensProtocol.eth 🌿", - "bio": "A permissionless, composable, & decentralized social graph that makes building a Web3 social platform easy.", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Developer Garden" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://lens.dev/" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "lensprotocol" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "followNftAddress": "0x5832bE646A8a7A1A7a7843efD6B8165aC06e360D", - "metadata": "ipfs://QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "isDefault": false, - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "handle": "lensprotocol.test", - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "ownedBy": "0x6C77a5a88C0AE712BAeABE12FeA81532060dcBf5", - "dispatcher": null, - "stats": { - "totalFollowers": 2103, - "totalFollowing": 0, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 1354 - }, - "followModule": null - } - } -} -``` -```javascript Query interface -type Query { - profile(request: SingleProfileQueryRequest!): Profile! -} -``` - - - -## Get by profile id - -```javascript Example operation -query Profile { - profile(request: { profileId: "0x01" }) { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } -} -``` -```javascript Example response -{ - "data": { - "profile": { - "id": "0x01", - "name": "LensProtocol.eth 🌿", - "bio": "A permissionless, composable, & decentralized social graph that makes building a Web3 social platform easy.", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Developer Garden" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://lens.dev/" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "lensprotocol" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "followNftAddress": "0x5832bE646A8a7A1A7a7843efD6B8165aC06e360D", - "metadata": "ipfs://QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "isDefault": false, - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "handle": "lensprotocol.test", - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "ownedBy": "0x6C77a5a88C0AE712BAeABE12FeA81532060dcBf5", - "dispatcher": null, - "stats": { - "totalFollowers": 2103, - "totalFollowing": 0, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 1354 - }, - "followModule": null - } - } -} -``` - - - -## Get by handle - -```javascript Example operation -query Profile { - profile(request: { handle: "lensprotocol.test" }) { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } -} -``` -```javascript Example response -{ - "data": { - "profile": { - "id": "0x01", - "name": "LensProtocol.eth 🌿", - "bio": "A permissionless, composable, & decentralized social graph that makes building a Web3 social platform easy.", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "location", - "value": "Developer Garden" - }, - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://lens.dev/" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "lensprotocol" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "followNftAddress": "0x5832bE646A8a7A1A7a7843efD6B8165aC06e360D", - "metadata": "ipfs://QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "isDefault": false, - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY9dUwYu67puaWBMxRKW98LPbXCznPwHUbhX5NeWnCJbX", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "handle": "lensprotocol.test", - "coverPicture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmTFLSXdEQ6qsSzaXaCSNtiv6wA56qq87ytXJ182dXDQJS", - "mimeType": null - }, - "__typename": "MediaSet" - }, - "ownedBy": "0x6C77a5a88C0AE712BAeABE12FeA81532060dcBf5", - "dispatcher": null, - "stats": { - "totalFollowers": 2103, - "totalFollowing": 0, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 1354 - }, - "followModule": null - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const profileById = await lensClient.profile.fetch({ - profileId: '0x0635' -}) - -const profileByHandle = await lensClient.profile.fetch({ - handle: 'handle.test' -}) -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/get-profiles.md b/documents/Lens API/profiles/get-profiles.md deleted file mode 100644 index e912998..0000000 --- a/documents/Lens API/profiles/get-profiles.md +++ /dev/null @@ -1,741 +0,0 @@ ---- -title: "Get profiles" -slug: "get-profiles" -hidden: false -createdAt: "2022-02-17T11:38:16.384Z" -updatedAt: "2023-03-15T17:42:45.547Z" ---- -> 📘 Full code example -> -> - -The profile query has a few different ways you can query the profiles. Using the power of GraphQL is super flexible and allows the same endpoint to be used in many different cases. - -# API details - -Below is the overview of the entire interface but we dig into specific queries below. - -> 📘 Hot tip -> -> If you do not know GraphQL that well remember things can be nullable if defined. In the schema how GraphQL knows it's nullable is without the `!` at the end here is an example: -> -> Not nullable: -> -> ownedBy: EthereumAddress! -> -> Nullable: -> -> ownedBy: EthereumAddress -> -> It's always worth generating the TypeScript types for the schema if your application is TypeScript here is a reference to how you would do that - - -```javascript Example response -{ - "data": { - "profiles": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.dev", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":1}", - "totalCount": 1 - } - } - } -} -``` -```javascript Query interface -type Query { - profiles(request: ProfileQueryRequest!): PaginatedProfileResult! -} -``` -```javascript Request -input ProfileQueryRequest { - limit: Int - cursor: Cursor - - # The profile ids - profileIds: [ProfileId!] - - # The ethereum addresses - ownedBy: [EthereumAddress!] - - # The handles for the profile - handles: [Handle!] - - # The mirrored publication id - whoMirroredPublicationId: InternalPublicationId -} -``` - - - -You will see the paging result behavior repeated a lot in the API; this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -Now you see the base query let's look at how we can use different request parameters to request profiles. - -## Get by profile ids - -You can get the profiles by passing in an array of `profileIds` please note if you try to pass in the `ownedBy` or `handles or `whoMirroredPublicationId`alongside this you will get a`ValidationError\` thrown. The same will happen if you pass in an empty array. - -```javascript Example operation -query Profiles { - profiles(request: { profileIds: ["0x01"], limit: 10 }) { - items { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "profiles": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.dev", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":1}", - "totalCount": 1 - } - } - } -} -``` - - - -## Get by owned by - -You can get the profiles by passing in an array of `ownedBy` which is an array of ethereum addresses, please note if you try to pass in the `profileIds` or `handles or `whoMirroredPublicationId`alongside this you will get a`ValidationError\` thrown. The same will happen if you pass in an empty array. - -```javascript Example operation -query Profiles { - profiles(request: { ownedBy: ["0xD020E01C0c90Ab005A01482d34B808874345FD82"], limit: 10 }) { - items { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "profiles": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.test", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":1}", - "totalCount": 1 - } - } - } -} -``` - - - -## Get by handles - -You can get the profiles by passing in an array of `handles`, please note if you try to pass in the `profileIds` or `ownedByor `whoMirroredPublicationId`alongside this you will get a`ValidationError\` thrown. The same will happen if you pass in an empty array. - -```javascript Example operation -query Profiles { - profiles(request: { handles: ["josh.test"], limit: 1 }) { - items { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "profiles": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.test", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":1}", - "totalCount": 1 - } - } - } -} -``` - - - -## Get by who has mirrored a publication - -You can get the profiles of who mirrored a publication using the `whoMirroredPublicationId`, please note if you try to pass in the `profileIds` or `ownedBy or `handles`alongside this you will get a`ValidationError\` thrown. - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. The backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all responses and also used in any request you which to do. - -```javascript Example operation -query Profiles { - profiles(request: { whoMirroredPublicationId: "0x09-0x01", limit: 10 }) { - items { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - __typename - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "profiles": { - "items": [ - { - "id": "0x01", - "name": "Josh", - "bio": "Amazing docs", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "josh.dev", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 6 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":1}", - "totalCount": 1 - } - } - } -} -``` - - - - - -# - -# Using LensClient SDK - -```typescript -// by profileIds -const profilesById = await lensClient.profile.fetchAll({ - profileIds: ["0x0635"], -}); - -console.log( - `Profiles fetched by ids: `, - profilesById.items.map((i) => ({ id: i.id, handle: i.handle })) -); - -// by ownedBy -const address = "0xe3D871d389BF78c091E29deCe83200E9d6B2B0C2"; -const allOwnedProfiles = await lensClient.profile.fetchAll({ - ownedBy: [address], -}); - -console.log( - `Profiles owned by ${address}: `, - allOwnedProfiles.items.map((i) => ({ id: i.id, handle: i.handle })) -); - -// by handles -const profilesByHandle = await lensClient.profile.fetchAll({ - handles: ["pukkynext.test"], -}); - -console.log( - `Profiles fetched by handles: `, - profilesByHandle.items.map((i) => ({ id: i.id, handle: i.handle })) -); - -// by whoMirroredPublicationId -const profilesWhoMirroredPublicationId = await lensClient.profile.fetchAll({ - whoMirroredPublicationId: "0x0635-0x0f", -}); - -console.log( - `Profiles who mirrored publication: `, - profilesWhoMirroredPublicationId.items.map((i) => ({ id: i.id, handle: i.handle })) -); - -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/mutual-profile-follows.md b/documents/Lens API/profiles/mutual-profile-follows.md deleted file mode 100644 index d49149b..0000000 --- a/documents/Lens API/profiles/mutual-profile-follows.md +++ /dev/null @@ -1,339 +0,0 @@ ---- -title: "Mutual profile follows" -slug: "mutual-profile-follows" -hidden: false -createdAt: "2022-09-23T11:35:49.418Z" -updatedAt: "2023-03-15T18:18:55.198Z" ---- -> 📘 Full code example -> -> - -This will return you mutual profiles based on the 2 profiles following. It will return to you all profiles that the profile you are viewing is followed by the profiles you follow. - -# API Design - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is you have a schema that should explain how the schema should look at what properties exist in that. In these docs we explore code examples and explain key concepts but we will not explain each property that exists in the response for example, as the schema already does that! - -```Text Example operation -query MutualFollowersProfiles { - mutualFollowersProfiles(request: { viewingProfileId: "0x01", yourProfileId: "0x02" }) { - items { - ...ProfileFields - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} -``` -```Text Example response -{ - "data": { - "mutualFollowersProfiles": { - "items": [ - { - "id": "0x03c5", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": true, - "handle": "piedpiper.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464_piedpiper.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 15, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x15", - "name": "Yoginth", - "bio": "요기 • Creator of @lenster 🌸 • Bullish on Ξ • BTS Fanboi ⟬⟭ • he/him 🌳", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://yogi.codes" - }, - { - "displayType": "string", - "traitType": "location", - "key": "location", - "value": "India" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "yogicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x519B98aCFe0d13161aE75E6aEA8C4C60f6418055", - "metadata": "https://arweave.net/WmAKdos7EbiH86mYXdhC9Js1YhgdlGNMw3ZOL6b38sM", - "isDefault": true, - "handle": "yoginth.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmR7vBHZm78hsymxYFkQBV4UC42Y4iGyHgyFwisMu9S66B", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 157, - "totalFollowing": 56, - "totalPosts": 150, - "totalComments": 151, - "totalMirrors": 68, - "totalPublications": 369, - "totalCollects": 115 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3" - } - }, - { - "id": "0x18", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0xBA8bB58FcF87f3E5089ccF28ee9d83B44588011E", - "metadata": "ipfs://QmeKBfKjQbzxN4d1woMtDruVPYS2xkwWyArEtjzjszmGU8", - "isDefault": true, - "handle": "devjoshstevens.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmZ2Y6NrwvCst88S6V6eQVocUqkL9Zbmw6MqpNWZwYt4op", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0xD8c789626CDb461ec9347f26DDbA98F9383aa457", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 27, - "totalFollowing": 38, - "totalPosts": 26, - "totalComments": 13, - "totalMirrors": 5, - "totalPublications": 44, - "totalCollects": 10 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "next": "{\"offset\":3}", - "totalCount": 3 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -## Request - -### viewingProfileId - required - -The profile id you are viewing - -### yourProfileId - required - -The profile id the user is looking from - - - -# - -# Using LensClient SDK - -```typescript -const mutualFollowers = await lensClient.profile.mutualFollowers({ - viewingProfileId, - yourProfileId, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/on-chain-identity.md b/documents/Lens API/profiles/on-chain-identity.md deleted file mode 100644 index 2215a9c..0000000 --- a/documents/Lens API/profiles/on-chain-identity.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "On chain identity" -slug: "on-chain-identity" -hidden: false -createdAt: "2022-09-23T11:55:32.540Z" -updatedAt: "2022-11-09T10:31:54.373Z" ---- -Every profile has an owner and with that, we are building up an on-chain identity for these profiles. This allows you to do powerful things like knowing if that profile has a human behind it, showing the ens name, and a lot more. We keep building this and adding to this further soon enough. The on-chain identity object is not in all profile examples to not bloat the request. - -# API design - -please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. - -```graphql Example operation -query Profile { - profile(request: { profileId: "0x06" }) { - onChainIdentity { - ens { - name - } - proofOfHumanity - sybilDotOrg { - verified - source { - twitter { - handle - } - } - } - worldcoin { - isHuman - } - } - } -} -``` -```json Example response -{ - "data": { - "profile": { - "onChainIdentity": { - "ens": { - "name": "svg.eth" - }, - "proofOfHumanity": true, - "sybilDotOrg": { - "verified": false, - "source": { - "twitter": { - "handle": null - } - } - }, - "worldcoin": { - "isHuman": true - } - } - } - } -} -``` - - - -## Response - -### ens - -- Returns you the ens if the profile owner has one - -### proofOfHumanity - -- The POH status of the profile owner - -### sybilDotOrg - - - -- The Sybil status of the profile owner - -### worldcoin - -- The worldcoin status of the profile owner \ No newline at end of file diff --git a/documents/Lens API/profiles/profile-interests.md b/documents/Lens API/profiles/profile-interests.md deleted file mode 100644 index 27b8654..0000000 --- a/documents/Lens API/profiles/profile-interests.md +++ /dev/null @@ -1,196 +0,0 @@ ---- -title: "Profile interests" -slug: "profile-interests" -hidden: false -createdAt: "2022-11-09T10:11:10.513Z" -updatedAt: "2023-03-15T18:24:58.079Z" ---- -Profiles can have interests so that the experience layer can filter and provide content that is more relevant and engaging to their audience. The Lens API supports the following interests categories, and subcategories: - -- Arts & Entertainment - - Books & Literature - - Art - - Design - - Photography - - Fashion - - Anime - - Memes - - Film & TV - - Music -- Business - - Creator Economy - - Finance - - Marketing -- Technology - - AI & ML - - Science - - Programming - - Tools - - Biotech -- Health & Fitness - - Exercise - - Biohacking -- Food & Drink - - Restaurants - - Cooking - - Cocktails - - Beer - - Wine -- Hobbies & Interests - - Arts & Crafts - - Gaming - - Travel - - Collecting - - Sports - - Cars -- News -- Family & Parenting -- Education -- Career -- Home & Garden - - Nature - - Animals - - Home Improvement - - Gardening -- Law, Government and Politics - - Regulation -- Crypto - - NFT - - DeFi - - Web3 - - Web3 Social - - Governance - - DAOs - - gm - - Metaverse - - Rekt - - Ethereum - - Bitcoin - - L1s - - L2s - - Scaling -- Lens -- NSFW - -Keep in mind that profile interests are now **off-chain** and will be used only to curate the way that API serves content. - -In addition, the API wants to stay unopinionated in terms of i18n and of how you choose to display interests to your users, so all interests are returned in english capitalised format, words are separated with underscore `_` and subcategories with double underscore `__`. - -# API design - -- Get all available interests. Public access. - -```graphql Query example -query ProfileInterests { - profileInterests -} -``` -```json Response example -{ - "data": { - "profileInterests": [ - 'ART_ENTERTAINMENT', - 'ART_ENTERTAINMENT__BOOKS', - 'ART_ENTERTAINMENT__ART', - 'ART_ENTERTAINMENT__DESIGN', - 'ART_ENTERTAINMENT__PHOTOGRAPHY', - 'ART_ENTERTAINMENT__FASHION', - 'ART_ENTERTAINMENT__ANIME', - 'ART_ENTERTAINMENT__MEMES', - 'ART_ENTERTAINMENT__FILM_TV', - 'ART_ENTERTAINMENT__MUSIC', - 'BUSINESS', - 'BUSINESS__CREATOR_ECONOMY', - 'BUSINESS__FINANCE', - 'BUSINESS__MARKETING', - 'TECHNOLOGY', - 'TECHNOLOGY__AI_ML', - 'TECHNOLOGY__SCIENCE', - 'TECHNOLOGY__PROGRAMMING', - 'TECHNOLOGY__TOOLS', - 'TECHNOLOGY__BIOTECH', - 'CAREER', - 'EDUCATION', - 'FAMILY_PARENTING', - 'HEALTH_FITNESS', - 'HEALTH_FITNESS__EXERCISE' - ] - } -} -``` - - - -- Get a profile's interests (these are fetched as part of the `Profile` object). Public access. - -```graphql Query example -query Profile { - profile(request: { profileId: "0x01" }) { - id - interests - } -} -``` -```json Response example -{ - "data": { - "profile": { - "id": "0x01", - "interests": ["NFTS"] - } - } -} -``` - - - -- Add interests to a profile - -Profiles can have up to 12 interests at this time. Will return null if successful, otherwise error. You need to be authorized with the provided `profileId` to call. - -```graphql Mutation example -mutation AddProfileInterest { - addProfileInterests(request: { - profileId: "0x01", - interests: ["NFTS"] - }) -} -``` - - - -- Remove interests from a profile - -As with the previous endpoint, this one also returns null on success otherwise error. You need to be authorized with the provided `profileId` to call. - -```graphql Mutation example -mutation RemoveProfileInterest { - removeProfileInterests(request: { - profileId: "0x01", - interests: ["NFTS"] - }) -} -``` - - - -# - -# Using LensClient SDK - -```typescript -// get all available interests -const profileInterests = await lensClient.profile.allInterests(); - -// add interests -await lensClient.profile.addInterests({ - interests: ["TECHNOLOGY__PROGRAMMING"], - profileId, -}); - -// remove interests -await lensClient.profile.removeInterests({ - interests: ["TECHNOLOGY__PROGRAMMING"], - profileId, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/profiles/recommended-profiles.md b/documents/Lens API/profiles/recommended-profiles.md deleted file mode 100644 index 13e5d06..0000000 --- a/documents/Lens API/profiles/recommended-profiles.md +++ /dev/null @@ -1,310 +0,0 @@ ---- -title: "Recommended profiles" -slug: "recommended-profiles" -hidden: false -createdAt: "2022-02-17T11:38:34.974Z" -updatedAt: "2023-03-15T17:53:50.709Z" ---- -> 📘 Full code example -> -> - -The API uses ML to populate people who we think you would like to follow. You can disable ML by using the `disableML` parameter if you wish to use basic curated profiles. It does not support a paging list as of yet. We continue to push these recommendations. By using this API, you inherit all improvements without changing the code. - -# API details - -```javascript Example operation -query RecommendedProfiles { - recommendedProfiles { - id - name - bio - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - isDefault - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - handle - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - __typename - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - symbol - name - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } -} -``` -```javascript Example response -{ - "data": { - "recommendedProfiles": [ - { - "id": "0x11", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "hh", - "coverPicture": null, - "ownedBy": "0x5905232b8ea73f1F2FCBE4297573733bf41b666d", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 0, - "totalPosts": 4, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x14", - "name": null, - "bio": null, - "location": null, - "website": null, - "twitter": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "lucasaave", - "coverPicture": null, - "ownedBy": "0x7953FE8b8cC7c6391683353aE016B9D90f072767", - "depatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 5, - "totalMirrors": 0, - "totalPublications": 5, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x06", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "lucas", - "coverPicture": null, - "ownedBy": "0x6ea7c12CbB8480236716d1EEB0B31C2950166F3B", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 0, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x13", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "pawelprofile", - "coverPicture": null, - "ownedBy": "0xb19C2890cf947AD3f0b7d7E5A9ffBce36d3f9bd2", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 8, - "totalPosts": 3, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - }, - { - "id": "0x01", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "picture": null, - "handle": "hey", - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - ] - } -} -``` -```javascript Query interface -type Query { - recommendedProfiles: [Profile!]! -} -``` - - - -## Dismiss profile recommendations - -You can use the following mutation to permanently dismiss one or more profile follow recommendations. Only authenticated users can call this, and any profileId provided will be permanently omitted from 'who to follow' recommendations. - -```graphql Mutation -mutation DismissRecommendedProfiles { - dismissRecommendedProfiles(request: {profileIds: ["0x01", "0x02"]}) -} -``` -```Text Example response -// returns null so no response -``` - - - - - -# - -# Using LensClient SDK - -You can use LensClient SDK to fetch recommended profiles and dismiss them. - -```typescript -// fetch recommendations -const recommendedProfiles = await lensClient.profile.allRecommended(); - -console.log( - `Recommended profiles: `, - recommendedProfiles.map((i) => ({ id: i.id, handle: i.handle })) -); - -// dismiss -await lensClient.profile.dismissRecommended({ profileIds: [recommendedProfiles[0].id] }); - - -``` \ No newline at end of file diff --git a/documents/Lens API/protocol-stats.md b/documents/Lens API/protocol-stats.md deleted file mode 100644 index 00bd546..0000000 --- a/documents/Lens API/protocol-stats.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Protocol stats" -slug: "protocol-stats" -hidden: false -createdAt: "2022-03-23T10:39:33.484Z" -updatedAt: "2022-03-23T10:41:14.067Z" ---- -Protocol stats are exposed to understand how busy everything is. - -Our protocol stats resolver have these queries: - -- [Global protocol stats](doc:global-protocol-stats) \ No newline at end of file diff --git a/documents/Lens API/protocol-stats/global-protocol-stats.md b/documents/Lens API/protocol-stats/global-protocol-stats.md deleted file mode 100644 index 5a10678..0000000 --- a/documents/Lens API/protocol-stats/global-protocol-stats.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: "Global protocol stats" -slug: "global-protocol-stats" -hidden: false -createdAt: "2022-03-23T10:40:55.030Z" -updatedAt: "2023-03-14T13:00:54.722Z" ---- -> 📘 Full code example -> -> - -This query returns to you the global protocol stats of key metrics. - -# API Design - -```javascript Example operation -query GlobalProtocolStats { - globalProtocolStats(request: null) { - totalProfiles - totalBurntProfiles - totalPosts - totalMirrors - totalComments - totalCollects - totalFollows - totalRevenue { - asset { - name - symbol - decimals - address - } - value - } - } -} -``` -```javascript Example response -{ - "data": { - "globalProtocolStats": { - "totalProfiles": 291, - "totalBurntProfiles": 10, - "totalPosts": 186, - "totalMirrors": 23, - "totalComments": 59, - "totalCollects": 19, - "totalFollows": 85, - "totalRevenue": [ - { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "6.94648" - } - ] - } - } -} -``` -```javascript Query interface -type Query { - globalProtocolStats(request: GlobalProtocolStatsRequest): GlobalProtocolStats! -} -``` -```javascript Request -input GlobalProtocolStatsRequest { - # Unix time from timestamp - if not supplied it will go from 0 timestamp - fromTimestamp: UnixTimestamp - - # Unix time to timestamp - if not supplied it go to the present timestamp - toTimestamp: UnixTimestamp - - # The App Id - sources: [Sources!] -} -``` -```javascript Response -type GlobalProtocolStats { - totalProfiles: Int! - totalBurntProfiles: Int! - totalPosts: Int! - totalMirrors: Int! - totalComments: Int! - totalCollects: Int! - totalFollows: Int! - totalRevenue: [Erc20Amount!]! -} -``` - - - -## Request - -Let's look at the query options we can use here to get for different things. - -```javascript get global stats -{ - // if this is not supplied it will not have a from cap - // it is a unix timestamp - "fromTimestamp": 1642934933, - // if this is not supplied it will not have a to cap - // it is a unix timestamp - "toTimestamp": 1648032533 - // also dont forget you can filter these stats on sources - // this will adjust the posts, mirrors and comments stats - // "sources": ["lost-place-dapp"] - } -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.stats.fetch({ - fromTimestamp: 1642934933, - toTimestamp: 1648032533, - sources: ['someAppId'] -}); -``` \ No newline at end of file diff --git a/documents/Lens API/public-big-query.md b/documents/Lens API/public-big-query.md deleted file mode 100644 index 0209533..0000000 --- a/documents/Lens API/public-big-query.md +++ /dev/null @@ -1,219 +0,0 @@ ---- -title: "Public BigQuery" -slug: "public-big-query" -excerpt: "Fast and flexible queries of all Lens data in bulk and on demand." -hidden: false -createdAt: "2023-02-27T15:37:14.700Z" -updatedAt: "2023-04-05T04:34:43.796Z" ---- -# Introduction - -Lens already has indexers, which snapshot the data and transform it into a relational, super easy-to-understand database. This is how we get our speed on queries and how we can power all the LENS apps with the API. This saves the data into a centralised postgres database and allows you to query it using graphQL API. This is perfect for apps which need data on query time; for example, a user who is logging in wants to see their feed or see someone's profile. Querying this through the API is perfect and fast. The complication comes when you wish to bulk pull data, say you wish to do some ML training, some analytic, general data profiling. Right now, you would need a dedicated endpoint to surface that information, and of course, us creating these endpoints, which maybe you are only interested in. This does not scale. On top of this, having all this data and not allowing leverage for builders to do stuff feels wrong. - -With this in mind, we have published the entire Lens social graph to a public [BigQuery](https://cloud.google.com/bigquery) dataset. This means you can query all the data in bulk, whatever you want, in any way you wish, to any demand. Public BigQuery datasets give you a 1TB allowance every month, but if you want more, just add some GCP credits. This information should be accessible by anyone without them having to write the complex task of indexers and have all that infrastructure set up. This solves that, bringing you the entire LENS graph in the cloud to query anytime you wish. - -# What can I do with this? - -You can pull huge data to do analytics say, a creator's analytics dashboard. You can pull huge amounts of day to run some ML code on it to showcase the discovery of publications. You can build your feeds with curated information very easily. This is the first step in allowing anyone to build custom features on top of LENS without the API has to do it for you. Think outside the box. You have the data. Go and build something epic with it. - -# How to query it - -You should read this to understand how you query public data sets from BigQuery . You can do it from the google cloud console or any BigQuery client libraries, which support mostly all languages. The easiest way if you want to play around with it is using the Analytic hub, as you can run queries directly through it. - -![](https://files.readme.io/1e2bc93-Untitled.png) - -We have three public data sets to query from: - -- mumbai - `lens-public-data.mumbai.schema_table` -- polygon - `lens-public-data.polygon.schema_table` -- sandbox`lens-public-data.sandbox.schema_table` - -**please note you MUST query this from the US region. If you try to use the EU region it will not be able to find it** - -# How it works - -It is very simple how it works. The diagram examples the flows: - -![](https://files.readme.io/cf1fa97-gleek-CndmuA9zJ7YHDiXNuGscvw.png) - -The data will always be **15 minutes behind**. This is the fastest setting you can have turned on with the data syncer. - -# schema - -We will dive into the DB setup for you; you can also generate an ERD on BigQuery to see how things lined up. The below will summarise all the tables and their usage; it won't go into full detail about their column types etc., as you can see in BigQuery for that. - -All examples above have to include the schema in the query. For example, to query ens address reverse records, it would be - -`lens-public-data.polygon.ens_address_reverse_record` - -To see all available tables, you can run the following query: - -```sql -SELECT table_name -FROM `lens-public-data.polygon.INFORMATION_SCHEMA.TABLES` -``` - -## ens - -This holds the reverse record for an address mapped to the ENS; it only looks at wallet addresses which own a profile. - -![](https://files.readme.io/861df5c-Untitled.png) - -## proof_of_humanity - -We index all owners of profiles to see if they have POH registered. - -![](https://files.readme.io/104c1ff-Untitled_1.png) - -## sybil_dot_org - -We index all owners of profiles to see if they are part of the Sybil dot org - -![](https://files.readme.io/81cffae-Untitled_2.png) - -## worldcoin - -We index any worldcoin human verification mapped to the profile id. The last seen block info table is just the state the indexer cares about. - -![](https://files.readme.io/2ff5f1d-Untitled.png) - -## public - -The public schema holds most of the logic most people will care about. - -### app stats - -Apps can have their stats, aka what you did on lenster, for example. These tables do counters for actions on each app. - -![](https://files.readme.io/8f2da9a-Untitled_1.png) - -### approval - -As we explain in the docs within the API, when you transfer a follower NFT to someone, it could look like you follow them when you did not. To avoid that, we have approval tables in which when someone transfers a follower NFT to a wallet, it goes into an awaiting approval state until it is shown as you follow them. - -![](https://files.readme.io/2d621da-Untitled_2.png) - -### module whitelists - -Throughout LENS, you have different types of modules to collect, reference and follow. These modules have to be whitelisted at the current time. These tables hold the mappings to those modules. - -![](https://files.readme.io/338e9d3-Untitled_3.png) - -### publication/follow NFT ownership - -After you collect/follow, that NFT is still tradable. These tables keep the owner status up to date even after the collection/follow has happened. - -![](https://files.readme.io/1c850c6-Untitled_4.png) - -### follower - -When you follow people, it's the wallet which follows, not profiles, so these tables keep that state in order. Please note it only writes once to the follower table, even if someone has followed that profile 100 times with the same wallet. A wallet can follow many times. - -![](https://files.readme.io/1ddd53d-Untitled_5.png) - -### hashtags - -You can hashtag words in publication content, and these tables' job is to keep it current. - -![](https://files.readme.io/d1c1dd1-Untitled_6.png) - -### indexed transactions - -This table holds all the transaction hashes it has indexed with the block info attached to it - -![](https://files.readme.io/52ff01d-Untitled.png) - -### last seen block info - -The indexer uses blooms to work out if it needs to check the block, and if that block has the information it should care about, that means it does not check every single block. This table has the last block it did check; it is used if the indexer ever goes down, and it can pick up from where it left off. - -![](https://files.readme.io/a0bb27a-Untitled_1.png) - -### mentions - -You can @people on LENS and attach their handle; these tables are in control of keeping the state updated about the mentions happening on the platform. - -![](https://files.readme.io/e114c13-Untitled_2.png) - -### notifications - -Notifications often happen throughout the platform, and these tables keep all the notification information in sync. - -![](https://files.readme.io/075d771-Untitled_3.png) - -### profile - -A very important factor of LENS is profiles. With this, you have many factors which hold state around the profile: - -- profile_dispatcher - what the dispatcher set for the profile -- profile_follow_nft - where the profile follow NFT address is deployed (if any as lazy loaded) -- profile_interests - any interests the profile has attached -- profile_curated - curated profiles we know great good content to allow our explore curated API to work -- profile_follow_module_details - the follow module details are currently set for the profile -- profile_follow_module_details_history - a change history of follow modules set for the profile -- profile_follow_module_follow_record - a list of follow modules redeemed -- profile_nft_gallery - the profile NFT galleries context -- profile_recommended_dismissed - the profiles that this address is not interested in following -- profile - the main profile - - is_metadata_processed - is a way to see if the profile metadata the user updated was completed - - nft\_\* - is if they have an NFT linked to their profile picture - -![](https://files.readme.io/a791b91-Untitled_4.png) - -### posts, mirrors and comments - -Publications are the core heart of LENS. These tables keep all that information up to date. - -Please note just because it is in here does not mean it was successful in following metadata standards. For successful publication the `s3_metadata_location` should be defined, the `has_error` should be false and the `is_metadata_processed` should be true. - -Mirrors are in the `profile_post` table if it has an `is_related_to_post` or `is_related_to_comment` then it is a mirror. - -![](https://files.readme.io/eb25641-Untitled.png) - -### publication stats - -A list of all publication stats. - -![](https://files.readme.io/0e171f5-Untitled_1.png) - -### protocol state - -The protocol state can change. This keeps track of it - -![](https://files.readme.io/3623f13-Untitled_2.png) - -### publication access control - -This holds the LIT access control logic around a publication. If it is pending, the access control has not been applied to a publication yet. - -![](https://files.readme.io/0750780-Untitled_3.png) - -### publication collect/reference modules - -These tables hold the collected and reference module details for a publication. It also holds the records of all the collects which have been done on that publication. - -![](https://files.readme.io/d3db0e6-Untitled_4.png) - -### reactions - -You can react to publications these table store that state. - -![](https://files.readme.io/b69d7aa-Untitled_5.png) - -### publication pointer - -Maps a publication ID to a publication type. - -![](https://files.readme.io/6a5b56a-Untitled_6.png) - -### publication tags - -These tables hold the publication tags which have been applied - -![](https://files.readme.io/7285284-Untitled_7.png) - -### reorg block status - -This marks blocks as safe and monitors the reorgs. - -![](https://files.readme.io/6770dae-Untitled_8.png) \ No newline at end of file diff --git a/documents/Lens API/publication-1.md b/documents/Lens API/publication-1.md deleted file mode 100644 index 6060527..0000000 --- a/documents/Lens API/publication-1.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Publication" -slug: "publication-1" -hidden: false -createdAt: "2022-02-17T17:59:45.389Z" -updatedAt: "2022-04-21T11:21:47.286Z" ---- -Publications are the posts, comments and mirrors that a profile posts. You can read more in-depth about what publications are [here](doc:publication). - -Make sure you read about the [Metadata standards](doc:metadata-standards) we have set for all publications to conform to. - -Note: if a publication does not conform to these standards we will not index the publication. These are the guidelines set for the API; the protocol itself does not validate these guidelines. Building a standard allows compatibility for all kinds of projects, so we advise sticking to the standards. If you found that there is anything missing, just get in touch. - -Our metadata standards can be extended so any suggestions are always welcome. - -Our publication resolver has these queries: - -- [Create post typed data](doc:create-post-typed-data) -- [Create comment typed data](doc:create-comment-typed-data) -- [Create mirror typed data](doc:create-mirror-typed-data) -- [Get publications](doc:get-publications) -- [Get publication](doc:get-publication) -- [Has mirrored publication](doc:has-mirrored-publication) -- [Has collected publication](doc:has-collected-publication) -- [Hide publication](doc:hide-publication) -- [Who collected publication](doc:who-collected-publication) \ No newline at end of file diff --git a/documents/Lens API/publication-1/app-comment-total.md b/documents/Lens API/publication-1/app-comment-total.md deleted file mode 100644 index 150444c..0000000 --- a/documents/Lens API/publication-1/app-comment-total.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: "App comment total" -slug: "app-comment-total" -hidden: false -createdAt: "2022-09-26T15:07:28.489Z" -updatedAt: "2023-03-16T15:26:44.924Z" ---- -As you can filter queries by sources this means comments on a publication may be different numbers. Let's look at an example: - -- Josh does a post on APP2 -- Sally comments on APP3 -- John comments on APP4 -- Paul comments on APP2 - -Josh's post has 3 comments but across many apps. When you filter on sources you only bring back the sources from those apps. This example below its showing you how we get publication ID `0x01-0x01` and we get back the number of comments that have been done on the app `your_app_id`. This allows us to get the correct counters etc. - -# API design - -```javascript Example operation -query Publications { - publications(request: { publicationIds: ["0x01-0x01"] }) { - items { - ... on Post { - stats { - totalAmountOfComments - commentsTotal(forSources: ["your_app_id"]) - } - } - ... on Comment { - stats { - totalAmountOfComments - commentsTotal(forSources: ["your_app_id"]) - } - } - ... on Mirror { - stats { - totalAmountOfComments - commentsTotal(forSources: ["your_app_id"]) - } - } - } - } -} -``` -```javascript Example response -{ - "data": { - "publications": { - "items": [ - { - "stats": { - "totalAmountOfComments": 3, - "commentsTotal": 1 - } - } - ] - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.stats( - { - publicationId, - }, - ["your_app_id"] // sources -); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/can-comment-publication.md b/documents/Lens API/publication-1/can-comment-publication.md deleted file mode 100644 index 27d03bf..0000000 --- a/documents/Lens API/publication-1/can-comment-publication.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Can comment publication" -slug: "can-comment-publication" -hidden: false -createdAt: "2022-09-23T08:33:47.065Z" -updatedAt: "2023-03-16T16:02:01.610Z" ---- -Reference modules allow you to place criteria on the comment and mirror commands on who is actually allowed to do it. For example, a publication could set only their followers can comment and mirror. You need a way to quickly look this up for the selected profile the user is browsing on. In the `canComment` field resolver you can pass in a `profileId`If you wish to know if they can comment or not, most apps would use the logged-in user's selected profile they are browsing on. - -# API design basic - -please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. Also, note you can use `canComment` anytime it returns a `Post`, `Comment` or `Mirror`. - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10, - }) { - items { - __typename - ... on Post { - canComment(profileId: "0x01") { - result - } - } - ... on Comment { - canComment(profileId: "0x01") { - result - } - } - ... on Mirror { - canComment(profileId: "0x01") { - result - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -`profileId` for `canComment` can pass in as a variable easily enough as well. You can imagine passing the logged-in user's profiles they are browsing on to see if they can comment on the publication. This can be hooked in like this for every query which returns a publication type (Post or Comment or Mirror) - -```javascript Example operation -query Publications($publicationsRequest: PublicationsQueryRequest!, $profileId: ProfileId) { - publications(request: $publicationsRequest) { - items { - __typename - ... on Post { - canComment(profileId: $profileId) { - result - } - } - ... on Comment { - canComment(profileId: $profileId) { - result - } - } - ... on Mirror { - canComment(profileId: $profileId) { - result - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -# - -# Using LensClient SDK - -Provide `observerId` as an argument to get results in the context of the observer profile. - -```typescript -const observerId = "0x01" - -const result = await lensClient.publication.fetchAll(request, observerId); - -const result = await lensClient.publication.fetch(request, observerId); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/can-mirror-publication.md b/documents/Lens API/publication-1/can-mirror-publication.md deleted file mode 100644 index 04ee195..0000000 --- a/documents/Lens API/publication-1/can-mirror-publication.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Can mirror publication" -slug: "can-mirror-publication" -hidden: false -createdAt: "2022-09-23T08:45:26.093Z" -updatedAt: "2023-03-16T16:02:31.784Z" ---- -Reference modules allow you to place criteria on the comment and mirror commands on who is actually allowed to do it. For example, a publication could set only their followers can comment and mirror. You need a way to quickly look this up for the selected profile the user is browsing on. In the `canMirror` field resolver you can pass in a `profileId`If you wish to know if they can mirror or not, most apps would use the logged-in user's selected profile they are browsing on. - -# API design basic - -please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. Also, note you can use `canMirror` anytime it returns a `Post`, `Comment` or `Mirror`. - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10, - }) { - items { - __typename - ... on Post { - canMirror(profileId: "0x01") { - result - } - } - ... on Comment { - canMirror(profileId: "0x01") { - result - } - } - ... on Mirror { - canMirror(profileId: "0x01") { - result - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -`profileId` for `canMirror` can pass in as a variable easily enough as well. You can imagine passing the logged-in user's profiles they are browsing on to see if they can comment on the publication. This can be hooked in like this for every query which returns a publication type (Post or Comment or Mirror) - -```javascript Example operation -query Publications($publicationsRequest: PublicationsQueryRequest!, $profileId: ProfileId) { - publications(request: $publicationsRequest) { - items { - __typename - ... on Post { - canMirror(profileId: $profileId) { - result - } - } - ... on Comment { - canMirror(profileId: $profileId) { - result - } - } - ... on Mirror { - canMirror(profileId: $profileId) { - result - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -# - -# Using LensClient SDK - -Provide `observerId` as an argument to get results in the context of the observer profile. - -```typescript -const observerId = "0x01" - -const result = await lensClient.publication.fetchAll(request, observerId); - -const result = await lensClient.publication.fetch(request, observerId); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/create-collected-typed-data.md b/documents/Lens API/publication-1/create-collected-typed-data.md deleted file mode 100644 index e0d66d3..0000000 --- a/documents/Lens API/publication-1/create-collected-typed-data.md +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: "Collect" -slug: "create-collected-typed-data" -hidden: false -createdAt: "2022-02-18T11:27:17.848Z" -updatedAt: "2023-03-16T15:17:59.041Z" ---- -> 📘 Full code example -> -> - -> 📘 This action can be gasless -> -> ) You can use the broadcast logic to send this gasless. Please note this is fully unlocked on mumbai but on polygon it is only whitelisted apps who can use it. - -This API call allows you to get the typed data to then call the `withSig` method to collect a publication on Lens. - -Please note each [Enabled modules currencies](doc:enabled-modules-currencies) need to have a [Approved allowance of modules](doc:approved-allowance-of-modules) greater than the amount the collect module is. If it is not then an API request will throw an error as the module will not be able to move funds on your behalf. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -```javascript Example operation -mutation CreateCollectTypedData { - createCollectTypedData(request: { - publicationId: "0x1d-0x01" - }) { - id - expiresAt - typedData { - types { - CollectWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - pubId - data - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createCollectTypedData": { - "id": "32d94413-90e2-40a2-aa73-0a55c30a9839", - "expiresAt": "2022-02-24T11:34:59.000Z", - "typedData": { - "types": { - "CollectWithSig": [ - { - "name": "collector", - "type": "address" - }, - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "pubId", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645702499, - "profileId": "0x1d", - "pubId": "0x01", - "data": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createCollectTypedData( - request: CreateCollectRequest! - ): CreateCollectBroadcastItemResult! -} -``` -```javascript Request -input CreateCollectRequest { - publicationId: InternalPublicationId! -} -``` -```javascript Response -# The broadcast item -type CreateCollectBroadcastItemResult { - # This broadcast item ID - id: BroadcastId! - - # The date the broadcast item expiries - expiresAt: DateTime! - - # The typed data - typedData: CreateCollectEIP712TypedData! -} - -# The eip 712 typed data domain -type EIP712TypedDataDomain { - # The name of the typed data domain - name: String! - - # The chainId - chainId: ChainId! - - # The version - version: String! - - # The verifying contract - verifyingContract: ContractAddress! -} - -# The eip 712 typed data field -type EIP712TypedDataField { - # The name of the typed data field - name: String! - - # The type of the typed data field - type: String! -} - -# The collect eip 712 typed data -type CreateCollectEIP712TypedData { - # The types - types: CreateCollectEIP712TypedDataTypes! - - # The typed data domain - domain: EIP712TypedDataDomain! - - # The values - value: CreateCollectEIP712TypedDataValue! -} - -# The collect eip 712 typed data types -type CreateCollectEIP712TypedDataTypes { - CollectWithSig: [EIP712TypedDataField!]! -} - -# The collect eip 712 typed data value -type CreateCollectEIP712TypedDataValue { - nonce: Nonce! - deadline: UnixTimestamp! - profileId: ProfileId! - pubId: PublicationId! - data: BlockchainData! -} - -# Nonce custom scalar type -scalar Nonce - -# Blockchain data scalar type -scalar BlockchainData - -# Broadcast scalar id type -scalar BroadcastId - -# Contract address custom scalar type -scalar ContractAddress - -# ProfileId custom scalar type -scalar ProfileId - -# UnixTimestamp custom scalar type -scalar UnixTimestamp - -# Publication id custom scalar type -scalar PublicationId -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - - - -# - -# Using LensClient SDK - -```typescript -// collect with typedData that require signature and broadcasting -const typedDataResult = await lensClient.publication.createCollectTypedData({ - publicationId: "", -}); - -// sign and broadcast -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/create-comment-typed-data.md b/documents/Lens API/publication-1/create-comment-typed-data.md deleted file mode 100644 index 1dfa638..0000000 --- a/documents/Lens API/publication-1/create-comment-typed-data.md +++ /dev/null @@ -1,781 +0,0 @@ ---- -title: "Comment" -slug: "create-comment-typed-data" -hidden: false -createdAt: "2022-02-18T11:30:45.045Z" -updatedAt: "2023-03-16T15:16:14.016Z" ---- -This API call allows you to get the typed data to then call the `withSig` method to do a comment on a post from a profile on lens. Comments are still publications and have all the power a Post does. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -> 📘 Hot tip -> -> It's super easy to enable modules within your publication using this typed data approach as the server lifts all the encoding and decoding of the modules for you. This allows you to just supply it as you would if you were using a web2 API. - -```javascript Example operation -mutation CreateCommentTypedData { - createCommentTypedData(request: { - profileId: "0x03", - publicationId: "0x01-0x01", - contentURI: "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - collectModule: { - revertCollectModule: true - }, - referenceModule: { - followerOnlyReferenceModule: false - } - }) { - id - expiresAt - typedData { - types { - CommentWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - profileIdPointed - pubIdPointed - contentURI - referenceModuleData - collectModule - collectModuleInitData - referenceModule - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createCommentTypedData": { - "id": "b03ab4b8-580c-4c99-84d0-036480f7f0c4", - "expiresAt": "2022-02-21T14:52:09.000Z", - "typedData": { - "types": { - "CommentWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "contentURI", - "type": "string" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "collectModule", - "type": "address" - }, - { - "name": "collectModuleInitData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645455129, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleData": "0x", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl.json", - "collectModule": "0x2732FfD7f7352c9492089C40A0C3368220a438D4", - "collectModuleInitData": "0x", - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createCommentTypedData( - request: CreatePublicCommentRequest! - ): CreateCommentBroadcastItemResult! -} -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### profileId - required - -You have to pass in a `profileId` that is mandatory. - -### publicationId - required - -You have to pass in a `publicationId ` that is mandatory. - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -### contentURI - required - -The metadata holds the main context of a publication, it holds your content, the media items attached to it, and is the metadata that people get when they collect. [Metadata standards](doc:metadata-standards) are defined here if you want to read what standard we have set. The link passed to use must be able to be called from our server and hold the standards we set out or we will not index the publication. - -#### collectModule - required - -Modules are quite complex, each module needs to be encoded in the correct way for the contracts not to throw. We tried to abstract any complex stuff out for you here and allow you to just pass in the params in web2 style. - -```js -input CollectModuleParams { - # The collect free collect module - freeCollectModule: FreeCollectModuleParams - - # The collect revert collect module - revertCollectModule: Boolean - - # The collect fee collect module - feeCollectModule: FeeCollectModuleParams - - # The collect limited fee collect module - limitedFeeCollectModule: LimitedFeeCollectModuleParams - - # The collect limited timed fee collect module - limitedTimedFeeCollectModule: LimitedTimedFeeCollectModuleParams - - # The collect timed fee collect module - timedFeeCollectModule: TimedFeeCollectModuleParams - - # The multirecipient fee collect module - multirecipientFeeCollectModule: MultirecipientFeeCollectModuleParams - - # The erc4626 vault fee collect module - erc4626FeeCollectModule: Erc4626FeeCollectModuleParams - - # The aave fee collect module - aaveFeeCollectModule: AaveFeeCollectModuleParams - - # unknown collect module only use if you know what your doing - unknownCollectModule: UnknownCollectModuleParams -} -``` - - - -Please note you can only supply one of these if you supply more than one the API will throw. We have to do it this way with optional parameters as GraphQL does not support unions on request yet. - -##### freeCollectModule - -This module works by allowing anyone to collect with no fee or no limit or no time. It just allows anyone to collect your publication. - -> 📘 freeCollectModule object constraints -> -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "freeCollectModule": { - "followerOnly": false - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### revertCollectModule - -This module works by disallowing all collects. If set if someone tried to collect from the contract level it would throw and revert. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "revertCollectModule": true - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### feeCollectModule - -This collect module has no time limit, followers only unlimited mints, and an optional referral fee. - -> 📘 feeCollectModule object constraints -> -> - unlimited collects can be done -> - currency must be a whitelisted module currency or it will throw an error -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "feeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### limitedFeeCollectModule - -This collect module has no time limit, follower only limited mints, and an optional referral fee - -> 📘 limitedFeeCollectModule object constraints -> -> - collect limit is how many you want the max amount to be collected, this is a string number because it can overflow in javascript. -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "limitedFeeCollectModule": { - "collectLimit": "100000", - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### limitedTimedFeeCollectModule - -This collect module has 24 hours with a fee and optional referral fee, follower only limited mints - -> 📘 limitedTimedFeeCollectModule object constraints -> -> - time is hardcoded in the contract as 24 hours you can not edit this time -> - collect limit is how many you want the max amount to be collected, this is a string number because it can overflow in javascript. -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "limitedTimedFeeCollectModule": { - "collectLimit": "100000", - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### timedFeeCollectModule - -This collect module has 24 hours with a fee and optional referral fee, follower only unlimited mints - -> 📘 timedFeeCollectModule object constraints -> -> - time is hardcoded in the contract as 24 hours you can not edit this time -> - unlimited collects can be done within the time period -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "timedFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### multirecipientFeeCollectModule - -This module supports splitting the collect fees between multiple recipients. It also supports timed _and_ limited fee collects optionally, so you can use it to support almost every use case. - -> 📘 multirecipientFeeCollectModule object constraints -> -> - You **must** set at least 1 recipient and a positive collect fee. -> - Every recipient splits the amount based on the `split` property, which takes values from 1-100 and the total **must** add up to 100. -> - Limited collects are _optional_ and apply only if you set a value to property `collectLimit`. Otherwise leave unset. -> - Timed collects are also _optional_ and apply only when you set `endTimestamp` property. -> - The remaining options perform the same way as in all other modules. - -```json JSON -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "multirecipientFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipients": [ - { - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "split": 50 - }, - { - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaB", - "split": 50 - } - ], - "referralFee": 10, - "followerOnly": false, - // "collectLimit": 5 -- if set, will end up in a limited collect - // "endTimestamp": "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### erc4626FeeCollectModule - -This module can be used when you want to set the fees to an ERC4626-compatible vault contract, generates receipt shares and forwards these to a given recipient, also supports optional timed and limited collects, exactly the same way as Multirecipient Fee Collect Module does. - -> 📘 erc4626FeeCollectModule object constraints -> -> - `vault` and `recipient`properties are required. `vault` must be a valid erc4626 contract address, while recipient must be a wallet address belonging to the user who will receive the generated shares after depositing to the vault. -> - `amount` is also required -> - All other properties apply as in the remaining - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "multirecipientFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "vault" "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", // must be a valid erc4626 vault - "referralFee": 10, - "followerOnly": false, - // collectLimit: 5 -- if set, will end up in a limited collect - // endTimestamp: "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -##### aaveFeeCollectModule - -This collect module receives the fees and instantly deposits them on Aave v3 on Polygon. Also optionally supports timed and limited collects. - -> 📘 aaveFeeCollectModule -> -> - You don't need to know the contract address for the pool you want to deposit too. You just need to supply the address of the whitelisted currency in the `amount` property and the API will try to find the contract and error out if the pool does not exist. -> - You also need to supply a `recipient` who will receive the aTokens after depositing to Aave v3. - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "multirecipientFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", // must be supported by polygon aave v3 - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10, - "followerOnly": false, - // collectLimit: 5 -- if set, will end up in a limited collect - // endTimestamp: "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } -``` - - - -##### unknownCollectModule - -This collect module is unknown and not type supported in the API. This means if you use this you have to encode and supply the data yourself to the API, the API will still allow you to use an unknown collect module but it won't validate it. Only use unknown collect modules if you can trust the collect module and know what you're doing. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - unknownCollectModule: { - contractAddress: "0x1F68931Bc4C77b2D394Bf23cb1A45842501da10e", - data: "0x01" - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - - - -#### referenceModule - required - -Modules are quite complex, each module needs to be encoded in the correct way for the contracts not to throw. We tried to abstract any complex stuff out for you here and allow you to just pass in the params in web2 style. - -```js -input ReferenceModuleParams { - # The follower only reference module - followerOnlyReferenceModule: Boolean - - # The degree of seperation for who can comment and mirror your stuff - degreesOfSeparationReferenceModule: DegreesOfSeparationReferenceModuleParams - - # unknown reference module - unknownReferenceModule: UnknownReferenceModuleParams -} -``` - - - -##### followerOnlyReferenceModule - -A simple reference module that validates that comments or mirrors originate from a profile owned by a follower. - -This is super easy to toggle just pass in the boolean in the `followerOnlyReferenceModule` property and it turn it on and off for that publication. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "followerOnlyReferenceModule": true - } - } -``` - - - -##### degreesOfSeparationReferenceModule - -This reference module allows you to set the degrees of separation in who can comment or mirror. If you do not know what degrees of separation you may have heard of the rule that with up to 6 links you can connect people together. With the protocol being open bots and spam is a things we want to handle and this tackles this. - -settings: - -`commentsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can comment. - -`mirrorsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can mirror. - -`degreesOfSeparation` - Int - Max 4 degrees - -- 0 degrees = nobody can comment or mirror including the poster -- 1 degree = only the profile who published it profiles it follows can comment and mirror -- 2 degree = only the profile who published it profiles it follows and the profiles they follow can comment and mirror it. -- 3 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow can comment and mirror it. -- 4 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow and the profiles they follow can comment and mirror it. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "degreesOfSeparationReferenceModule": { - "commentsRestricted": true, - "mirrorsRestricted": true, - "degreesOfSeparation": 2 - } - } - } -``` - - - -##### unknownReferenceModule - -This reference module is unknown and not type supported in the API. This means if you use this you have to encode and supply the data yourself to the API, the API will still allow you to use the unknown reference module but it won't validate it. Only use unknown reference modules if you can trust the reference module and know what you're doing. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "unknownReferenceModule": { - "contractAddress": "0x1F68931Bc4C77b2D394Bf23cb1A45842501da10e", - "data": "0x01" - } - } - } -``` - - - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. - -## Putting it together - - shows you a live running example of how you would generate the signed typed data from the API and send it through the `withSig` methods. - -# Gasless - -> 🚧 If you are on mumbai anyone can use gasless but if your on polygon only whitelisted apps can currently use this - -You have 2 options when doing gasless you have `broadcast` and also the `dispatcher`. The dispatcher supports a subset of methods that allows you to do actions without signing, these actions are protocol calls that can not drain funds from any wallet making them classed as safe actions, not all methods are supported by the dispatcher. Posting is one of those allowed dispatcher methods. You can set up a dispatcher for the user using and then broadcast that transaction which is described in that document. - -> 📘 Full code example of gasless -> -> - -## Broadcast - -This doc explains how you would broadcast a transaction with the demo example in there. You basically use all of the examples in the GitHub code snippet but instead of calling the `withSig` methods on the hub directly, you pass the signature into the broadcast call. This is all shown in the full code GitHub example above. - -## Using dispatcher - -This takes in the same request as the `withSig` method so nothing needs to change in that regard. You then can track the `txId` to see what it is indexed. Look at the code examples for more low-level detail. - -```javascript Example operation -mutation CreateCommentViaDispatcher { - createCommentViaDispatcher(request: { - profileId: "0x03", - publicationId: "0x01-0x01", - contentURI: "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - collectModule: { - revertCollectModule: true - }, - referenceModule: { - followerOnlyReferenceModule: false - } - }) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example result -{ - "data": { - "createPostViaDispatcher": { - "txHash": "0xc37eed339fb06320906fdb0a0078ae8e5e7d6f1496e01084489180cd3cb3abe6", - "txId": "83ae3af8-220c-4e9d-be7c-6cdf3b50fa44" - } - } -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -# - -# Using LensClient SDK - -```typescript -const metadata = { - // valid metadata -}; - -// upload metadata to ipfs or arweave - upload is your custom function that returns contentURI -const contentURI = await upload(metadata); - -// create a comment via dispatcher, you need to have the dispatcher enabled for the profile -const viaDispatcherResult = await lensClient.publication.createCommentViaDispatcher({ - profileId, - publicationId: '', - contentURI, - collectModule: { - revertCollectModule: true, // collect disabled - }, - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// or with typedData that require signature and broadcasting -const typedDataResult = await lensClient.publication.createCommentTypedData({ - profileId, - publicationId: '', - contentURI, - collectModule: { - revertCollectModule: true, // collect disabled - }, - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// sign and broadcast -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/create-mirror-typed-data.md b/documents/Lens API/publication-1/create-mirror-typed-data.md deleted file mode 100644 index 8e7d8ca..0000000 --- a/documents/Lens API/publication-1/create-mirror-typed-data.md +++ /dev/null @@ -1,445 +0,0 @@ ---- -title: "Mirror" -slug: "create-mirror-typed-data" -hidden: false -createdAt: "2022-02-18T11:31:14.976Z" -updatedAt: "2023-03-16T15:16:47.024Z" ---- -This API call allows you to get the typed data to then call the `withSig` method to mirror a publication from a profile on lens. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -> 📘 Hot tip -> -> It's super easy to enable modules within your publication using this typed data approach as the server lifts all the encoding and decoding of the modules for you. This allows you to just supply it as you would if you were using a web2 API. - -```javascript Example operation -mutation CreateMirrorTypedData { - createMirrorTypedData(request: { - profileId: "0x03", - publicationId: "0x01-0x01", - referenceModule: { - followerOnlyReferenceModule: false - } - }) { - id - expiresAt - typedData { - types { - MirrorWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - profileIdPointed - pubIdPointed - referenceModule - referenceModuleData - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createMirrorTypedData": { - "id": "34c2e30f-658b-4fc1-a985-d4a5f795d47d", - "expiresAt": "2022-02-21T16:29:20.000Z", - "typedData": { - "types": { - "MirrorWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645460960, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleInitData": "0x" - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createMirrorTypedData( - request: CreateMirrorRequest! - ): CreateMirrorBroadcastItemResult! -} -``` -```javascript Request -input CreateMirrorRequest { - # Profile id - profileId: ProfileId! - - # Publication id of what you want to mirror on remember if this is a comment it will be that as the id - publicationId: InternalPublicationId! - - # The reference module info - referenceModule: ReferenceModuleParams -} - -# ProfileId custom scalar type -scalar ProfileId - -# Internal publication id custom scalar type -scalar InternalPublicationId - -input ReferenceModuleParams { - # The follower only reference module - followerOnlyReferenceModule: Boolean -} -``` -```javascript Response -# The broadcast item -type CreateMirrorBroadcastItemResult { - # This broadcast item ID - id: BroadcastId! - - # The date the broadcast item expiries - expiresAt: DateTime! - - # The typed data - typedData: CreateMirrorEIP712TypedData! -} - -# The eip 712 typed data domain -type EIP712TypedDataDomain { - # The name of the typed data domain - name: String! - - # The chainId - chainId: ChainId! - - # The version - version: String! - - # The verifying contract - verifyingContract: ContractAddress! -} - -# The eip 712 typed data field -type EIP712TypedDataField { - # The name of the typed data field - name: String! - - # The type of the typed data field - type: String! -} - -# The mirror eip 712 typed data -type CreateMirrorEIP712TypedData { - # The types - types: CreateMirrorEIP712TypedDataTypes! - - # The typed data domain - domain: EIP712TypedDataDomain! - - # The values - value: CreateMirrorEIP712TypedDataValue! -} - -# The mirror eip 712 typed data types -type CreateMirrorEIP712TypedDataTypes { - MirrorWithSig: [EIP712TypedDataField!]! -} - -# The mirror eip 712 typed data value -type CreateMirrorEIP712TypedDataValue { - nonce: Nonce! - deadline: UnixTimestamp! - profileId: ProfileId! - profileIdPointed: ProfileId! - pubIdPointed: PublicationId! - referenceModule: ContractAddress! - referenceModuleData: ReferenceModuleData! -} - -# reference module data scalar type -scalar ReferenceModuleData - -# Broadcast scalar id type -scalar BroadcastId - -# Contract address custom scalar type -scalar ContractAddress - -# ProfileId custom scalar type -scalar ProfileId - -# UnixTimestamp custom scalar type -scalar UnixTimestamp -``` - - - -## Request - -Let's touch on this request so it's super clear. - -### profiled - required - -You have to pass in a `profileId` that is mandatory. - -### publicationId - required - -You have to pass in a `publicationId ` that is mandatory. - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -#### referenceModule - required - -Modules are quite complex, each module needs to be encoded in the correct way for the contracts not to throw. We tried to abstract any complex stuff out for you here and allow you to just pass in the params in web2 style. Mirrors can have their own reference modules as well separate from the mirrored publication. Please note to mirror from a profile it must pass the reference module check which is defined in `canMirror`. - -```js -input ReferenceModuleParams { - # The follower only reference module - followerOnlyReferenceModule: Boolean - - # The degree of seperation for who can comment and mirror your stuff - degreesOfSeparationReferenceModule: DegreesOfSeparationReferenceModuleParams - - # unknown reference module - unknownReferenceModule: UnknownReferenceModuleParams -} -``` - - - -##### followerOnlyReferenceModule - -A simple reference module that validates that comments or mirrors originate from a profile owned by a follower. - -This is super easy to toggle just pass in the boolean in the `followerOnlyReferenceModule` property and it turns it on and off for that publication. - -Usage: - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "referenceModule": { - "followerOnlyReferenceModule": true - } - } -``` - - - -##### degreesOfSeparationReferenceModule - -This reference module allows you to set the degrees of separation in who can comment or mirror. If you do not know what degrees of separation you may have heard of the rule that with up to 6 links you can connect people together. With the protocol being open bots and spam is a things we want to handle and this tackles this. - -settings: - -`commentsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can comment. - -`mirrorsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can mirror. - -`degreesOfSeparation` - Int - Max 4 degrees - -- 0 degrees = nobody can comment or mirror including the poster -- 1 degree = only the profile who published it profiles it follows can comment and mirror -- 2 degree = only the profile who published it profiles it follows and the profiles they follow can comment and mirror it. -- 3 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow can comment and mirror it. -- 4 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow and the profiles they follow can comment and mirror it. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "degreesOfSeparationReferenceModule": { - "commentsRestricted": true, - "mirrorsRestricted": true, - "degreesOfSeparation": 2 - } - } - } -``` - - - -##### unknownReferenceModule - -This reference module is unknown and not type supported in the API. This means if you use this you have to encode and supply the data yourself to the API, the API will still allow you to use the unknown reference module but it won't validate it. Only use unknown reference modules if you can trust the reference module and know what you're doing. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "unknownReferenceModule": { - "contractAddress": "0x1F68931Bc4C77b2D394Bf23cb1A45842501da10e", - "data": "0x01" - } - } - } -``` - - - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. - -## Putting it together - - shows you a live running example of how you would generate the signed typed data from the API and send it through the `withSig` methods. - -# Gasless - -> 🚧 If you are on mumbai anyone can use gasless but if your on polygon only whitelisted apps can currently use this - -You have 2 options when doing gasless you have `broadcast` and also the `dispatcher`. The dispatcher supports a subset of methods that allows you to do actions without signing, these actions are protocol calls that can not drain funds from any wallet making them classed as safe actions, not all methods are supported by the dispatcher. Posting is one of those allowed dispatcher methods. You can set up a dispatcher for the user using and then broadcast that transaction which is described in that document. - -> 📘 Full code example of gasless -> -> - -## Broadcast - -This doc explains how you would broadcast a transaction with the demo example in there. You basically use all of the examples in the GitHub code snippet but instead of calling the `withSig` methods on the hub directly, you pass the signature into the broadcast call. This is all shown in the full code GitHub example above. - -## Using dispatcher - -This takes in the same request as the `withSig` method so nothing needs to change in that regard. You then can track the `txId` to see what it is indexed. Look at the code examples for more low-level detail. - -```javascript Example operation -mutation CreateMirrorViaDispatcher { - createMirrorViaDispatcher(request: { - profileId: "0x03", - publicationId: "0x01-0x01", - referenceModule: { - followerOnlyReferenceModule: false - } - }) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example result -{ - "data": { - "createPostViaDispatcher": { - "txHash": "0xc37eed339fb06320906fdb0a0078ae8e5e7d6f1496e01084489180cd3cb3abe6", - "txId": "83ae3af8-220c-4e9d-be7c-6cdf3b50fa44" - } - } -} -``` - - - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -# - -# Using LensClient SDK - -```typescript -// create a mirror via dispatcher, you need to have the dispatcher enabled for the profile -const viaDispatcherResult = await lensClient.publication.createMirrorViaDispatcher({ - profileId, - publicationId: "", - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// or with typedData that require signature and broadcasting -const typedDataResult = await lensClient.publication.createMirrorTypedData({ - profileId, - publicationId: "", - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// sign and broadcast -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/create-post-typed-data.md b/documents/Lens API/publication-1/create-post-typed-data.md deleted file mode 100644 index d37c1fb..0000000 --- a/documents/Lens API/publication-1/create-post-typed-data.md +++ /dev/null @@ -1,837 +0,0 @@ ---- -title: "Post" -slug: "create-post-typed-data" -hidden: false -createdAt: "2022-02-18T11:30:30.783Z" -updatedAt: "2023-05-12T21:12:08.168Z" ---- -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it [here](https://eips.ethereum.org/EIPS/eip-712). - -Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified. - -When using this API, the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request. - -We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the `withSig` methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions. - -# API Design - -> 📘 Hot tip -> -> It's super easy to enable modules within your publication using this typed data approach as the server lifts all the encoding and decoding of the modules for you. This allows you to just supply it as you would if you were using a web2 API. - -```javascript Example request -mutation CreatePostTypedData { - createPostTypedData(request: { - profileId: "0x03", - contentURI: "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - collectModule: { - revertCollectModule: true - }, - referenceModule: { - followerOnlyReferenceModule: false - } - }) { - id - expiresAt - typedData { - types { - PostWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - contentURI - collectModule - collectModuleInitData - referenceModule - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createPostTypedData": { - "id": "18ad653a-af18-4be5-9246-06be8dcaf3f9", - "expiresAt": "2022-02-21T13:00:37.000Z", - "typedData": { - "types": { - "PostWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "contentURI", - "type": "string" - }, - { - "name": "collectModule", - "type": "address" - }, - { - "name": "collectModuleInitData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645448437, - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl.json", - "collectModule": "0x45B7907d5c5d2aF9157898601B7B3e18670891c3", - "collectModuleInitData": "0x", - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` - -## Request - -Let's touch on this request so its super clear. - -### profileId - required - -You have to pass in a `profileId` that is mandatory. - -### contentURI - required - -The metadata holds the main context of a publication, your content, as well as the media items attached to it, and is the metadata that people get when they collect. [Metadata standards](doc:metadata-standards) are defined here if you want to read what standard we have set. The link passed to use must be able to be called from our server and hold the standards we set out or we will not index the publication. - -#### collectModule - required - -See collect module options [here](https://docs.lens.xyz/docs/create-post-typed-data#collect-modules). - -## Putting it together - - shows you a live running example of how you would generate the signed typed data from the API and send it through the `withSig` methods. - -# Gasless - -> 🚧 If you are on mumbai anyone can use gasless but if your on polygon only whitelisted apps can currently use this - -You have 2 options when doing gasless you have `broadcast` and also the `dispatcher`. The dispatcher supports a subset of methods that allows you to do actions without signing, these actions are protocol calls that can not drain funds from any wallet making them classed as safe actions, not all methods are supported by the dispatcher. Posting is one of those allowed dispatcher methods. You can set up a dispatcher for the user using and then broadcast that transaction which is described in that document. - -> 📘 Full code example of gasless -> -> - -## Broadcast - -This doc explains how you would broadcast a transaction with the demo example in there. You basically use all of the examples in the GitHub code snippet but instead of calling the `withSig` methods on the hub directly, you pass the signature into the broadcast call. This is all shown in the full code GitHub example above. - -## Using dispatcher - -This takes in the same request as the `withSig` method so nothing needs to change in that regard. You then can track the `txId` to see what it is indexed. Look at the code examples for more low level detail. - -```javascript Example operation -mutation CreatePostViaDispatcher { - createPostViaDispatcher( - request: { - profileId: "0x01" - contentURI: "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl" - collectModule: { freeCollectModule: { followerOnly: true } } - referenceModule: { followerOnlyReferenceModule: false } - } - ) { - ... on RelayerResult { - txHash - txId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example result -{ - "data": { - "createPostViaDispatcher": { - "txHash": "0xc37eed339fb06320906fdb0a0078ae8e5e7d6f1496e01084489180cd3cb3abe6", - "txId": "83ae3af8-220c-4e9d-be7c-6cdf3b50fa44" - } - } -} -``` - -# Hooking in without using the type data - -You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what `seaport` on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing. - -# Using LensClient SDK - -```typescript -const metadata = { - // valid metadata -}; - -// upload metadata to ipfs or arweave - upload is your custom function that returns contentURI -const contentURI = await upload(metadata); - -// create a post via dispatcher, you need to have the dispatcher enabled for the profile -const viaDispatcherResult = await lensClient.publication.createPostViaDispatcher({ - profileId, - contentURI, - collectModule: { - revertCollectModule: true, // collect disabled - }, - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// or with typedData that require signature and broadcasting -const typedDataResult = await lensClient.publication.createPostTypedData({ - profileId, - contentURI, - collectModule: { - revertCollectModule: true, // collect disabled - }, - referenceModule: { - followerOnlyReferenceModule: false, // anybody can comment or mirror - }, -}); - -// sign and broadcast - -``` - -The `contentURI` can be either an IPFS or Arweave hash formatted in the following way: - -```javascript -// IPFS -contentURI: ipfs://your-ipfs-hash - -// Arweave -contentURI: https://arweave.net/your-arweave-hash -// or -contentURI: ar://your-arweave-hash - -// when uploading to Arweave, be sure to set the "Content-Type" to "application/json" -``` - -### Collect Modules - -Modules are quite complex, each module needs to be encoded in the correct way for the contracts not to throw. We tried to abstract any complex stuff out for you here and allow you to just pass in the params in web2 style. - -```js -input CollectModuleParams { - # The collect free collect module - freeCollectModule: Boolean - - # The collect revert collect module - revertCollectModule: Boolean - - # The collect fee collect module - feeCollectModule: FeeCollectModuleParams - - # The collect limited fee collect module - limitedFeeCollectModule: LimitedFeeCollectModuleParams - - # The collect limited timed fee collect module - limitedTimedFeeCollectModule: LimitedTimedFeeCollectModuleParams - - # The collect timed fee collect module - timedFeeCollectModule: TimedFeeCollectModuleParams - - # The new simple collect module that covers most usecases - simpleCollectModule: SimpleCollectModuleParams - - # The multirecipient fee collect module - multirecipientFeeCollectModule: MultirecipientFeeCollectModuleParams - - # The erc4626 vault fee collect module - erc4626FeeCollectModule: Erc4626FeeCollectModuleParams - - # The aave fee collect module - aaveFeeCollectModule: AaveFeeCollectModuleParams - - # unknown collect module only use if you know what your doing - unknownCollectModule: UnknownCollectModuleParams -} -``` - -Please note you can only supply one of these if you supply more than one the API will throw. We have to do it this way with optional parameters as GraphQL does not support unions on request yet. - -##### simpleCollectModule - -This is the latest collect module that supports most use cases, including paid collects, limited and timed free collects and more! - -> 📘 Hot tip -> -> We highly recommend you to migrate to this collect module as it provides the most straightforward integration! - -Some examples: - -###### Post collectible up to 100 times for free - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "simpleCollectModule": { - "collectLimit": "100", - "followerOnly": false, - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -###### Now same as above but only for your followers - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "simpleCollectModule": { - "collectLimit": "100", - "followerOnly": true, - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -###### Plain old free collect for your followers - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "simpleCollectModule": { - "followerOnly": true, - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -###### Post collectible for 1 MATIC until 1/1/2024 by everyone with no limit, includes 10% referral fee - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "simpleCollectModule": { - "fee": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "1" - }, - "referralFee": 10, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "endTimestamp": "2024-01-01T00:00:00", - "followerOnly": false - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -###### Post collectible for 1 MATIC 100 times until 1/1/2024 by your followers, no referral fee - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "simpleCollectModule": { - "fee": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "1" - }, - "referralFee": 0, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "collectLimit": "100", - "endTimestamp": "2024-01-01T00:00:00", - "followerOnly": true - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -##### freeCollectModule - -This module works by allowing anyone to collect with no fee or no limit or no time. It just allows anyone to collect your publication. - -> 📘 freeCollectModule object constraints -> -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "freeCollectModule": { - "followerOnly": true - } - }, - referenceModule: { - "followerOnlyReferenceModule": false - } - } -``` - -##### revertCollectModule - -This module works by disallowing all collects. If set if someone tried to collect from the contract level it would throw and revert. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "revertCollectModule": true - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### feeCollectModule - -This collect module has no time limit, followers only unlimited mints, and an optional referral fee. - -> 📘 feeCollectModule object constraints -> -> - unlimited collects can be done -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "feeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### limitedFeeCollectModule - -This collect module has no time limit, follower only limited mints, and an optional referral fee. - -> 📘 limitedFeeCollectModule object constraints -> -> - collect limit is how many you want the max amount to be collected, this is a string number because it can overflow in javascript. -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "limitedFeeCollectModule": { - "collectLimit": "100000", - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### limitedTimedFeeCollectModule - -This collect module has 24 hours with a fee and optional referral fee, follower only limited mints - -> 📘 limitedTimedFeeCollectModule object constraints -> -> - time is hardcoded in the contract as 24 hours you can not edit this time -> - collect limit is how many you want the max amount to be collected, this is a string number because it can overflow in javascript -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "limitedTimedFeeCollectModule": { - "collectLimit": "100000", - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### timedFeeCollectModule - -This collect module has 24 hours with a fee and optional referral fee, follower only unlimited mints - -> 📘 timedFeeCollectModule object constraints -> -> - time is hardcoded in the contract as 24 hours you can not edit this time -> - unlimited collects can be done within the time period -> - currency must be a whitelisted module currency or it will throw -> - value which should be passed in as the normal amount not shifted to the decimal places as our server does this for you. So if you want 1 WETH you would enter 1 as a value. -> - recipient is where do you want the funds to go to -> - referralFee is forced here for a clear interface, if you do not want any referral fee put 0. The referral fee is a percent out of 100 so a number is fine but it only supports 2 decimal places aka 10.45 is fine but 10.234 is not. The max amount is 100 you can enter. -> - followerOnly allow or disable the ability to collect by all profiles or only the followers. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "timedFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10.5, - "followerOnly": false - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### multirecipientFeeCollectModule - -This module supports splitting the collect fees between multiple recipients. It also supports timed _and_ limited fee collects optionally, so you can use it to support almost every use case. - -> 📘 multirecipientFeeCollectModule object constraints -> -> - You **must** set at least 1 recipient and a positive collect fee. -> - You can split the amount between up to 5 recipients. -> - Every recipient splits the amount based on the `split` property, which takes values from 1-100 and the total **must** add up to 100. -> - Limited collects are _optional_ and apply only if you set a value to property `collectLimit`. Otherwise leave unset. -> - Timed collects are also _optional_ and apply only when you set `endTimestamp` property. -> - The remaining options perform the same way as in all other modules. - -```json JSON -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "multirecipientFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipients": [ - { - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "split": 50 - }, - { - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaB", - "split": 50 - } - ], - "referralFee": 10, - "followerOnly": false, - // "collectLimit": 5 -- if set, will end up in a limited collect - // "endTimestamp": "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### erc4626FeeCollectModule - -This module can be used when you want to set the fees to an ERC4626-compatible vault contract, generates receipt shares and forwards these to a given recipient, also supports optional timed and limited collects, exactly the same way as Multirecipient Fee Collect Module does. - -> 📘 erc4626FeeCollectModule object constraints -> -> - `vault` and `recipient`properties are required. `vault` must be a valid erc4626 contract address, while recipient must be a wallet address belonging to the user who will receive the generated shares after depositing to the vault. -> - `amount` is also required -> - All other properties apply as in the remaining - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "erc4626FeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "vault" "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", // must be a valid erc4626 vault - "referralFee": 10, - "followerOnly": false, - // collectLimit: 5 -- if set, will end up in a limited collect - // endTimestamp: "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -##### aaveFeeCollectModule - -This collect module receives the fees and instantly deposits them on Aave v3 on Polygon. Also optionally supports timed and limited collects. - -> 📘 aaveFeeCollectModule -> -> - You don't need to know the contract address for the pool you want to deposit too. You just need to supply the address of the whitelisted currency in the `amount` property and the API will try to find the contract and error out if the pool does not exist. -> - You also need to supply a `recipient` who will receive the aTokens after depositing to Aave v3. - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "aaveFeeCollectModule": { - "amount": { - "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011", // must be supported by polygon aave v3 - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "referralFee": 10, - "followerOnly": false, - // collectLimit: 5 -- if set, will end up in a limited collect - // endTimestamp: "2024-01-01T00:00:00" -- if set will set a timestamp after which, attempted collects will revert - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } -} -``` - -##### unknownCollectModule - -This collect module is unknown and not type supported in the API. This means if you use this you have to encode and supply the data yourself to the API, the API will still allow you to use an unknown collect module but it won't validate it. Only use unknown collect modules if you can trust the collect module and know what you're doing. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "unknownCollectModule": { - "contractAddress": "0x1F68931Bc4C77b2D394Bf23cb1A45842501da10e", - "data": "0x01" - } - }, - "referenceModule": { - "followerOnlyReferenceModule": false - } - } -``` - -#### referenceModule - required - -Modules are quite complex, each module needs to be encoded in the correct way for the contracts not to throw. We tried to abstract any complex stuff out for you here and allow you to just pass in the params in web2 style. - -```js -input ReferenceModuleParams { - # The follower only reference module - followerOnlyReferenceModule: Boolean - - # The degree of seperation for who can comment and mirror your stuff - degreesOfSeparationReferenceModule: DegreesOfSeparationReferenceModuleParams - - # unknown reference module - unknownReferenceModule: UnknownReferenceModuleParams -} -``` - -##### followerOnlyReferenceModule - -A simple reference module that validates that comments or mirrors originate from a profile owned by a follower. - -This is super easy to toggle just pass in the boolean in the `followerOnlyReferenceModule` property and it turns it on and off for that publication. - -Usage: - -```json -{ - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "freeCollectModule": { "followerOnly": false } - }, - referenceModule: { - "followerOnlyReferenceModule": true - } - } -``` - -##### degreesOfSeparationReferenceModule - -This reference module allows you to set the degrees of separation in who can comment or mirror. If you do not know what degrees of separation you may have heard of the rule that with up to 6 links you can connect people together. With the protocol being open bots and spam is a things we want to handle and this tackles this. - -settings: - -`commentsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can comment. - -`mirrorsRestricted` - Boolean - if it's set to true the degree of separation is applied if false it is not which means anyone can mirror. - -`degreesOfSeparation` - Int - Max 4 degrees - -- 0 degrees = nobody can comment or mirror including the poster -- 1 degree = only the profile who published it profiles it follows can comment and mirror -- 2 degree = only the profile who published it profiles it follows and the profiles they follow can comment and mirror it. -- 3 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow can comment and mirror it. -- 4 degree = only the profile who published it profiles it follows and the profiles they follow and the profiles they follow and the profiles they follow can comment and mirror it. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "degreesOfSeparationReferenceModule": { - "commentsRestricted": true, - "mirrorsRestricted": true, - "degreesOfSeparation": 2 - } - } - } -``` - -##### unknownReferenceModule - -This reference module is unknown and not type supported in the API. This means if you use this you have to encode and supply the data yourself to the API, the API will still allow you to use the unknown reference module but it won't validate it. Only use unknown reference modules if you can trust the reference module and know what you're doing. - -```json -{ - "profileId": "0x03", - "publicationId": "0x01-0x01", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - "collectModule": { - "emptyCollectModule": true - }, - "referenceModule": { - "unknownReferenceModule": { - "contractAddress": "0x1F68931Bc4C77b2D394Bf23cb1A45842501da10e", - "data": "0x01" - } - } - } -``` - -> 📘 The API will support more modules which get whitelisted as they get approved. -> -> as they do this doc will be updated alongside it. \ No newline at end of file diff --git a/documents/Lens API/publication-1/data-availability-comment.md b/documents/Lens API/publication-1/data-availability-comment.md deleted file mode 100644 index 0a55502..0000000 --- a/documents/Lens API/publication-1/data-availability-comment.md +++ /dev/null @@ -1,259 +0,0 @@ ---- -title: "Data Availability (DA) Comment" -slug: "data-availability-comment" -hidden: false -createdAt: "2023-04-26T02:55:15.566Z" -updatedAt: "2023-04-26T16:28:50.003Z" ---- -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -DA transactions allow lens to scale to higher load at cheap costs. It is a great use case for non-financial web3 social transactions like posts, comments, and shares. - -Two types of DA publications are available through the API, one for use with the dispatcher if you have trusted the dispatcher to do stuff on your behalf and one if you wish to use the typed data approach. - -For DA v1, publications can not be collectable or have reference modules. - -The content should be readable right away, so if, for example, you pinned it to IPFS, you can not trigger this call until other nodes have seen it, or it will reject. We suggest using Bundlr for any decentralised storage. - -**DA comments can only be made on another DA publication.** - -# API Design - with the dispatcher - -```javascript Example operation -mutation CreateDataAvailabilityCommentViaDispatcher { - createDataAvailabilityCommentViaDispatcher(request: { - from: "0x03", - commentOn: "0x01-0x01", - contentURI: "ar://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl" - }) { - ... on CreateDataAvailabilityPublicationResult { - id - proofs - dataAvailabilityId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example response -{ - "data": { - "createCommentTypedData": { - "id": "b03ab4b8-580c-4c99-84d0-036480f7f0c4", - "expiresAt": "2022-02-21T14:52:09.000Z", - "typedData": { - "types": { - "CommentWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "contentURI", - "type": "string" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "collectModule", - "type": "address" - }, - { - "name": "collectModuleInitData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645455129, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleData": "0x", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl.json", - "collectModule": "0x2732FfD7f7352c9492089C40A0C3368220a438D4", - "collectModuleInitData": "0x", - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createCommentTypedData( - request: CreatePublicCommentRequest! - ): CreateCommentBroadcastItemResult! -} -``` - - - -# API Design - without dispatcher - -Any time you do any typed data signing for DA, you need to use the`broadcastDataAvailability`, which will broadcast the transaction for you. - -```javascript Example operation -mutation CreateDataAvailabilityCommentTypedData { - createDataAvailabilityCommentTypedData(request: { - from: "0x03", - commentOn: "0x01-0x01", - contentURI: "ar://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl" - }) { - id - expiresAt - typedData { - types { - CommentWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - profileIdPointed - pubIdPointed - contentURI - referenceModuleData - collectModule - collectModuleInitData - referenceModule - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createCommentTypedData": { - "id": "b03ab4b8-580c-4c99-84d0-036480f7f0c4", - "expiresAt": "2022-02-21T14:52:09.000Z", - "typedData": { - "types": { - "CommentWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "contentURI", - "type": "string" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "collectModule", - "type": "address" - }, - { - "name": "collectModuleInitData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645455129, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleData": "0x", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl.json", - "collectModule": "0x2732FfD7f7352c9492089C40A0C3368220a438D4", - "collectModuleInitData": "0x", - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createCommentTypedData( - request: CreatePublicCommentRequest! - ): CreateCommentBroadcastItemResult! -} -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/data-availability-mirror.md b/documents/Lens API/publication-1/data-availability-mirror.md deleted file mode 100644 index dc1f6b8..0000000 --- a/documents/Lens API/publication-1/data-availability-mirror.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -title: "Data Availability (DA) Mirror" -slug: "data-availability-mirror" -hidden: false -createdAt: "2023-04-26T03:13:24.283Z" -updatedAt: "2023-04-26T16:31:14.408Z" ---- -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -DA transactions allow lens to scale to higher load at cheap costs. It is a great use case for non-financial web3 social transactions like posts, comments, and shares. - -Two types of DA publications are available through the API, one for use with the dispatcher if you have trusted the dispatcher to do stuff on your behalf and one if you wish to use the typed data approach. - -For DA v1, publications can not be collectable or have reference modules. - -The content should be readable right away, so if, for example, you pinned it to IPFS, you can not trigger this call until other nodes have seen it, or it will reject. We suggest using Bundlr for any decentralised storage. - -Also, DA mirrors can only be done on another DA publication. - -# API Design - with dispatcher - -```javascript Example operation -mutation CreateDataAvailabilityMirrorViaDispatcher { - createDataAvailabilityMirrorViaDispatcher(request: { - from: "0x03", - mirror: "0x01-0x01" - }) { - ... on CreateDataAvailabilityPublicationResult { - id - proofs - dataAvailabilityId - } - ... on RelayError { - reason - } - } -} -``` -```javascript Example response -{ - "data": { - "createDataAvailabilityMirrorViaDispatcher": { - "id": "34c2e30f-658b-4fc1-a985-d4a5f795d47d", - "expiresAt": "2022-02-21T16:29:20.000Z", - "typedData": { - "types": { - "MirrorWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645460960, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleInitData": "0x" - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createDataAvailabilityMirrorViaDispatcher( - request: CreateDataAvailabilityMirrorRequest! - ): CreateDataAvailabilityPublicationResult! -} -``` - - - -# API Design - without dispatcher - -Any time you do any typed data signing for DA, you need to use the`broadcastDataAvailability`, which will broadcast the transaction for you. - -```javascript Example operation -mutation CreateDataAvailabilityMirrorTypedData { - createDataAvailabilityMirrorTypedData(request: { - from: "0x03", - mirror: "0x01-0x01" - }) { - id - expiresAt - typedData { - types { - MirrorWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - profileIdPointed - pubIdPointed - referenceModule - referenceModuleData - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createDataAvailabilityMirrorViaDispatcher": { - "id": "34c2e30f-658b-4fc1-a985-d4a5f795d47d", - "expiresAt": "2022-02-21T16:29:20.000Z", - "typedData": { - "types": { - "MirrorWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "profileIdPointed", - "type": "uint256" - }, - { - "name": "pubIdPointed", - "type": "uint256" - }, - { - "name": "referenceModuleData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645460960, - "profileId": "0x03", - "profileIdPointed": "0x01", - "pubIdPointed": "0x01", - "referenceModuleInitData": "0x" - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` -```javascript Query interface -type Mutation { - createDataAvailabilityMirrorViaDispatcher( - request: CreateDataAvailabilityMirrorRequest! - ): CreateDataAvailabilityPublicationResult! -} -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/data-availability-post.md b/documents/Lens API/publication-1/data-availability-post.md deleted file mode 100644 index 741bfa5..0000000 --- a/documents/Lens API/publication-1/data-availability-post.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: "Data Availability (DA) Post" -slug: "data-availability-post" -excerpt: "Data Availability = DA" -hidden: false -createdAt: "2023-04-25T23:08:58.618Z" -updatedAt: "2023-05-11T20:09:42.318Z" ---- -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -DA transactions allow lens to scale to higher load at cheap costs. It is a great use case for non-financial web3 social transactions like posts, comments, and shares. - -Two types of DA publications are available through the API, one for use with the dispatcher if you have trusted the dispatcher to do stuff on your behalf and one if you wish to use the typed data approach. - -For DA v1, publications can not be collectable or have reference modules. - -The content should be readable right away, so if, for example, you pinned it to IPFS, you can not trigger this call until other nodes have seen it, or it will reject. We suggest using Bundlr for any decentralised storage. - -# API Design - with dispatcher - -```javascript Example request -mutation CreateDataAvailabilityPostViaDispatcher { - createDataAvailabilityPostViaDispatcher(request: { - profileId: "0x03", - contentURI: "ar://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl" - }) { - ... on CreateDataAvailabilityPublicationResult { - id - proofs - dataAvailabilityId - } - ... on RelayError { - reason - } - } -} -``` - -# API Design - without dispatcher - -Any time you do any typed data signing for DA, you need to use the`broadcastDataAvailability` , which will broadcast the transaction for you. See an example [here](https://github.com/lens-protocol/api-examples/blob/c9b433186a7c1fb521fc16152122d37db8382dcb/src/publications/post-data-availability.ts#L73) and [here](https://github.com/lens-protocol/api-examples/blob/feature/DA/src/broadcast/broadcast-data-availability.ts). - -```javascript Example request -mutation CreateDataAvailabilityPostTypedData { - createDataAvailabilityPostTypedData(request: { - profileId: "0x03", - contentURI: "ar://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl", - }) { - id - expiresAt - typedData { - types { - PostWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - profileId - contentURI - collectModule - collectModuleInitData - referenceModule - referenceModuleInitData - } - } - } -} -``` -```javascript Example response -{ - "data": { - "createDataAvailabilityPostTypedData": { - "id": "18ad653a-af18-4be5-9246-06be8dcaf3f9", - "expiresAt": "2022-02-21T13:00:37.000Z", - "typedData": { - "types": { - "PostWithSig": [ - { - "name": "profileId", - "type": "uint256" - }, - { - "name": "contentURI", - "type": "string" - }, - { - "name": "collectModule", - "type": "address" - }, - { - "name": "collectModuleInitData", - "type": "bytes" - }, - { - "name": "referenceModule", - "type": "address" - }, - { - "name": "referenceModuleInitData", - "type": "bytes" - }, - { - "name": "nonce", - "type": "uint256" - }, - { - "name": "deadline", - "type": "uint256" - } - ] - }, - "domain": { - "name": "Lens Protocol Profile", - "chainId": 80001, - "version": "1", - "verifyingContract": "0x23C1ce2b0865406955Da08F1D31c13fcc3f72A3a" - }, - "value": { - "nonce": 0, - "deadline": 1645448437, - "profileId": "0x03", - "contentURI": "ipfs://QmPogtffEF3oAbKERsoR4Ky8aTvLgBF5totp5AuF8YN6vl.json", - "collectModule": "0x45B7907d5c5d2aF9157898601B7B3e18670891c3", - "collectModuleInitData": "0x", - "referenceModule": "0x0000000000000000000000000000000000000000", - "referenceModuleInitData": "0x" - } - } - } - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/gated.md b/documents/Lens API/publication-1/gated.md deleted file mode 100644 index 209b83b..0000000 --- a/documents/Lens API/publication-1/gated.md +++ /dev/null @@ -1,386 +0,0 @@ ---- -title: "Gated publications" -slug: "gated" -hidden: false -createdAt: "2022-10-06T12:33:07.752Z" -updatedAt: "2023-02-15T10:07:10.979Z" ---- -Lens Protocol now supports the creation of gated content experiences so you can share your garden with just the people you wish. Gated content on Lens allows a trustless way to control content accessibility, as encryption and decryption happen on the client side. The Gated Publications feature uses LIT Protocol decentralized access control behind the scenes. - -### So what can I do with it? - -When you create a new Gated Publication, Lens users can now specify access conditions. Access controls mean that decrypting the publication content and media will only be available to (for example): - -- Users who have collected your publication -- Your followers -- Users that own any NFT from a specific collection (examples: a DAO membership NFT, an NFT of a collected publication posted on Lens, a Nouns DAO NFT etc.). -- Users that own an NFT with a given TokenId, or a range of TokenIds (example: Your first 100 followers) -- The owner of a specific Lens Profile or EOA address, for exclusive content. -- Users who own some balance of an ERC20 token (example: People who have more than X stETH or who hold Y amount of a DAO governance token) -- You can also combine the above using boolean AND and OR conditions. - -The possibility of creating gated experiences enables various kinds of interesting use-cases for gating and monetizing your content in the Lens Ecosystem, giving creators and publishers more control over how content is consumed. - -### Privacy - -The hidden metadata stays private end-to-end as it will be encrypted and decrypted only by the user who fulfills the access control condition. The only public piece of information is the `encryptionKey` which cannot decrypt data by itself, but only when combined with a second key obtained by LIT Protocol, which is only possible when a user successfully satisfies the access conditions. - -### How to use - -To post or decrypt gated content, you will need the `@lens-protocol/sdk-gated` NPM package that you can find [here](https://npmjs.org/@lens-protocol/sdk-gated). It works on both browser and node.js contexts, and allows you to encrypt metadata and upload them to your preferred storage, as well as decrypting any existing metadata as long as you satisfy the conditions. - -First of all, you should know that when posting any gated content, what is actually gated is certain parts of its metadata, specifically the fields: - -`'content' -, 'image', 'media', 'animation_url, 'external_url'` - -This means that the posting process remains the same as with posting regular content, but in this case, the Lens API indexer picks up on some additional properties that will exist on any encrypted metadata generated by the [@lens-protocol/sdk-gated](https://www.npmjs.com/package/@lens-protocol/sdk-gated) package. - -That said, from a client perspective, there are couple of things to take care of. First off, create an instance of the LensSDKGated class. - -```typescript Typescript -const client = await LensGatedSDK.create({ - provider: new Web3Provider(window.ethereum), // or a jsonrpcsigner - signer: someSigner, //from wagmi or a wallet - env: LensEnvironment.Mumbai, -}); - -``` - - - -You can choose between `Polygon`, `Mumbai` and `MumbaiSandbox` environments. - -You can optionally call the `connect` method to initialize it with a given address and environment, otherwise it will get called automatically the first time you try to encrypt or decrypt content with the values it gets from your Provider. - -## Encrypting content - -To encrypt content, you need the `encryptMetadata` method. Gets some metadata, your profileId (to make sure your encrypted data is accessible by you), the access conditions and a file upload handler with the following signature: - -`(encryptedMetadata: EncryptedMetadata): Promise` - -This gives you the freedom to reuse your existing code in order to upload metadata to your preferred storage. It's the final argument the encrypted metadata call in the code example below. It's omitted from the code example for clarity. - -> 📘 Keep in mind -> -> Gated content only supports the Metadata V2 format, see [here](doc:metadata-standards). - -```typescript Encrypting metadata on the browser -import { Web3Provider } from '@ethersproject/providers' -import {AndCondition, OrCondition, FollowCondition, CollectCondition, EncryptedMetadata, EoaOwnership, Erc20TokenOwnership, MetadataV2, NftOwnership, ProfileOwnership, PublicationMainFocus, ContractType, ScalarOperator, LensGatedSDK, LensEnvironment, } from '@lens-protocol/sdk-gated' - -let metadata: MetadataV2 = { - version: '2.0.0', - name: 'name', - description: 'description', - attributes: [], - content: 'content', - metadata_id: '1', - appId: 'app_id', - mainContentFocus: PublicationMainFocus.TextOnly, - locale: 'en', -} - -const uploadMetadataHandler = async (data: EncryptedMetadata): Promise => { - // Upload the encrypted metadata to your server and return a publicly accessible url - return Promise.resolve('test') -} - -const nftAccessCondition: NftOwnership = { - contractAddress: '0x0000000000000000000000000000000000000000', // the address of the NFT collection, make sure it is a valid address depending on the chosen network - chainID: 80001, // the chain ID of the network the NFT collection is deployed on; - contractType: ContractType.Erc721, // the type of the NFT collection, ERC721 and ERC1155 are supported - tokenIds: ['1', '2', '3'], // OPTIONAL - the token IDs of the NFTs that grant access to the metadata, if ommitted, owning any NFT from the collection will grant access -} - -(async () => { - const sdk = await LensGatedSDK.create({ - provider: new Web3Provider(window.ethereum), - signer: someSigner, - env: LensEnvironment.Mumbai, - }); - - // this must be called anytime you change networks, exposed so you can add this to your Web3Provider event handling - // but not necessary to call explicitly - await sdk.connect({ - address: '0x1234123412341234123412341234123412341234', // your signer's wallet address - env: LensEnvironment.Mumbai - }) - - const { contentURI, encryptedMetadata } = await sdk.gated.encryptMetadata( - metadata, - '0x01', // the signed in user's profile id - { - nft: nftAccessCondition - }, // or any other access condition object - uploadMetadataHandler, - ) - console.log(contentURI) - console.log(encryptedMetadata) - // contentURI is ready to be used in the `contentURI` field of your `createPostTypedMetadata` call - // also exposing the encrypted metadata in case you want to do something with it - // ... create post using the Lens API ... - -})(); - -``` -```json Encrypted Metadata JSON Example -{ - "version": "2.0.0", - "metadata_id": "0e2db793-001d-4bf4-a7e2-04788761d065", - "description": "Description", - "content": "This publication is gated", - "external_url": null, - "image": null, - "imageMimeType": null, - "name": "Name", - "attributes": [], - "media": [], - "appId": "api_examples_github", - "animation_url": null, - "encryptionParams": { - "encryptionProvider": "lit-protocol", - "accessCondition": { - "type": "NFT", - "chainID": 80001, - "contractAddress": "0x5832bE646A8a7A1A7a7843efD6B8165aC06e360D", - "contractType": "ERC721", - "tokenIds": [] - }, - "providerSpecificParams": { - "encryptionKey": "a loooong hex string that LIT will use to decrypt your content as long as you satisfy the conditions", - }, - "encryptedFields": { - "content": "WhpXUao7QU7iQg79UsCw0-ptkoy_fSbfEoqEs6_Zj2s=", // encrypted content - "image": null, - "animation_url": null, - "external_url": null - } - }, - "locale": "en-us", - "tags": [ - "using_api_examples" - ], - "mainContentFocus": "TEXT_ONLY" -} -``` - - - -This will give you a `contentURI` that you can then use on your regular posting flow. It also exposes the `encryptedMetadata` object because you will need to supply the `encryptionKey` on your upcoming call to `createPostTypedData`. Don't worry, this key is not enough to decrypt your data, it is used to query LIT Protocol, which upon verification that you do fulfill the access conditions, will then expose the actual decryption key. - -> 📘 Gasless gated posts -> -> You can also post gated content gasless as long as you have enabled the dispatcher in your profile! -> -> When doing so, make sure you use the `createPostViaDispatcher` or `createCommentViaDispatcher` endpoints instead, and the rest of the process stays the same. - -```typescript Create typed data - const createPostRequest = { - profileId, - contentURI: 'ipfs://' + contentURI.path, - collectModule: { - freeCollectModule: { followerOnly: false }, - }, - referenceModule: { - followerOnlyReferenceModule: false, - }, - // ******* added this - gated: { - nft: nftAccessConditions, - encryptedSymmetricKey: - encryptedMetadata.encryptionParams.providerSpecificParams.encryptionKey, - }, - // ******* - }; - - // the remaining code is the same as in regular posting - const signedResult = await signCreatePostTypedData(createPostRequest); - console.log('create post: signedResult', signedResult); - - const typedData = signedResult.result.typedData; - - const { v, r, s } = splitSignature(signedResult.signature); - - const tx = await lensHub.postWithSig({ - profileId: typedData.value.profileId, - contentURI: typedData.value.contentURI, - collectModule: typedData.value.collectModule, - collectModuleInitData: typedData.value.collectModuleInitData, - referenceModule: typedData.value.referenceModule, - referenceModuleInitData: typedData.value.referenceModuleInitData, - sig: { - v, - r, - s, - deadline: typedData.value.deadline, - }, - }); - -``` - - - -Any content you post with the code above will have its metadata fields encrypted and replaced with placeholders. The actual content will only be available to people satisfying the access conditions, after calling `decryptMetadata` on the `@lens-protocol/sdk-gated` package. - -## Decrypting content - -Given you have instantiated a `LensGatedSDK` client with your wallet, and you have fetched some gated publication via the API, you can then simply: - -```typescript -const { error, decrypted } = await sdk.gated.decryptMetadata(encryptedMetadata) -console.log(error) // in case something went wrong or you dont fullfill the criteria -console.log(decrypted) // otherwise, the decrypted MetadataV2 will be here -``` - - - -## Access Condition types - -Here are the supported access condition types. Check out the remaining examples to see how they are used in action. - -> 📘 Remember! -> -> When you supply a condition to the `encryptMetadata` function, it takes a `AccessConditionOutput` object as input, so make sure to wrap it in its corresponding type attribute as described in the following object: - -``` -export type AccessConditionOutput = { - __typename?: 'AccessConditionOutput'; - /** AND condition */ - and?: Maybe; - /** Profile follow condition */ - collect?: Maybe; - /** EOA ownership condition */ - eoa?: Maybe; - /** Profile follow condition */ - follow?: Maybe; - /** NFT ownership condition */ - nft?: Maybe; - /** OR condition */ - or?: Maybe; - /** Profile ownership condition */ - profile?: Maybe; - /** ERC20 token ownership condition */ - token?: Maybe; -}; -``` - - - -### NFT Ownership - -Will evaluate to true if the decryptor owns an NFT from that collection. If `tokenIds` are not provided, then owning _any_ NFT from the collection will satisfy the condition. - -```typescript NFT Ownership -const nftAccessCondition = { - contractAddress: '0x0000000000000000000000000000000000000000', // the address of the NFT collection, make sure it is a valid address depending on the chosen network - chainID: 80001, // the chain ID of the network the NFT collection is deployed on; - contractType: ContractType.Erc721, // the type of the NFT collection, ERC721 and ERC1155 are supported - tokenIds: ['1', '2', '3'], // OPTIONAL - the token IDs of the NFTs that grant access to the metadata, if ommitted, owning any NFT from the collection will grant access -} -``` - - - -### EOA Address Ownership - -Evaluates to true if the decryptor has signed in from the provided EOA address. - -``` -const eoaAccessCondition: EoaOwnership = { - address: '0x0000000000000000000000000000000000000000', // the address of the EOA that grants access to the metadata -} -``` - - - -### ERC20 Token Ownership - -Will evaluate to true if the decryptor satisfies some condition regarding the given ERC20 token. - -``` -const erc20AccessCondition: Erc20TokenOwnership = { - contractAddress: '0x0000000000000000000000000000000000000000', // the address of the ERC20 token that signers should own - chainID: 80001, // the chain ID of the network - amount: '1000000000000000000', // the amount of the ERC20 token that grants access to the metadata - decimals: 18, // the decimals of the ERC20 token that grants access to the metadata - condition: ScalarOperator.GreaterThanOrEqual // the condition that must be met to grant access to the metadata, supported conditions are: '==', '!=', '>', '<', '>=', '<=' -} - -``` - - - -### Profile Ownership - -Will evaluate to true if the decryptor owns that ProfileId - -``` -const profileAccessCondition: ProfileOwnership = { - profileId: '0x01' -} -``` - - - -### Profile Follow - -Will evaluate to true if you follow that ProfileId - -``` -const followAccessCondition: FollowCondition = { - profileId: '0x01', -} -``` - - - -### Collected publication - -Will evaluate to true if the person trying to decrypt the content owns a collected NFT of the given publication. Can take `thisPublication=true` when encrypting metadata for people who will collect that specific pub. You can use either of these 2 properties, but not both of them. - -``` -const collectAccessCondition: CollectCondition = { - thisPublication: true, -} - -const collectAccessCondition2: CollectCondition = { - publicationId: '0x01-0x01', -} -``` - - - -### Boolean conditions - -These support up to 5 conditions and they cannot have nested boolean conditions right now. - -``` -const andCondition: AndCondition = { - criteria: [ - { - token: erc20AccessCondition - }, - { - follow: followAccessCondition - } - ] -} - -const orCondition: OrCondition = { - criteria: [ - { - collect: collectAccessCondition, - }, - { - profile: profileAccessCondition - } - ] -} -``` - - - -### Full stack project setup - -You can view an example full stack application implementing Lens token-gating [here](https://github.com/dabit3/lens-token-gating). \ No newline at end of file diff --git a/documents/Lens API/publication-1/get-publication.md b/documents/Lens API/publication-1/get-publication.md deleted file mode 100644 index 38643b6..0000000 --- a/documents/Lens API/publication-1/get-publication.md +++ /dev/null @@ -1,479 +0,0 @@ ---- -title: "Get publication" -slug: "get-publication" -hidden: false -createdAt: "2022-02-18T11:30:10.353Z" -updatedAt: "2023-03-25T13:08:54.907Z" ---- -> 📘 Full code example -> -> - -This query returns to you the publication information. Remember posts, comments and mirrors are all publications. - -# API Design - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is you have a schema that should explain how the schema should look at what properties exist in that. In these docs we explore code examples and explain key concepts but we will not explain each property that exists in the response for example, as the schema already does that! - -```javascript Example operation -query Publication { - publication(request: { - publicationId: "0x01-0x01" - }) { - __typename - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - ... on Mirror { - ...MirrorFields - } - } -} - -fragment MediaFields on Media { - url - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments - totalUpvotes -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - hasCollectedByMe -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} - -``` -```javascript Example response -{ - "data": { - "publication": { - "__typename": "Post", - "id": "0x01-0x01", - "profile": { - "id": "0x01", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "hey", - "picture": null, - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "", - "description": "", - "content": "Hello", - "media": null, - "attributes": [] - }, - "createdAt": "2022-02-10T09:50:46.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule" - }, - "referenceModule": null, - "appId": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - } -} -``` - - - -> 📘 Hot tip -> -> If you do not know GraphQL that well remember things can be nullable if defined as so in the schema how GraphQL knows its nullable is without the `!` at the end here is an example: -> -> Not nullable: -> -> ownedBy: EthereumAddress! -> -> Nullable: -> -> ownedBy: EthereumAddress -> -> It's always worth generating the TypeScript types for the schema if your application is TypeScript here is a reference to how you would do that - - -## Request - -Let's look into the request a little more: - -### publicationId - -You can query the publication using the `internalPublicationId` and return information about the publication. - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -### txHash - -There is a case where your user does a new post or comment or mirror and you send the transaction. At this point, you do not know the publication id without having to do some extra logic. This is the perfect time where you may want to query the publication by the `txHash` to get the publication and update your internal UI cache or something else. - -Please note you can only supply one of these if you supply more than one the API will throw. We have to do it this way with optional parameters as GraphQL does not support unions on request yet. - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.fetch(request: PublicationQueryRequest); - -type PublicationQueryRequest = { - /** The publication id */ - publicationId?: InputMaybe; - /** The tx hash */ - txHash?: InputMaybe; -}; -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/get-publications.md b/documents/Lens API/publication-1/get-publications.md deleted file mode 100644 index 85f727b..0000000 --- a/documents/Lens API/publication-1/get-publications.md +++ /dev/null @@ -1,558 +0,0 @@ ---- -title: "Get publications" -slug: "get-publications" -hidden: false -createdAt: "2022-02-18T11:30:00.617Z" -updatedAt: "2023-03-16T15:22:53.990Z" ---- -> 📘 Full code example -> -> - -> 🚧 If the user is logged in pass in the auth token as it fix some UX issues with comment ordering - -This query returns a list of publications based on your request query. Remember, posts, comments and mirrors are all publications. - -# API Design - -We have ML ranking on the comments to allow the more relevant comments to appear at the top. By default, this is on, but you can decide to go to normal descending ordering by passing in `commentsOfOrdering`as `DESC`. We will continue improving this ML code to make it better and better. If your app uses this it just inherits this ML work. - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract. It is a counter per each profile. So if @josh posts a publication, that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is that you have a schema that should explain how the schema should look at what properties exist in that. In these docs, we explore code examples and explain key concepts, but we will not explain each property that exists in the response for example, as the schema already does that! - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x01", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10 - }) { - items { - __typename - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - ... on Mirror { - ...MirrorFields - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments - totalUpvotes - totalDownvotes -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - hasCollectedByMe -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} - -``` -```javascript Example response -{ - "data": { - "publications": { - "items": [ - { - "__typename": "Post", - "id": "0x01-0x01", - "profile": { - "id": "0x01", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "hey", - "picture": null, - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "", - "description": "", - "content": "Hello", - "media": null, - "attributes": [] - }, - "createdAt": "2022-02-10T09:50:46.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule" - }, - "referenceModule": null, - "appId": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"0x01-0x01\",\"timestamp\":1644486646,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"0x01-0x01\",\"timestamp\":1644486646,\"cursorDirection\":\"AFTER\"}", - "totalCount": 1 - } - } - } -} -``` -```javascript Query interface -type Query { - publications(request: PublicationsQueryRequest!): PaginatedPublicationResult! -} -``` - - - -You will see the paging result behaviour repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result, you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result, you can pass this previous and next cursor in the request cursor property. - -## Request - -Let's look at the query options we can use here to get a lot of data for different things. - -```json Get comments of a publication -// This returns you the publication comments for publication 0x01-0x01 -{ - "commentsOf": "0x01-0x01", - "commentsOfOrdering": "RANKING", - // we highly suggest on the comment section you show the "relevant" first and - // the "none-relevant" are hidden away and can be showed with a "more" or a tab section UX - // this allows the most relevant comments to be seen - // the spam comments being a bit more out of sight - "commentsRankingFilter: "RELEVANT" - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - } -``` -```json Get publications by profile id -// This returns you the publications for 0x01 profile filtered by the -// the publication types you requested - super cool query! -{ - "profileId": "0x01", - // you can filter the publication types along side it - "publicationTypes": ["POST", "COMMENT", "MIRROR"] - // also dont forget you can filter these queries on sources (appId) as well - // "sources": ["lost-place-dapp"] - } -``` -```json Get publications by collected by wallet address -// This returns you the publications that the `collectedBy` ethereum address -// has collected. -{ - "collectedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - // you can filter the publication types along side it - "publicationTypes": ["POST", "COMMENT"], - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - } -``` -```json Get publications by publication id -// This returns you the publications for given publication ids. -{ - // if you query a internal publication id which does not exist - // then it just will not be returned in the response - "publicationIds": ["0x12-0x02", "0x12-0x03"], - // also dont forget you can filter these queries on sources as well - // "sources": ["lost-place-dapp"] - } -``` - - - -Please note you can only supply one of these if you supply more than one the API will throw. We have to do it this way with optional parameters as GraphQL does not support unions on request yet. - - - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.fetchAll(request: PublicationsQueryRequest); - -type PublicationsQueryRequest = { - /** The ethereum address */ - collectedBy?: InputMaybe; - /** The publication id you wish to get comments for */ - commentsOf?: InputMaybe; - /** The comment ordering type - only used when you use commentsOf */ - commentsOfOrdering?: InputMaybe; - /** The comment ranking filter, you can use - only used when you use commentsOf + commentsOfOrdering=ranking */ - commentsRankingFilter?: InputMaybe; - cursor?: InputMaybe; - customFilters?: InputMaybe>; - limit?: InputMaybe; - metadata?: InputMaybe; - /** Profile id */ - profileId?: InputMaybe; - /** Profile ids */ - profileIds?: InputMaybe>; - /** The publication id */ - publicationIds?: InputMaybe>; - /** The publication types you want to query */ - publicationTypes?: InputMaybe>; - /** The App Id */ - sources?: InputMaybe>; -}; -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/has-collected-publication.md b/documents/Lens API/publication-1/has-collected-publication.md deleted file mode 100644 index 68ee99f..0000000 --- a/documents/Lens API/publication-1/has-collected-publication.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Has collected publication" -slug: "has-collected-publication" -hidden: false -createdAt: "2022-03-14T12:54:32.201Z" -updatedAt: "2023-03-16T16:01:27.565Z" ---- -You need to know if the logged-in user has collected a publication it's viewing, to do this you need to look at the `hasCollectedByMe` property on the publication response. This is shown in the examples when fetching back a publication. - -It will always be false if calling when not logged in, but **_when passing in the auth header it will work_** if that wallet has collected it already. - -# API Design basic - -Please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10, - }) { - items { - __typename - ... on Post { - hasCollectedByMe - } - ... on Comment { - hasCollectedByMe - } - ... on Mirror { - hasCollectedByMe - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -For a single publication: - -```graphql -query Publication { - publication(request: { - publicationId: "0x01-0x01" - }) { - __typename - ... on Post { - hasCollectedByMe - } - } -} -``` - - - -# - -# Using LensClient SDK - -The authorization header is always passed with the API request if the lensClient is authenticated. - -```typescript -const isAuthenticated = await lensClient.authentication.isAuthenticated(); - -// if isAuthenticated === true -// then results from publication queries will contain valid value for hasCollectedByMe - -const result = await lensClient.publication.fetch(request); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/has-mirrored-publication.md b/documents/Lens API/publication-1/has-mirrored-publication.md deleted file mode 100644 index 1e672b4..0000000 --- a/documents/Lens API/publication-1/has-mirrored-publication.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: "Has mirrored publication" -slug: "has-mirrored-publication" -hidden: false -createdAt: "2022-02-18T11:30:21.134Z" -updatedAt: "2023-03-16T15:57:51.807Z" ---- -You need to know if a user has mirrored a certain publication, to do this you need to look at the `mirrors` property on the publication response. - -This returns an array of publications ids of the mirrored publication as a profile can mirror a publication many times. In the mirrors field resolver you can pass in a `profileId` you wish to know the mirrrors state for, most apps would use the logged in users selected profile they are browsing on. - -# API design basic - -please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10, - }) { - items { - __typename - ... on Post { - mirrors(by: "0x01") - } - ... on Comment { - mirrors(by: "0x01") - } - ... on Mirror { - mirrors(by: "0x01") - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -`profileId` for `mirrors` can pass in as a variable easily enough as well. You can imagine passing the logged-in users profile they are browsing on to see if they have mirrored the publication. This can be hooked in like this for every query which returns a publication type (Post or Comment or Mirror) - -```javascript Example operation -query Publications($publicationsRequest: PublicationsQueryRequest!, $profileId: ProfileId) { - publications(request: $publicationsRequest) { - items { - __typename - ... on Post { - mirrors(by: $profileId) - } - ... on Comment { - mirrors(by: $profileId) - } - ... on Mirror { - mirrors(by: $profileId) - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -Or, for a specific publication: - -```graphql -query Publication { - publication(request: { - publicationId: "0x01-0x01" - }) { - __typename - ... on Post { - mirrors(by: "0x01") - } - } -} -``` - - - -# - -# Using LensClient SDK - -Provide `observerId` as an argument to get results in the context of the observer profile. - -```typescript -const observerId = "0x01" - -const result = await lensClient.publication.fetchAll(request, observerId); - -const result = await lensClient.publication.fetch(request, observerId); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/hide-publication.md b/documents/Lens API/publication-1/hide-publication.md deleted file mode 100644 index 81afc83..0000000 --- a/documents/Lens API/publication-1/hide-publication.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Hide publication" -slug: "hide-publication" -hidden: false -createdAt: "2022-02-18T11:31:24.219Z" -updatedAt: "2023-03-16T16:08:54.411Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Once you publish something on-chain you can not remove it, that said if you have used a centralized link for storage you can remove it on the centralized side and the content will not be able to be loaded. If you are using IPFS you can unpin the content. - -Since our indexer moves the content into its own storage our API will still show it. - -However, this mutation allows you to hide the publication you posted from our API's storage, but this DOES NOT do anything on-chain. This is a nice way to allow your users to "delete" publications and it will hide the content and media which was uploaded for it. The publication will still come back so UIs can render all the comments related to it and so it doesn't destroy the pointers, UIs can then design it how they wish but as said above the content and media will not be brought back for the UIs to render. If an application does not use our API and has their own subgraph or indexer they can still show this publication and read from the contentURI if that is not removed. - -You must own the publication to hide it, this is not the functionality to hide stuff that other people post this is to hide a publication you have done. - -# API design - -returns a `VoidScalar` which means no response is returned if you do look at the response data it will be data.hidePublication= null but you do not need to look at the response for anything which returns `void`. If it does not throw it is successful. - -```javascript Example operation -mutation HidePublication { - hidePublication(request: { publicationId: "0x01-0x01" }) -} -``` -```javascript Query interface -type Mutation { - hidePublication(request: HidePublicationRequest!): Void -} -``` -```javascript Request -input HidePublicationRequest { - # Publication id - publicationId: InternalPublicationId! -} - -# Internal publication id custom scalar type -scalar InternalPublicationId -``` - - - -# - -# Using LensClient SDK - -```typescript -await lensClient.publication.hide({ - publicationId: "0x01-0x01", -}); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/media.md b/documents/Lens API/publication-1/media.md deleted file mode 100644 index cce7d88..0000000 --- a/documents/Lens API/publication-1/media.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: "Media uploads" -slug: "media" -hidden: false -createdAt: "2022-11-09T14:28:54.976Z" -updatedAt: "2023-03-27T22:37:21.744Z" ---- -> 📘 Full code example -> -> - -Media endpoints will allow the users to upload AUDIO and VIDEO directly to the API without using IPFS or a storage provider. It will create a copy of the file in our cache and streaming system before pinning it to the decentralised IPFS. All on-chain metadata will point to the decentralised IPFS CID, not our cache system. - -first, you need to create the media type and then push the file to the signed URL. When the file is fully updated using the `SignedURL` you then can create the post/comment with the Media on the metadata. We will explain in more detail below. - -Once the publication is mined, the Lens API will push the file to an IPFS storage making sure on-chain leverages the decentralised vision. - -# API details - -## params on the request - -| name | type | desc | -| :------ | :------- | :---------------------------------------------------------------------------------- | -| itemCid | IfpsCid | You need to precalculate the CID of the file before upload it with the presignedURL | -| type | MimeType | Mime type of the file to upload | -| altTag | String | Alternative text to show on the embed object | -| cover | Url | Url cover image | - -## example - -> 🚧 Only works with AUDIO and VIDEO. - -> 📘 Hot tip -> -> If you want to add a Cover first need to be pushed to a IPFS service, we only take care of the Audio/Video attached on the item media. - -```typescript Example Operation -mutation CreateAttachMediaData($request: { - itemCid: "QmTAznyH583xUgEyY5zdrPB2LSGY7FUBPDddWKj58GmBgp", - type: "video/mp4", - altTag: "video test", - cover: "ifps://QmVwvsJrFzAAb1fPe5uXF4QpPib1T6gjc3xLpS96BUsTL6" - }) { - createAttachMediaData(request: $request) { - media { - altTag - cover - item - source - type - } - signedUrl - } -} -``` -```json JSON -{ - signedUrl: 'https://statics-mumbai-lens-local.s3.eu-west-1.amazonaws.com/upload/QmTAznyH583xUgEyY5zdrPB2LSGY7FUBPDddWKj58GmBgp?Content-Type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZVP63HMY2HDU7HOB%2F20221109%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20221109T145729Z&X-Amz-Expires=300&X-Amz-Signature=820605678aab218a537d9524325fc3f30d70a3c9cbbed4d661bb966aadb3bd13&X-Amz-SignedHeaders=host%3Bx-amz-meta-contenttype%3Bx-amz-meta-createdat%3Bx-amz-meta-issuer%3Bx-amz-meta-user&x-amz-meta-contenttype=video%2Fmp4&x-amz-meta-createdat=1668005849003&x-amz-meta-issuer=lens&x-amz-meta-user=0x2adB75AB75957Cb1A13c23191E153aF167fe7f73', - media: { - item: 'ifps://QmTAznyH583xUgEyY5zdrPB2LSGY7FUBPDddWKj58GmBgp', - type: 'video/mp4', - cover: null, - source: 'LENS', - altTag: 'video test', - - }, -} -``` - - - -> 📘 Tip: -> -> For upload the image need to be done with the http method PUT - -Once you get the presignedUrl [(more info)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html) , you can upload the file to S3. - -```typescript Push file to S3 - -const file = fs.readFileSync(path.join(__dirname, 'file/video.mp4')); -const response = await fetch(signedUrl, {method: 'PUT', body: file}); - - -``` - - - -## Allowed formats - -### Video - -- video / webm -- video / mp4 -- video / x - m4v -- video / ogv -- video / ogg - -### Audio - -- audio / wav -- audio / mpeg -- audio / ogg -- audio / midi - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.createAttachMediaData({ - itemCid: "QmTAznyH583xUgEyY5zdrPB2LSGY7FUBPDddWKj58GmBgp", - type: "video/mp4", - altTag: "video test", - cover: "ifps://QmVwvsJrFzAAb1fPe5uXF4QpPib1T6gjc3xLpS96BUsTL6" -}); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/metadata-publication-filters.md b/documents/Lens API/publication-1/metadata-publication-filters.md deleted file mode 100644 index 8d0a100..0000000 --- a/documents/Lens API/publication-1/metadata-publication-filters.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: "Metadata filters - publication" -slug: "metadata-publication-filters" -hidden: false -createdAt: "2022-09-23T13:16:33.798Z" -updatedAt: "2023-03-16T16:14:57.059Z" ---- -On anything which returns a `Post` `Comment` `Mirror` or anything to do with a publication you have ability to filter on that metadata. - -# API Design - -Will use publications as an example but please note this is a filter on a lot more endpoints so make sure you look at the graphQL schema for the best visibility. - -```javascript example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - metadata: { - locale: "en-us", - contentWarning: { - includeOneOf: [SPOILER] - }, - mainContentFocus: [VIDEO, IMAGE] - tags: { - oneOf: ["tag1"], - all: ["tag2", "tag3"] - } - } - }) { - items { - __typename - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -## Request - -### locale - optional - -This is the locale you which to filter on you can just pass in the region code or language code or both as the example above shows. - -### contentWarning - optional - -By default all flagged content warning publications is not brought back when querying but if you want to bring them back you can add this filter and it will include them. - -#### includeOneOf - -It must include at least one of the array. - -### mainContentFocus - optional - -You can filter on the main content focus, if you do not supply anything for it then it bring back them all. - -### tags - optional - -On a publication you can now add tags for discovery this allows you to filter on them. - -#### oneOf - -It only needs to match 1 of the array passed in to bring it back. Remember publications can be tagged by many tags. - -#### all - -It must match all tags supplied. - - - -# - -# Using LensClient SDK - -```typescript -import { PublicationContentWarning, PublicationMainFocus } from "@lens-protocol/client"; - -const result = await lensClient.publication.fetchAll({ - metadata: { - locale: "en-us", - contentWarning: { - includeOneOf: [PublicationContentWarning.Spoiler], - }, - mainContentFocus: [PublicationMainFocus.Video, PublicationMainFocus.Image], - tags: { - oneOf: ["tag1"], - all: ["tag2", "tag3"], - }, - }, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/metadata-standards.md b/documents/Lens API/publication-1/metadata-standards.md deleted file mode 100644 index c959d68..0000000 --- a/documents/Lens API/publication-1/metadata-standards.md +++ /dev/null @@ -1,502 +0,0 @@ ---- -title: "Metadata standards" -slug: "metadata-standards" -hidden: false -createdAt: "2022-02-18T17:25:31.324Z" -updatedAt: "2023-01-27T08:50:07.818Z" ---- -As everything is an NFT in theory - even if it can not be collected - setting metadata standards is necessary for all publications. This will outline what we propose you should conform to if you are building on Lens Protocol. This does not mean you can not set up your own standards; rather, it means that our API will not index a publication unless it matches these standards. - -These standards can be continuously improved - and we are open to feedback from the community on how we can keep pushing the standards and making them better. - -# Metadata structure - -Lens supports metadata that is structured according to the [official ERC721 metadata standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md) or the [Enjin Metadata suggestions](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema). - -All Metadata standards we set are supported on OpenSea and other marketplaces. - -Here is the full overview of the latest metadata standard we will go through each field below. - -Please note that legacy metadata standards will not be talked about in this doc as we do not want to confuse new builders on what the standards are. Saying this we will always support old standards and migrate the data to keep them as close as possible to new metadata standards. - -Please note `null` will be classed as undefined (optional parameters) if used. - -```ts json -interface PublicationMetadataMedia { - item: Url; - /** - * This is the mime type of media - */ - type?: MimeType | null; - - /** - * The alt tags for accessibility - */ - altTag?: string | null; - - /** - * The cover for any video or audio you attached - */ - cover?: string | null; -} - -enum PublicationMetadataVersions { - one = '1.0.0', - // please use metadata v2 when doing anything! v1 is supported but discontinued. - two = '2.0.0' -} - -enum PublicationMetadataDisplayType { - number = 'number', - string = 'string', - date = 'date', -} - -interface PublicationMetadataAttribute { - displayType?: MetadataDisplayType | undefined | null; - traitType?: string | undefined | null; - value: string; -} - -enum PublicationContentWarning { - NSFW = 'NSFW', - SENSITIVE = 'SENSITIVE', - SPOILER = 'SPOILER', -} - -enum PublicationMainFocus { - VIDEO = 'VIDEO', - IMAGE = 'IMAGE', - ARTICLE = 'ARTICLE', - TEXT_ONLY = 'TEXT_ONLY', - AUDIO = 'AUDIO', - LINK = 'LINK', - EMBED = 'EMBED', -} - -interface Metadata { - /** - * The metadata version. - */ - version: PublicationMetadataVersions; - - /** - * The metadata lens_id can be anything but if your uploading to ipfs - * you will want it to be random.. using uuid could be an option! - */ - metadata_id: string; - - /** - * A human-readable description of the item. - */ - description?: Markdown | undefined | null; - - /** - * The content of a publication. If this is blank `media` must be defined or its out of spec. - */ - content?: Markdown | undefined | null; - - /** - * IOS 639-1 language code aka en or it and ISO 3166-1 alpha-2 region code aka US or IT aka en-US or it-IT - * Full spec > https://tools.ietf.org/search/bcp47 - */ - locale: Locale; - - /** - * Ability to tag your publication - */ - tags?: string[] | undefined | null; - - /** - * Ability to add a content warning - */ - contentWarning?: PublicationContentWarning | undefined | null; - - /** - * Main content focus that for this publication - */ - mainContentFocus: PublicationMainFocus; - - /** - * This is the URL that will appear below the asset's image on OpenSea and others etc - * and will allow users to leave OpenSea and view the item on the site. - */ - external_url?: Url | undefined | null; - - /** - * Name of the item. - */ - name: string; - - /** - * These are the attributes for the item, which will show up on the OpenSea and others NFT trading websites on the - item. - */ - attributes?: PublicationMetadataAttribute[] | undefined | null; - - /** - * legacy to support OpenSea will store any NFT image here. - */ - image?: Url | undefined | null; - - /** - * This is the mime type of image. This is used if you uploading more advanced cover images - * as sometimes IPFS does not emit the content header so this solves the pr - */ - imageMimeType?: MimeType | undefined | null; - - /** - * This is lens supported attached media items to the publication - */ - media?: PublicationMetadataMedia[] | undefined | null; - - /** - * In spec for OpenSea and other providers - also used when using EMBED main publication focus - * A URL to a multi-media attachment for the item. The file extensions GLTF, GLB, WEBM, MP4, M4V, OGV, - * and OGG are supported, along with the audio-only extensions MP3, WAV, and OGA. - * Animation_url also supports HTML pages, allowing you to build rich experiences and interactive NFTs using JavaScript canvas, - * WebGL, and more. Scripts and relative paths within the HTML page are now supported. However, access to browser extensions is not supported. - - */ - animation_url?: Url | undefined | null; - - /** - * This is the appId the content belongs to - */ - appId?: AppId | undefined | null; -} -``` - - - -## version - required! - -### type - -```ts -export enum PublicationMetadataVersions { - one = '1.0.0', - two = '2.0.0, -} -``` - - - -We expect this standard to keep growing as more is added, so defining the version number makes sense to allow us to parse it differently from the API standpoint. This doc will be kept updated with version changes. - -The latest version to use when defining metadata version is - `PublicationMetadataVersions.two` aka ` '2.0.0'` - -## metadata_id - required - -### type - -`string` - -We force a metadata_id on the metadata because we would prefer content for each user is a different IPFS link if using IPFS. so having a metadata_id on here enforces that you want to make each publication for each person different even if they post the same content. You can create your own ids or use [uuid](https://www.npmjs.com/package/uuid) to make sure this will always be different when building up your metadata. - -## description - optional - -> 🚧 Even though its optional we advise you to use this - -### type - -`Markdown` which is a schema type for string - -As your publication can be NFT if collected, you can set a description for it which when you use opensea or other marketplaces it will show context about it to people who own it or may want to trade it. - -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/2288406-lens1.PNG", - "lens1.PNG", - 535 - ], - "sizing": "100" - } - ] -} -[/block] - - - -## content - required if no `media` attached - -### type - -`Markdown` which is a schema type for string - -This contains your publication text. So if you write a post saying "Hello World" and attach an image the "Hello World" will be in that `content` property. - -This supports markdown as well. - -## locale - required - -### type - -`Locale` which is a schema type for string - -IOS 639-1 language code aka en or it and ISO 3166-1 alpha-2 region code aka US or IT aka en-US or it-IT. - -This field describes which language and region the text/media is in. You can just pass in the language if you do not know the region or care about the region. - -example - en-Us - -example of just language - en - -Both would be allowed. - -## tags - -### type - -`string[]` - -Ability to tag dynamically on a publication, this will allow you to do queries on these tags throughout the API. - -- can not have more than 5 tags per publication or it will be rejected -- each tag char length can be no more then 50 - -## contentWarning - -### type - -```ts -export enum PublicationContentWarning { - NSFW = 'NSFW', - SENSITIVE = 'SENSITIVE', - SPOILER = 'SPOILER', -} -``` - - - -Ability to tag content warnings on publications if known already. These by default are hidden from the main APIs you have to explictly ask to include content warning types for them to come back in the queries. - -It is not required but if you try to put something outside of the enum above it be will be rejected by the indexer. - -## mainContentFocus - required - -### type - -```ts -export enum PublicationMainFocus { - VIDEO = 'VIDEO', - IMAGE = 'IMAGE', - ARTICLE = 'ARTICLE', - TEXT_ONLY = 'TEXT_ONLY', - AUDIO = 'AUDIO', - LINK = 'LINK', - EMBED = 'EMBED', -} -``` - - - -Main publication focus is one of the main ways you can add a category for the publication. For example, if you are uploading an image and content then it should be tagged as IMAGE as the main publication focus is that. This will allow clients to build really nice layouts for each main focus. All these main publication focus are filterable on all queries allowing you to bring it whichever you decide your app wants. Data migration has been run on old metadata standards so every publication will have a `mainPublicationFocus` - be as creative as you wish! - -#### VIDEO - -- to pass validation it must include a video in the `media` property which matches one of our supported formats. If it does not it will be rejected. You can of course have other media items in the array alongside the video. Please note we do not check the headers of these items so make sure your web app does not support anything passed these types. - -formats: - - video/webm - - video/mp4 - - video/x-m4v - - video/ogv - - video/quicktime - - video/mpeg - - video/ogg - -#### IMAGE - -- to pass validation it must include an image in the `media` property which matches one of our supported formats. If it does not it will be rejected. You can of course have other media items in the array alongside the image. Please note we do not check the headers of these items so make sure your web app does not support anything passed these types. - -formats: - - image/gif - - image/jpeg - - image/png - - image/tiff - - image/x-ms-bmp - - image/svg+xml - - image/webp - -#### ARTICLE - -- See an article as a way someone can write more than just a small publication. This will allow other UIs knowledge about this as being classed as different from the other publications. The only requirement on this is it must have `content` defined. No constraints are put on the length that's down to the UIs to decide. Articles can have media all attached as you would a normal article. - -#### TEXT_ONLY - -- Text only explains itself, this is a publication with text only. If the person has attached any form of media that should live in image, audio, video, or article. To pass validation on this it needs to have `content` defined and no media items attached with it. - -#### AUDIO - -- to pass validation it must include an audio file in the `media` property which matches one of our supported formats. You can of course have other media items in the array alongside the audio file. Please note we do not check the headers of these items so make sure your web app does not support anything passed these types. - -formats: - - audio/wav - - audio/mpeg - - audio/ogg - - audio/mp4 - - audio/aac - - audio/webm - - audio/flac - -#### LINK - -- This is a way to explain that the main focus is the link itself which may exist within some content. The validation on this is that the content must have a valid `https` link inside it. - -#### EMBED - -- Pushing the standard even further opensea introduced the metadata standard of `animated_url` allowing you to embed a webpage into an NFT. This is follows suite and allows you to define that this publication should be embedded. The validation constraint on this is that it must have an animated_url defined. We advise you like `opensea` do not render these in the timelines, profiles etc and only render it on click on the publication itself. Beware when used badly users could be scammed - make it clear it is an iframe and make sure alerting users and protecting them is your key focus. Also note you can filter these out from your queries if you wish not to support them. - -## external_url - optional - -### type - -`Url` which is a schema type for string - -This is the URL that will appear below the asset's image on OpenSea and others etc and will allow users to leave OpenSea and view the item on the site. You could use this as a deep link into your dApp or something else. - -## name - required - -### type - -`string` - -This is the name of your publication this is a key bit of data OpenSea uses to show the NFT so we have enforced it to make sure no bad NFTs are created. - -## attributes - -Please supply an empty array if no attributes are present as recommended best practice. - -### type - -```ts -export enum PublicationMetadataDisplayType { - number = 'number', - string = 'string', - date = 'date', -} - -export interface PublicationMetadataAttribute { - displayType?: MetadataDisplayType; - traitType?: string; - value: string; -} -``` - - - -To give your publication a little more detail, OpenSea and other marketplaces allow you to add custom "attributes" to your metadata that will show up underneath each of your assets. Remember a publication only becomes an NFT if collected. - -These are the attributes for the item, which will show up on the OpenSea and others NFT trading websites on the item. - -## image - required only optional if you use `animation_url` instead - -### type - -`Url` which is a schema type for string. - -We have brought in a new type called `media` which supports more than just images which we will cover down below but as publications can be NFTs if collected, you must still supply the NFT image link else it will not render an image on opensea if collected by someone. This is the NFT visual the person will be collecting. - -Some rules to follow which will allow this to work all the time: - -- Remember people can upload many images/videos/audio items to media as this is the more social aspect of the metadata but the NFT image itself must only be 1. Make sure you always supply it as what you want the users to see in their wallets when they collect your publication. - -- If you are uploading a video or audio to be collected that needs to go in `animation_url` but the cover for it needs to go in `image` as well. - -## imageMimeType - required if image is supplied - -### type - -`imageMimeType` which is a schema type for string - -### Supported mime types for images - -currently supporting image mime types: - -- image/gif -- image/jpeg -- image/png -- image/tiff -- image/x-ms-bmp -- image/svg+xml -- image/webp - -Sometimes the IPFS link which is passed to the image metadata does not contain the content header for the image. This can cause some issues rendering; to protect against this, when you upload an image make sure you put its mime type in this property as well. This will mean all UIs who build on lens can always render it on their UI. - -## media - required if the content is null - -### type - -`MetadataMedia[]` - -```ts -export interface PublicationMetadataMedia { - item: Url; - /** - * This is the mime type of media - */ - type?: MimeType | null; - - /** - * The alt tags for accessibility - */ - altTag?: string | null; - - /** - * The cover for any video or audio you attached - */ - cover?: string | null; -} -``` - - - -### Supported mime types for images/audio/videos - -#### Images - -- image/gif -- image/jpeg -- image/png -- image/tiff -- image/x-ms-bmp -- image/svg+xml -- image/webp - -#### Videos - -- video/webm -- video/mp4 -- video/x-m4v -- video/ogv -- video/ogg - -#### Audio - -- audio/wav -- audio/mpeg -- audio/ogg - -You can upload an array of images/videos/audios you wish to share with your audience. - -## animation_url - required only optional if you use `image` instead - -### type - -`Url` which is a schema type for string - -A URL to a multi-media attachment for the item. The file extensions GLTF, GLB, WEBM, MP4, M4V, OGV, and OGG are supported, along with the audio-only extensions MP3, WAV, and OGA. - -Animation_url also supports HTML pages, allowing you to build rich experiences and interactive NFTs using JavaScript canvas, WebGL, and more. Scripts and relative paths within the HTML page are now supported. However, access to browser extensions is not supported. - -## appId - optional - -### type - -`string` - -You may want to tag the publication with an `appId` this will then allow you to filter on that `appId` for publications on the [Publication](doc:publication-1) queries. \ No newline at end of file diff --git a/documents/Lens API/publication-1/profile-publications-for-sale.md b/documents/Lens API/publication-1/profile-publications-for-sale.md deleted file mode 100644 index d578c6b..0000000 --- a/documents/Lens API/publication-1/profile-publications-for-sale.md +++ /dev/null @@ -1,456 +0,0 @@ ---- -title: "For sale publications" -slug: "profile-publications-for-sale" -hidden: false -createdAt: "2022-09-23T10:14:23.812Z" -updatedAt: "2023-03-16T16:10:48.606Z" ---- -> 📘 Full code example -> -> - -This query returns you all the publications that are on sale for the profile. - -# API Design - -```javascript Example operation -query ProfilePublicationsForSale { - profilePublicationsForSale(request: { profileId: "0x03" }) { - items { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - hasCollectedByMe -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} -``` -```javascript Example response -{ - "data": { - "profilePublicationsForSale": { - "items": [ - { - "__typename": "Post", - "id": "0x01-0x01", - "profile": { - "id": "0x01", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "hey", - "picture": null, - "coverPicture": null, - "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "", - "description": "", - "content": "Hello", - "media": null, - "attributes": [] - }, - "createdAt": "2022-02-10T09:50:46.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule" - }, - "referenceModule": null, - "appId": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"0x01-0x01\",\"timestamp\":1644486646,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"0x01-0x01\",\"timestamp\":1644486646,\"cursorDirection\":\"AFTER\"}", - "totalCount": 1 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API, this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -## Request - -### profileId - required - -You must supply the `profileId` you wish to get all the publications they have for sale - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.allForSale({ - profileId: "0x03", -}); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/publication-metadata-status.md b/documents/Lens API/publication-1/publication-metadata-status.md deleted file mode 100644 index 3de75ca..0000000 --- a/documents/Lens API/publication-1/publication-metadata-status.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Publication metadata status" -slug: "publication-metadata-status" -hidden: false -createdAt: "2022-09-26T14:18:53.172Z" -updatedAt: "2023-03-16T16:17:08.171Z" ---- -You sometimes need to debug why your publication has not been snapshotted and not appearing when querying the API. This is a very common thing that a lot of developers find and it's because you have not followed the metadata standards set for the publication. This endpoint returns you the error reason so you can see why it failed. - -# API Design - -In the example response, you can see it's saying this one failed because they put metadata version as 200 which isn't a supported version. - -Metadata standards can be read here - -```javascript By publication id -query PublicationMetadataStatus { - publicationMetadataStatus(request: { publicationId: "0x0e-0x34" }) { - status - reason - } -} -``` -```javascript By tx hash -query PublicationMetadataStatus { - publicationMetadataStatus(request: { txHash: "0x13c21e9085f336a1ef5c002afe8dd4f0c6b55126e7468cf3fa98b21c2186d688" }) { - status - reason - } -} -``` -```javascript By tx id -query PublicationMetadataStatus { - publicationMetadataStatus(request: { txId: "ae0650e3-4e12-4be3-9575-1d96b3f8d3d1" }) { - status - reason - } -} -``` -```javascript Example response -{ - "data": { - "publicationMetadataStatus": { - "status": "METADATA_VALIDATION_FAILED", - "reason": "Metadata version 200 is not supported" - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.metadataStatus({ - publicationId: "0x0e-0x34" -}); -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/validate-metadata.md b/documents/Lens API/publication-1/validate-metadata.md deleted file mode 100644 index 0621cd6..0000000 --- a/documents/Lens API/publication-1/validate-metadata.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Validate metadata" -slug: "validate-metadata" -hidden: false -createdAt: "2022-09-26T14:37:30.355Z" -updatedAt: "2023-03-16T15:04:31.479Z" ---- -Some developers get confused when getting started on what is valid metadata and what is not. They miss a property or pass in a wrong type which is hard to debug if you do this. This endpoint allows you to pass in the metadata and see if it's valid, if it is not valid it tells you why. This is great for debugging when you're getting up and running with the LENS API. - -# API Design - -You can validate metadata v1 and metadata v2 within the request, in this example we just show validating on metadata v2 as this is the latest and suggested metadata to follow. - -```javascript Example request -query ValidatePublicationMetadata { - validatePublicationMetadata(request: { - metadatav2: { - version: "2.0.0", - mainContentFocus: TEXT_ONLY, - metadata_id: "6162716327186732", - description: "Description", - locale: "en-US", - content: "Content", - external_url: null, - image: null, - imageMimeType: null, - name: "Name", - attributes: [], - tags: ["using_api_examples"], - appId: "api_examples_github", - } - }) { - valid - reason - } -} -``` -```javascript Example success response -{ - "data": { - "validatePublicationMetadata": { - "valid": true, - "reason": null - } - } -} -``` -```Text Example fail response -{ - "data": { - "validatePublicationMetadata": { - "valid": false, - "reason": "Invalid metadata version - should be 2.0.0" - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const metadata = { - appId: "lenster", - attributes: [ - { - displayType: PublicationMetadataDisplayTypes.String, - traitType: "Created with", - value: "LensClient SDK", - }, - ], - content: "Post created with LensClient SDK", - description: "Description of the post created with LensClient SDK", - locale: "en-US", - mainContentFocus: PublicationMainFocus.TextOnly, - metadata_id: uuid.v4(), - name: "Post created with LensClient SDK", - tags: ["lens-sdk"], - version: "2.0.0", -}; - -const validateResult = await lensClient.publication.validateMetadata(metadata); - -if (!validateResult.valid) { - throw new Error(`Metadata is not valid.`); -} -``` \ No newline at end of file diff --git a/documents/Lens API/publication-1/who-collected-publication.md b/documents/Lens API/publication-1/who-collected-publication.md deleted file mode 100644 index 8f4edd8..0000000 --- a/documents/Lens API/publication-1/who-collected-publication.md +++ /dev/null @@ -1,371 +0,0 @@ ---- -title: "Who collected publication" -slug: "who-collected-publication" -hidden: false -createdAt: "2022-04-21T10:57:03.765Z" -updatedAt: "2023-03-16T16:09:52.455Z" ---- -> 📘 Full code example -> -> - -This query returns to you all the wallets which collected the publication. - -# API Design - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -```javascript Example operation -query WhoCollectedPublication { - whoCollectedPublication(request: { publicationId: "0x0f-0x01" }) { - items { - address - defaultProfile { - id - name - bio - isDefault - attributes { - displayType - traitType - key - value - } - followNftAddress - metadata - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - chainId - verified - } - ... on MediaSet { - original { - url - mimeType - } - } - } - ownedBy - dispatcher { - address - canUseRelay - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - contractAddress - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - } - ... on RevertFollowModuleSettings { - type - } - } - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` -```javascript Example response -{ - "data": { - "whoCollectedPublication": { - "items": [ - { - "address": "0xD93a672802806e129410B070F206f1e4fFdeebD4", - "defaultProfile": { - "id": "0x95", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "followNftAddress": null, - "metadata": null, - "handle": "cherrytree503", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY9LvouQF5jX64sSHF31RL5oUER9hFsaCUShwU1EytsMc", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xD93a672802806e129410B070F206f1e4fFdeebD4", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 6, - "totalPosts": 6, - "totalComments": 11, - "totalMirrors": 3, - "totalPublications": 20, - "totalCollects": 2 - }, - "followModule": { - "type": "FeeFollowModule", - "contractAddress": "0x286c330beFfC157139ffCc32e97aC2f1fC7D1092", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "0.0001" - }, - "recipient": "0xD93a672802806e129410B070F206f1e4fFdeebD4" - } - } - }, - { - "address": "0xc5Aabb752A6A55FAa7040cA12046fd62D3C52193", - "defaultProfile": { - "id": "0xf4", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "hebochang", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qmc2BvR9pUo5N8iVhd6N3TuB3EqQaMr6oqSxrupuHG1qgM", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xc5Aabb752A6A55FAa7040cA12046fd62D3C52193", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 2, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 6, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "address": "0xCbDcF67DF1C4aA7431a6d8710fD7241b52Bc7b6a", - "defaultProfile": { - "id": "0x0e", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "catcat", - "picture": null, - "coverPicture": null, - "ownedBy": "0xCbDcF67DF1C4aA7431a6d8710fD7241b52Bc7b6a", - "dispatcher": null, - "stats": { - "totalFollowers": 5, - "totalFollowing": 1, - "totalPosts": 5, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 7, - "totalCollects": 1 - }, - "followModule": null - } - }, - { - "address": "0xB8189417c4B63c3F093fC0df72F64D983E904aF4", - "defaultProfile": { - "id": "0x2e", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "tastix", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/tastix.svg", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xB8189417c4B63c3F093fC0df72F64D983E904aF4", - "dispatcher": null, - "stats": { - "totalFollowers": 2, - "totalFollowing": 9, - "totalPosts": 6, - "totalComments": 3, - "totalMirrors": 5, - "totalPublications": 14, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "address": "0x2BB2Cd55BE34Eb2D3Cd29Cf7c881aB313961bFC1", - "defaultProfile": { - "id": "0x20", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "excusiux", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmVJ2PjGXjuWa3MRB9x3d4odsBn6E6G85cpWcLDDfBDgme", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x2BB2Cd55BE34Eb2D3Cd29Cf7c881aB313961bFC1", - "dispatcher": null, - "stats": { - "totalFollowers": 5, - "totalFollowing": 4, - "totalPosts": 1, - "totalComments": 2, - "totalMirrors": 1, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "address": "0xe5AB0dDf6704BB1f1918c23D10B316DD41F3a349", - "defaultProfile": { - "id": "0x1e", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "alice", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/QmY7WEGzavjdh9zmLyFTdGj4FvTgjB58Mdvaky9p3NvdiF", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0xe5AB0dDf6704BB1f1918c23D10B316DD41F3a349", - "dispatcher": null, - "stats": { - "totalFollowers": 53, - "totalFollowing": 18, - "totalPosts": 5, - "totalComments": 46, - "totalMirrors": 1, - "totalPublications": 52, - "totalCollects": 39 - }, - "followModule": null - } - }, - { - "address": "0x5545c35680fA583a8320bDBb76e3e57912c09423", - "defaultProfile": null - }, - { - "address": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "defaultProfile": { - "id": "0x0f", - "name": null, - "bio": null, - "isDefault": true, - "attributes": [], - "metadata": null, - "handle": "yoginth", - "picture": { - "original": { - "url": "https://ipfs.infura.io/ipfs/Qma8mXoeorvPqodDazf7xqARoFD394s1njkze7q1X4CK8U", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x3A5bd1E37b099aE3386D13947b6a90d97675e5e3", - "dispatcher": null, - "stats": { - "totalFollowers": 111, - "totalFollowing": 15, - "totalPosts": 89, - "totalComments": 64, - "totalMirrors": 15, - "totalPublications": 168, - "totalCollects": 215 - }, - "followModule": null - } - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"0x0f-0x010xD93a672802806e129410B070F206f1e4fFdeebD40x0b\",\"timestamp\":0,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"0x0f-0x010x3A5bd1E37b099aE3386D13947b6a90d97675e5e30x01\",\"timestamp\":0,\"cursorDirection\":\"AFTER\"}", - "totalCount": 8 - } - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.publication.allWalletsWhoCollected({ - publicationId: "0x01-0x01", -}); -``` \ No newline at end of file diff --git a/documents/Lens API/querying-from-an-application.md b/documents/Lens API/querying-from-an-application.md deleted file mode 100644 index cd2c649..0000000 --- a/documents/Lens API/querying-from-an-application.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Querying from an Application" -slug: "querying-from-an-application" -hidden: false -createdAt: "2022-02-17T10:47:07.065Z" -updatedAt: "2023-03-03T14:30:41.398Z" ---- -## Using GraphQL client - -If you have used GraphQL endpoints before, then you can skip this section, which explains what GraphQL clients you can use to start querying this data. We will suggest two libraries but of course, there are a lot more and no single one is the best, pick the best one for your solution. - -- [Apollo client](doc:apollo-client) -- [URQL](doc:urql) - -For all our code demos we will be using Apollo client to show you how you would call this with the client. - -## Using LensClient SDK - -We built a low-level TypeScript LensClient SDK to make the interactions with the API easier. You will find examples of how to use the LensClient SDK together with the description of each endpoint of the API and related GraphQL requests. The package is available on npm as `@lens-protocol/client`. - -- [LensClient SDK](doc:lensclient-sdk) \ No newline at end of file diff --git a/documents/Lens API/querying-from-an-application/apollo-client.md b/documents/Lens API/querying-from-an-application/apollo-client.md deleted file mode 100644 index 929de36..0000000 --- a/documents/Lens API/querying-from-an-application/apollo-client.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: "Apollo client" -slug: "apollo-client" -hidden: false -createdAt: "2022-02-18T10:45:38.301Z" -updatedAt: "2022-11-09T10:33:08.461Z" ---- -# Apollo client - -[apollo client](https://www.apollographql.com/docs/) is an awesome library that supports all web frameworks like angular, react, and vue but it also supports mobile clients like IOS, Android, and react-native. It is super easy to use. - -## Installing - -open the terminal in your client and run: - -```shell -$ npm install @apollo/client graphql -``` - - - -## Usage - -### Exposing the client - -You can create the `ApolloClient` which you then use for all public API queries like: - -```typescript -import { ApolloClient, InMemoryCache } from '@apollo/client' - -const APIURL = 'https://api-mumbai.lens.dev/'; - -export const apolloClient= new ApolloClient({ - uri: APIURL, - cache: new InMemoryCache(), -}) -``` - - - -### Querying the API - -Then you can use it to query the Lens public API: - -```typescript -import { apolloClient } from './apollo-client'; -import { gql } from '@apollo/client' - -const query = ` - query { - ping - } -` - -export const queryExample = async () => { - const response = await apolloClient.query({ - query: gql(query), - }) - console.log('Lens example data: ', response) -} -``` - - - -A lot of queries need variables to be passed in, this is super easy by using the `variables` argument in the query - -```typescript -import { apolloClient } from './apollo-client'; -import { gql } from '@apollo/client' - -const query = `query($request: ChallengeRequest!) { - challenge(request: $request) { - text - } - } -` - -export const queryExample = async () => { - const response = await apolloClient.query({ - query: gql(query), - variables: { - request: { - address: "0xdfd7D26fd33473F475b57556118F8251464a24eb" - }, - }, - }) - console.log('Lens example data: ', response) -} -``` - - - -### Mutations using the API - -While we use queries to fetch data, we use mutations to modify server-side data. - -```typescript -import { apolloClient } from './apollo-client'; -import { gql } from '@apollo/client' - -const AUTHENTICATION = ` - mutation($request: SignedAuthChallenge!) { - authenticate(request: $request) { - accessToken - refreshToken - } - } -` - -export const authenticate = (address, signature) => { - return apolloClient.mutate({ - mutation: gql(AUTHENTICATION), - variables: { - request: { - address, - signature, - }, - }, - }) -} -``` \ No newline at end of file diff --git a/documents/Lens API/querying-from-an-application/lensclient-sdk.md b/documents/Lens API/querying-from-an-application/lensclient-sdk.md deleted file mode 100644 index 10e515f..0000000 --- a/documents/Lens API/querying-from-an-application/lensclient-sdk.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: "LensClient SDK" -slug: "lensclient-sdk" -hidden: false -createdAt: "2023-03-02T14:50:20.282Z" -updatedAt: "2023-04-11T16:37:58.028Z" ---- -# LensClient SDK - -LensClient SDK is built in TypeScript and it makes the interactions with the API easier. You don't need to worry about GraphQL parts, just call simple methods of the client to achieve what you want with the Lens Protocol. - -## Installing - -Open the terminal and run: - -```shell -$ npm install @lens-protocol/client -``` - - - -## Usage - -Initialize the client with the preferred environment and storage options. - -```typescript -import { LensClient, development } from "@lens-protocol/client"; - -const lensClient = new LensClient({ - environment: development -}); -``` - - - -## Reference - -You can find all methods available in the LensClient SDK grouped by module on [the reference page](doc:client-sdk-reference). - -```typescript -new LensClient(config: LensConfig); - -type LensConfig = { - environment: Environment; - storage?: IStorageProvider; -}; -``` - - - -### Parameters - -`environment: Environment` (required) - possible values `production` or `development` - -- Configure LensClient to use production (`production`) or test (`development`) environment - -`storage: IStorageProvider` (optional) - -- LensClient manages the authentication tokens for you, it can also store them for future use if you provide `storage` instance. It could be browser-based LocalStorage or some storage solution in a React-Native environment, or even a file or database, it's up to you as long as it follows the `IStorageProvider` interface. - -```typescript -export interface IStorageProvider { - getItem(key: string): Promise | string | null; - setItem(key: string, value: string): Promise | Promise | void | string; - removeItem(key: string): Promise | Promise | void; -} -``` - - - -example implementation for LocalStorage - -```typescript -class LocalStorageProvider implements IStorageProvider { - getItem(key: string) { - return window.localStorage.getItem(key); - } - - setItem(key: string, value: string) { - window.localStorage.setItem(key, value); - } - - removeItem(key: string) { - window.localStorage.removeItem(key); - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/querying-from-an-application/urql.md b/documents/Lens API/querying-from-an-application/urql.md deleted file mode 100644 index cfb970f..0000000 --- a/documents/Lens API/querying-from-an-application/urql.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "URQL" -slug: "urql" -hidden: false -createdAt: "2022-02-18T10:46:14.934Z" -updatedAt: "2022-11-09T10:33:19.628Z" ---- -# URQL - -[URQL](https://formidable.com/open-source/urql/) is a lighter library than the apollo client but allows you to query the API all the same. - -## Installing - -open the terminal in your client and run: - -```bash -$ npm install urql graphql -``` - - - -## Usage - -### Exposing the client - -You can create the `URQLClient` which you then use for all public API queries like: - -```typescript -import { createClient } from 'urql' - -const APIURL = 'https://api-mumbai.lens.dev/'; - -export const urqlClient= createClient({ - url: APIURL, -}) -``` - - - -### Querying the API - -Then you can use it to query the Lens public API: - -```typescript -import { urqlClient } from './urql-client'; - -const pingQuery = ` - query { - ping - } -` - -export const queryExample = async () => { - const response = await urqlClient.query(pingQuery).toPromise(); - console.log('Lens example data: ', response) -} -``` \ No newline at end of file diff --git a/documents/Lens API/reactions.md b/documents/Lens API/reactions.md deleted file mode 100644 index 44dfe11..0000000 --- a/documents/Lens API/reactions.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Reactions" -slug: "reactions" -hidden: false -createdAt: "2022-06-20T12:23:10.711Z" -updatedAt: "2023-02-23T00:54:44.495Z" ---- -The reaction resolver allows the profile to react to publications off-chain. - -- [Add reaction](doc:add-reaction) -- [Remove reaction](doc:remove-reaction) -- [Get reaction](doc:get-reaction) -- [Who Reacted](https://docs.lens.xyz/docs/who-reaction-publication) \ No newline at end of file diff --git a/documents/Lens API/reactions/add-reaction.md b/documents/Lens API/reactions/add-reaction.md deleted file mode 100644 index adb03c3..0000000 --- a/documents/Lens API/reactions/add-reaction.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: "Add reaction" -slug: "add-reaction" -hidden: false -createdAt: "2022-06-20T12:25:14.210Z" -updatedAt: "2023-03-14T13:34:39.805Z" ---- -> 📘 Full code example -> -> - -This API call allows you to react to publications with a profile off-chain without needing to sign. For now, reactions are stored on the server but we working on a way to decentralised likes without making UX really horrible with signing on every single reaction. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -# API Design - -Add a reaction to a publication, please note if you pass in another reaction it will toggle it. What I mean by that is if you `UPVOTE` it then `DOWNVOTE` it the server will swap the `UPVOTE` to the `DOWNVOTE`. - -This returns a void so no need to care about its response if successful. - -```javascript Example operation -mutation AddReaction { - addReaction(request: { profileId: "0x01", reaction: UPVOTE, publicationId: "0x02-0x01" }) -} -``` - - - -## Request - -### profileId - required - -The profile id you wish to react from the authenticated user must own that profile. - -### reaction - required - -currently, we support `UPVOTE` and `DOWNVOTE` dApp can make them work as they wish for example on lenster they have a heart button that only uses `UPVOTE` but other dApp use both. - -### publicationId - required - -which publication do you wish to react to - - - -# - -# Using LensClient SDK - -```typescript -import { ReactionTypes } from "@lens-protocol/client"; - -// lensClient is authenticated - -const result = await lensClient.reactions.add({ - profileId: '0x01', - publicationId: '0x02-0x01', - reaction: ReactionTypes.Upvote, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/reactions/get-reaction.md b/documents/Lens API/reactions/get-reaction.md deleted file mode 100644 index 7bd9b6c..0000000 --- a/documents/Lens API/reactions/get-reaction.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Get reaction" -slug: "get-reaction" -hidden: false -createdAt: "2022-06-20T12:25:44.249Z" -updatedAt: "2022-09-23T11:56:20.215Z" ---- -To get the reaction you have to use the field resolver `reaction` passing in a `profileId`. - -Below is a publications query that gets all the publications for profile `0x09`. In the reaction field resolver you can pass in a `profileId` you wish to know the reaction state for, most apps would use the logged in users selected profile they are browsing on. - -# API design - -please note the example below doesn't pick all the content out of the publication it just shows you the field used to get that back. - -```javascript Example operation -query Publications { - publications(request: { - profileId: "0x09", - publicationTypes: [POST, COMMENT, MIRROR], - limit: 10, - }) { - items { - __typename - ... on Post { - reaction(request: { profileId: "0x01" }) - } - ... on Comment { - reaction(request: { profileId: "0x01" }) - } - ... on Mirror { - reaction(request: { profileId: "0x01" }) - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` - - - -`profileId` for `reaction` can pass in as a variable easily enough as well. You can imagine passing the logged-in users profile they are browsing on to see if they have reacted to the publication. This can be hooked in like this for every query which returns a publication type (Post or Comment or Mirror) - -```javascript Example operation -query Publications($publicationsRequest: PublicationsQueryRequest!, $reactionRequest: ReactionFieldResolverRequest) { - publications(request: $publicationsRequest) { - items { - __typename - ... on Post { - reaction(request: $reactionRequest) - } - ... on Comment { - reaction(request: $reactionRequest) - } - ... on Mirror { - reaction(request: $reactionRequest) - } - } - pageInfo { - prev - next - totalCount - } - } -} -``` \ No newline at end of file diff --git a/documents/Lens API/reactions/remove-reaction.md b/documents/Lens API/reactions/remove-reaction.md deleted file mode 100644 index 54efc60..0000000 --- a/documents/Lens API/reactions/remove-reaction.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: "Remove reaction" -slug: "remove-reaction" -hidden: false -createdAt: "2022-06-20T12:53:27.898Z" -updatedAt: "2023-03-14T13:35:41.536Z" ---- -> 📘 Full code example -> -> - -This API call allows you to remove a react from publications with a profile off-chain without needing to sign. For now, reactions are stored on the server but we working on a way to decentralised likes without making UX really horrible with signing on every single reaction. - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -# API Design - -Add a reaction to a publication, please note if you pass in another reaction it will toggle it. What I mean by that is if you `UPVOTE` it then `DOWNVOTE` it the server will swap the `UPVOTE` to the `DOWNVOTE`. - -This returns a void so no need to care about its response if successful. - -```javascript Example operation -mutation RemoveReaction { - removeReaction(request: { profileId: "0x01", reaction: UPVOTE, publicationId: "0x02-0x01" }) -} -``` - - - -## Request - -### profileId - required - -The profile id you wish to remove the react from, the authenticated user must own that profile. - -### reaction - required - -The reaction you want to remove from the publication, we support `UPVOTE` and `DOWNVOTE` dApp can make them work as they wish for example on lenster they have a heart button that only uses `UPVOTE` but other dApp use both. - -### publicationId - required - -which publication do you wish to remove reaction from - - - -# - -# Using LensClient SDK - -```typescript -import { ReactionTypes } from "@lens-protocol/client"; - -// lensClient is authenticated - -const result = await lensClient.reactions.remove({ - profileId: '0x01', - publicationId: '0x02-0x01', - reaction: ReactionTypes.Upvote, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/reactions/who-reaction-publication.md b/documents/Lens API/reactions/who-reaction-publication.md deleted file mode 100644 index 14a122d..0000000 --- a/documents/Lens API/reactions/who-reaction-publication.md +++ /dev/null @@ -1,1465 +0,0 @@ ---- -title: "Who reacted publication" -slug: "who-reaction-publication" -hidden: false -createdAt: "2022-09-23T11:45:54.462Z" -updatedAt: "2023-03-14T13:31:41.065Z" ---- -> 📘 Full code example -> -> - -This query returns all the profiles who reacted to the publication. - -# API Design - -> 📘 Use the GraphQL schema... -> -> One of the huge advantages of GraphQL is you have a schema that should explain how the schema should look at what properties exist in that. In these docs we explore code examples and explain key concepts but we will not explain each property that exists in the response for example, as the schema already does that! - -```javascript Example operation -query WhoReactedPublication { - whoReactedPublication(request: { publicationId: "0x01-0x01" }) { - items { - reactionId - reaction - reactionAt - profile { - ...ProfileFields - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} -``` -```Text Example response -{ - "data": { - "whoReactedPublication": { - "items": [ - { - "reactionId": "UPVOTE-0x45da-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-09-12T23:11:29.091Z", - "profile": { - "id": "0x45da", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0xDe516501d9d3D71e6aF555115E75583b49f7C883", - "metadata": null, - "isDefault": false, - "handle": "web3wes.test", - "picture": { - "original": { - "url": "https://media-exp1.licdn.com/dms/image/C5603AQE6pH_bmNbVOg/profile-displayphoto-shrink_800_800/0/1651855193308?e=1668643200&v=beta&t=ofhjxGqOgUfLMp5l9RMQdOpKozLZf9ejex5mnssAhQg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x4B297bdAf5aC6FEdD1166706D65F6f8fb70d2B9A", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 1, - "totalPosts": 5, - "totalComments": 0, - "totalMirrors": 1, - "totalPublications": 6, - "totalCollects": 1 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x45ba-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-09-10T09:42:37.136Z", - "profile": { - "id": "0x45ba", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0xa6f36BB2885bDa7a6A7D541c25e98b03c576b133", - "metadata": null, - "isDefault": false, - "handle": "gabrielaxy.test", - "picture": { - "original": { - "url": "ipfs://bafybeidya62ib6dxmflnr63drbzncs6hejwxohluxwakx2javrw6ioxok4", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x2787a5fDD79939A0ee191F8Ec4989fD1e337Da7B", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 2, - "totalFollowing": 5, - "totalPosts": 3, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 5, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x3675-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-07-08T17:03:44.539Z", - "profile": { - "id": "0x3675", - "name": "Ram's channel", - "bio": "Creating contents on web development @ramtest.test", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://writeonce.dev" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "ram00759595" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x8CEd7e4DE83116697bC3B60984C99cc70686FAdB", - "metadata": "https://lens.infura-ipfs.io/ipfs/QmR3J4bYsNmaajxgf92Zs4ghz6z2b6ZH5RPW8RjYZB4ZNY", - "isDefault": false, - "handle": "ramtest.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmXJH9BiQ8tkv2rmQU98Rh1y33KT5yvFQvFkCkaWXpdBpv", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmNbkUtYACajuKk7zTyw5V1u6aQCaA3YUCi49u6kYqzrx6", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x81FE4D2f3348E5422B649706df64466Ad0Ac65cB", - "dispatcher": null, - "stats": { - "totalFollowers": 5, - "totalFollowing": 20, - "totalPosts": 43, - "totalComments": 14, - "totalMirrors": 2, - "totalPublications": 59, - "totalCollects": 12 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "2.0" - }, - "recipient": "0x81FE4D2f3348E5422B649706df64466Ad0Ac65cB" - } - } - }, - { - "reactionId": "UPVOTE-0x2f-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-07-08T15:06:47.006Z", - "profile": { - "id": "0x2f", - "name": "Sasi", - "bio": "creator of lenstube.xyz", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x892f2077f1fAc7044FaA236A9530F38CF53206f6", - "metadata": "https://arweave.net/WG2jrPK2h7cDSitAzwu8PspxFDFp2hLYNFU0wOL9KrQ", - "isDefault": false, - "handle": "sasicodes.test", - "picture": { - "original": { - "url": "ipfs://bafkreicoufxi7em44m3z2rbgebr3ewrawovnewmprnncnsnubnrtrr5x64", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 53, - "totalFollowing": 15, - "totalPosts": 364, - "totalComments": 185, - "totalMirrors": 78, - "totalPublications": 627, - "totalCollects": 191 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464" - } - } - }, - { - "reactionId": "UPVOTE-0x380c-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-30T10:33:21.487Z", - "profile": { - "id": "0x380c", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "fantomdegen.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/fantomdegen.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x2a06913D5b8748b222E1236768C24ca19198B374", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 6, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x3708-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-29T06:55:18.814Z", - "profile": { - "id": "0x3708", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "rjann.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/rjann.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x66bE827847F68cbb6C2C0D25BA187AF06E7da2CD", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 0, - "totalComments": 2, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x3435-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-25T03:20:49.632Z", - "profile": { - "id": "0x3435", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x4a8Aa78950aBeF17C4F6F181Deb00A16CA35Cc33", - "metadata": null, - "isDefault": false, - "handle": "lensweb3.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/lensweb3.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x9010F1450aDF66B099cbD8BE193dF2488CF3fA1F", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 1, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 1 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x341b-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-24T15:55:17.050Z", - "profile": { - "id": "0x341b", - "name": "Z Series", - "bio": "for fun", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmQErYdEu3ZEnRKHrP8Afi6uPDaX4NZ38XSCS5QozLut2R", - "isDefault": false, - "handle": "epics.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmPTTGJYRvqXq94umbe7rXqxSGCrUmjykKQAAg8xTHrJvN", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmXGHyD9nbznjXWZPt1VU2o3QpSTKrBrMZkuHNpTVF7Jkk", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x3c89C10490368f2180d583a530E4d2DE8e35e4EE", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x3414-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-24T15:32:04.788Z", - "profile": { - "id": "0x3414", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "vladyan.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/vladyan.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0xA734a2DE4578b49749Ff1D17F23D37a31c9C9955", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 0, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x33ca-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-24T07:52:35.783Z", - "profile": { - "id": "0x33ca", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "ayaan.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/ayaan.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x758825be077634172956158482E7Fbff4Fc5679B", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 2, - "totalPosts": 0, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x2ea1-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-24T06:48:13.389Z", - "profile": { - "id": "0x2ea1", - "name": "0xTang", - "bio": "动漫爱好者!", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://twitter.com/CryptoTangCN" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "https://twitter.com/CryptoTangCN" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x608477A091D949D1Cc32baB8b7A2c67A3B856571", - "metadata": "https://lens.infura-ipfs.io/ipfs/QmYb8WvZxUUbAJtVrCTXLPYMhbLMkm7P6rL17qoK337eTQ", - "isDefault": false, - "handle": "0xtang.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/0xtang.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x4cc395AB5546E2Bb42a5454A53c86370EE084A52", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 4, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x097c-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-24T05:47:55.532Z", - "profile": { - "id": "0x097c", - "name": null, - "bio": "Some random stuff", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "@Axpoker" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmRGrpRyuNEY9pr6KXcNcUWK72cG3vwTstPB1cRJk6f34A", - "isDefault": false, - "handle": "soyjeff.test", - "picture": { - "original": { - "url": "https://avatars.dicebear.com/api/bottts/soyjeff.svg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmfZWk1dvGsT5ZHuGRbN8og3VM3uR4Xo12GrYP83KidrYb", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x109028eC6F566402A921dE2785636d246d0c1a0c", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x33a9-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T23:45:49.888Z", - "profile": { - "id": "0x33a9", - "name": "eloweten", - "bio": "MY CHNL", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmXfY6d4iNzMyuCuNEw3hghgfwZes86QwcrV5phAHtQZgQ", - "isDefault": false, - "handle": "eloweten.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmWhnmGLfP4ke94xcuJchXkzgKvb6bFmBLF7hWBTKNTuJS", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmTZYa8cVvFMvEP9T1xXE6sDba2HAsh4JDywTm4ubCNxrF", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x01DDB26F7C215eD317B83cF0c0023DB7BD36117a", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x339d-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T18:04:26.237Z", - "profile": { - "id": "0x339d", - "name": "xyfyn", - "bio": "random videos.", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "@xyfyn" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmauHY4Vr2vUvdcdJgz1EJHTwjp64MeyFhrYzZcUskfhh2", - "isDefault": false, - "handle": "xyfyn.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmUv9zCGZnzEkkPcyaTzkwL4zBxq8NkLH3XsVTMsvn6Gvr", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmemHS2dpeNmJfNVVf8zXHTxiB3ccwKVGW4q7cLA2qjcw6", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x1c0243788F08b0eC6c0977d564fe0c64F13e0C9b", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 4, - "totalPosts": 2, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 1 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x338e-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T16:05:45.205Z", - "profile": { - "id": "0x338e", - "name": "Uncle bear", - "bio": "To find about something new", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmZ9Tg8ShxCPLujCxPw6rrgCifJQdAzk7k3cGANa1p9L18", - "isDefault": false, - "handle": "bounce.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/Qmd4HDHXEixUngZ8RUL4oZzSpexKPG1kjkAw2bCcpKNQPe", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmdR3jtNAUKpkXynhK18iQEX9JCtNghYs9jLza7vSoL9ob", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x83aFc53f479Ca6b7AB634F1f815FF3f0E0dca096", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 2, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x1c1c-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T14:11:23.537Z", - "profile": { - "id": "0x1c1c", - "name": null, - "bio": "Trader", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "http://twitter.com/Giang45067283" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "@Giang45067283" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmWpUTWVHLrx6j2YJyeYoHZ71F79W8vqzbpyqa3yKGqMGx", - "isDefault": false, - "handle": "clearlove.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/clearlove.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x2F2b1DE6fe0f64b20Bc02E0D135724C64Ae509dC", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 0, - "totalPosts": 4, - "totalComments": 2, - "totalMirrors": 0, - "totalPublications": 6, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x2e-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T13:45:48.682Z", - "profile": { - "id": "0x2e", - "name": "sasi.eth", - "bio": "https://testnet.lenstube.xyz/sasidharan.test", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x02ba79D5C54Cecef46483b987fAcF91700547019", - "metadata": "https://lens.infura-ipfs.io/ipfs/QmTmbQYpVCubcRnQfTnRwmZcJ76iAqjPdT9RBMuCscG63a", - "isDefault": false, - "handle": "sasidharan.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmXGoeBsAyaFXaz3Z1CDtGWczakhaWPcDbBqCM4YqgkXpw", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0xa8535b8049948bE1bFeb1404daEabbD407792411", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 4, - "totalFollowing": 1, - "totalPosts": 23, - "totalComments": 5, - "totalMirrors": 3, - "totalPublications": 31, - "totalCollects": 4 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x32ff-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T08:03:34.889Z", - "profile": { - "id": "0x32ff", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "sarfarazahmed.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/sarfarazahmed.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x4aB4bcA921FEf23A34c700d9E2f20a68401bF049", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 0, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x32e5-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T06:54:42.579Z", - "profile": { - "id": "0x32e5", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": "0x0d9d34995EFf3f144A1A2BDC7a0a9A1762E12D88", - "metadata": null, - "isDefault": false, - "handle": "dgreatest.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/dgreatest.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0xe3a244EecFBC928e12B83252224B48F84E0a27C4", - "dispatcher": null, - "stats": { - "totalFollowers": 1, - "totalFollowing": 2, - "totalPosts": 2, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x32df-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T06:40:26.209Z", - "profile": { - "id": "0x32df", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "coolajay.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/coolajay.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x4074d42Cee2EcAa011414Ddb2D36EFfee4D23dA9", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 2, - "totalPosts": 0, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x1e9b-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T06:36:37.284Z", - "profile": { - "id": "0x1e9b", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "lenschanel.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/lenschanel.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0xBaa94A36Da956390207521DcA8493Bab196b9DD4", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 4, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 5, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x329b-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T04:52:52.266Z", - "profile": { - "id": "0x329b", - "name": "Salo", - "bio": "Crypto trader, investor", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmWFsaRdW3XzszNK6DUwhoqRtopJnL83chvzsWjt4yfhai", - "isDefault": false, - "handle": "kriptomankalens.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmUmd2gh9U2nZ9wyMHUuh6GXfb5QaFpiQSauu91USQnDGZ", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmdSY2vMLCcJrvLy95KKX1LpHQz8b4FaaphEY7AKFNWNk1", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x5371CAD18FE79EFecDf093f498719439fe9E53E4", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 4, - "totalPosts": 1, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 1, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x329c-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T04:49:32.353Z", - "profile": { - "id": "0x329c", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "motivate.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/motivate.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x5B993CAd70b3Cd0856Ef71cAE270eec88A51FFA4", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 0, - "totalComments": 4, - "totalMirrors": 0, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x0e76-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-23T02:39:40.200Z", - "profile": { - "id": "0x0e76", - "name": "straitchain", - "bio": "about straitchain information", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://www.straitchain.com/" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "https://lens.infura-ipfs.io/ipfs/QmRPbuM8LDEDKQR8DExnjTav7pUcgjF5TkTNM4naZQZdvc", - "isDefault": false, - "handle": "harry.test", - "picture": { - "original": { - "url": "https://avatars.dicebear.com/api/bottts/harry.svg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "ownedBy": "0x99b4c88ff35D2C62529C7D91B6eaC89E2df0357A", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 3, - "totalMirrors": 0, - "totalPublications": 4, - "totalCollects": 0 - }, - "followModule": null - } - }, - { - "reactionId": "UPVOTE-0x3265-0x01-0x01", - "reaction": "UPVOTE", - "reactionAt": "2022-06-22T18:28:55.298Z", - "profile": { - "id": "0x3265", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": null, - "isDefault": false, - "handle": "lrmmdc.test", - "picture": { - "original": { - "url": "https://avatar.tobi.sh/lrmmdc.png", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0xcF80D9106dc6d1079588A7d1fD477C58804b145B", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 1, - "totalComments": 1, - "totalMirrors": 0, - "totalPublications": 2, - "totalCollects": 0 - }, - "followModule": null - } - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"UPVOTE-0x45da-0x01-0x01\",\"timestamp\":1663024289,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"UPVOTE-0x3265-0x01-0x01\",\"timestamp\":1655922535,\"cursorDirection\":\"AFTER\"}", - "totalCount": 161 - } - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.reactions.toPublication({ - publicationId: '0x05-0x04', -}); -``` \ No newline at end of file diff --git a/documents/Lens API/reporting.md b/documents/Lens API/reporting.md deleted file mode 100644 index 62dfd1c..0000000 --- a/documents/Lens API/reporting.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Reporting" -slug: "reporting" -hidden: false -createdAt: "2022-02-17T17:59:58.179Z" -updatedAt: "2022-03-09T14:14:43.641Z" ---- -The reporting resolver to allow users to report things that may cause offense. - -Our reporting resolver has these queries: - -- [Report publication](doc:report-publication) \ No newline at end of file diff --git a/documents/Lens API/reporting/report-publication.md b/documents/Lens API/reporting/report-publication.md deleted file mode 100644 index 1e8462d..0000000 --- a/documents/Lens API/reporting/report-publication.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: "Report publication" -slug: "report-publication" -hidden: false -createdAt: "2022-02-18T11:31:47.823Z" -updatedAt: "2023-03-14T13:40:00.059Z" ---- -> 📘 Full code example -> -> - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -This mutation report publication allows a user to report something with a reason. - -# API Design - -returns a `VoidScalar` which means no response is returned if you do look at the response data it will be data.reportPublication= null but you do not need to look at the response for anything which returns `void`. If it does not throw it is successful. - -```javascript Example operation -mutation ReportPublication { - reportPublication(request: { - publicationId: "0x01-0x01", - reason: { - sensitiveReason: { - reason: SENSITIVE, - subreason: OFFENSIVE - } - }, - additionalComments: "Dislike this post" - }) -} -``` -```javascript Query interface -type Mutation { - reportPublication(request: ReportPublicationRequest!): Void -} -``` -```javascript Request -input ReportPublicationRequest { - publicationId: InternalPublicationId! - reason: ReportingReasonInputParams! - additionalComments: String -} - -input ReportingReasonInputParams { - sensitiveReason: SensitiveReasonInputParams - illegalReason: IllegalReasonInputParams - fraudReason: FraudReasonInputParams -} - -input SensitiveReasonInputParams { - reason: PublicationReportingReason! - subreason: PublicationReportingSensitiveSubreason! -} - -# Publication reporting reason -enum PublicationReportingReason { - SENSITIVE - ILLEGAL - FRAUD -} - -# Publication reporting sensitive subreason -enum PublicationReportingSensitiveSubreason { - NSFW - OFFENSIVE -} - -input IllegalReasonInputParams { - reason: PublicationReportingReason! - subreason: PublicationReportingIllegalSubreason! -} - -# Publication reporting illegal subreason -enum PublicationReportingIllegalSubreason { - ANIMAL_ABUSE - HUMAN_ABUSE -} - -input FraudReasonInputParams { - reason: PublicationReportingReason! - subreason: PublicationReportingFraudSubreason! -} - -# Publication reporting fraud subreason -enum PublicationReportingFraudSubreason { - SCAM - IMPERSONATION -} -``` - - - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -## Request - -Let's look into more detail of the `reason` part of the request as there are many ways you can report. - -The `reason` is an object of 3 things `sensitiveReason`, `illegalReason` , `fraudReason` due to not being able to do unions in GraphQL you should only pass 1 in of those properties. The beauty of GraphQL is that the schema will explain how those types should be shaped and export the enums for you as well. - - - -# - -# Using LensClient SDK - -```typescript -import { buildReportingReasonInputParams, PublicationReportReason } from "@lens-protocol/client"; - -// lensClient is authenticated - -const result = await lensClient.publication.report({ - publicationId: '0x014e-0x0a', - reason: buildReportingReasonInputParams(PublicationReportReason.FAKE_ENGAGEMENT), - additionalComments: 'comment', -}); -``` \ No newline at end of file diff --git a/documents/Lens API/revenue.md b/documents/Lens API/revenue.md deleted file mode 100644 index b06f034..0000000 --- a/documents/Lens API/revenue.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Revenue" -slug: "revenue" -hidden: false -createdAt: "2022-02-17T18:00:06.438Z" -updatedAt: "2023-03-14T13:47:43.231Z" ---- -With built-in ways to earn on Lens Protocol, you need a way to be able to see a breakdown of the amount/value of what you have earned. - -Our revenue resolver has these queries: - -- [Profile publication revenue](doc:profile-publication-revenue) -- [Profile follow revenue](doc:profile-follow-revenue) -- [Publication revenue](doc:publication-revenue) \ No newline at end of file diff --git a/documents/Lens API/revenue/profile-follow-revenue.md b/documents/Lens API/revenue/profile-follow-revenue.md deleted file mode 100644 index f719da3..0000000 --- a/documents/Lens API/revenue/profile-follow-revenue.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "Profile follow revenue" -slug: "profile-follow-revenue" -hidden: false -createdAt: "2022-09-23T10:40:40.205Z" -updatedAt: "2023-03-14T13:43:47.607Z" ---- -> 📘 Full code example -> -> - -This query returns the amounts earned on the requested profile for all follows. It will group them up by currency. - -# API Design - -```javascript Example operation -query ProfileFollowRevenue { - profileFollowRevenue(request: { profileId: "0x15" }) { - revenues { - total { - asset { - name - symbol - decimals - address - } - value - } - } - } -} -``` -```javascript Example response -{ - "data": { - "profileFollowRevenue": { - "revenues": [ - { - "total": { - "asset": { - "name": "WETH", - "symbol": "WETH", - "decimals": 18, - "address": "0x3C68CE8504087f89c640D02d133646d98e64ddd9" - }, - "value": "0.31" - } - }, - { - "total": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "190.0012" - } - } - ] - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.revenue.profileFollow({ profileId: '0x0185' }); -``` \ No newline at end of file diff --git a/documents/Lens API/revenue/profile-publication-revenue.md b/documents/Lens API/revenue/profile-publication-revenue.md deleted file mode 100644 index d0c0d0f..0000000 --- a/documents/Lens API/revenue/profile-publication-revenue.md +++ /dev/null @@ -1,534 +0,0 @@ ---- -title: "Profile publication revenue" -slug: "profile-publication-revenue" -hidden: false -metadata: -createdAt: "2022-02-18T11:32:18.193Z" -updatedAt: "2023-03-14T13:47:29.400Z" ---- -> 📘 Full code example -> -> - -This query returns the amounts earned on the requested profile for all publications. It will only return publications that have earned any fees. - -# API Design - -```javascript Example operation -query Revenue { - profilePublicationRevenue(request: { profileId: "0x41", limit: 10 }) { - items { - publication { - __typename - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - ... on Mirror { - ...MirrorFields - } - } - revenue { - total { - asset { - name - symbol - decimals - address - } - value - } - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} -``` -```javascript Example response -{ - "data": { - "profilePublicationRevenue": { - "items": [ - { - "publication": { - "__typename": "Post", - "id": "0x41-0x03", - "profile": { - "id": "0x41", - "name": "carle", - "bio": "cool", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://twitter.com/Liao15904673" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "@Liao15904673" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": "https://lens.infura-ipfs.io/ipfs/QmQojajzy28PoCMVyfvm2RY9tLSAQWUBAfHVXTmgN8rfR2", - "isDefault": true, - "handle": "crypto.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmW5LJEgu4CaFntjj4gKFL74Z2rZ3bHXVTLUqxL2j2JgGa", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x9D6AfD3Dd7cbe2429764788c2ef3a607D57943d6", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 3, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 3 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 3, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "亏钱dao", - "description": "", - "content": "", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "string", - "value": "crowdfund" - }, - { - "displayType": null, - "traitType": "string", - "value": "100" - } - ] - }, - "createdAt": "2022-05-11T16:28:12.000Z", - "collectModule": { - "__typename": "FeeCollectModuleSettings", - "type": "FeeCollectModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "0.1" - }, - "recipient": "0x9D6AfD3Dd7cbe2429764788c2ef3a607D57943d6", - "referralFee": 10 - }, - "referenceModule": null, - "appId": "lenster crowdfund" - }, - "revenue": { - "total": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "0.3" - } - } - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"0x41-0x03\",\"timestamp\":1652286492,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"0x41-0x03\",\"timestamp\":1652286492,\"cursorDirection\":\"AFTER\"}", - "totalCount": 1 - } - } - } -} -``` - - - -You will see the paging result behavior repeated a lot in the API. This is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result, you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -The request also takes in: - -- `sources` which allows you to pass in an array of `appIds` -- `types` which allows you to filter the revenue on `[COMMENT, MIRROR, POST]` aka if you only wanted to get back comments and mirrors you would do `types: [COMMENT, MIRROR]` - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.revenue.profilePublication({ profileId: '0x0185' }); -``` \ No newline at end of file diff --git a/documents/Lens API/revenue/publication-revenue.md b/documents/Lens API/revenue/publication-revenue.md deleted file mode 100644 index 050d3ae..0000000 --- a/documents/Lens API/revenue/publication-revenue.md +++ /dev/null @@ -1,510 +0,0 @@ ---- -title: "Publication revenue" -slug: "publication-revenue" -hidden: false -createdAt: "2022-03-23T12:34:10.254Z" -updatedAt: "2023-03-14T13:43:20.601Z" ---- -> 📘 Full code example -> -> - -This query returns the amounts earned on the requested publication. - -# API Design - -> 📘 Did you know... -> -> The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. Our backend generates what we call an `InternalPublicationId` which is built up from `{profileId}-{publicationId}` creating a unique ID that can be queried against our database. You will see that `InternalPublicationId` is used on all our responses and also used in any request you which to do. - -```javascript Example operation -query PublicationRevenue { - publicationRevenue(request: { publicationId: "0x41-0x03" }) { - publication { - __typename - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - ... on Mirror { - ...MirrorFields - } - } - revenue { - total { - asset { - name - symbol - decimals - address - } - value - } - } - } -} - -fragment MediaFields on Media { - url - width - height - mimeType -} - -fragment ProfileFields on Profile { - id - name - bio - attributes { - displayType - traitType - key - value - } - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - small { - ...MediaFields - } - medium { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment MirrorFields on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} -``` -```javascript Example response -{ - "data": { - "publicationRevenue": { - "publication": { - "__typename": "Post", - "id": "0x41-0x03", - "profile": { - "id": "0x41", - "name": "carle", - "bio": "cool", - "attributes": [ - { - "displayType": null, - "traitType": "string", - "key": "website", - "value": "https://twitter.com/Liao15904673" - }, - { - "displayType": null, - "traitType": "string", - "key": "twitter", - "value": "@Liao15904673" - }, - { - "displayType": null, - "traitType": "boolean", - "key": "isBeta", - "value": "true" - }, - { - "displayType": null, - "traitType": "string", - "key": "app", - "value": "Lenster" - } - ], - "metadata": "https://lens.infura-ipfs.io/ipfs/QmQojajzy28PoCMVyfvm2RY9tLSAQWUBAfHVXTmgN8rfR2", - "isDefault": true, - "handle": "crypto.test", - "picture": { - "original": { - "url": "https://lens.infura-ipfs.io/ipfs/QmW5LJEgu4CaFntjj4gKFL74Z2rZ3bHXVTLUqxL2j2JgGa", - "width": null, - "height": null, - "mimeType": null - }, - "small": null, - "medium": null - }, - "coverPicture": null, - "ownedBy": "0x9D6AfD3Dd7cbe2429764788c2ef3a607D57943d6", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 1, - "totalPosts": 3, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 3, - "totalCollects": 3 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 3, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "亏钱dao", - "description": "", - "content": "", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "string", - "value": "crowdfund" - }, - { - "displayType": null, - "traitType": "string", - "value": "100" - } - ] - }, - "createdAt": "2022-05-11T16:28:12.000Z", - "collectModule": { - "__typename": "FeeCollectModuleSettings", - "type": "FeeCollectModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "0.1" - }, - "recipient": "0x9D6AfD3Dd7cbe2429764788c2ef3a607D57943d6", - "referralFee": 10 - }, - "referenceModule": null, - "appId": "lenster crowdfund" - }, - "revenue": { - "total": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "0.3" - } - } - } - } -} -``` - - - -# - -# Using LensClient SDK - -```typescript -const result = await lensClient.revenue.publication({ publicationId: '0x15-0x028e' }); -``` \ No newline at end of file diff --git a/documents/Lens API/search.md b/documents/Lens API/search.md deleted file mode 100644 index fb22a95..0000000 --- a/documents/Lens API/search.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Search" -slug: "search" -hidden: false -createdAt: "2022-02-17T18:00:13.623Z" -updatedAt: "2022-03-09T14:09:50.116Z" ---- -Search is fundamental to any application leveraging the Lens Social Graph. Our current search query allows you to search across hashtags on publications or profile handles. This query returns either a `Post` and `Comment` or `Profile`. - -Querying the protocol publications for content and profiles is fundamental for social visibility and something we will continue to improve on. - -Our search resolver has these queries: - -- [Search profiles and publications](doc:search-profiles-and-publications) \ No newline at end of file diff --git a/documents/Lens API/search/search-profiles-and-publications.md b/documents/Lens API/search/search-profiles-and-publications.md deleted file mode 100644 index 93591fc..0000000 --- a/documents/Lens API/search/search-profiles-and-publications.md +++ /dev/null @@ -1,742 +0,0 @@ ---- -title: "Search profiles or publications" -slug: "search-profiles-and-publications" -hidden: false -createdAt: "2022-02-18T11:33:01.520Z" -updatedAt: "2023-03-14T13:51:21.463Z" ---- -> 📘 Full code example -> -> Search profiles - -> -> Search publications - - -This query allows you to search across hashtags on publications or profile handles. This query returns either a `Post` and `Comment` or `Profile`. - -Querying the protocol publications for content and profiles is fundamental for social visibility and something we will continue to improve on. - -# API details - -You can search against profile handles or search against hashtags. Both will be explained in detail below. - -> 📘 Hot tip -> -> If you do not know GraphQL that well remember things can be nullable if defined as so in the schema how GraphQL knows its nullable is without the `!` at the end here is an example: -> -> Not nullable: -> -> ownedBy: EthereumAddress! -> -> Nullable: -> -> ownedBy: EthereumAddress -> -> It's always worth generating the TypeScript types for the schema if your application is TypeScript here is a reference to how you would do that - - -You will see the paging result behavior repeated a lot in the API. This is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result, you will always get returned a `pageInfo` which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property. - -## Search across profiles - - You can use the `type` property on the request which allows you to search on the same endpoint to define the type of search you want. - -```javascript Example operation -query Search { - search(request: { - query: "josh", - type: PROFILE, - limit: 10 - }) { - ... on ProfileSearchResult { - __typename - items { - ... on Profile { - ...ProfileFields - } - } - pageInfo { - prev - totalCount - next - } - } - } -} - -fragment MediaFields on Media { - url - mimeType -} - -fragment ProfileFields on Profile { - profileId: id, - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - followNftAddress - metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } - } -} -``` -```javascript Example response -{ - "data": { - "search": { - "__typename": "ProfileSearchResult", - "items": [ - { - "profileId": "0x032f1a", - "name": "josh stevens", - "bio": "hey this is my profile", - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "joshworld", - "picture": null, - "coverPicture": null, - "ownedBy": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF", - "dispatcher": { - "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - }, - "stats": { - "totalFollowers": 0, - "totalFollowing": 2, - "totalPosts": 4, - "totalComments": 0, - "totalMirrors": 1, - "totalPublications": 5, - "totalCollects": 0 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "WETH", - "symbol": "WETH", - "decimals": 18, - "address": "0x3C68CE8504087f89c640D02d133646d98e64ddd9" - }, - "value": "0.01" - }, - "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF" - } - }, - { - "profileId": "0x02f5f4", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "josh2184zlpd", - "picture": null, - "coverPicture": null, - "ownedBy": "0x667E0ecA80f283b5417588034b3C0bAb8deed505", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - }, - { - "profileId": "0x1d27", - "name": null, - "bio": null, - "attributes": [ - { - "displayType": null, - "traitType": null, - "key": "custom_field", - "value": "yes this is custom" - } - ], - "isFollowedByMe": false, - "isFollowing": false, - "followNftAddress": null, - "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP", - "isDefault": false, - "handle": "joshfundz", - "picture": null, - "coverPicture": null, - "ownedBy": "0x85c49F70AA4EaC48892917bD0cedCD4E8EE9c754", - "dispatcher": null, - "stats": { - "totalFollowers": 0, - "totalFollowing": 0, - "totalPosts": 0, - "totalComments": 0, - "totalMirrors": 0, - "totalPublications": 0, - "totalCollects": 0 - }, - "followModule": null - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "totalCount": 3, - "next": "{\"offset\":10}" - } - } - } -} -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.search.profiles({ - query: 'josh', - limit: 10, -}); -``` - - - -## Search across publications - -For now, the search will search across anything which has hashtags and tags, this will be expanded to a full-text search soon. So if someone posted #foo that can be searched but if someone posted "I like #foo" only "foo" would be searchable and not "like". A full-text search API is under active development and will be released at a later point. - -```javascript Example operation -query Search { - search(request: { - query: "hello", - type: PUBLICATION, - limit: 10 - }) { - ... on PublicationSearchResult { - __typename - items { - __typename - ... on Comment { - ...CommentFields - } - ... on Post { - ...PostFields - } - } - pageInfo { - prev - totalCount - next - } - } - ... on ProfileSearchResult { - __typename - items { - ... on Profile { - ...ProfileFields - } - } - pageInfo { - prev - totalCount - next - } - } - } -} - -fragment MediaFields on Media { - url - mimeType -} - -fragment MirrorBaseFields on Mirror { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId -} - -fragment ProfileFields on Profile { - profileId: id, - name - bio - attributes { - displayType - traitType - key - value - } - isFollowedByMe - isFollowing(who: null) - metadataUrl: metadata - isDefault - handle - picture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - coverPicture { - ... on NftImage { - contractAddress - tokenId - uri - verified - } - ... on MediaSet { - original { - ...MediaFields - } - } - } - ownedBy - dispatcher { - address - } - stats { - totalFollowers - totalFollowing - totalPosts - totalComments - totalMirrors - totalPublications - totalCollects - } - followModule { - ...FollowModuleFields - } -} - -fragment PublicationStatsFields on PublicationStats { - totalAmountOfMirrors - totalAmountOfCollects - totalAmountOfComments -} - -fragment MetadataOutputFields on MetadataOutput { - name - description - content - media { - original { - ...MediaFields - } - } - attributes { - displayType - traitType - value - } -} - -fragment Erc20Fields on Erc20 { - name - symbol - decimals - address -} - -fragment PostFields on Post { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentBaseFields on Comment { - id - profile { - ...ProfileFields - } - stats { - ...PublicationStatsFields - } - metadata { - ...MetadataOutputFields - } - createdAt - collectModule { - ...CollectModuleFields - } - referenceModule { - ...ReferenceModuleFields - } - appId - hidden - reaction(request: null) - mirrors(by: null) - hasCollectedByMe -} - -fragment CommentFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - mirrorOf { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentMirrorOfFields - } - } - } - } -} - -fragment CommentMirrorOfFields on Comment { - ...CommentBaseFields - mainPost { - ... on Post { - ...PostFields - } - ... on Mirror { - ...MirrorBaseFields - } - } -} - -fragment FollowModuleFields on FollowModule { - ... on FeeFollowModuleSettings { - type - amount { - asset { - name - symbol - decimals - address - } - value - } - recipient - } - ... on ProfileFollowModuleSettings { - type - contractAddress - } - ... on RevertFollowModuleSettings { - type - contractAddress - } - ... on UnknownFollowModuleSettings { - type - contractAddress - followModuleReturnData - } -} - -fragment CollectModuleFields on CollectModule { - __typename - ... on FreeCollectModuleSettings { - type - followerOnly - contractAddress - } - ... on FeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - } - ... on LimitedTimedFeeCollectModuleSettings { - type - collectLimit - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on RevertCollectModuleSettings { - type - } - ... on TimedFeeCollectModuleSettings { - type - amount { - asset { - ...Erc20Fields - } - value - } - recipient - referralFee - endTimestamp - } - ... on UnknownCollectModuleSettings { - type - contractAddress - collectModuleReturnData - } -} - -fragment ReferenceModuleFields on ReferenceModule { - ... on FollowOnlyReferenceModuleSettings { - type - contractAddress - } - ... on UnknownReferenceModuleSettings { - type - contractAddress - referenceModuleReturnData - } - ... on DegreesOfSeparationReferenceModuleSettings { - type - contractAddress - commentsRestricted - mirrorsRestricted - degreesOfSeparation - } -} -``` -```javascript Example response -{ - "data": { - "search": { - "__typename": "PublicationSearchResult", - "items": [ - { - "__typename": "Post", - "id": "0x5181-0x15", - "profile": { - "profileId": "0x5181", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": false, - "isFollowing": false, - "metadataUrl": null, - "isDefault": false, - "handle": "0x5181.burned", - "picture": { - "original": { - "url": "https://cdn.stamp.fyi/avatar/eth:0xd53e135f063740af88f71c776fe6d53d703bcab4?s=250", - "mimeType": null - } - }, - "coverPicture": null, - "ownedBy": "0x0000000000000000000000000000000000000000", - "dispatcher": null, - "stats": { - "totalFollowers": 3, - "totalFollowing": 0, - "totalPosts": 34, - "totalComments": 4, - "totalMirrors": 0, - "totalPublications": 38, - "totalCollects": 1 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "Post by @olofandersson2.test", - "description": "hello #foo #bar #web3 #hej_hoj #lol_ #123 #TestFoo tag#hello tag. #hello", - "content": "hello #foo #bar #web3 #hej_hoj #lol_ #123 #TestFoo tag#hello tag. #hello", - "media": [], - "attributes": [ - { - "displayType": "string", - "traitType": "type", - "value": "text_only" - } - ] - }, - "createdAt": "2022-11-12T15:06:16.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenster", - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - ], - "pageInfo": { - "prev": "{\"offset\":0}", - "totalCount": 7, - "next": "{\"offset\":7}" - } - } - } -} -``` - - - -### Using LensClient SDK - -```typescript -const result = await lensClient.search.publications({ - query: 'hello', - limit: 10, -}); -``` \ No newline at end of file diff --git a/documents/Lens API/timeline.md b/documents/Lens API/timeline.md deleted file mode 100644 index 82689d0..0000000 --- a/documents/Lens API/timeline.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Feed" -slug: "timeline" -hidden: false -createdAt: "2022-02-17T18:00:19.525Z" -updatedAt: "2023-02-23T00:54:12.666Z" ---- -Feeds(timelines) is one of the most fundamental elements to create a successful social media site. It can be used to show the user what is happening on the social feeds of people they follow and what they are liking. The timeline queries will continue to get smarter, eventually bringing in AI and data profiling. We will continue to improve what data is returned by the API. The beauty of this is if you use the API you just inherit this functionality without having to update anything. - -Our timeline resolver has these queries: - -- [Profile Feed](doc:profile-feed) \ No newline at end of file diff --git a/documents/Lens API/timeline/profile-feed.md b/documents/Lens API/timeline/profile-feed.md deleted file mode 100644 index 0c4cf19..0000000 --- a/documents/Lens API/timeline/profile-feed.md +++ /dev/null @@ -1,1547 +0,0 @@ ---- -title: "Profile feed" -slug: "profile-feed" -hidden: false -createdAt: "2022-10-11T16:40:24.511Z" -updatedAt: "2023-03-31T14:18:50.940Z" ---- -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -Feed is one of the most fundamental elements that a successful social media site needs. It can be used to show the user what is happening on the social feeds of people they follow and what they like. The feed queries will get smarter, eventually bringing in AI and data profiling. We will continue to improve what data is returned by the API. The beauty of this is if you use the API you just inherit this functionality without having to update anything. This also is fully open so if you wish to see someone else's feed just supply their profile id in! - -# What the feed brings back - -## Post - -If one of the profiles you follow posts it will appear on your timeline. - -## Comment - -If one of the profiles you follow comments on a publication it will appear on your timeline. - -## Mirror - -If one of the profiles you follow mirrors a publication it will appear in your timeline. Remember people can mirror a post or a comment. - -## Collected - -If one of the profiles you follow collects a post or a comment it will appear on your timeline. - -# API Design - -Below is an example of a request to get a feed for a profile. Feeds are fully open so anyone can see what another profile's feed looks like. This is also aggregated per page so you do not see repeated data, you will of course always get some loop over but that is the same on big social media sites. The main aim is for you to see all the information nicely. We talk about the response in more detail below. Please note the limit is the number of EVENTS you get back it is not the total count of aggregate lines. For example, if you asked for 5 and that all have been aggregated into one feed item you only get 1 back, we advise you to use a limit of 50 for this which should give plenty of information for the user to see and page nicely. - -```javascript Example operation -query Feed { - feed(request: { profileId: "0x1b", limit: 50 }) { - items { - root { - ... on Post { - ...PostFields - } - ... on Comment { - ...CommentFields - } - } - electedMirror { - mirrorId - profile { - id - handle - } - timestamp - } - mirrors { - profile { - id - handle - } - timestamp - } - collects { - profile { - id - handle - } - timestamp - } - reactions { - profile { - id - handle - } - reaction - timestamp - } - comments { - ...CommentFields - } - } - pageInfo { - prev - next - totalCount - } - } -} - -fragment MediaFields on Media { - - url - - mimeType - -} - -fragment ProfileFields on Profile { - - id - - name - - bio - - attributes { - - displayType - - traitType - - key - - value - - } - - isFollowedByMe - - isFollowing(who: null) - - followNftAddress - - metadata - - isDefault - - handle - - picture { - - ... on NftImage { - - contractAddress - - tokenId - - uri - - verified - - } - - ... on MediaSet { - - original { - - ...MediaFields - - } - - } - - } - - coverPicture { - - ... on NftImage { - - contractAddress - - tokenId - - uri - - verified - - } - - ... on MediaSet { - - original { - - ...MediaFields - - } - - } - - } - - ownedBy - - dispatcher { - - address - - } - - stats { - - totalFollowers - - totalFollowing - - totalPosts - - totalComments - - totalMirrors - - totalPublications - - totalCollects - - } - - followModule { - - ...FollowModuleFields - - } - -} - -fragment PublicationStatsFields on PublicationStats { - - totalAmountOfMirrors - - totalAmountOfCollects - - totalAmountOfComments - -} - -fragment MetadataOutputFields on MetadataOutput { - - name - - description - - content - - media { - - original { - - ...MediaFields - - } - - } - - attributes { - - displayType - - traitType - - value - - } - -} - -fragment Erc20Fields on Erc20 { - - name - - symbol - - decimals - - address - -} - -fragment PostFields on Post { - - id - - profile { - - ...ProfileFields - - } - - stats { - - ...PublicationStatsFields - - } - - metadata { - - ...MetadataOutputFields - - } - - createdAt - - collectModule { - - ...CollectModuleFields - - } - - referenceModule { - - ...ReferenceModuleFields - - } - - appId - - collectedBy { - - ...WalletFields - - } - - hidden - - reaction(request: null) - - mirrors(by: null) - - hasCollectedByMe - -} - -fragment MirrorBaseFields on Mirror { - - id - - profile { - - ...ProfileFields - - } - - stats { - - ...PublicationStatsFields - - } - - metadata { - - ...MetadataOutputFields - - } - - createdAt - - collectModule { - - ...CollectModuleFields - - } - - referenceModule { - - ...ReferenceModuleFields - - } - - appId - - hidden - - reaction(request: null) - - hasCollectedByMe - -} - -fragment CommentBaseFields on Comment { - - id - - profile { - - ...ProfileFields - - } - - stats { - - ...PublicationStatsFields - - } - - metadata { - - ...MetadataOutputFields - - } - - createdAt - - collectModule { - - ...CollectModuleFields - - } - - referenceModule { - - ...ReferenceModuleFields - - } - - appId - - collectedBy { - - ...WalletFields - - } - - hidden - - reaction(request: null) - - mirrors(by: null) - - hasCollectedByMe - -} - -fragment CommentFields on Comment { - - ...CommentBaseFields - - mainPost { - - ... on Post { - - ...PostFields - - } - - ... on Mirror { - - ...MirrorBaseFields - - mirrorOf { - - ... on Post { - - ...PostFields - - } - - ... on Comment { - - ...CommentMirrorOfFields - - } - - } - - } - - } - -} - -fragment CommentMirrorOfFields on Comment { - - ...CommentBaseFields - - mainPost { - - ... on Post { - - ...PostFields - - } - - ... on Mirror { - - ...MirrorBaseFields - - } - - } - -} - -fragment WalletFields on Wallet { - - address, - - defaultProfile { - - ...ProfileFields - - } - -} - -fragment FollowModuleFields on FollowModule { - - ... on FeeFollowModuleSettings { - - type - - amount { - - asset { - - name - - symbol - - decimals - - address - - } - - value - - } - - recipient - - } - - ... on ProfileFollowModuleSettings { - - type - - contractAddress - - } - - ... on RevertFollowModuleSettings { - - type - - contractAddress - - } - - ... on UnknownFollowModuleSettings { - - type - - contractAddress - - followModuleReturnData - - } - -} - -fragment CollectModuleFields on CollectModule { - - __typename - - ... on FreeCollectModuleSettings { - - type - - followerOnly - - contractAddress - - } - - ... on FeeCollectModuleSettings { - - type - - amount { - - asset { - - ...Erc20Fields - - } - - value - - } - - recipient - - referralFee - - } - - ... on LimitedFeeCollectModuleSettings { - - type - - collectLimit - - amount { - - asset { - - ...Erc20Fields - - } - - value - - } - - recipient - - referralFee - - } - - ... on LimitedTimedFeeCollectModuleSettings { - - type - - collectLimit - - amount { - - asset { - - ...Erc20Fields - - } - - value - - } - - recipient - - referralFee - - endTimestamp - - } - - ... on RevertCollectModuleSettings { - - type - - } - - ... on TimedFeeCollectModuleSettings { - - type - - amount { - - asset { - - ...Erc20Fields - - } - - value - - } - - recipient - - referralFee - - endTimestamp - - } - - ... on UnknownCollectModuleSettings { - - type - - contractAddress - - collectModuleReturnData - - } - -} - -fragment ReferenceModuleFields on ReferenceModule { - - ... on FollowOnlyReferenceModuleSettings { - - type - - contractAddress - - } - - ... on UnknownReferenceModuleSettings { - - type - - contractAddress - - referenceModuleReturnData - - } - - ... on DegreesOfSeparationReferenceModuleSettings { - - type - - contractAddress - - commentsRestricted - - mirrorsRestricted - - degreesOfSeparation - - } - -} -``` -```json Example response -{ - "data": { - "feed": { - "items": [ - { - "root": { - "id": "0x06-0x02", - "profile": { - "id": "0x06", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x4950D4cC58055341Ed88A106563C447D1Ee0dE56", - "metadata": null, - "isDefault": true, - "handle": "davidev.test", - "picture": null, - "coverPicture": null, - "ownedBy": "0x52EAF3F04cbac0a4B9878A75AB2523722325D4D4", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 43, - "totalFollowing": 0, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 6, - "totalCollects": 5 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 2, - "totalAmountOfCollects": 2, - "totalAmountOfComments": 2 - }, - "metadata": { - "name": "Post by @davidev.test", - "description": "test", - "content": "test", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "string", - "value": "post" - } - ] - }, - "createdAt": "2022-09-27T16:51:38.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenster", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - "electedMirror": { - "mirrorId": "0x06-0x05", - "profile": { - "id": "0x06", - "handle": "davidev.test" - }, - "timestamp": "2022-10-10T16:28:05.000Z" - }, - "mirrors": [ - { - "profile": { - "id": "0x06", - "handle": "davidev.test" - }, - "timestamp": "2022-10-10T16:28:05.000Z" - } - ], - "collects": [], - "reactions": [], - "comments": [ - { - "id": "0x06-0x06", - "profile": { - "id": "0x06", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x4950D4cC58055341Ed88A106563C447D1Ee0dE56", - "metadata": null, - "isDefault": true, - "handle": "davidev.test", - "picture": null, - "coverPicture": null, - "ownedBy": "0x52EAF3F04cbac0a4B9878A75AB2523722325D4D4", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 43, - "totalFollowing": 0, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 6, - "totalCollects": 5 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 1 - }, - "metadata": { - "name": "Comment by @davidev.test", - "description": "josh asked nicely, so i am commenting.\n\nthanks josh", - "content": "josh asked nicely, so i am commenting.\n\nthanks josh", - "media": [], - "attributes": [] - }, - "createdAt": "2022-10-10T16:33:36.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenster", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false, - "mainPost": { - "id": "0x06-0x02", - "profile": { - "id": "0x06", - "name": null, - "bio": null, - "attributes": [], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x4950D4cC58055341Ed88A106563C447D1Ee0dE56", - "metadata": null, - "isDefault": true, - "handle": "davidev.test", - "picture": null, - "coverPicture": null, - "ownedBy": "0x52EAF3F04cbac0a4B9878A75AB2523722325D4D4", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 43, - "totalFollowing": 0, - "totalPosts": 4, - "totalComments": 1, - "totalMirrors": 1, - "totalPublications": 6, - "totalCollects": 5 - }, - "followModule": null - }, - "stats": { - "totalAmountOfMirrors": 2, - "totalAmountOfCollects": 2, - "totalAmountOfComments": 2 - }, - "metadata": { - "name": "Post by @davidev.test", - "description": "test", - "content": "test", - "media": [], - "attributes": [ - { - "displayType": null, - "traitType": "string", - "value": "post" - } - ] - }, - "createdAt": "2022-09-27T16:51:38.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenster", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - } - } - ] - }, - { - "root": { - "id": "0x2f-0x01f4", - "profile": { - "id": "0x2f", - "name": "Sasi", - "bio": "creator of lenstube.xyz", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": "string", - "traitType": "location", - "key": "location", - "value": "India" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x892f2077f1fAc7044FaA236A9530F38CF53206f6", - "metadata": "https://arweave.net/yN7RHvK1ln3xW_nhCmBuh-d34-ROu73uBhKmh660bQA", - "isDefault": true, - "handle": "sasicodes.test", - "picture": { - "original": { - "url": "ipfs://bafkreidippdvp2ukyzzjtp5ykggvrr5ujrivf47f5p3bec6fyzkdfins7u", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "mimeType": null - } - }, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 54, - "totalFollowing": 14, - "totalPosts": 266, - "totalComments": 141, - "totalMirrors": 69, - "totalPublications": 476, - "totalCollects": 200 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464" - } - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "teststst", - "description": "", - "content": "teststst", - "media": [ - { - "original": { - "url": "https://arweave.net/p232ty-xtV2WlVocCfrakKi5lCPtVv3iR9ULnhyT_bY", - "mimeType": "video/mp4" - } - } - ], - "attributes": [ - { - "displayType": "string", - "traitType": "publication", - "value": "video" - }, - { - "displayType": "string", - "traitType": "handle", - "value": "sasicodes.test" - }, - { - "displayType": "string", - "traitType": "app", - "value": "lenstube" - }, - { - "displayType": "string", - "traitType": "durationInSeconds", - "value": "27.89" - } - ] - }, - "createdAt": "2022-10-09T08:12:46.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenstube", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - "electedMirror": null, - "mirrors": [], - "collects": [], - "reactions": [], - "comments": [] - }, - { - "root": { - "id": "0x2f-0x01f3", - "profile": { - "id": "0x2f", - "name": "Sasi", - "bio": "creator of lenstube.xyz", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": "string", - "traitType": "location", - "key": "location", - "value": "India" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x892f2077f1fAc7044FaA236A9530F38CF53206f6", - "metadata": "https://arweave.net/yN7RHvK1ln3xW_nhCmBuh-d34-ROu73uBhKmh660bQA", - "isDefault": true, - "handle": "sasicodes.test", - "picture": { - "original": { - "url": "ipfs://bafkreidippdvp2ukyzzjtp5ykggvrr5ujrivf47f5p3bec6fyzkdfins7u", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "mimeType": null - } - }, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 54, - "totalFollowing": 14, - "totalPosts": 266, - "totalComments": 141, - "totalMirrors": 69, - "totalPublications": 476, - "totalCollects": 200 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464" - } - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "dasdads", - "description": "", - "content": "dasdads", - "media": [ - { - "original": { - "url": "https://arweave.net/cwFS6M_jx6BxU-CRBTIZ3fCVW7wZBQG3Zupo8mZeoQo", - "mimeType": "video/mp4" - } - } - ], - "attributes": [ - { - "displayType": "string", - "traitType": "publication", - "value": "video" - }, - { - "displayType": "string", - "traitType": "handle", - "value": "sasicodes.test" - }, - { - "displayType": "string", - "traitType": "app", - "value": "lenstube" - }, - { - "displayType": "string", - "traitType": "durationInSeconds", - "value": "44.50" - } - ] - }, - "createdAt": "2022-10-09T08:08:30.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenstube", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - "electedMirror": null, - "mirrors": [], - "collects": [], - "reactions": [], - "comments": [] - }, - { - "root": { - "id": "0x2f-0x01f2", - "profile": { - "id": "0x2f", - "name": "Sasi", - "bio": "creator of lenstube.xyz", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": "string", - "traitType": "location", - "key": "location", - "value": "India" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x892f2077f1fAc7044FaA236A9530F38CF53206f6", - "metadata": "https://arweave.net/yN7RHvK1ln3xW_nhCmBuh-d34-ROu73uBhKmh660bQA", - "isDefault": true, - "handle": "sasicodes.test", - "picture": { - "original": { - "url": "ipfs://bafkreidippdvp2ukyzzjtp5ykggvrr5ujrivf47f5p3bec6fyzkdfins7u", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "mimeType": null - } - }, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 54, - "totalFollowing": 14, - "totalPosts": 266, - "totalComments": 141, - "totalMirrors": 69, - "totalPublications": 476, - "totalCollects": 200 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464" - } - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "teststt", - "description": "", - "content": "teststt", - "media": [ - { - "original": { - "url": "https://arweave.net/Ix-BIWBILptT3UMRC_srj4WlI_vbyuY6pGpwB8B4taI", - "mimeType": "video/mp4" - } - } - ], - "attributes": [ - { - "displayType": "string", - "traitType": "publication", - "value": "video" - }, - { - "displayType": "string", - "traitType": "handle", - "value": "sasicodes.test" - }, - { - "displayType": "string", - "traitType": "app", - "value": "lenstube" - }, - { - "displayType": "string", - "traitType": "durationInSeconds", - "value": "44.50" - } - ] - }, - "createdAt": "2022-10-09T08:06:40.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenstube", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - "electedMirror": null, - "mirrors": [], - "collects": [], - "reactions": [], - "comments": [] - }, - { - "root": { - "id": "0x2f-0x01f1", - "profile": { - "id": "0x2f", - "name": "Sasi", - "bio": "creator of lenstube.xyz", - "attributes": [ - { - "displayType": "string", - "traitType": "website", - "key": "website", - "value": "https://sasi.codes" - }, - { - "displayType": "string", - "traitType": "location", - "key": "location", - "value": "India" - }, - { - "displayType": "string", - "traitType": "twitter", - "key": "twitter", - "value": "sasicodes" - }, - { - "displayType": "string", - "traitType": "app", - "key": "app", - "value": "lenstube" - } - ], - "isFollowedByMe": true, - "isFollowing": false, - "followNftAddress": "0x892f2077f1fAc7044FaA236A9530F38CF53206f6", - "metadata": "https://arweave.net/yN7RHvK1ln3xW_nhCmBuh-d34-ROu73uBhKmh660bQA", - "isDefault": true, - "handle": "sasicodes.test", - "picture": { - "original": { - "url": "ipfs://bafkreidippdvp2ukyzzjtp5ykggvrr5ujrivf47f5p3bec6fyzkdfins7u", - "mimeType": null - } - }, - "coverPicture": { - "original": { - "url": "https://assets.lenstube.xyz/images/coverGradient.jpeg", - "mimeType": null - } - }, - "ownedBy": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464", - "dispatcher": { - "address": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F" - }, - "stats": { - "totalFollowers": 54, - "totalFollowing": 14, - "totalPosts": 266, - "totalComments": 141, - "totalMirrors": 69, - "totalPublications": 476, - "totalCollects": 200 - }, - "followModule": { - "type": "FeeFollowModule", - "amount": { - "asset": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "address": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889" - }, - "value": "1.0" - }, - "recipient": "0x01d79BcEaEaaDfb8fD2F2f53005289CFcF483464" - } - }, - "stats": { - "totalAmountOfMirrors": 0, - "totalAmountOfCollects": 0, - "totalAmountOfComments": 0 - }, - "metadata": { - "name": "sdasdasd", - "description": "", - "content": "sdasdasd", - "media": [ - { - "original": { - "url": "https://arweave.net/2R2V770PHbmOgyvYyvk4NQxudR-cNYTgyhKWwvQtJQU", - "mimeType": "video/mp4" - } - } - ], - "attributes": [ - { - "displayType": "string", - "traitType": "publication", - "value": "video" - }, - { - "displayType": "string", - "traitType": "handle", - "value": "sasicodes.test" - }, - { - "displayType": "string", - "traitType": "app", - "value": "lenstube" - }, - { - "displayType": "string", - "traitType": "durationInSeconds", - "value": "44.50" - } - ] - }, - "createdAt": "2022-10-09T07:55:58.000Z", - "collectModule": { - "__typename": "FreeCollectModuleSettings", - "type": "FreeCollectModule", - "followerOnly": false, - "contractAddress": "0x0BE6bD7092ee83D44a6eC1D949626FeE48caB30c" - }, - "referenceModule": null, - "appId": "lenstube", - "collectedBy": null, - "hidden": false, - "reaction": null, - "mirrors": [], - "hasCollectedByMe": false - }, - "electedMirror": null, - "mirrors": [], - "collects": [], - "reactions": [], - "comments": [] - } - ], - "pageInfo": { - "prev": "{\"entityIdentifier\":\"\",\"timestamp\":1665419616,\"cursorDirection\":\"BEFORE\"}", - "next": "{\"entityIdentifier\":\"\",\"timestamp\":1665302158,\"cursorDirection\":\"AFTER\"}", - "totalCount": null - } - } - } -} -``` - - - -## Response - -The response is aggregated for you to allow you to build really nice feeds. - -### root - -This contains the feed item root which is a POST or a COMMENT, this is the main context around your feed item. - -### electedMirror - -When a user collects it should collect the elected mirror id so that the user can get some profits for the collect if referral fees are set. This is sharing the elected mirror what this means is the first person in that aggregation who mirrored is elected. - -**mirrorId** - the publication mirror id - -**profile** - the profile who has got elected for this - -**timestamp** - when that was mirrored - -### mirrors - -The profiles which have mirrored this publication in the aggregation. The first 1 in the array is the most recent profile to mirror. - -**profile** - the profile that mirrored - -**timestamp** - when that was mirrored - -### collects - -The profiles which have collected this publication in the aggregation. The first 1 in the array is the most recent profile that collected. - -**profile** - the profile collected - -**timestamp** - when that profile collected - -### comments - -The comments were published to the publication in the aggregation. The first 1 in the array is the most recent comment. - -# - -# Using LensClient SDK - -```typescript -// lensClient is authenticated - -const result = await lensClient.feed.fetch({ - profileId: '0x123' -}); - -// or -const result = await lensClient.feed.fetchHighlights({ - profileId: '0x123' -}), -``` \ No newline at end of file diff --git a/documents/Lens API/user.md b/documents/Lens API/user.md deleted file mode 100644 index acb2722..0000000 --- a/documents/Lens API/user.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Nonce management typed data" -slug: "user" -hidden: false -createdAt: "2022-06-20T11:23:06.457Z" -updatedAt: "2023-03-14T13:02:12.370Z" ---- -> 🚧 This is quite low level -> -> This section is a bit more advanced low-level feature to make the clients faster with nonce management handled on the client itself. - -> 📘 full code repo - -When using typed data signatures to send the transactions within the typed data you may have seen a `nonce`. This is used for security reasons to avoid anyone replaying signatures and a lot of other reasons which we will not dig into here, basically, this makes it secure. - -Each contract aka `lensHub` and `periphery` and all followers NFT contracts manage their own nonces so nonce 1 on `lensHub` has no relation to the nonce on `periphery` and so on. Now the main issue is that because `evm` state will only change when the transaction has been mined you have to wait for transaction 1 to be fully mined before you allow the user to send their next action (as it will get gas estimate issues as Ethereum source of truth is the current state and doesn't take into consideration the pending transactions). - -What does this mean: - -1. I on wallet x follow profile y using follow with sig using nonce 1 -2. I then straight away try to follow someone else using follow with sig -3. If the tx on step 1 is not been mined yet step 2 will throw an estimate gas issue before you try to pass in the nonce -4. this means you have slow UX waiting for things to finish before you can do another action - -you may be asking yeah ok but how do I get around that well in theory your client "knows" when someone has done a transaction so if the client managed the nonce itself it could allow. This leads me to talk about how you can get the information from the server to manage this yourself and avoid it when creating typed data. - -# userSigNonces - -> 🚧 This request is protected by authentication -> -> hint: this means it requires an x-access-token header put in the request with your authentication token. - -You can call this query to get the current nonces of the `lensHub` and the `periphery`. - -- periphery includes profile metadata and approval follow -- lens hub includes everything else minus `unfollow` which is a nonce on the `followNftAddress` contract but probably an edge case, for now, you can leave as not many people will unfollow then unfollow again, and so on. - -```javascript Example operation -query UserSigNonces { - userSigNonces { - lensHubOnChainSigNonce - peripheryOnChainSigNonce - } -} -``` -```javascript Example response -{ - "data": { - "userSigNonces": - { - "lensHubOnChainSigNonce": "1", - "peripheryOnChainSigNonce": "6" - } - } -} -``` - - - -This will allow you to query the states on page load and then hold these states in memory. If the user then does an action let's say post and sends the transaction you can +1 onto the `lensHubOnChainSigNonce` once you got the `txHash`, if rejected you do not need to do anything. Please note you will have some cases with MM where if the user acts very strange and clicks many actions and never approves or rejects the transactions they will have many approval modals to approve or reject with the same nonce meaning after the first approval the rest would fail. It is down to the client to handle that edge case if that means you do not allow them to do anything until that action has been approved or rejected or whatever UX you think is best. - -Also because users may be using other clients it's worth calling this query to compare states every now and again with your in-memory nonce to make sure they have not done something on another UI. We do have in the backlog ability to broadcast this through the client via WebSockets but it is currently not done. - -Once you got your nonce management for different actions mapped you can override the nonce on every typed data request using the `options` which is a type of `TypedDataOptions` that can be supplied when generating the typed data. Below is an example of me generating the typed data with an override nonce as my client is managing nonces to make the UX quick and fast. - -```js -mutation CreateSetDefaultProfileTypedData { - createSetDefaultProfileTypedData(request: { profileId: "0x01" }, options: { overrideSigNonce: 1 }) { - id - expiresAt - typedData { - types { - SetDefaultProfileWithSig { - name - type - } - } - domain { - name - chainId - version - verifyingContract - } - value { - nonce - deadline - wallet - profileId - } - } - } -} -``` - - - -Ok, you got the client managing nonces and +1 on them when actions happen you also passed in the custom nonce on typed data calls the last part is understanding overriding the gas limits to avoid estimating gas. Within ethers when you do a contract call the parameter are the inputs then you have an option at the end that you can supply a `gasLimit` which means it won't check `estimateGas` and allows you to send it. - -```javascript - const tx = await lensHub.commentWithSig( - { - profileId: typedData.value.profileId, - contentURI: typedData.value.contentURI, - profileIdPointed: typedData.value.profileIdPointed, - pubIdPointed: typedData.value.pubIdPointed, - collectModule: typedData.value.collectModule, - collectModuleInitData: typedData.value.collectModuleInitData, - referenceModule: typedData.value.referenceModule, - referenceModuleInitData: typedData.value.referenceModuleInitData, - referenceModuleData: typedData.value.referenceModuleData, - sig: { - v, - r, - s, - deadline: typedData.value.deadline, - }, - }, - { gasLimit: 500000 } - ); -``` - - - -# - -# Using LensClient SDK - -```typescript -// lensClient is authenticated - -const result = await lensClient.nonces.fetch(); -``` \ No newline at end of file diff --git a/documents/Major Concepts/built-in-governance.md b/documents/Major Concepts/built-in-governance.md deleted file mode 100644 index 96c0689..0000000 --- a/documents/Major Concepts/built-in-governance.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Built-In Governance" -slug: "built-in-governance" -excerpt: "Follow NFTs include built-in governance mechanisms -- any profile can spin up a DAO in minutes!" -hidden: true -createdAt: "2022-02-02T19:43:41.080Z" -updatedAt: "2022-02-08T14:58:09.292Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/b884716-illustration_governance.svg", - "illustration_governance.svg", - 536, - 240, - "#00501e" - ] - } - ] -} -[/block] -## Follow NFT Overview -When following a profile, followers obtain a `FollowNFT,` which is the core building block of the Lens Protocol social graph! From a technical perspective, these NFTs contain governance-specific logic that allows for the following: -* Power delegation (via `delegate()`) -* Power delegation by meta-transaction (via `delegateBySig()`) -* Fetching power at a specific block number (via `getPowerByBlockNumber()`) -* Fetching total delegated supply at a specific block number (via `getDelegatedSupplyByBlockNumber()`) - -Note that by default, delegation is inactive, so followers need to delegate, either to themselves or to another trusted user to partake in governance! - -Now that's cool and all... But how do you *use* this to build a *DAO?* -## Just DAO It! -To spin up a DAO, all you've got to do is deploy a contract that interfaces with the Follow NFT's built-in functionality. It should allow for proposal creation and interface with the given profile's Follow NFTs to read governance power at the appropriate blocks for voting -- that's it! - -In a nutshell, a governance contract would need to handle... -* Proposal creation -* Voting with FollowNFTs at the given past snapshot (facilitated by the aforementioned FollowNFT functions!) -* Proposal Queuing -* Proposal execution - -But this is just a basic list of requirements and only scratches the surface of what's possible! \ No newline at end of file diff --git a/documents/Major Concepts/collect.md b/documents/Major Concepts/collect.md deleted file mode 100644 index 8054806..0000000 --- a/documents/Major Concepts/collect.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Collect" -slug: "collect" -hidden: false -createdAt: "2022-01-25T21:56:55.079Z" -updatedAt: "2022-02-08T15:52:26.624Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/88c9245-illustration_collect.svg", - "illustration_collect.svg", - 536, - 240, - "#00501e" - ] - } - ] -} -[/block] -Collects allow creators to monetize their content. Because creators own their content via the Lens Protocol, they are able to allow their followers to purchase that content. - -When a user posts a [publication](doc:publication) to their [Profile NFT](doc:profile) they have the option to set a Collect Module. This module will allow other users to mint NFTs that link to the publication's ContentURI. This module can contain any arbitrary logic to apply to the minting process and the resulting NFT. - -A creator can attach a collect module that allows collecting to be open for a certain amount of time or only allow a certain number of collects. Developers can also make their collect modules to add even more functionality! \ No newline at end of file diff --git a/documents/Major Concepts/comment.md b/documents/Major Concepts/comment.md deleted file mode 100644 index 339c293..0000000 --- a/documents/Major Concepts/comment.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Comment" -slug: "comment" -hidden: false -createdAt: "2022-01-25T21:56:48.157Z" -updatedAt: "2022-02-06T18:20:40.770Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/6527e50-illustration_comment.svg", - "illustration_comment.svg", - 328, - 240, - "#00501e" - ] - } - ] -} -[/block] -Comments allow users to provide additional commentary on other publications. They are treated the same as base [Publications](doc:publication) with extra checks and features. Like publications, comments live in the user's [Profile NFT](doc:profile) and therefore are wholly owned by the user. - -Since comments reference other publications, they are subject to the original publication's Reference Module conditions. If a publication has a reference module that limits comments only to accounts who [follow](doc:follow) the original poster, and the commenter does not hold a Follow NFT, the transaction to comment will fail. - -Just like regular publications, comments also have Collect and Reference Modules. Collect modules define how a comment can be minted into an NFT that references the comment's ContentURI. The Reference module contains logic that determines who can comment or mirror the new comment. \ No newline at end of file diff --git a/documents/Major Concepts/follow.md b/documents/Major Concepts/follow.md deleted file mode 100644 index 96822b4..0000000 --- a/documents/Major Concepts/follow.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Follow" -slug: "follow" -hidden: false -createdAt: "2022-01-27T03:45:52.046Z" -updatedAt: "2022-02-07T01:59:28.017Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/3e0f3f7-illustration_follow.svg", - "illustration_follow.svg", - 328, - 240, - "#e5ffbe" - ] - } - ] -} -[/block] -"Following" on the Lens Protocol differs from following in Web2 social applications. When users follow a profile on the Lens Protocol, they are given a Follow NFT, which creators and communities can encode with additional value. - -[Profiles NFTs](doc:profile) can attach a particular Follow Module to each ProfileNFT, which contains all of the logic used to determine if a user attempting to follow the profile should be issued a Follow NFT. For example, a profile could attach a follow module that requires a user to pay 5 MATIC to receive a Follow NFT. - -The ID of each newly issued Follow NFT for given profile increments by 1, such that the first follower's NFT has an ID of 1; the tenth has an ID of 10, and so on. - -Additionally, Follow NFTs have built-in governance capabilities, such as vote delegation, to allow for the creation of Social DAOs using Lens Protocol. Creators, DAOs, or other organizations can create voting strategies using Follow NFTs and their various properties--for example: "The first 1000 follows have one vote each" or "The longer you have followed, the more voting power you have." - -We look forward to seeing all of the new Follow Modules and Follower Governance strategies the community comes up with! \ No newline at end of file diff --git a/documents/Major Concepts/mirror.md b/documents/Major Concepts/mirror.md deleted file mode 100644 index 6ddbc09..0000000 --- a/documents/Major Concepts/mirror.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Mirror" -slug: "mirror" -hidden: false -createdAt: "2022-01-25T21:55:14.960Z" -updatedAt: "2022-02-06T18:23:53.893Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/8320c1f-illustration_mirror.svg", - "illustration_mirror.svg", - 328, - 240, - "#00501e" - ] - } - ] -} -[/block] -Mirrors are the curation tool of the Lens Protocol. They are the protocol's equivalent to reposting or re-amplifying content. Mirrors are treated the same as [publications](doc:publication) with a few additional checks and a few more minor features. - -Since mirrors reference other publications, they are subject to the conditions of the original publication's Reference Module. If a publication has a reference module that limits mirrors only to accounts that follow the original poster, and the mirroring account does not hold a Follow NFT, the transaction to mirror will fail. - -Since mirrors only repost existing content, they do not have a ContentURI field and therefore cannot be collected and do not have a Collect Module of their own. Mirrors can have their own reference module, which can define what accounts will be able to mirror or comment on the mirror. \ No newline at end of file diff --git a/documents/Major Concepts/multisig-governance.md b/documents/Major Concepts/multisig-governance.md deleted file mode 100644 index de3c6a5..0000000 --- a/documents/Major Concepts/multisig-governance.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Community Multisig" -slug: "multisig-governance" -hidden: false -createdAt: "2022-02-07T14:03:06.080Z" -updatedAt: "2022-09-01T11:44:32.592Z" ---- -To ensure the safety of the Lens Protocol’s users and promote the development of a robust, constructive network, the protocol will be launched in a guarded manner, that is, controlled by a community multisig consisting of trusted parties throughout the Web3 ecosystem. The transition to multisig as well as the signers will be announced soon! - -This multisig will be able to authorize the following actions: -- Setting up Governance and Emergency Admin Addresses -- Setting Treasury Addresses and Fees -- Whitelisting Assets -- Moving the Lens Protocol System into a PublishingPaused or fully Paused state -- Whitelisting addresses to create profiles -- Whitelisting Follow, Collect, and Reference Modules -- Upgrading the Lens Protocol Hub Contract - -Notwithstanding its abilities, the multisig will not be able to do the following: -- Coopt, affect or otherwise move funds from any user of the system -- Burn any Follower or Collect NFT -- Burn or edit any non-Lens NFT -- Take any action on any other deployment of the Lens Protocol - -For launch, all fees will be disabled and the following assets will be whitelisted: -- WMATIC [(0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270)](https://polygonscan.com/token/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270) -- WETH [(0x7ceb23fd6bc0add59e62ac25578270cff1b9f619)](https://polygonscan.com/token/0x7ceb23fd6bc0add59e62ac25578270cff1b9f619) -- USDC [(0x2791bca1f2de4661ed88a30c99a7a9449aa84174)](https://polygonscan.com/token/0x2791bca1f2de4661ed88a30c99a7a9449aa84174) -- DAI [(0x8f3cf7ad23cd3cadbd9735aff958023239c6a063)](https://polygonscan.com/token/0x8f3cf7ad23cd3cadbd9735aff958023239c6a063) \ No newline at end of file diff --git a/documents/Major Concepts/profile.md b/documents/Major Concepts/profile.md deleted file mode 100644 index 99257b4..0000000 --- a/documents/Major Concepts/profile.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Profile" -slug: "profile" -hidden: false -createdAt: "2022-01-25T21:54:55.714Z" -updatedAt: "2023-04-27T23:19:15.993Z" ---- -[block:image] -{ - "images": [ - { - "image": [ - "https://files.readme.io/5ab3179-illustration_cultivate.svg", - "illustration_cultivate.svg", - 372, - 340, - "#00501e" - ] - } - ] -} -[/block] -The Profile NFT is the main object in the Lens Protocol. It is ownership over this NFT that gives you control of your content. Individual addresses own ProfileNFTs, and an address can contain multiple ProfileNFTs. What differentiates the Lens Profile NFT from other on-chain identities is the ability to post [Publications](doc:publication) to it. The Profile NFT contains the history of all of the posts, [mirrors](doc:mirror), [comments](doc:comment), and other content you generate. - -Additionally, Profile NFTs contain a [FollowModule](doc:follow). This module contains the logic that allows different accounts to be issued Follow NFTs to record their relationship to the main profile on-chain. - -Profiles can only be minted by addresses that have been whitelisted by governance. This ensures that, given the low-fee environment present on Polygon, the namespace is not reserved by squatters. If you are building an application on Lens that requires the minting of Profiles, please join the [Discord](https://discord.gg/lensprotocol) and get in touch! \ No newline at end of file diff --git a/documents/Major Concepts/publication.md b/documents/Major Concepts/publication.md deleted file mode 100644 index 4dd5a8f..0000000 --- a/documents/Major Concepts/publication.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: "Publication" -slug: "publication" -hidden: false -createdAt: "2022-01-25T21:55:19.920Z" -updatedAt: "2022-10-02T16:15:13.149Z" ---- -![](https://files.readme.io/bf7d31b-illustration_post.svg "illustration_post.svg") - - - -Publications are the lifeblood of the Lens Protocol. They are all of the original content, comments, and mirrors produced by creators, curators, and users alike. Publications come in three primary types: posts, comments, and mirrors. Posts are the base object, with mirror and comment providing additional functionality. To learn more about [Mirrors](doc:mirror) and [Comments](doc:comment) please go to their respective documentation pages. - -Publications are posted directly to a user's [ProfileNFTs](doc:profile); this ensures that all content created by a user remains user-owned and in their wallet. Publications are **NOT** NFT's. - -Publications have a ContentURI which points to the specific content the publication contains, this can point to text, an image, a video, or other arbitrary content stored on either a decentralized protocol such as [IPFS](https://ipfs.io/) or [Arweave](https://www.arweave.org/), or a centralized storage provider like AWS S3. - -Publications also have two attached modules, a Collect Module, and a Reference Module. The [Collect Module](doc:collect) contains the logic that allows other users to mint your publication into an NFT. This NFT will reference the original Publication's URI. The Reference Module controls references to the publication itself. It contains the logic that determines who can [comment](doc:comment) and [mirror](doc:mirror) the publication. \ No newline at end of file diff --git a/documents/React Hooks SDK/advanced.md b/documents/React Hooks SDK/advanced.md deleted file mode 100644 index 0480122..0000000 --- a/documents/React Hooks SDK/advanced.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Advanced" -slug: "advanced" -hidden: false -createdAt: "2023-01-19T17:41:14.691Z" -updatedAt: "2023-01-20T14:42:29.985Z" ---- -- [Error handling](doc:error-handling) \ No newline at end of file diff --git a/documents/React Hooks SDK/advanced/error-handling.md b/documents/React Hooks SDK/advanced/error-handling.md deleted file mode 100644 index 2624a56..0000000 --- a/documents/React Hooks SDK/advanced/error-handling.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: "Error handling" -slug: "error-handling" -excerpt: "The Lens SDK minimizes the possibility of incurring an error scenario when using the Lens Protocol. Said that, there are some circumstances that could lead to errors that might require external intervention, either by you or the end-user. This page gives you an overview of these scenarios." -hidden: false -createdAt: "2023-01-19T17:41:35.097Z" -updatedAt: "2023-04-03T15:53:57.576Z" ---- -## Async errors - -In the vast majority of the operations, the Lens SDK makes use of optimistic update strategies to return control to the user in a timely fashion. Several of these operations might involve long-lasting tasks that due to their nature might require from a handful of seconds up to minutes to settle. - -When configuring the `` wrapper you can specify an `errorHandler` function. - -```html JSX - - - -``` - - - -If one of these long-lasting tasks fails the Lens SDK will invoke the `errorHandler` function to notify you of the failure. - -The `errorHandler` function has the following signature: - -```typescript -function errorHandler( - error: - | FailedTransactionError -): void; -``` - - - -where: - -- `FailedTransactionError` - a user-initiated operation involving a blockchain transaction failed. - It has 2 properties: - - - `data: TransactionData` - the transaction data associated with the given transaction request. The transaction data contains a `request: SupportedRequestModel` with all the details - Depending on the stage at which the transaction has failed the `TransactionData` can be: - - `PendingTransactionData` - the transaction failed at a very early stage of creation even before receiving a TX hash. - - `BroadcastedTransactionData` - the transaction failed after has been broadcasted to the network. At this stage, the transaction has an associated TX hash. - - `reason: TransactionError` - the error object that contains the `reason` of the failure. Currently, the reason could be one of these: - ````typescript - ```typescript - enum TransactionErrorReason { - /** - * The tx failed to be broadcasted. - */ - CANNOT_EXECUTE = 'CANNOT_EXECUTE', - - /** - * The tx was broadcasted but it was not indexed by the Lens API - * within the expected timeout. - */ - INDEXING_TIMEOUT = 'INDEXING_TIMEOUT', - - /** - * Tthe tx was broadcasted but it was not mined within the - * expected timeout - */ - MINING_TIMEOUT = 'MINING_TIMEOUT', - - /** - * The gas-less broadcasting of the tx was rejected. - * This is probably due to reaching the wallet's time quota limit. - */ - REJECTED = 'REJECTED', - - /** - * The tx was reverted. - */ - REVERTED = 'REVERTED', - - /** - * A not recognized failure. - */ - UNKNOWN = 'UNKNOWN', - } - ``` - ```` - - -> 🚧 Errors, errors everywhere... -> -> The `LensProvider` `onError` handler would evolve over time with more errors being added so make sure you get notified by your tooling (.e.g typescript compiler) that new errors are not handled after updating the `@lens-protocol/react` version. - -## Generic local errors - -A lot of hooks that modify state report the `error` as a part of the hook return value (e.g. `useWalletLogin`). - -``` - const { execute, error, isPending } = useWalletLogin(); -``` - - - -Sometimes the errors are specific to the operation being involved (e.g. `FailedUploadError` when creating publication) but a lot of hooks share some common errors related to handling transaction errors. - -Below is the list of errors that are likely to happen when modifying the state which may involve creating a transaction: - -- `PendingSigningRequestError` - during a signing operation the Lens SDK detected that a previous signing request is still pending. This is done to prevent Lens signing requests from piling up in the user's wallet interface and becoming a source of confusion on what is the user required to do at any given time. -- `UserRejectedError` - the user canceled the operation. This is the typical case of user canceling the signing operation from their Wallet but its use can be extended to future use cases. -- `WalletConnectionError` - there was an issue while connecting to the user's wallet. The `reason` property gives more details on what happened: - -```typescript -export enum WalletConnectionErrorReason { - /** - * The operation required the wallet to be on a specific network - * and it was not possible to switch network. - */ - - INCORRECT_CHAIN = 'INCORRECT_CHAIN', - /** - * The operation required signing from a specific address, - * instead the connected wallet is associated with another address. - */ - - WRONG_ACCOUNT = 'WRONG_ACCOUNT', - - /** - * There is a pending connection request that - * was not yet cancelled or approved. - */ - STALE_CONNECTION_REQUEST = 'STALE_CONNECTION_REQUEST', -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/create-first-post.md b/documents/React Hooks SDK/create-first-post.md deleted file mode 100644 index 9b79f2d..0000000 --- a/documents/React Hooks SDK/create-first-post.md +++ /dev/null @@ -1,677 +0,0 @@ ---- -title: "Create your first post" -slug: "create-first-post" -excerpt: "This guide will show you different ways to create a post on Lens" -hidden: false -createdAt: "2023-05-10T07:40:41.457Z" -updatedAt: "2023-05-26T15:13:15.914Z" ---- -When you create a post, the Lens Protocol requires you to upload the so-called Publication Metadata into a public location. The Lens SDK simplify this process by dealing with the actual Publication Metadata structure so the only thing you need to do is define the content of the publication and the rules around who can interact with your post, read it, and/or collect it. - -## Publication Metadata upload - -The first step is to define your Publication Metadata upload handler. You can define this once and for all and use in different part of your application. - -The upload handler needs to: - -- accept an opaque `data` structure, -- serialize it as JSON if necessary (rest assured the data structure the Lens SDK generates does not contain circular references), -- upload it to a publicly accessible data storage, -- return the URL that will serve the file to consumers. - -```typescript upload.ts -export const uploadJson = (data: unknown): Promise => { - const serialized = JSON.stringify(data); - - const url = // upload serialized to a public location - - return url; -} -``` - -> 🚧 Metadata as JSON -> -> It's important that the data storage solution you choose is able to serve the file as JSON (i.e. `Content: application/json`) so that later on the Lens API background workers can fetch it and index it correctly. -> -> It's not mandatory but it's a good custom to upload Publication Metadata in a location that is in-line with the Lens ethos: decentalized and immutable. [IPFS](https://ipfs.tech/) and [Arweave](https://www.arweave.org/) are two popular choices in this space. - -## Text-only post - -Once you have you Publication Metadata upload handler, let's see what it takes to create a purely textual post. [Here](https://lens-protocol.github.io/lens-sdk/types/_lens_protocol_react_web.CreatePostArgs.html) is an overview of the metadata values you can pass in to the create function. [Here](https://docs.lens.xyz/docs/metadata-standards#metadata-structure) is an overview of the entire metadata standard. - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - }); - }; - // ... -} -``` - -In the example above we assumed you defined some kind of composer component. For brevity we omitted the actual input fields and just focused on an hypothetical submit handler. Adapt this to your needs. - -You might notice the `useCreatePost` hook requires a reference to a `publisher: ProfileOwnedByMe`, this is a specialized type of `Profile` that is associated with the current logged-in wallet. See [Profile Management](doc:profile-management) to know what hooks returns this specialized profile type. - -## Publication Metadata upload - Full Example (Next.js) - -Here is an example using a Next.js API route with Bundlr Network, to show you how you might put it all together. - -```typescript -/* Server */ -// Next.js Route Handler example at /api/upload/page.ts (or your API implementation) -export async function POST(req: NextRequest) { - const data = await req.json() - const bundlr = new Bundlr("http://node1.bundlr.network", "matic", process.env.BNDLR_KEY) - await bundlr.ready() - const tx = await bundlr.upload(JSON.stringify(data), { - tags: [{ name: 'Content-Type', value: 'application/json' }], - }) - - return NextResponse.json({ url: `https://arweave.net/${tx.id}` }) -} - -/* Client */ -// useCreatePost hook -const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - -// Upload function -async function uploadJson(data: unknown) { - try { - const response = await fetch('/api/upload', { - method: 'POST', - body: JSON.stringify(data), - }) - const json = await response.json() - return json.url - } catch(err) { - console.log({ err }) - } -} - -// create post function -async function createPost() { - await create({ - content: "Hello World", - contentFocus: ContentFocus.TEXT, - locale: 'en', - }) -} - -// button - -``` - -To view the entire codebase including imports and authentication, click [here](https://gist.github.com/dabit3/2e5039c0267dd1660e2e82e5b870717d). - -## App specific posts - -Occasionally some apps might have the desire to flag publications as being generated by them. Contextually the same app might have the need to just show publications created using the app itself. -The Lens SDK approaches this problem at the main configuration level. - -```typescript -import { LensConfig, development } from '@lens-protocol/react-web'; -import { bindings as wagmiBindings } from '@lens-protocol/wagmi'; - -const lensConfig: LensConfig = { - bindings: wagmiBindings(), - environment: development, -}; -``` - -When you create the `LenConfig` you can specify an `appId` field. The content of this field will be automatically included as part of the Publication Metadata of any publication (post or comment) created via the SDK. See the [Getting Started](doc:sdk-react-getting-started) to see how the `LensConfig` is then used. - -```typescript -import { appId, LensConfig, development } from '@lens-protocol/react-web'; -import { bindings as wagmiBindings } from '@lens-protocol/wagmi'; - -const lensConfig: LensConfig = { - appId: appId('bob'), - bindings: wagmiBindings(), - environment: development, -}; -``` - -The `appId` helper used in the example assures type-safety and, in the near future, it will validate the given ID. - -Without further configuration, an instance of the Lens SDK configured as above will surface ALL Lens ecosystems publications including the ones flagged with the provided `appId`. - -If you want to filter content returned by all publications related hooks to just the one created by your app you can specify a `sources` array like so. - -```typescript -import { appId, LensConfig, development } from '@lens-protocol/react-web'; -import { bindings as wagmiBindings } from '@lens-protocol/wagmi'; - -const lensConfig: LensConfig = { - appId: appId('bob'), - sources: [appId('bob')], - bindings: wagmiBindings(), - environment: development, -}; -``` - -From now on, all publication hooks will yield publications created by your application. - -> 🚧 More than one source -> -> Given the `sources` is an array of `AppId`, you can also provide more than just your own App ID: -> -> ```typescript -> sources: [appId('bob'), appId('lenster')] -> ``` - -## The post language - -In the previous example you might have noticed the `locale` property set to `en`. This is one of the few fields that are required in order to create a new publication. - -The locale string is in the format of `-` or just ``, where: - -- `language-tag` is a two-letter [ISO 639-1](https://www.loc.gov/standards/iso639-2/php/code_list.php) language code, e.g. `en` or `it` -- `region-tag` is a two-letter [ISO 3166-1 alpha-2](https://www.iso.org/obp/ui/#search) region code, e.g. `US` or `IT` - -You can just pass in the language tag if you do not know the region or don't need to be specific. - -By just specifying the `language-tag` portion you are saying the post is primarily in that language (e.g. `en` english content that should be suitable to most english speakers). With the `region-tag` portion you can specify the use of a dialect or customs typical of a specific region (e.g. `en-GB` English as spoke in United Kingdom). This might include but not be limited to: formatting of currency values, formatting of dates, units of measurement, specific dialect declensions. - -## Collect policy - -When not specified the default collect policy is that nobody can collect your post. - -You can specify the following collect policies: - -- No-collect policy -- Free collect policy -- Charge collect policy - -### No-collect policy - -The publication cannot be collected (same as default, you can omit it if need to). - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost, CollectPolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.NO_COLLECT - } - }); - } - - // ... -} -``` - -> 🚧 Momoka support -> -> Starting from Lens SDK v1.1.0, all non-collectable post will automatically leverage the Momoka infrastructure. - -### Collectable policies - -The Lens Protocol supports a variety of collect settings that among other things allow to charge a fee for when a publication gets collected. The underlying collect module configuration is a non-trivial task of selecting the correct Collect Module and define its parameters. - -The Lens SDK abstracts this complexity away from you and, while retaining the full potential of the underlying Protocol capabilities, it let you focus on the collect constraints you want to set for your post. The Lens SDK will take into consideration the configuration you provided and select the correct collect module for the job. - -#### Collect NFT Metadata - -All collectable policies requires you to define extra metadata fields that are eventually relevant for the Collect NFTs. You might be already familiar with some of these directly or indirectly as they are quite common in other ERC-721 implementations. These fields are typically used in the UI of NFT marketplaces like OpenSea. - -The Lens SDK accepts type-safe versions of these fields, so that you can focus on the data and the SDK will take care of the correct formatting. - -```typescript -import { NftAttributeDisplayType, NftMetadata } from '@lens-protocol/react-web' - -const metadata: NftMetadata = { - name: 'The name of the collect NFT', // the NFT title on OpenSea - description: 'A short description for the NFT', // also visible on OpenSea NFT details page - - // Visible on OpenSea under traits - attributes: [ - { - displayType: NftAttributeDisplayType.Date, - value: new Date(), // actual Data instance - traitType: 'DoB' - }, - { - displayType: NftAttributeDisplayType.Number, - value: 42, // an actual JS number - traitType: 'Level' - }, - { - displayType: NftAttributeDisplayType.String, - value: '#ababab', // an arbitrary JS string - traitType: 'Color' - }, - ] -} -``` - -#### Followers only restriction - -All collectable policies allow to specify if the profile collecting (the wallet owning the profile to be precise) needs to follow the publication author's profile. - -This is possible via the `followersOnly` field. See the following collect policies examples to see how this field should be used. - -#### Free collect policy - -It's a collect policy where the publication can be collected for free. You can restrict the collect to just the followers of your `publisher` profile via the `followersOnly` field. - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost, CollectPolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.FREE, - metadata, // as defined before - followersOnly: true - } - }); - } - - // ... -} -``` - -#### Collect fees - -The Lens SDK defines all currency amounts via a lightweight abstraction called `Amount`. Collect policy fees are defined via a specialized `Amount` type. The possible ERC-20 tokens do depend on the underlying Lens Protocol capabilities. With time the Lens Protocol will support more and more ERC-20 tokens. - -You can find all ERC-20 currently supported by the Lens Protocol via the `useCurrencies` hook. You can use this hook to create a simple currency selector UI like so: - -```typescript -import { useCurrencies, Erc20 } from '@lens-protocol/react-web'; - -function CurrencySelector({ onChange }: { onChange: (currency: Erc20) => void) { - const { data: currencies, error, loading } = useCurrencies(); - - const handleChange = (event: React.ChangeEvent) => { - const currency = currencies.find((currency) => currency.symbol === event.target.value); - if (currency) onChange(currency); - }; - - if (loading) return

Loading...

; - - if (error) return

Error: {error.message}

; - - return ( - - ); -} -``` - -The example is written for a web application but it can simply be adapted to a React Native app (just remember to import from `@lens-protocol/react` instead of `@lens-protocol/react-web`). - -#### Mirror reward - -The mirror reward represent the percentage of the fee that goes to the mirror profile's owner when the publication gets collected via a mirror. - -Collect policies that involve a fee do require you to specify this a `mirrorReward` field. The field accepts a percentage value between 0 and 100 and has precision up to 0.01 percentage points (e.g. `0.001 = 0%`, `0.01 = 0.01%`, `0.1 = 0.1%`, `1 = 1%`, `99 = 99%`, `99.99 = 99.99%`, `99.999 = 100%`). - -#### Collect limit (optional) - -Collect policies involving a fee allows you to also specify an optional maximum number of Collect NFTs that can be generated from a given publication. This effectively allow you to create scarcity of a given publication Collect NFT. - -The collect limit can be specified via the `collectLimit` field and it's an integer number between `1` and [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). - -If not provided there is virtually no limit to the amount of Collect NFTs that can be minted from the given publication. - -#### Single recipient collect policy - -The single recipient collect policy is a fee-based collect policy that allows to define a single recipient for the collect fee. - -You must also provide: - -- `metadata` -- `mirrorReward` - it could be 0 -- `followersOnly` restriction -- `timeLimited` - a bespoke flag that makes the publication collectable for up to 24 hours from the time the post gets finalized on-chain -- `collectLimit` - -```typescript Composer.tsx -import { Amount, ContentFocus, Erc20, ProfileOwnedByMe, useCreatePost, CollectPolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const [currency, setCurrency] = useState(null); // use setCurrency in your - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - if (!currency) return; - - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.CHARGE, - metadata: { /* NftMetadata */ }, - followersOnly: true, // only followers can collect - collectLimit: 100, // only 100 available (this is optional) - mirrorReward: 5, // 5% goes to the mirror author if collected via a mirror - - fee: Amount.erc20(currency, 1), - recipient: publisher.ownedBy, // or another address the user defines - timeLimited: false - } - }); - } - - // ... -} -``` - -#### Multiple recipients collect policy - -The multiple recipient collect policy is very similar to the single recipient collect policy but with 2 main differences: - -- the most obvious one is that you can specify more than one recipient address. It will also requires you to specify the percentage value (number between 0 to 100 with) they would get from each collect fee. The total percentage amount should add up to 100% -- the second difference is that you can specify a time limit as a future predefined deadline via the `endTimestamp` field - -Everything else is as per other collect policies: `collectLimit`, `mirrorReward`, `followersOnly` and NFT `metadata`. - -```typescript Composer.tsx -import { Amount, ContentFocus, Erc20, ProfileOwnedByMe, useCreatePost, CollectPolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const [currency, setCurrency] = useState(null); // use setCurrency in your - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - if (!currency) return; - - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.CHARGE, - metadata: { /* NftMetadata */ }, - followersOnly: true, // only followers can collect - collectLimit: 100, // only 100 available (this is optional) - mirrorReward: 5, // 5% goes to the mirror author if collected via a mirror - - fee: Amount.erc20(currency, 10), - recipients: [ - { - recipient: publisher.ownedBy, - split: 80, // 80% - }, - { - recipient: '0x....', - split: 20, // 20% - } - ], - endTimestamp: new Date(2023, 11, 25).getTime() - } - }); - } - - // ... -} -``` - -## Reference policy - -When not specified the the default reference policy is that anybody can comment and/or mirror your post. - -You can specify the following reference policies: - -- Anybody -- Followers only -- Degrees of separation - -### Anybody - -Anybody can reference the post (same as default, you can omit it if need to) - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost, ReferencePolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - reference: { - type: ReferencePolicyType.ANYONE - } - }); - } - - // ... -} -``` - -### Followers only - -Only your followers can comment and/or mirror the post - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost, ReferencePolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - reference: { - type: ReferencePolicyType.FOLLOWERS_ONLY - } - }); - } - - // ... -} -``` - -### Degrees of separation - -You can fine tune what reference operations are restricted (comments and/or mirrors) and the maximum distance a profile can be from your profile in your social graph. This distance is called "degree of separation" and is a cardinal number where: - -- 1: only your direct followers can reference the post -- 2: up to followers of your followers can reference the post -- N: up to N hops in the followers-of-followers chain can reference the post - -```typescript Composer.tsx -import { ContentFocus, ProfileOwnedByMe, useCreatePost, ReferencePolicyType } from '@lens-protocol/react-web'; -import { uploadJson } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - reference: { - type: ReferencePolicyType.DEGREES_OF_SEPARATION, - params: { - degreesOfSeparation: 2, // only direct followers and followers of direct followers can comment - commentsRestricted: true, //only comments are restricted - mirrorsRestricted: false, // anybody can mirror - } - } - }); - } - - // ... -} -``` - -#### The special case for 0 degrees of separation - -The careful reader might have noticed that `degreesOfSeparation` could technically accept `0` as possible value. This is effectively achieving the same result as blocking all reference activities (according to the `commentsRestricted`, `mirrorsRestricted` flags) for the given post. - -## Media post - -By media posts we mean publications where the primary objective is to share an image, audio, video file OR a collection of thereof. - -In order to define a media post you must specify a `contentFocus` that is one between: `ContentFocus.AUDIO`, `ContentFocus.IMAGE`, `ContentFocus.VIDEO`. - -You need to first upload the files into a public location then provide the media details to the `useCreatePost` callback arguments like so: - -```typescript Composer.tsx -import { useState } from 'react'; -import { ContentFocus, ImageType, ProfileOwnedByMe, useCreatePost } from '@lens-protocol/react-web'; -import { uploadJson, uploadMediaFile } from './upload' - -function Composer({ publisher }: { publisher: ProfileOwnedByMe }) { - const [selectedFile, selectFile] = useState(null) - const { execute: create, error, isPending } = useCreatePost({ publisher, upload: uploadJson }); - - const onSubmit = async () => { - if (!selectedFile) return - - const url = await uploadMediaFile(selectedFile); - - await create({ - contentFocus: ContentFocus.IMAGE, - locale: 'en', - media: [ - { - url, - mimeType: ImageType.PNG - } - ] - }); - } - - // ... -} -``` - -In the example above we assumed you defined an `uploadMediaFile(file: File): string` function that is able to accept a Web API [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) instance, upload it to a non-specified public location and return the public URL from where the file will be served from. Given the degree of freedom one have it's difficult to provide an exhaustive example that works for everybody. As reference you can find an [example function](https://github.com/lens-protocol/lens-sdk/blob/main/examples/web-wagmi/src/upload.ts#L61-L84) in the Lens SDK monorepo. - -### Multiple media files - -You can create a publication that contains multiple media files of the same typology (audio, image, or video) by providing more items to the `media` field: - -```typescript -await create({ - contentFocus: ContentFocus.IMAGE, - locale: 'en', - media: await Promise.all(files.map(async (file) => { - const url = await uploadMediaFile(file); - - return { - url, - mimeType: ImageType.PNG - }; - })) -}); -``` - -Whilst there is almost not virtual limit to the number of media files referenced by the same publication, try to be conscious that Lens publications are portable and might be served by other apps in the Lens ecosystem. - -> 🚧 Media file upload -> -> As per Publication Metadata, the Lens SDK does not force you to make any choice on where to upload your media files. We do still recommend to follow the Lens ethos and use a decentralized and possibly immutable data storage solution (e.g. IPFS or Arweave). This is even more true if the publication is a collectable posts. The potential collectors will receive collect NFTs that are truly immutable and decentralized starting from the on-chain data, passing through the NFT metadata, all the way to the referenced media files. - -### Contextual information - -Alongside the `media` list you can provide contextual informations via the `content` field. This is meant to give the consumer some corollary information about the media files. Think of this as an opportunity to add a video description, lyrics for an song, the description of an image gallery. - -```typescript -await create({ - contentFocus: ContentFocus.AUDIO, - locale: 'en', - content: ` - # Lyrics - - Coming out of my cage - And I've been doing just fine - Gotta gotta be down - Because I want it all - It started out with a kiss - How did it end up like this? - It was only a kiss, it was only a kiss - ... - `, - media: media: [ - { - url, - mimeType: AudioType.MP3, - altTag: 'Mr. Brightside - The Killers (cover by Ronnie)' - } - ] -}); -``` - -### Alternative media text - -It's good custom to provide a media alternative content in the form of a textual representation of the media to any media item you specify. You can do so via the `altTag` field of each `media` item. - -```typescript -await create({ - contentFocus: ContentFocus.IMAGE, - locale: 'en', - media: media: [ - { - url, - mimeType: ImageType.PNG, - altTag: 'A flying blue elephant' - } - ] -}); -``` - -### Cover images - -A common need when specifying Audio and Video posts is to provide a cover image that could represent the cover picture of an song or can be used as thumbnail for a video. - -You can do so by uploading an image using the same facilities you used for the main media file and specify the cover image URL via the `cover` field of each `media` item. - -```typescript -const songUrl = await uploadMediaFile(songFile); - -const coverUrl = await uploadMediaFile(coverImage); - -await create({ - contentFocus: ContentFocus.AUDIO, - locale: 'en', - media: [ - { - url: songUrl, - mimeType: AudioType.MP3, - cover: coverUrl - } - ] -}) -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/cyan-nails-turn-react-native-integration.md b/documents/React Hooks SDK/cyan-nails-turn-react-native-integration.md deleted file mode 100644 index 8cbaa55..0000000 --- a/documents/React Hooks SDK/cyan-nails-turn-react-native-integration.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "React Native integration" -slug: "cyan-nails-turn-react-native-integration" -hidden: false -createdAt: "2023-02-01T09:35:13.933Z" -updatedAt: "2023-03-20T07:44:01.356Z" ---- -The Lens SDK was built with `react-native` support in mind. Due to the nature of `react-native` environment some additional setup steps are required compared to the web. - -The first major difference is tha you should install the `@lens-protocol/react` package rather than `@lens-protocol/react-web` like you see in the examples. Then you can follow the rest of the examples, unless clearly specified, as they are still relevant also for React Native integrations. Only the import and some minor `` configuration aspects are different. - -For the most up-to-date integration steps for react-native visit the `README.md` of our `react-native` example app - - -The [example app](https://github.com/lens-protocol/lens-sdk/tree/main/examples/react-native) showcases the integration with the`@lens-protocol/react` and the way to build and provide custom `IStorageProvider` and `IBindings` implementations. \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery.md b/documents/React Hooks SDK/discovery.md deleted file mode 100644 index 8792638..0000000 --- a/documents/React Hooks SDK/discovery.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Discovery" -slug: "discovery" -hidden: false -createdAt: "2022-12-23T09:21:20.342Z" -updatedAt: "2023-01-16T10:20:59.188Z" ---- -- [useFeed](doc:use-feed) -- [useExploreProfiles](doc:use-explore-profiles) -- [useExplorePublications](doc:use-explore-publications) -- [useSearchProfiles](doc:use-search-profiles) -- [useSearchPublications](doc:use-search-publications) \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery/use-explore-profiles.md b/documents/React Hooks SDK/discovery/use-explore-profiles.md deleted file mode 100644 index d38e649..0000000 --- a/documents/React Hooks SDK/discovery/use-explore-profiles.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "useExploreProfiles" -slug: "use-explore-profiles" -hidden: false -createdAt: "2022-12-23T17:10:46.544Z" -updatedAt: "2023-03-20T07:14:46.612Z" ---- -`useExploreProfiles` is a React Hook used to query Lens profiles. - -```typescript -const { data, loading, hasMore, next } = useExploreProfiles(args) -``` - - - -## Usage - -```typescript TypeScript -import { useExploreProfiles } from '@lens-protocol/react-web'; - -function ExploreProfiles() { -const { data, loading } = useExploreProfiles(); -} -``` - - - -## Reference - -### `useExploreProfiles(args)` - -### Parameters - -`observerId: string` (optional) - -- The id of the profile that is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean, - hasMore: boolean, // whether there are more profiles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery/use-explore-publications.md b/documents/React Hooks SDK/discovery/use-explore-publications.md deleted file mode 100644 index 6c6b9d8..0000000 --- a/documents/React Hooks SDK/discovery/use-explore-publications.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "useExplorePublications" -slug: "use-explore-publications" -hidden: false -createdAt: "2023-01-13T14:48:20.781Z" -updatedAt: "2023-04-11T19:50:49.451Z" ---- -`useExplorePublications` is a React Hook used to explore different publications on Lens Protocol from a variety of people that you may not yet follow. - -```typescript -const { data, loading, hasMore, next } = useExplorePublications(args) -``` - - - -## Usage - -```typescript TypeScript -import { useExplorePublications } from '@lens-protocol/react-web'; - -function useExplorePublications() { - const { data, loading, hasMore, next } = useExplorePublications(); -} -``` - - - -## Reference - -### `useExplorePublications(args)` - -### Parameters - -`observerId: string` (optional) - -- The id of the profile that is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -`metadataFilter: PublicationMetadataFilters` (optional) - -- Any optional [metadata](https://docs.lens.xyz/docs/use-publications#publicationmetadatafilters) to filter publications by - -### Returns - -```typescript -{ - data: PublicationFragment[], - loading: boolean, - hasMore: boolean, // whether there are more publications after the current batch - next(): () => void, // fetches the next publications and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery/use-feed.md b/documents/React Hooks SDK/discovery/use-feed.md deleted file mode 100644 index 0b677b5..0000000 --- a/documents/React Hooks SDK/discovery/use-feed.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "useFeed" -slug: "use-feed" -hidden: false -createdAt: "2022-12-23T16:50:51.237Z" -updatedAt: "2023-03-20T07:10:54.690Z" ---- -`useFeed` is a React Hook that lets you fetch the feed of a given profile. - -```typescript -const { data, loading, hasMore, next } = useFeed(args) -``` - - - -## Usage - -```typescript TypeScript -import { useFeed } from '@lens-protocol/react-web'; - -function Feed() { -const { - data: feedItems, - loading, - hasMore, - next, - } = useFeed({ - profileId: '0x02', - limit: 10, - }); -} -``` - - - -## Reference - -### `useFeed(args)` - -### Parameters - -- `profileId: string` (required) - the id of the profile to fetch the feed for -- `observerId: string` (optional) - the id of the profile who is running the query, usually the logged-in/active profile -- `limit: number` (optional) - the amount of items to return per page. This is performed in a best effort fashion. The API might return slightly less items than requests. This does not mean the list reached the end of the data available. Use the `hasMore` returned flag to determine if more items are available in the following page of results. -- `metadataFilter: PublicationMetadataFilters` (optional) - Any optional [metadata](https://docs.lens.xyz/docs/use-publications#publicationmetadatafilters) to filter publications by. - -### Returns - -```typescript -{ - data: FeedItemFragment[], - loading: boolean, - hasMore: boolean, // whether there are more publications after the current batch - next(): () => void, // fetches the next publications and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery/use-search-profiles.md b/documents/React Hooks SDK/discovery/use-search-profiles.md deleted file mode 100644 index 8f17c03..0000000 --- a/documents/React Hooks SDK/discovery/use-search-profiles.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "useSearchProfiles" -slug: "use-search-profiles" -hidden: false -createdAt: "2023-01-12T07:06:41.027Z" -updatedAt: "2023-03-20T07:14:54.705Z" ---- -`useSearchProfiles` is a React Hook used to query Lens profiles based on a query. - -```typescript -const { data, loading, hasMore, next } = useSearchProfiles(args) -``` - - - -## Usage - -```typescript TypeScript -import { useSearchProfiles } from "@lens-protocol/react-web" - -function SearchProfiles() { - const { data, loading } = useSearchProfiles({ query: 'web3'}) -``` - - - -## Reference - -### `useSearchPublications(args)` - -### Parameters - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -`query: string` (required) - -- The query that will be used to search profiles - -### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean, - hasMore: boolean, // whether there are more profiles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/discovery/use-search-publications.md b/documents/React Hooks SDK/discovery/use-search-publications.md deleted file mode 100644 index 143f137..0000000 --- a/documents/React Hooks SDK/discovery/use-search-publications.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "useSearchPublications" -slug: "use-search-publications" -hidden: false -createdAt: "2023-01-12T07:21:37.816Z" -updatedAt: "2023-03-20T07:14:58.482Z" ---- -`useSearchPublications` is a React Hook used to query Lens publications based on a query. - -```typescript -const { data, loading, hasMore, next } = useSearchPublications(args) -``` - - - -## Usage - -```typescript TypeScript -import { useSearchPublications } from "@lens-protocol/react-web" - -function SearchPublications() { - const { data, loading } = useSearchPublications({ query: 'web3'}) - } -``` - - - -## Reference - -### `useSearchPublications(args)` - -### Parameters - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -`query: string` (required) - -- The query that will be used to search publications - -`sortCriteria: PublicationSortCriteria` (optional) - -- the criteria for sorting the result - -`publicationTypes: PublicationTypes[]` (optional) - -- the types of publications to query - -### Returns - -```typescript -{ - data: Publication, - loading: boolean, - hasMore: boolean, // whether there are more profiles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/follow-a-profile.md b/documents/React Hooks SDK/follow-a-profile.md deleted file mode 100644 index 0318cc8..0000000 --- a/documents/React Hooks SDK/follow-a-profile.md +++ /dev/null @@ -1,758 +0,0 @@ ---- -title: "Follow a profile" -slug: "follow-a-profile" -excerpt: "This guide will show everything you need to know about following profiles" -hidden: false -createdAt: "2023-05-25T07:25:39.921Z" -updatedAt: "2023-05-26T12:14:33.241Z" ---- -When it comes to follow a Profile there two concepts coming into play. The Follow Policy of the followed Profile and the actual following action performed by the follower. Let's look at them in order. - -## Setup your Follow Policy - -The Follow Policies for a given Profile can be categorized into 4 types: - -- Anybody can follow -- No one can follow -- Only another Profile owner can follow -- Charge a fee to follow - -The first thing then to do is to build a UI that allows to make this initial choice. - -```typescript FollowTypeOption.tsx -import { FollowPolicyType, ProfileOwnedByMe, useUpdateFollowPolicy } from '@lens-protocol/react-web'; - -type FollowTypeOptionProps = { - label: string; - value: FollowPolicyType; - type: FollowPolicyType; - onChange: (followPolicyType: FollowPolicyType) => void -} - -export function FollowTypeOption({ label, type, onChange, value }: FollowTypeOptionProps) { - return ( - - ) -} -``` - -Not that we have a component representing the single Follow Policy type we can start building our form. - -```typescript MyFollowPolicy.tsx -import { useState } from 'react'; -import { FollowPolicyType, ProfileOwnedByMe, useUpdateFollowPolicy } from '@lens-protocol/react-web'; - -import { FollowTypeOption } from './FollowTypeOption'; - -function MyFollowPolicy({ profile }: { profile: ProfileOwnedByMe }) { - const [followType, setFollowType] = useState(FollowPolicyType.ANYONE) - - return ( -
- - - - - - - - - // to be continued... - - ) -} -``` - -We are almost there, the most interesting thing now is to build a UI that allows to setup a follow fee for the `FollowPolicyType.CHARGE` option. - -First we need to be able to select a currency among the ones supported by the Lens Protocol. To do that we will use the `useCurrencies` hook. - -```typescript CurrencySelector.tsx -import { Erc20, useCurrencies } from '@lens-protocol/react-web'; - -type CurrencySelectorProps = { - onChange: (currency: Erc20) => void -} - -export function CurrencySelector({ onChange }: CurrencySelectorProps) { - const { data: currencies, error, loading } = useCurrencies(); - - const handleChange = (event: React.ChangeEvent) => { - const currency = currencies.find((currency) => currency.symbol === event.target.value); - if (currency) onChange(currency); - }; - - if (loading) return

Loading...

; - - if (error) return

Error: {error.message}

; - - return ( - - ); -} -``` - -We can now create an `AmountField` component that encapsulates the UI that allows to select a currency and provide an amount. Keep this around it will become handy in other contexts. - -```typescript AmountField.tsx -import React, { useState } from 'react'; - -import { Amount, Erc20Amount, Erc20 } from '@lens-protocol/react-web'; - -import { CurrencySelector } from './CurrencySelector'; - -type AmountProps = { - onChange: (fee: Erc20Amount) => void; -} - -export function AmountField({ onChange }: AmountProps) { - const [currency, setCurrency] = useState(null); - const [amount, setAmount] = useState('0'); - - const updateAmount = (event: React.ChangeEvent) => { - setAmount(event.target.value) - - if (currency) { - onChange(Amount.erc20(currency, event.target.value)); - } - }; - - const updateCurrency = (newCurrency: Erc20) => { - setAmount('0') - setCurrency(newCurrency) - }; - - return ( -
- - - -
- ); -} -``` - -Let's put it all together now. - -```typescript MyFollowPolicy.tsx -import { useState } from 'react'; - -import { Amount, FollowPolicyType, ProfileOwnedByMe, useUpdateFollowPolicy } from '@lens-protocol/react-web'; - -import { FollowTypeOption } from './FollowTypeOption'; -import { AmountField } from './AmountField'; - -function MyFollowPolicy({ profile }: { profile: ProfileOwnedByMe }) { - const { execute: updateFollowPolicy, isPending, error } = useUpdateFollowPolicy({ profile }); - const [followType, setFollowType] = useState(FollowPolicyType.ANYONE) - - const [fee, setFee] = useState(null) - - const onSubmit = async () => { - if (followType === FollowPolicyType.CHARGE) { - if (fee === null) { - window.alert('You must provide a follow fee'); - return; - } - - await updateFollowPolicy({ - type: FollowPolicyType.CHARGE, - amount: fee, - recipient: profile.ownedBy - }); - - return; - } - - await updateFollowPolicy({ type: followType }); - }; - - return ( -
- // .. other options omitted for brevity - - - - {followType === FollowPolicyType.CHARGE && ( - - )} - - - - ); -} -``` - -You might have noticed in the `onSubmit` handler that the `FollowPolicyType.CHARGE` also allow to specify a `recipient` (i.e. an address that will receive the fee). In the example we used the Profile owner address (i.e. the current logged-in wallet address). [This example](https://github.com/lens-protocol/lens-sdk/blob/main/examples/web-wagmi/src/profiles/UseUpdateFollowPolicy.tsx) in the Lens SDK monorepo shows how to let the user specify a different recipient address. - -> 🚧 What about follow module settings? -> -> If you are already familiar with the Lens Protocol, you might have noticed that Follow Policy sounds relatively familiar and close to the concept of follow module settings. -> -> This because Follow Policy is a powerful abstraction on top of follow module settings. It's provided by the Lens SDK React hooks in order to: -> -> ### Make read/write type-safe -> -> The TypeScript definition for the follow module settings is auto-generated out of GraphQL schema. Although the code generation tools are quite smart the TypeScript type system is significantly more powerful than GraphQL. As result the code generation process inevitably needs to play by the rules of a less capable GraphQL types (this is not a critique, we love GraphQL, it's just an honest assessment). -> -> The resulting TS type definition is not type safe and error prone. -> -> The Follow Policy makes explicit the rules that MUST be observed in order to setup correctly the underlying follow modules. -> -> ### Decouple consumer's code -> -> By having an abstraction between the consumer's code and the follow module settings, the Lens SDK act as a natural cushion that allow the Lens Protocol to evolve fast. Very, very, very fast!! The Lens SDK will take care of the details. As the time goes by new follow modules will be added and others will be deprecated. The Lens SDK will make your adoption of new feature as simple as updating a package. - -## How to follow a profile - -When it comes to build a UX that allows to follow a Profile the first thing is usually exposing to the user the Follow Policy details. - -All Profiles returned by the Lens SDK React hook have these extra properties: - -- `followPolicy: FollowPolicy` exposes the Follow Policy the followee user decided -- `followStatus: FollowStatus` exposes dynamic informations relevant for knowing when is possible to follow a given Profile - -Let's see how to use it to create a `FollowButton` component. - -```typescript FollowButton.tsx -import { FollowPolicy, FollowPolicyType, Profile } from '@lens-protocol/react-web'; - -type FollowButtonProps = { - followee: Profile; -} - -function formatButtonText(policy: FollowPolicy): string { - switch (policy.type) { - case FollowPolicyType.ONLY_PROFILE_OWNERS: - case FollowPolicyType.ANYONE: - return 'Follow'; - - case FollowPolicyType.CHARGE: - return `Pay ${policy.amount.toSignificantDigits(6)} ${policy.amount.asset.symbol} to follow`; - - default: - return `You cannot follow`; - } -} - -export function FollowButton({ followee }: FollowButtonProps) { - if (followee.followStatus.isFollowedByMe) { - return ( -

You are following {followee.handle}

- ) - } - - return ( - - ); -} -``` - -> 🚧 Why use `followStatus`? -> -> If you are familiar with the Lens API you might already seen other Profile fields that can be used to achieve similar needs. While it's true that one could technically infer `followStatus.isFollowedByMe` and `followStatus.canFollow` from other Profile fields, those **other fields are a frozen snapshot of the Profile** at the time the data was retrieved from the API. -> -> On the other hand **`followStatus` takes into account the dynamic nature of the app**. It takes into account any inflight follow/unfollow requests (e.g. tx that are not mined or indexed yet) and gives you the cohesive state you need to build a solid UX. - -Now let's add the actual follow capability via the `useFollow` hook. - -```typescript FollowButton.tsx -import { Profile, ProfileOwnedByMe, useFollow } from '@lens-protocol/react-web'; - -type FollowButtonProps = { - followee: Profile; - follower: ProfileOwnedByMe; -} - -// formatButtonText helper omitted for brevity - -export function FollowButton({ followee, follower }: FollowButtonProps) { - const { execute: follow, error, isPending } = useFollow({ followee, follower }); - - return ( - <> - - - {error && {error.message}} - - ); -} -``` - -> 👍 `ProfileOwnedByMe`? -> -> You might remember this specialized type of profile from [Profile Management](doc:profile-management) guide. -> -> This is a special type of Profile returned by hooks such as `useActiveProfile` (or `useProfilesOwnedByMe`) so to be used in scenario we have to know the Profile that is the "actor" performing a given operation. -> -> This not only makes the whole SDK more type safe but also promotes an usage of hooks and wrapping component that minimize re-rendering and simplify data flow. - -### Error handling - -In the example above we just render the `error.message` under the follow button. This might be quick but probably not very user friendly. Mostly because the error message are aimed at integrators and not end-users. - -In this section we will explore 2 ways of handling errors. - -#### Format error messages - -The most straightforward way to deal with error is just to have a formatting component that translates the error type into a user friendly message. - -```typescript FollowButton.tsx -import { FollowOperation, useFollow } from '@lens-protocol/react-web'; - -// other details omitted for brevity - -function FormatErrorMessage({ error }: { error: FollowOperation['error'] }) { - if (!error) { - return null; - } - - switch (error.name) { - case 'InsufficientAllowanceError': - return Your wallet does not have enough allowance to perform this transaction. - - case 'InsufficientFundsError': - return Your wallet does not have enough funds to cover the requested follow fee. - - case 'PendingSigningRequestError': - return There is a pending signing request in your wallet. Please sign or reject it before proceeding. - - case 'UserRejectedError': - return You rejected the signing. - - case 'WalletConnectionError': - case 'BroadcastingError': - case 'PrematureFollowError': - return An unexpected error occurred. Please try again. - } -} - -export function FollowButton({ followee, follower }: FollowButtonProps) { - const { execute: follow, error, isPending } = useFollow({ followee, follower }); - - return ( - <> - - - - - ); -} -``` - -You can find the most up-to-date list of error types that `useFollow` could return in the corresponding [reference docs](https://lens-protocol.github.io/lens-sdk/types/_lens_protocol_react_web.FollowOperation.html). - -#### Handle operation result - -Another way to handle errors is imperatively at the call site. `useFollow` like many other SDK hooks that perform operations do resolve with a [`Result`](https://lens-protocol.github.io/lens-sdk/types/_lens_protocol_react_web.Result.html) object. Let's see how to use it to manage error scenarios. - -```typescript FollowButton.tsx -import { toast } from 'react-hot-toast'; - -import { PendingSigningRequestError, useFollow } from '@lens-protocol/react-web'; - -// other details omitted for brevity - -export function FollowButton({ followee, follower }: FollowButtonProps) { - const { execute, isPending } = useFollow({ followee, follower }); - - const follow = async () => { - const result = await execute(); - - if (result.isFailure()) { - if (result.error instanceof PendingSigningRequestError) { - toast.error( - 'There is a pending signing request in your wallet. Please sign or reject it before proceeding.' - ); - return; - } - - // other result.error handling as appropriate - } - } - - return ( - - ); -} -``` - -##### What's happening? - -- we put a `follow` callback that sits in between the button `onClick` and the `useFollow` `execute` function. -- we no longer use the `error` returned by the `useFollow` hook -- inside this `follow` callback we do the following: - - we call the `useFollow` `execute` function and keep the `result` - - in case the `result` is a failure we handle the `result.error`. In this example we use [`react-hot-toast`](https://react-hot-toast.com/), adapt it to your needs. - -##### Note - -In this example we used the [`instanceof` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof) to determine the nature of the error. Both the approach of using the `error.name` and `instanceof` are valid approaches and can be mixed with the 2 different error handling strategies. - -### Insufficient ERC-20 balance - -When performing a paid follow (i.e. following a Profile with `FollowPolicyType.CHARGE` Follow Policy) one of the error you can encounter is: `InsufficientFundsError`. - -It indicates that the logged-in wallet does not have enough tokens of the required ERC-20 currency. - -How to manage this error really depends on the capabilities of your app. One could simply inform the user so they can go and buy tokens from an exchange or, if you have a built-in on-ramp feature you could help the user in the process. - -In the example below we will just implement a warning scenario. - -```typescript FollowButton.tsx -import { toast } from 'react-hot-toast'; - -import { InsufficientFundsError, useFollow } from '@lens-protocol/react-web'; - -// other details omitted for brevity - -export function FollowButton({ followee, follower }: FollowButtonProps) { - const { execute, isPending } = useFollow({ followee, follower }); - - const follow = async () => { - const result = await execute(); - - if (result.isFailure()) { - if (result.error instanceof InsufficientFundsError) { - const amount = result.error.requestedAmount; - - toast.error( - `You don't have enough ${amount.asset.symbol} in your wallet. \n` + - `Buy ${amount.toSignificantDigits(6)} ${amount.asset.symbol} on an exchange and try again. \n` + - `Make sure to put the funds on you wallet on the Polygon network` - ); - return; - } - - // other result.error handling as appropriate - } - } - - return ( - - ); -} -``` - -##### What's happening? - -- we opt to do error handling using the `result` object. See section above. -- we detect the `result.error` is of type `InsufficientFundsError` and then we leverage the `error.requestedAmount` property to create a user friendly message. In this case the `error.requestedAmount` is the same exact value of `followPolicy.amount` and it's reported here for your convenience. -- we render a \` - -### Insufficient ERC-20 Allowance - -Another common scenario you are likely to need to deal with is: `InsufficientAllowanceError`. - -It indicates that, although there is enough ERC-20 funds in the user's wallet, the corresponding ERC-20 contract has not been given the required pre-authorization to let the specific Lens Protocol contract withdraw the follow fee. - -The concept of ERC-20 token Allowance is very crypto-native. It's not the intent of this document to explain in details the concept, there are better articles out there explaining this at length. - -For the purpose of our explanation we can just say the ERC-20 Allowance is a security mechanism that aims to protect the owner's funds. - -You might have encountered this concept in other dApps when you are asked to sign and pay for the **Approve transaction** before moving forward. - -The underlying idea is that in order for a 3rd party actor (called the "spender") to be able to interact with one's ERC-20 funds, the funds owner needs to provide a pre-authorization (the Allowance "amount"). The Allowance can be for an exact amount or for a larger amount. The Allowance can be revoked by setting it to 0. The Allowance does no constitute per se a final authorization to withdraw the funds. The owner would normally still need to provide a second authorization for the 3rd party to access the funds. - -> 🚧 Caveat -> -> At the time of this writing not all ERC-20s supported by the Lens Protocol have facility to make it possible to perform the operation in a [gasless](doc:gasless) fashion. -> -> This imply that the **user's wallet is responsible for signing and paying gas costs for the Approve transaction**. - -This is the sequence of events we are going to guide the user through: - -1. user attempts to perform a paid follow -2. the user sees a UI informing them that they have to sign and pay for the Approve transaction -3. the user retries the paid follow - -Let's detect the `InsufficientAllowanceError` and show an informative UI. - -```typescript FollowButton.tsx -import { useState } from 'react'; - -import { Erc20Amount, InsufficientAllowanceError, useFollow } from '@lens-protocol/react-web'; - -import { ApproveFollowModal } from './ApproveFollowModal'; - -// other details omitted for brevity - -export function FollowButton({ followee, follower }: FollowButtonProps) { - let [showApproveModal, setShowApproveModal] = useState(false) - - const { execute, isPending } = useFollow({ followee, follower }); - - const follow = async () => { - const result = await execute(); - - if (result.isFailure()) { - if (result.error instanceof InsufficientAllowanceError) { - setShowApproveModal(true); - return; - } - - // other result.error handling as appropriate - } - } - - return ( - <> - - - {showApproveModal && ( - setShowApproveModal(false) }/> - )} - - ); -} -``` - -#### What's happening? - -- we add a state that controls the visibility of a new component called `` -- we detect the `InsufficientAllowanceError` and we update the state so to show the component. - -Let's see how the `` component could look like. - -```typescript ApproveFollowModal.tsx -import { Dialog } from '@headlessui/react'; -import invariant from 'tiny-invariant'; - -import { FollowPolicyType, useApproveModule } from '@lens-protocol/react-web'; - -type ApproveFollowModalProps = { - followee: Profile; - onClode: () => void -} - -function noop() {} - -export function ApproveFollowModal({ followee, onClose }: ApproveFollowModalProps) { - const { execute, error, loading } = useApproveModule(); - - const followPolicy = followee.followPolicy.amount; - - invariant(followPolicy.type === FollowPolicyType.CHARGE, 'followee.followPolicy.type must be CHARGE') - - const approve = async () => { - const restult = await execute({ - // The follow fee - amount: followPolicy.amount, - - // The follow module contract address - spender: followPolicy.contractAddress, - - // In this case we want to approve the exact amount, TokenAllowanceLimit.INFINITE is another option - limit: TokenAllowanceLimit.EXACT - }); - - if (result.isSuccess()) { - onClose(); - } - }; - - return ( - - - Pre-approve follow - -

- This operation allows you to pre-approve the Lens Follow Module - (address: {followPolicy.contractAddress}) - associated with {followee.handle} follow settings - to withdraw {fee.toSignificantDigits(6)} {fee.asset.symbol}. -

- - {error &&

{error.message}

} - - - -
-
- ); -} -``` - -#### What's happening? - -- we use the `followPolicy` details to inform the user about the operation they are about to perform -- we use the `useApproveModule` to aid the process of signing and sending the Approve transaction. Specifically we call the `execute` callback with: - - the follow fee amount - - the follow module contract address - - the limit to use, allows just for the exact amount. -- we disable buttons and the closing of the modal while `loading` is `true` -- we close the modal when the operation `result` succeeds. - -#### Notes - -- We used [Headless UI ``](https://headlessui.com/react/dialog) to build a modal. This is not integral part of this guide. Use the tool that works best for you. -- In the example above we used `TokenAllowanceLimit.EXACT` as allowance `limit`. These are the options available and what they mean: - - `TokenAllowanceLimit.EXACT` limits the `spender` to use just the specified `amount`. Any other paid follow will show the `InsufficientAllowanceError` again. - - `TokenAllowanceLimit.INFINITE` sets the pre-approval limit for the given ERC-20 to infinite. Basically this sort the effect of not surfacing `InsufficientAllowanceError` again in case of another paid follow involving the same ERC-20. -- We also used [`tiny-invariant`](https://www.npmjs.com/package/tiny-invariant) function to conveniently narrow down the type of `followPolicy` to [`ChargeFollowPolicy`](https://lens-protocol.github.io/lens-sdk/types/_lens_protocol_react_web.ChargeFollowPolicy.html) so to not have to second guess its properties later in the component. This is not the only way to solve this, your call. - -> 👍 EIP-1559 -> -> The `useApproveModule` hook implements [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) gas price estimation strategy. - -#### One last thing - -We are almost there. The last thing to do is manage error for the `useApproveModule` hook. - -In the example above we just print the `error.message` into the modal content. As for the case of `useFollow` error handling, the `error.message` here is not very user friendly so we might want adopt one of the 2 strategies outlined before. Of which we just show the formatting error approach here. - -```typescript ApproveFollowModal.tsx -import { Dialog } from '@headlessui/react'; -import invariant from 'tiny-invariant'; - -import { ApproveModuleOperation, useApproveModule } from '@lens-protocol/react-web'; - -function FormatErrorMessage({ error }: { error: ApproveModuleOperation['error'] }) { - if (!error) { - return null; - } - - switch (error.name) { - case 'InsufficientGasError': - return You don't have enough MATIC to cover the gas costs of this transaction - - case 'PendingSigningRequestError': - return There is a pending signing request in your wallet. Please sign or reject it before proceeding. - - case 'UserRejectedError': - return You rejected the signing. - - case 'TransactionError': - case 'WalletConnectionError': - return An unexpected error occurred. Please try again. - } -} - -export function ApproveFollowModal({ followee, onClose }: ApproveFollowModalProps) { - const { execute, error, loading } = useApproveModule(); - - // omitted for brevity - - return ( - - - Pre-approve follow - -

- This operation allows you to pre-approve the Lens Follow Module - (address: {followPolicy.contractAddress}) - associated with {followee.handle} follow settings - to withdraw {fee.toSignificantDigits(6)} {fee.asset.symbol}. -

- - - - - -
-
- ); -} -``` - -Worth noting here: - -- the `InsufficientGasError` is an error specific to operations that requires user's wallet MATIC to pay for the transaction costs. Similar to `InsufficientFundsError` you should adapt the UX to what best works for your users (on-ramp, exchange, etc.). -- the `TransactionError` is the one we encountered in [Error handling](doc:error-handling) and gives some more details about the reason for the failure. - -## How to unfollow - -Finally let's cover how to unfollow a Profile. We are going to use the `useUnfollow` hook. As it's very similar to the follow feature, just specular in its outcome, we are going to take a quick shortcut and show you the full example. - -```typescript UnfollowButton.tsx -import { Profile, ProfileOwnedByMe, useUnfollow } from '@lens-protocol/react-web'; - -type UnfollowButtonProps = { - followee: Profile; - follower: ProfileOwnedByMe; -} - -export function UnfollowButton({ followee, follower }: UnfollowButtonProps) { - const { execute: unfollow, error, isPending } = useUnfollow({ followee, follower }); - - return ( - <> - - - {error && {error.message}} - - ); -} -``` - -Notice the use of `followee.followStatus.canUnfollow` to determine if at any given point in time the operation can be performed. This accounts for any transient state (for example a pending follow request not yet finalized). - -> 👍 Bonus track -> -> The `UnfollowButton` example shown above is great to communicate the essence of the `useUnfollow` hook, but we think it's NOT the most common way to use it. -> -> Check [this example](https://github.com/lens-protocol/lens-sdk/blob/main/examples/web-wagmi/src/profiles/UseFollowAndUnfollow.tsx) in the Lens SDK monorepo that shows you how to build a follow/unfollow feature within the same button component. \ No newline at end of file diff --git a/documents/React Hooks SDK/hooks-authentication.md b/documents/React Hooks SDK/hooks-authentication.md deleted file mode 100644 index a3f7bf7..0000000 --- a/documents/React Hooks SDK/hooks-authentication.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Authentication" -slug: "hooks-authentication" -excerpt: "Sign-in, Sign-out and in between" -hidden: false -createdAt: "2023-04-04T07:27:51.068Z" -updatedAt: "2023-04-12T10:16:11.071Z" ---- -## Sign in - -Although the following example uses [wagmi](https://wagmi.sh/) it can be adapted to any wallet integration that results in an [ethers](https://ethers.org/) `Signer`. - -```typescript -import { useWalletLogin } from '@lens-protocol/react-web'; -import { useAccount, useConnect, useDisconnect } from 'wagmi'; -import { InjectedConnector } from 'wagmi/connectors/injected'; - -function LoginButton() { - const { execute: login, error: loginError, isPending: isLoginPending } = useWalletLogin(); - - const { isConnected } = useAccount(); - const { disconnectAsync } = useDisconnect(); - - const { connectAsync } = useConnect({ - connector: new InjectedConnector(), - }); - - const onLoginClick = async () => { - if (isConnected) { - await disconnectAsync(); - } - - const { connector } = await connectAsync(); - - if (connector instanceof InjectedConnector) { - const signer = await connector.getSigner(); - await login(signer); - } - }; - - return ( -
- {loginError &&

{loginError}

} - -
- ); -} -``` - - - -## Determine if the user is authenticated - -The Lens SDK makes use of the provided `Signer` instance only when really necessary and, once authenticated, it keeps track of it's own authentication status independently from the user's wallet. - -This allows to provide an app user experience that is reminiscent of traditional web2 social apps in the sense that user can come back to their authenticated browser tab (or app in the case of a React Native integration) they are not prompted to sign over and over authentication challenges. Also if your user were to open multiple dApps and switch network and/or accounts, this means that as they come back to your social app power by the Lens SDK they won't be prompted to switch back. The app will still be authenticated. Only at the time that a signature is required the Lens SDK will prompt the user to do the correct changes (e.g. switch back to Polygon network, etc). - -This also has the nice benefits of allowing the user to connect multiple wallets to the same dApps for the purpose of proving ownership of tokens/NFTs that are not hold on the wallet holding the Lens profile. We will get back to this when we will talk about using an NFT on another wallet as profile picture. - -```typescript -import { useActiveWallet } from '@lens-protocol/react-web'; - -function HomePage() { - const { data: wallet, loading } = useActiveWallet(); - - if (loading) { - return

Loading...

; - } - - if (wallet) { - return

You are logged-in with {wallet.address}

; - } - - return

You are logged-out

; -} -``` - - - -## Sign out - -```typescript -import { useWalletLogout } from '@lens-protocol/react-web'; - -function LogoutButton() { - const { execute: logout, isPending } = useWalletLogout(); - - return ( - - ); -} -``` - - - -Although the `useWalletLogout` returns an `isPending` flag, the sign-out operation tends to be pretty fast so do not expect to account for long wait. You probably don't need to do more than you see in the example above. \ No newline at end of file diff --git a/documents/React Hooks SDK/profile-management.md b/documents/React Hooks SDK/profile-management.md deleted file mode 100644 index 6e3df17..0000000 --- a/documents/React Hooks SDK/profile-management.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: "Profile Management" -slug: "profile-management" -excerpt: "Manage your own profiles" -hidden: false -createdAt: "2023-04-04T07:28:14.553Z" -updatedAt: "2023-05-25T09:24:52.349Z" ---- -## Active Profile - -On successful login via the `useWalletLogin` hook, the Lens SDK retrieves the Lens Profile owned by the authenticated wallet address and selects the first profile as the Active Profile. - -The Active Profile is then used throughout the SDK hooks to provide a cohesive view on the data. - -We can retrieve the Active Profile by means of the `useActiveProfile` hook: - -```typescript -import { useActiveProfile } from '@lens-protocol/react-web'; - -function MyProfile() { - const { data, error, loading } = useActiveProfile(); - - if (loading) return

Loading...

; - - if (error) return

Error: {error.message}

; - - if (data === null) return

No active profile

; - - return ( -
-

Active profile: {data.handle}

-
- ); -} -``` - -> 📘 Pro-tip -> -> For the TypeScript enthusiast out there, you might have noticed that the `useActiveProfile` yields a specialized type of profile called `ProfileOwnedByMe`. -> -> In and around the SDK your will find hooks that requires to know the Lens profile that is performing a given operation. Those hooks makes it clear that they need a profile owned by the logged-in wallet using the type `ProfileOwnedByMe`. See for example `collector` in `useCollect` hook or `follower` in `useFollow` hook. -> -> You can pass the profile returned by the `useActiveProfile` directly to those hook arguments and you can improve the type safety of your Lens integration with not extra effort. - -## Change the Active Profile - -If the logged-in wallet has more than one Lens profiles you can list all the profiles by means of the `useProfilesOwnedByMe`: - -```typescript -import { useProfilesOwnedByMe } from '@lens-protocol/react-web'; - -function MyProfiles() { - const { data: profiles, error, loading } = useProfilesOwnedByMe(); - - if (loading) return
Loading...
; - - if (error) return
Error: {error.message}
; - - return ( -
    - {profiles.map((profile) => ( -
  • {profile.name}
  • - ))} -
- ); -} -``` - -The `useProfilesOwnedByMe` is a paginated hook, so it returns the usual `hasMore` flag and `next`callback you found already in other paginated hooks. See [this example](https://github.com/lens-protocol/lens-sdk/blob/main/examples/web-wagmi/src/hooks/useInfiniteScroll.ts) of infinite scroll pagination leveraging this standardized paginated return type. - -We can now use the `useActiveProfileSwitch` to create a simple profile switcher interface: - -```typescript -import { useActiveProfileSwitch, useActiveProfile, useProfilesOwnedByMe } from '@lens-protocol/react-web'; - -function ProfileSwitcher() { - const { data: activeProfile } = useActiveProfile(); - const { execute: switchActiveProfile, isPending } = useActiveProfileSwitch(); - const { data: profiles, error, loading } = useProfilesOwnedByMe(); - - if (loading) return

Loading...

; - - if (error) return

Error: {error.message}

; - - return ( -
-

Active profile: {activeProfile?.handle}

-
    - {profiles.map((profile) => ( -
  • - -
  • - ))} -
-
- ); -} -``` - -> 👍 Pro-tip -> -> Again, for the TypeScript enthusiast might notice that `useProfilesOwnedByMe` returns `ProfileOwnedByMe` instances and that `useActiveProfileSwitch` callback accepts `ProfileOwnedByMe` only. -> -> This has 2 benefits: -> -> - self-document the hooks by informing how hooks can be composed together -> - provides type safety that avoid run-time issues before they can occur. - -## Log in as profile X - -Finally, if you know the profile you intend to use you can log-in and select the profile as the Active Profile to use in one go by passing the profile handle to the `useWalletLogin` callback: - -```typescript -import { useWalletLogin } from '@lens-protocol/react-web'; - -function LoginButton() { - const { execute: login, error: loginError, isPending: isLoginPending } = useWalletLogin(); - - const onLoginClick = async () => { - const handle = window.prompt('Type the profile handle you want to login with') - - // signer is available here, omitted for brevity - await login(signer, handle); - }; - - return ( -
- {loginError &&

{loginError}

} - -
- ); -} -``` - -The example above focuses on the alternative use of the `useWalletLogin` hook and omits several details of a proper login integration. See the [Authentication](doc:hooks-authentication) guide to see a more comprehensive example. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-misc.md b/documents/React Hooks SDK/sdk-misc.md deleted file mode 100644 index f6969af..0000000 --- a/documents/React Hooks SDK/sdk-misc.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Misc" -slug: "sdk-misc" -hidden: false -createdAt: "2022-12-23T09:25:13.693Z" -updatedAt: "2023-01-16T10:29:55.159Z" ---- -- [useCurrencies](doc:use-currencies) -- [useNotifications](doc:use-notifications) -- [useUnreadNotificationCount](doc:use-unread-notification-count) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-misc/use-currencies.md b/documents/React Hooks SDK/sdk-misc/use-currencies.md deleted file mode 100644 index 4e72781..0000000 --- a/documents/React Hooks SDK/sdk-misc/use-currencies.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "useCurrencies" -slug: "use-currencies" -hidden: false -createdAt: "2022-12-23T15:42:20.026Z" -updatedAt: "2023-03-20T07:31:19.850Z" ---- -`useCurrencies` is a React Hook that returns the list of ERC20 supported by the Lens Protocol. - -```typescript -const { data, loading } = useCurrencies(); -``` - - - -## Usage - -When configuring [Collect Modules](https://docs.lens.xyz/docs/icollectmodulesol) and [Follow Modules](https://docs.lens.xyz/docs/ifollowmodulesol) that involve a fee you need to specify an amount which requires to specify the corresponding ERC20 accepted as fee. - -The Lens SDK abstracts away these details and all it asks in its input data are instances of an `Amount` class. To instantiate an `Amount` you need to provide a string with the amount (as human readable string) and a reference to the correct `Erc20` which is a type that encapsulates currency details (ERC20 included). - -When invoked the `useCurrencies` hook interrogates the Lens API to retrieve the list of supported ERC20s and returns a list of `Erc20`. - -You can call `useCurrencies` to populate for example a drop-down that let the user select which currency to use to configure a fee. - -```typescript -import { useCurrencies } from '@lens-protocol/react-web'; - - -function CurrencyDropdown() { - const { data, loading } = useCurrencies(); - - if (loading) return null; - - return ( - - ) -} -``` - - - -## Reference - -### `useCurrencies()` - -```typescript -const { data, loading } = useActiveProfile(); -``` - - - -#### Parameters - -- `useCurrencies` does not take any parameters. - -#### Returns - -- `data` array of `Erc20` -- `loading` a flag that let you determine if `data` is ready to be read. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-misc/use-notifications.md b/documents/React Hooks SDK/sdk-misc/use-notifications.md deleted file mode 100644 index 0a2ac21..0000000 --- a/documents/React Hooks SDK/sdk-misc/use-notifications.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "useNotifications" -slug: "use-notifications" -hidden: false -createdAt: "2022-12-23T17:06:00.737Z" -updatedAt: "2023-03-20T07:31:24.000Z" ---- -`useNotifications` is a React Hook used to get all notifications for the authenticated user. - -```typescript -const { data, loading, hasMore, next } = useNotifications(args) -``` - - - -## Usage - -```typescript TypeScript -import { useNotifications } from '@lens-protocol/react-web'; - -function Notifications() { -const { - data, - loading, - hasMore, - next, - } = useNotifications({ - profileId: '0x77-0x0149', - limit: 10, - }); -} -``` - - - -## Reference - -### `useNotifications(args)` - -### Parameters - -`profileId: string` (required) - -- The id of the authenticated profile who is running the query. - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: Notification[], - loading: boolean, - hasMore: boolean, // whether there are more notifications after the current batch - next(): () => void, // fetches the next notifications and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-misc/use-unread-notification-count.md b/documents/React Hooks SDK/sdk-misc/use-unread-notification-count.md deleted file mode 100644 index b2583fe..0000000 --- a/documents/React Hooks SDK/sdk-misc/use-unread-notification-count.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "useUnreadNotificationCount" -slug: "use-unread-notification-count" -hidden: false -createdAt: "2022-12-23T16:10:24.213Z" -updatedAt: "2023-03-20T07:31:27.905Z" ---- -`useUnreadNotificationsCount` is a React Hook that let you know the number of unread notifications. - -```typescript -const { unreadNotificationCount, loading, clear } = useUnreadNotificationCount({ profileId }) -``` - - - -## Usage - -```typescript -import { useUnreadNotificationCount } from '@lens-protocol/react-web'; - - -function NotificationsCount({ profileId }: { profileId: string }) { - const { unreadNotificationCount, loading, clear } = useUnreadNotificationCount({ profileId }) - - if (loading) return null; - - return ( -
-

You have {unreadNotificationCount} unread notifications

- -
- ) -} -``` - - - -## Reference - -### `useUnreadNotificationCount(args)` - -```typescript -const { unreadNotificationCount, loading, clear } = useUnreadNotificationCount({ profileId }); -``` - - - -#### Parameters - -- `profileId: string` the profile Id you are interested in. - -#### Returns - -```typescript -{ - unreadNotificationCount: number; - loading: boolean; // whether unreadNotificationCount is readable or not - clear: () => Promise; // function to clear the counter -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile.md b/documents/React Hooks SDK/sdk-profile.md deleted file mode 100644 index 857c249..0000000 --- a/documents/React Hooks SDK/sdk-profile.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Profile" -slug: "sdk-profile" -hidden: false -createdAt: "2022-12-23T08:52:04.508Z" -updatedAt: "2023-03-03T10:24:56.258Z" ---- -- [useProfile](doc:use-profile) -- [useActiveProfile](doc:use-active-profile) -- [useProfilesOwnedBy](doc:use-profiles-owned-by) -- [useProfilesOwnedByMe](doc:use-profiles-owned-by-me) -- [useCreateProfile](doc:use-create-profile) -- [useProfileFollowers](doc:use-profile-followers) -- [useProfileFollowing](doc:use-profile-following) -- [useMutualFollowers](doc:use-mutual-followers) -- [useProfilesToFollow](doc:use-profiles-to-follow) -- [useFollow](doc:use-follow) -- [useUnfollow](doc:use-unfollow) -- [useUpdateProfileDetails](doc:use-update-profile-details) -- [useUpdateProfileImage](doc:use-update-profile-image) -- [useUpdateDispatcherConfig](doc:use-update-dispatcher-config) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-active-profile.md b/documents/React Hooks SDK/sdk-profile/use-active-profile.md deleted file mode 100644 index 083d711..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-active-profile.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "useActiveProfile" -slug: "use-active-profile" -hidden: false -createdAt: "2022-12-23T13:59:01.519Z" -updatedAt: "2023-03-20T06:58:16.719Z" ---- -`useActiveProfile` is a React Hook that lets you access the currently active Profile. - -```typescript -const { data, loading } = useActiveProfile(); -``` - - - -## Usage - -An `Signer` can own multiple Lens profiles. The Lens SDK has the concept of Active Profile. It's an in memory reference to a Profile object owned by the logged-in `Signer`. It is also persisted in the underlying `IStorageProvider` (see [`LensConfig`](doc:sdk-getting-started) until log out. - -Call `useActiveProfile` whenever you need access to the active Profile data. - -```typescript -import { useActiveProfile } from '@lens-protocol/react-web'; - -function ActiveProfileHandle() { - const { data, error, loading } = useActiveProfile(); - - if (loading) return

Loading...

- - if (error) return

{error.message}

- - if (data === null) return

No active profile selected

- - return

@{data.handle}

-} -``` - - - -> 📘 Which profile? -> -> During the login the first profile owned by the authenticated `Signer` will be selected as the active profile. - -## Reference - -### `useActiveProfile()` - -```typescript -function ActiveProfileHandle() { - const { data, error, loading } = useActiveProfile(); - // ... -} -``` - - - -#### Parameters - -- `useActiveProfile` does not take any parameters. - -#### Returns - -- `data` the `ProfileOwnedByMeFragment` data or `null` if there is no active profile. -- `error` any error it might occur while retrieving active profile data. -- `loading` a flag that let you determine if `data` is ready to be read. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-create-profile.md b/documents/React Hooks SDK/sdk-profile/use-create-profile.md deleted file mode 100644 index f6991bc..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-create-profile.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "useCreateProfile" -slug: "use-create-profile" -excerpt: "`useCreateProfile` is a React Hook that lets you create a new Lens Profile owned by the connected wallet." -hidden: false -createdAt: "2023-01-16T10:40:30.183Z" -updatedAt: "2023-03-20T07:04:10.122Z" ---- -> 🚧 Testnet only -> -> Lens Protocol is currently gated and will be opening up soon for anyone to mint a profile, for now only Testnet allows `useCreateProfile` to work. - -```typescript -const { execute, error, isPending } = useCreateProfile(); -``` - - - -## Usage - -Call `useCreateProfile` in the component responsible to accept the desired handle. - -``` -import { isValidHandle, useCreateProfile } from '@lens-protocol/react-web'; - - -const [handle, setHandle] = useState(null); - -const { execute: create, error, isPending } = useCreateProfile(); - -const onSubmit = async (e: FormEvent) => { - e.preventDefault(); - if (!handle) return; - await create(handle); -}; -``` - - - -```html JSX -
- { - if (isValidHandle(e.target.value)) { - setHandle(e.target.value); - } else { - setHandle(null); - } - }} - /> - - -
-``` - - - -> 🚧 -> -> `isValidHandle` is available from 0.3.x onward. - -## Reference - -### `useCreateprofile` - -#### Parameters - -`useCreateProfile` does not take any parameters. - -#### Returns - -Returns an object with: - -- `execute`: a function you can use to initiate the creation of a new Lens Profile. -- `isPending`: a boolean notifying you when the operation is still in progress. -- `error`: any error that might occur in normal operation conditions will be returned via this property. Default value `null` - - `DuplicatedHandleError` - the provided handle has already been taken - -### `execute` function - -You can use the `execute` function to initiate the profile creation process. Depending on the network conditions, this might take a while as the hook waits for the operation to be executed and indexed by the Lens API. - -#### Parameters - -It accepts a string with the desired handle. The handle should not contain the `.test` suffix (nor the `.lens` for the Lens Protocol main-net deployment). - -#### Returns - -It returns a `Promise` that you can use to sync with the state of your component. For example you can clear the content of any text input field when such promise resolves. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-follow.md b/documents/React Hooks SDK/sdk-profile/use-follow.md deleted file mode 100644 index a49f9b1..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-follow.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: "useFollow" -slug: "use-follow" -hidden: false -createdAt: "2023-01-05T16:18:01.001Z" -updatedAt: "2023-03-20T07:14:04.549Z" ---- -`useFollow` is a React Hook that lets you follow a profile. - -```typescript -const { execute, error, isPending } = useFollow({ followee, follower }); -``` - - - -## Usage - -```typescript -import { ProfileFragment, useFollow } from '@lens-protocol/react-web'; - -type ProfileFollowProps = { - profile: ProfileFragment; -}; - -export function FollowProfile({ profile }: ProfileFollowProps) { - const { execute: follow, error, isPending } = useFollow({ profile }); - - if (profile.isFollowedByMe) { - return

Following

; - } - - if (error) { - return

{error.message}

- } - - return ( - - ); -} - -``` - - - -## Reference - -### `useFollow()` - -Call `useFollow` where your follow button markup is and provide the profile that you would like to follow. - -```typescript -type ProfileFollowProps = { - followee: ProfileFragment; - follower: ProfileOwnedByMeFragment; -}; - -function FollowProfile({ followee, follower }: ProfileFollowProps) { - const { execute, isPending } = useFollow({ followee, follower }); - // ... -} -``` - - - -#### Parameters - -- `followee: ProfileFragment`: the profile you wish to follow -- `follower: ProfileOwnedByMeFragment`: one of the profile owned by the authenticated wallet as returned by `useActiveProfile` for example (or you can use the `isProfileOwnedByMe` helper to narrow down the type correctly from a `ProfileFragment` instance). - -#### Returns - -- `execute` an async function that returns void used to follow a profile on button click -- `error` any error that might occur in normal operating conditions will be returned via this property. Possible values are: - - `InsufficientAllowanceError`: the `followee` follow policy requires an ERC20 fee to be paid. The corresponding follow module contract address (i.e. the spender) is not authorized in the specific ERC20 contract to transact for the requested amount in behalf of the authenticated wallet address. You can use the `useApproveModule` hook to increase the allowance. You can see a working example of `useApproveModule` in the Lens SDK monorepo [here](https://github.com/lens-protocol/lens-sdk/blob/main/examples/web-wagmi/src/misc/UseApproveModule.tsx). - Once done, you can retry this operation. - - `InsufficientFundsError`: the `followee` follow policy requires an ERC20 fee to be paid. The authenticated wallet address does not hold enough amount of the specific ERC20 to perform the operation. Use this error together with the `followee.amount: Amount` to communicate to the user what token they need to source in order to complete the operation. - - `PrematureFollowError`: there is a pending unfollow request for the same `followee` profile that is not finalized yet. You can use the `followee.followStatus.canFollow` to eagerly determine if the operation is available so to not have to incur into this error (e.g. you can show an alert to the user if they prematurely try to follow again the same profile). - - `PendingSigningRequestError | UserRejectedError | WalletConnectionError`: see [Error handling](doc:error-handling#generic-local-errors) -- `isPending` a boolean flag that informs you if a follow request for the given `followee` by the provided `follower` is in progress. - -### `execute` function - -The `execute` function returned by `useFollow` allows you to programmatically follow a profile, usually in a on click handler of a button. It takes no parameters. - -#### Parameters - -`execute` takes no parameters (the required data is supplied to `useFollow` directly for state management consistency reasons). \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-mutual-followers.md b/documents/React Hooks SDK/sdk-profile/use-mutual-followers.md deleted file mode 100644 index 40a9eef..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-mutual-followers.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "useMutualFollowers" -slug: "use-mutual-followers" -hidden: false -createdAt: "2022-12-23T16:25:43.921Z" -updatedAt: "2023-03-20T07:04:33.236Z" ---- -`useMutualFollowers` is a React Hook that lets you query the followers in common between two profiles. - -```typescript -const { data, loading, hasMore, next } = useMutualFollowers(args) -``` - - - -## Usage - -```typescript TypeScript -import { useMutualFollowers } from '@lens-protocol/react-web'; - -function MutualFollowers() { -const { data, loading } = useMutualFollowers({ - observerId: '0x02', - viewingProfileId: '0x03', - }); -} -``` - - - -## Reference - -### `useMutualFollowers(args)` - -### Parameters - -`observerId: string` (required) - -- The id of the profile who is running the query, usually the logged in/active profile - -`viewingProfileId: string` (optional) - -- The id of the profile to compare the followers with - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean, - hasMore: boolean, // whether there are more mutual followers after the current batch - next(): () => void, // fetches the next mutual followers and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profile-followers.md b/documents/React Hooks SDK/sdk-profile/use-profile-followers.md deleted file mode 100644 index 1b5be7d..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profile-followers.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "useProfileFollowers" -slug: "use-profile-followers" -hidden: false -createdAt: "2022-12-23T16:46:20.708Z" -updatedAt: "2023-03-20T07:04:17.354Z" ---- -`useProfileFollowers` is a React Hook that lets you query the followers of a profile. - -```typescript -const { data, loading, hasMore, next } = useProfileFollowers(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfileFollowers } from '@lens-protocol/react-web'; - -function Followers() { -const { - data: followers, - loading, - hasMore, - next, - } = useProfileFollowers({ - profileId: '0x77-0x0149', - limit: 10, - }); -} -``` - - - -## Reference - -### `useProfileFollowers(args)` - -### Parameters - -`profileId: string` (required) - -- The id of the profile that we want to fetch the followers - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: FollowersFragment[], - loading: boolean, - hasMore: boolean, // whether there are more followers after the current batch - next(): () => void, // fetches the next followers and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profile-following.md b/documents/React Hooks SDK/sdk-profile/use-profile-following.md deleted file mode 100644 index cf956a4..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profile-following.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "useProfileFollowing" -slug: "use-profile-following" -hidden: false -createdAt: "2022-12-23T17:14:00.803Z" -updatedAt: "2023-03-20T07:04:24.495Z" ---- -`useProfileFollowing` is a React Hook that lets you query the profiles that a wallet is following. - -```typescript -const { data, loading, hasMore, next } = useProfileFollowing(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfileFollowing } from '@lens-protocol/react-web'; - -function Followers() { -const { - data: following, - loading, - hasMore, - next, - } = useProfileFollowing({ - walletAddress: '0xD28E808647D596F33Dcc3436E193A9566fc7aC07', - limit: 10, - }); -} -``` - - - -## Reference - -### `useProfileFollowing(args)` - -```typescript - -const { - data: following, - loading, - hasMore, - next, - } = useProfileFollowing({ - walletAddress, - limit, - observerId - }); -``` - - - -### Parameters - -`walletAddress: string` (required) - -- The wallet address for which we want to know the followed profiles - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: FollowingFragment[], - loading: boolean, - hasMore: boolean, // whether there are more profiles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profile.md b/documents/React Hooks SDK/sdk-profile/use-profile.md deleted file mode 100644 index 4b0fa05..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profile.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "useProfile" -slug: "use-profile" -hidden: false -createdAt: "2022-12-23T13:59:35.385Z" -updatedAt: "2023-03-20T06:58:03.193Z" ---- -`useProfile` is a React Hook that lets you fetch a Lens profile by handle or by profile ID. - -```typescript -const result = useProfile(args); -``` - - - -## Usage - -```typescript -import { useProfile } from '@lens-protocol/react-web'; - -function ProfilePage() { - const { data: profile, loading } = useProfile({ handle: 'lensprotocol.test'}); - // ... -} -``` - - - -## Reference - -### `useProfile(args)` - -```typescript -const { data, loading } = useProfile({ handle, profileId, observerId}) -``` - - - -#### Parameters - -- `handle: string`: The lens handle that you want to fetch. -- `profileId: string`: The profile ID that you want to fetch. -- `observerId: string` (optional): The id of the profile who is running the query, usually the logged in/active profile. - -> ❗️ The hook will throw an error if both `handle` and `profileId` are defined - -#### Returns - -```typescript -{ - data: ProfileFragment; // the profile data - loading: boolean; // a flag that let you determine if data is ready to be read -} - -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by-me.md b/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by-me.md deleted file mode 100644 index 333d514..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by-me.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "useProfilesOwnedByMe" -slug: "use-profiles-owned-by-me" -hidden: false -createdAt: "2023-02-28T15:05:35.543Z" -updatedAt: "2023-03-20T07:04:03.468Z" ---- -`useProfilesOwnedByMe` is a React Hook that lets you query the profiles owned by the currently active wallet. This differs from the `useProfilesOwnedBy` hook where the results of this hook include newly created profiles belonging to the active wallet address. - -```typescript -const { data, loading, hasMore, next } = useProfilesOwnedByMe(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfilesOwnedByMe } from '@lens-protocol/react-web'; - -function MyProfiles() { -const { - data: profiles, - loading, - hasMore, - next, - } = useProfilesOwnedByMe({ - limit: 10, - }); -} -``` - - - -## Reference - -### `useProfilesOwnedByMe(args)` - -### Parameters - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: ProfileOwnedByMeFragment[], - loading: boolean, - hasMore: boolean, // whether there are more profles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by.md b/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by.md deleted file mode 100644 index 8a16246..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profiles-owned-by.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "useProfilesOwnedBy" -slug: "use-profiles-owned-by" -hidden: false -createdAt: "2023-02-28T15:03:09.867Z" -updatedAt: "2023-03-20T06:58:24.686Z" ---- -`useProfilesOwnedBy` is a React Hook that lets you query the profiles owned by a specific wallet address. - -```typescript -const { data, loading, hasMore, next } = useProfilesOwnedBy(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfilesOwnedBy } from '@lens-protocol/react-web'; - -function ProfilesOwnedBy() { -const { - data: profiles, - loading, - hasMore, - next, - } = useProfilesOwnedBy({ - address: "0x0000000000000000000000000000000000000000" - limit: 10, - }); -} -``` - - - -## Reference - -### `useProfilesOwnedBy(args)` - -### Parameters - -`address: string` (required) - -- The address to query for to view profiles owned - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean, - hasMore: boolean, // whether there are more profles after the current batch - next(): () => void, // fetches the next profiles and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-profiles-to-follow.md b/documents/React Hooks SDK/sdk-profile/use-profiles-to-follow.md deleted file mode 100644 index 7b85875..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-profiles-to-follow.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "useProfilesToFollow" -slug: "use-profiles-to-follow" -hidden: false -createdAt: "2023-01-16T10:42:12.812Z" -updatedAt: "2023-03-20T07:04:41.913Z" ---- -`useProfilesToFollow` is a React Hook that lets you query suggested profiles to follow. - -```typescript -const { data: profiles, loading } = useProfilesToFollow() -``` - - - -## Usage - -```typescript TypeScript -import { useProfilesToFollow } from '@lens-protocol/react-web'; - -function ProfilesToFollow() { - const { data: profiles, loading } = useProfilesToFollow(); - - if (loading) return ; - - return ( -
- {profiles.map((profile) => ( - - ))} -
- ); -} -``` - - - -## Reference - -### `useProfilesToFollow()` - -#### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-unfollow.md b/documents/React Hooks SDK/sdk-profile/use-unfollow.md deleted file mode 100644 index 6d3e42b..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-unfollow.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "useUnfollow" -slug: "use-unfollow" -hidden: false -createdAt: "2023-01-13T14:15:39.567Z" -updatedAt: "2023-03-20T07:13:47.318Z" ---- -`useUnfollow` is a React Hook that lets you unfollow a profile. - -```typescript -const { execute, error, isPending } = useUnfollow(); -``` - - - -## Usage - -```typescript -import { ProfileFragment, useUnfollow } from '@lens-protocol/react-web'; - -type ProfileUnfollowProps = { - profile: ProfileFragment; -}; - -export function UnfollowProfile({ profile }: ProfileUnfollowProps) { - const { execute: unfollow, isPending } = useUnfollow({ profile }); - - if (!profile.isFollowedByMe) { - return null; - } - - return ( - - ); -} - -``` - - - -## Reference - -### `useUnfollow()` - -Call `useUnfollow` where your unfollow button markup is and provide the profile that you would like to unfollow. - -```typescript -type ProfileUnfollowProps = { - profile: ProfileFragment; -}; - -export function UnfollowProfile({ profile }: ProfileUnfollowProps) { - const { unfollow, isPending } = useUnfollow({ profile }); - // ... -} -``` - - - -#### Parameters - -- `profile: ProfileFragment`: the profile you wish to unfollow - -#### Returns - -- `unfollow` an async function that returns void used to unfollow a profile on button click -- `isPending` a boolean flag that informs you if an unfollow is in progress - -### `execute` function - -The `execute` function returned by `useUnfollow` allows you to programmatically unfollow a profile, usually in a on click handler of a button. It takes no parameters. - -#### Parameters - -`execute` takes no parameters (the profile is supplied to `useUnfollow` directly) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-update-dispatcher-config.md b/documents/React Hooks SDK/sdk-profile/use-update-dispatcher-config.md deleted file mode 100644 index aee4b89..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-update-dispatcher-config.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "useUpdateDispatcherConfig" -slug: "use-update-dispatcher-config" -hidden: false -createdAt: "2023-01-16T10:51:21.428Z" -updatedAt: "2023-03-20T07:10:45.694Z" ---- -`useUpdateDispatcherConfig` is a React Hook that lets you update a dispatcher configuration on the Profile you own. - -> 👍 Reduce signing hassle -> -> Enabling the dispatcher let's you deliver better UX to your users by removing the need for singing on the most common Lens operations. -> -> As of now, the dispatcher works for post, comment, mirror, updating profile metadata and updating profile image. -> -> Read more about dispatcher in our API docs: - -```typescript -const { update, error, isPending } = useUpdateDispatcherConfig({ profile }); -``` - - - -## Usage - -Call the `update` method from your event handler (quite likely attached to some `button`). - -> 🐛 Remember to gracefully handle errors -> -> Don't just ignore the error returned from the `useUpdateDispatcherConfig` hook. These are a valid scenarios that can happen to your user while using your app. - -```typescript -import { - ProfileFragment, - useUpdateDispatcherConfig, -} from '@lens-protocol/react-web'; - -type UpdateDispatcherConfigButtonProps = { - profile: ProfileFragment; -}; - -function UpdateDispatcherConfigButton({ profile }: UpdateDispatcherConfigButtonProps) { - const [isEnabled, setIsEnabled] = useState(profile.dispatcher !== null); - const { update, error, isPending } = useUpdateDispatcherConfig({ profile }); - - const submit = async (e: React.FormEvent) => { - e.preventDefault(); - - await update({ enabled: isEnabled }); - }; - - return ( -
-
-

- - setIsEnabled((current) => !current)} - /> -

- - - - {error &&

{error.message}

} -
-
- ); -} -``` - - - -## Reference - -### `useUpdateDispatcherConfig(args)` - -Call `useUpdateDispatcherConfig` in the component responsible to update dispatcher configuration. - -```typescript -function UpdateDispatcherConfigForm({ profile }) { - const { update, error, isPending } = useUpdateDispatcherConfig({ profile }); - // ... -} -``` - - - -#### Parameters - -- `profile` This is the author profile of the new comment. It must be a profile owned by the authenticated `Signer` (see [useWalletLogin](doc:use-wallet-login)). You can retrieve the currently active profile via the [`useActiveProfile`](doc:use-active-profile) hook. - -#### Returns - -Returns an object with: - -- `update`: a function you can use to initiate the update of the dispatcher configuration. -- `isPending`: a boolean notifying you when the operation is still in progress. -- > 📘 Important to know - > - > `isPending` flag for `useUpdateDispatcherConfig` behaves differently from other hook. - > - > We always try to be very optimistic about the response which works good for creating publications, mirroring, following but updating dispatcher config is different in that case. - > - > Given that dispatcher configuration affects how all new transactions are processed the `useUpdateDispatcherConfig` `isPending` flag waits until the transaction was mined and processed by backend. -- `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `update` function - -You can use the `update` function to initiate the process that leads to a new comment. - -#### Parameters - -It accepts a simple object with just `enabled` key that should flag if the dispatcher should be enabled or disabled. - -```typescript -{ - enabled: boolean -} -``` - - - -#### Returns - -It returns a `Promise` that you can use to sync with the state of your component. For example, you can clear the content of any text input field when such Promise resolves. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-update-profile-details.md b/documents/React Hooks SDK/sdk-profile/use-update-profile-details.md deleted file mode 100644 index 90e99f6..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-update-profile-details.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: "useUpdateProfileDetails" -slug: "use-update-profile-details" -hidden: false -createdAt: "2023-01-30T09:37:21.117Z" -updatedAt: "2023-03-20T07:12:56.052Z" ---- -`useUpdateProfileDetails` is a React Hook that lets the active user update their profile details like name, bio, coverPicture and other custom attributes. - -```typescript TypeScript -const { execute, error, isPending } = useUpdateProfileDetails({ profile, upload }); - -``` - - - -## Usage - -Define an `upload` function that conforms to the signature: - -```typescript upload.ts -export const upload = (data: unknown): Promise => { - const serialized = JSON.stringify(data); - - const url = // upload serialized to a public location - - return url; -} -``` - - - -You can then wire the `useUpdateProfileDetails` into your component: - -```typescript TypeScript -import { - ProfileFragment, - useUpdateProfileDetails, -} from '@lens-protocol/react-web'; - -function UpdateProfileDetails({ profile }: { profile: ProfileFragment }) { - const { execute: update, error, isPending } = useUpdateProfileDetails({ - profile, - upload - }); - - async function onSubmit(event: React.FormEvent) { - event.preventDefault(); - - const formData = new FormData(event.currentTarget); - - const name = formData.get('name') as string; - const bio = formData.get('bio') as string | null; - const attributes = { - location: (formData.get('location') as string | null) || null, - website: (formData.get('website') as string | null) || null, - }; - await update({ name, bio, attributes }); - } - - // ... -} -``` - - - -You can then pass the `onSubmit` handler to your form. - -## Reference - -### `useUpdateProfileDetails(args)` - -#### Parameters - -- `profile: ProfileFragment` active profile whose details you want to update. -- `upload` the user-defined upload function. Must conform to the `(data: unknown) => Promise` signature. It receives a JS Object (safe for serialization) and should return the public URL where the JSON file has been saved. The file must be served as `Content-Type: application/json`. It's the function's responsibility to serialize, upload and return the file URL. - -#### Returns - -Returns an object with: - -- `update`: a function you can use to update the profile details. -- `isPending`: a boolean notifying you if the operation is in progress. -- `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `execute(details: ProfileDetails)` function - -You can use the `execute` function to update profile details. - -#### Parameters - -- `details: ProfileDetails` - -```typescript -type ProfileDetails = { - name: string; - bio?: string | null; - coverPicture?: string | null; - attributes?: PartialAttributesUpdate; -}; -``` - - - -#### Returns - -- `Promise` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-profile/use-update-profile-image.md b/documents/React Hooks SDK/sdk-profile/use-update-profile-image.md deleted file mode 100644 index 843cb39..0000000 --- a/documents/React Hooks SDK/sdk-profile/use-update-profile-image.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: "useUpdateProfileImage" -slug: "use-update-profile-image" -hidden: false -createdAt: "2023-01-11T15:14:59.754Z" -updatedAt: "2023-03-20T07:13:08.545Z" ---- -`useUpdateProfileImage` is a React Hook that lets the active user change their profile image. - -```typescript TypeScript -const { execute, error, isPending } = useUpdateProfileImage({ - profile -}); -``` - - - -## Usage - -```typescript TypeScript -import { - ProfileFragment, - useUpdateProfileImage, -} from '@lens-protocol/react-web'; - -function UpdateProfileImage({ profile }: { profile: ProfileFragment }) { - const { execute: update, error, isPending } = useUpdateProfileImage({ - profile, - }); - - const handleClick = async () => { - const imageUrl = 'https://arweave.net/uiNDIjXbrgaSclOjgo0ia1gs9RKqY6XoUsdlqSBTKDI'; - await update(imageUrl); - }; - - return ( -
- - - {error &&

{error.message}

} - {isPending &&

Updating your Lens profile's image...

} -
- ); -} -``` - - - -## Reference - -### `useUpdateProfileImage(args)` - -#### Parameters - -- `profile: ProfileFragment` profile whose image you want to update. - -#### Returns - -Returns an object with: - -- `update`: a function you can use to update the profile image. -- `isPending`: a boolean notifying you if the operation is in progress. -- **Optional** `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `execute(fileUrl)` function - -You can use the `execute` function to update profile image. - -#### Parameters - -- `fileUrl: string` public URL to an image file - -#### Returns - -- `Promise` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication.md b/documents/React Hooks SDK/sdk-publication.md deleted file mode 100644 index 33fa4a1..0000000 --- a/documents/React Hooks SDK/sdk-publication.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Publication" -slug: "sdk-publication" -hidden: false -createdAt: "2022-12-23T09:19:38.239Z" -updatedAt: "2023-03-03T10:19:46.001Z" ---- -- [usePublication](doc:use-publication) -- [usePublications](doc:use-publications) -- [useComments](doc:use-comments) -- [useCreatePost](doc:use-create-post) -- [useCreateComment](doc:use-create-comment) -- [useCreateMirror](doc:use-create-mirror) -- [useCollectedPublications](doc:use-collected-publications) -- [useWhoCollectedPublication](doc:use-who-collected-publication) -- [useWhoMirroredPublication](doc:use-who-mirrored-publication) -- [useReaction](doc:use-reaction) -- [useWhoReacted](doc:use-who-reacted) -- [useReportPublication](doc:use-report-publication) -- [useHidePublication](doc:use-hide-publication) -- [useProfilePublicationsForSale](doc:use-profile-publications-for-sale) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-collected-publications.md b/documents/React Hooks SDK/sdk-publication/use-collected-publications.md deleted file mode 100644 index 59fe34c..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-collected-publications.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "useCollectedPublications" -slug: "use-collected-publications" -hidden: false -createdAt: "2022-12-23T16:29:16.717Z" -updatedAt: "2023-03-20T06:55:09.608Z" ---- -`useCollectedPublications` is a React Hook that lets you query for all publications collected by a wallet address. - -```typescript -const { data, loading, hasMore, next } = useCollectedPublications(args) -``` - - - -## Usage - -```typescript TypeScript -import { useCollectedPublications } from '@lens-protocol/react-web'; - -function CollectedPublications() { -const { - data: collectedPublications, - loading, - hasMore, - next, - } = useCollectedPublications({ walletAddress: '0x42a578e3557f5854B27D48E7d753fEb2f428546D' }); -} -``` - - - -## Reference - -### `useCollectedPublications(args)` - -### Parameters - -`walletAddress: string` (required) - -- The wallet address that has collected the publications - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: PublicationFragment[], - loading: boolean, - hasMore: boolean, // whether there are more publications after the current batch - next(): () => void, // fetches the next publications and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-comments.md b/documents/React Hooks SDK/sdk-publication/use-comments.md deleted file mode 100644 index 73422d7..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-comments.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "useComments" -slug: "use-comments" -hidden: false -createdAt: "2022-12-23T16:45:44.413Z" -updatedAt: "2023-03-20T06:54:45.618Z" ---- -`useComments` is a React Hook that lets you query the comments for a given publication. - -```typescript -const { data, loading, hasMore, next } = useComments(args) -``` - - - -## Usage - -```typescript TypeScript -import { useComments } from '@lens-protocol/react-web'; - -function Comments() { -const { - data: comments, - loading, - hasMore, - next, - } = useComments({ - commentsOf: '0x77-0x0149', - limit: 10, - }); -} -``` - - - -## Reference - -### `useComments(args)` - -### Parameters - -`commentsOf: string` (required) - -- The id of the publication to retrieve the comments for - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: CommentFragment[], - loading: boolean, - hasMore: boolean, // whether there are more comments after the current batch - next(): () => void, // fetches the next comments and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-create-comment.md b/documents/React Hooks SDK/sdk-publication/use-create-comment.md deleted file mode 100644 index 0a2cfcd..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-create-comment.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: "useCreateComment" -slug: "use-create-comment" -hidden: false -createdAt: "2023-01-03T08:16:54.012Z" -updatedAt: "2023-05-10T07:58:43.818Z" ---- -`useCreateComment` is a React Hook that lets you create a comment to a publication using a Profile you own. - -```typescript -const { execute, error, isPending } = useCreateComment({ profile, upload }); -``` - -## Usage - -Define an `upload` function that conforms to the signature: - -```typescript upload.ts -export const upload = (data: unknown): Promise => { - const serialized = JSON.stringify(data); - - const url = // upload serialized to a public location - - return url; -} -``` - -> 📘 Looking for an inspiration? -> -> Check the [web-wagmi](https://github.com/lens-protocol/lens-sdk/tree/main/examples/web-wagmi) example in the Lens SDK monorepo. There is an example `upload` function that uses [Bundlr](https://github.com/Bundlr-Network) to upload the file to Aerwave. - -You can then wire the `useCreateComment` into your _composer_ component: - -```typescript -import { ContentFocus, CollectPolicyType, ProfileOwnedByMe, ReferencePolicy, useCreateComment } from '@lens-protocol/react'; -import { upload } from './upload' - -function Composer({ profile, publicationId }: { profile: ProfileOwnedByMe, publicationId: string ) { - const { execute: create, error, isPending } = useCreateComment({ profile, upload }); - - const onSubmit = async (content: string) => { - await create({ - publicationId, - content, - profileId: profile.id, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.NO_COLLECT - }, - reference: { - type: ReferencePolicy.ANYBODY - } - }); - }; - // ... -} -``` - -You can then pass the `onSubmit` handler to your form - -## Reference - -### `useCreateComment(args)` - -Call `useCreateComment` in the component responsible for submitting the user's input. - -```typescript -function Composer({ profile }) { - const { create, error?, isPending } = useCreateComment({ profile, upload }); - // ... -} -``` - -#### Parameters - -- `upload` the user-defined upload function. Must conform to the `(data: unknown) => Promise` signature. It receives a JS Object (safe for serialization) and should return the public URL where the JSON file has been saved. The file must be served as `Content-Type: application/json`. It's the function's responsibility to serialize, upload and return the file URL. -- `profile`This is the author profile of the new comment. It must be a profile owned by the authenticated `Signer` (see [useWalletLogin](doc:use-wallet-login)). You can retrieve the currently active profile via the [`useActiveProfile`](doc:use-active-profile) hook. - -#### Returns - -Returns an object with: - -- `execute`: a function you can use to initiate the creation of a new comment. -- `isPending`: a boolean notifying you when the operation is still in progress. -- **Optional** `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `execute` function - -You can use the `execute` function to initiate the process that leads to a new comment. - -#### Parameters - -It accepts a complex object with all the required configurations. The TS definition will help you to know what configuration to provide and when. - -```typescript -{ - publicationId: string - profileId: string, - content?: string, - contentFocus: ContentFocus, - locale: string, - collect: CollectPolicy, - reference: ReferencePolicy -} -``` - -where `publicationId` is an id to a publication the comment should be assigned to. - -where `locale` is a subset of the Locale Identifiers specification. See the full specification [here](https://docs.lens.xyz/docs/metadata-standards#locale---required). - -> 📘 Pro tip -> -> Use the TypeScript definition to navigate the possible values for each field and subfields. The type definition provided will guide you through the dependency rules of the [Lens Publication Metadata v2](https://docs.lens.xyz/docs/metadata-standards#metadata-structure) so you don't have to know them. - -#### Returns - -It returns a `Promise` that you can use to sync with the state of your component. For example, you can clear the content of any text input field when such Promise resolves. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-create-mirror.md b/documents/React Hooks SDK/sdk-publication/use-create-mirror.md deleted file mode 100644 index d648eb8..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-create-mirror.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: "useCreateMirror" -slug: "use-create-mirror" -hidden: false -createdAt: "2023-01-12T14:44:25.973Z" -updatedAt: "2023-03-20T06:56:49.757Z" ---- -`useCreateMirror` is a React Hook that lets you create a mirror to a publication using a Profile you own. - -> 📘 Don't know what a `mirror` is? -> -> Refer to the Lens Protocol documentation for [mirror](https://docs.lens.xyz/docs/mirror). - -> 👍 Good to know -> -> Mirroring a mirror under the hood get's the orignal publication and applies the operation. Although Lens API (or smart contracts) allow to mirror a mirror, SDK is more strict and only post and comment can be mirrored. - -```typescript -const { execute, error, isPending } = useCreateMirror(); -``` - - - -## Usage - -Call the `create` method from your event handler (quite likely attached to some `button`). - -> 🐛 Remember to gracefully handle errors -> -> Don't just ignore the `error` returned from the `useCreateMirror` hook. These are a valid scenarios that can happen to your user while using your app. - -```typescript -import { - CommentFragment, - PostFragment, - ProfileFragment, - ReferencePolicy, - useCreateMirror, -} from '@lens-protocol/react-web'; - -type MirrorButtonProps = { - publication: PostFragment | CommentFragment; - profile: ProfileFragment; -}; - -function MirrorButton({ publication, profile }: MirrorButtonProps) { - const { execute: create, isPending, error } = useCreateMirror(); - - const isMirroredByMe = publication.isOptimisticMirroredByMe || publication.mirrors.length > 0; - - return ( -
- - - {error &&

Error: {error.message}

} -
- ); -} - -``` - - - -## Reference - -### `useCreateMirror()` - -#### Parameters - -The `useCreateMirror` hook has no parameters. - -#### Returns - -Returns an object with: - -- `execute`: a function you can use to initiate the creation of a new comment. -- `isPending`: a boolean notifying you when the operation is still in progress. -- **Optional** `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `execute` function - -You can use the `execute` function to initiate the process that leads to a new mirror. - -#### Parameters - -It accepts a complex object with all the required configurations. The TS definition will help you to know what configuration to provide and when. - -```typescript -{ - publication: PostFragment | CommentFragment, - profile: ProfileFragment, - reference: ReferencePolicy, -} -``` - - - -#### Returns - -It returns a `Promise` that you can use to sync with the state of your component. For example, you can clear the content of any text input field when such Promise resolves. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-create-post.md b/documents/React Hooks SDK/sdk-publication/use-create-post.md deleted file mode 100644 index ccb4d6e..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-create-post.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: "useCreatePost" -slug: "use-create-post" -hidden: false -createdAt: "2022-12-23T12:03:19.898Z" -updatedAt: "2023-05-10T07:52:24.829Z" ---- -`useCreatePost` is a React Hook that lets you create a post for a Profile you own. - -```typescript -const { execute, error, isPending } = useCreatePost({ publisher, upload }); -``` - -## Usage - -Define an `upload` function that conforms to the signature: - -```typescript upload.ts -export const upload = (data: unknown): Promise => { - const serialized = JSON.stringify(data); - - const url = // upload serialized to a public location - - return url; -} -``` - -> 📘 Looking for an inspiration? -> -> Check the [web-wagmi](https://github.com/lens-protocol/lens-sdk/tree/main/examples/web-wagmi) example in the Lens SDK monorepo. There is an example `upload` function that uses [Bundlr](https://github.com/Bundlr-Network) to upload the file to Aerwave. - -You can then wire the `useCreatePost` into your _composer_ component: - -```typescript -import { ContentFocus, CollectPolicyType, ProfileOwnedByMeFragment, ReferencePolicy, useCreatePost } from '@lens-protocol/react'; -import { upload } from './upload' - -function Composer({ profile }: { profile: ProfileOwnedByMeFragment }) { - const { execute: create, error, isPending } = useCreatePost({ publisher: profile, upload }); - - const onSubmit = async (content: string) => { - await create({ - content, - contentFocus: ContentFocus.TEXT, - locale: 'en', - collect: { - type: CollectPolicyType.NO_COLLECT - }, - reference: { - type: ReferencePolicy.ANYBODY - } - }); - }; - // ... -} -``` - -You can then pass the `onSubmit` handler to your form - -## Reference - -### `useCreatePost(args)` - -Call `useCreatePost` in the component responsible for submitting the user's input. - -```typescript -function Composer({ profile }) { - const { execute, error, isPending } = useCreatePost({ publisher, upload }); - // ... -} -``` - -#### Parameters - -- `upload` the user-defined upload function. Must conform to the `(data: unknown) => Promise` signature. It receives a JS Object (safe for serialization) and should return the public URL where the JSON file has been saved. The file must be served as `Content-Type: application/json`. It's the function's responsibility to serialize, upload and return the file URL. -- `publisher` this is the author profile of the new post. It must be a profile owned by the authenticated `Signer` (see [useWalletLogin](doc:use-wallet-login)) as it is returned by [`useActiveProfile`](doc:use-active-profile) or [`useProfilesOwnedByMe`](doc:use-profiles-owned-by-me) hooks. - -#### Returns - -Returns an object with: - -- `create`: a function you can use to initiate the creation of a new post. -- `isPending`: a boolean notifying you when the operation is still in progress. -- `error`: any error that might occur in normal operating conditions will be returned via this property. Default value `null`. - -### `execute` function - -You can use the `execute` function to initiate the process that leads to a new post. - -#### Parameters - -It accepts a complex object with all the required configurations. The TS definition will help you to know what configuration to provide and when. - -```typescript -{ - profileId: profile.id, - content?: string, - contentFocus: ContentFocus, - locale: string, - collect: CollectPolicy, - reference: ReferencePolicy -} -``` - -where `locale` is a subset of the Locale Identifiers specification. See the full specification [here](https://docs.lens.xyz/docs/metadata-standards#locale---required). - -> 📘 Pro tip -> -> Use the TypeScript definition to navigate the possible values for each field and subfields. The type definition provided will guide you through the dependency rules of the [Lens Publication Metadata v2](https://docs.lens.xyz/docs/metadata-standards#metadata-structure) so you don't have to know them. - -#### Returns - -It returns a `Promise` that you can use to sync with the state of your component. For example you can clear the content of any text input field when such promise resolves. \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-hide-publication.md b/documents/React Hooks SDK/sdk-publication/use-hide-publication.md deleted file mode 100644 index e170da2..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-hide-publication.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: "useHidePublication" -slug: "use-hide-publication" -hidden: false -createdAt: "2023-01-18T12:05:34.988Z" -updatedAt: "2023-03-20T06:56:03.122Z" ---- -`useHidePublication` is a React hook that allows you to hide a publication an active profile owns. - -```typescript -const { hide, isPending } = useHidePublication(); -``` - - - -> 📘 Important to know -> -> Once you publish something on-chain you can not remove it. -> -> Hiding publication only hides it from the API's storage, it **does not** do anything on-chain. -> -> This is just a nice way to allow users to "delete" publication by hiding content and media which was uploaded for it. -> -> You must own the publication to hide it, if you want to report someone else publication there is a separarate hook called `[useReportPublication](https://docs.lens.xyz/docs/use-report-publication)`. -> -> Refer to the API documention to get more information about how hiding works: - -## Usage - -```typescript -import { - PublicationFragment, - useHidePublication, - isPublicationOwnedByMe, -} from '@lens-protocol/react-web'; - -type HidePublicationProps = { - publication: PublicationFragment; -}; - -export function HidePublication({ publication }: HidePublicationProps) { - const { hide, isPending } = useHidePublication(); - - if (!isPublicationOwnedByMe(publication)) { - return

Can't hide publication that's not owned by you

; - } - - return ( - - ); -} -``` - - - -## Reference - -### `useHidePublication()` - -#### Returns - -The hook returns an object with: - -- `hide`: a function you can use to hide a publication. -- `isPending`: a boolean indicating whether the operation is still in progress. - -### `hide(request: HidePublicationRequest)` function - -You can use the `hide` function to hide a publication. - -#### Parameters - -- `request: HidePublicationRequest` read below for details - -#### Returns - -- `Promise` - -### HidePublicationRequest - -This is an object that contains the following properties: - -- `publication: PublicationOwnedByMeFragment`: the publication to hide \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-profile-publications-for-sale.md b/documents/React Hooks SDK/sdk-publication/use-profile-publications-for-sale.md deleted file mode 100644 index eb2939b..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-profile-publications-for-sale.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "useProfilePublicationsForSale" -slug: "use-profile-publications-for-sale" -hidden: false -createdAt: "2023-02-10T14:38:45.258Z" -updatedAt: "2023-03-20T06:56:09.833Z" ---- -`useProfilePublicationsForSale` is a React hook used to query publications for sale by a profile. - -```typescript -const { data, loading, hasMore, next } = useProfilePublicationsForSale(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfilePublicationsForSale } from '@lens-protocol/react-web'; - -function ProfilePublicationsForSale() { - const { - data, - loading, - hasMore, - next, - } = useProfilePublicationsForSale({ - profileId: '0x1b-0x0118', - observerId: '0x02', - limit: 10, - }); -} -``` - - - -## Reference - -### `useProfilePublicationsForSale(args)` - -### Parameters - -`profileId: string` (required) - -- The id of the profile that posted the publications for sale - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -### Returns - -```typescript -{ - data: PublicationFragment[], - loading: boolean, - hasMore: boolean, // whether there are more results after the current batch - next(): () => void // fetches the next batch and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-publication.md b/documents/React Hooks SDK/sdk-publication/use-publication.md deleted file mode 100644 index 35ba23b..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-publication.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "usePublication" -slug: "use-publication" -hidden: false -createdAt: "2022-12-23T15:27:41.379Z" -updatedAt: "2023-03-20T06:54:30.080Z" ---- -`usePublication` is a React hook that allows you to find a specific publication using it's identifier. - -```typescript -const { data, loading } = usePublication(args) -``` - - - -## Usage - -```typescript TypeScript -import { usePublication } from '@lens-protocol/react-web'; - -function Publication() { -const { data: publication, loading } = usePublication({ - publicationId: '0x77-0x0149', - }); -} -``` - - - -## Reference - -### `usePublication(args)` - -### Parameters - -- `publicationId` (required) - -The id of the publication to fetch - -- `observerId` (optional) - -The id of the profile who is running the query, usually the logged in/active profile. - -### Returns - -```typescript -{ - data: PublicationFragment, - loading: boolean -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-publications.md b/documents/React Hooks SDK/sdk-publication/use-publications.md deleted file mode 100644 index c7dbf8e..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-publications.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: "usePublications" -slug: "use-publications" -hidden: false -createdAt: "2022-12-23T14:31:39.812Z" -updatedAt: "2023-03-20T06:54:38.841Z" ---- -> 🚧 Supported Arguments -> -> This hook currently only supports a subset of the arguments exposed by the API. In future releases, all arguments will be supported. - -`usePublications` is a React Hook that lets you query for publications that match the criteria that you specify. - -```typescript -const { data, loading, hasMore, next } = usePublications(args) -``` - - - -## Usage - -```typescript TypeScript -import { usePublications } from '@lens-protocol/react-web'; - -function Publications() { -const { - data: publication, - loading, - hasMore, - next, - } = usePublications({ - profileId: '0x77-0x0149', - limit: 10, - }); -} -``` - - - -## Reference - -### `usePublication(args)` - -### Parameters - -`profileId: string` (required) - -- The id of the profile that posted the publications - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -`metadataFilter: PublicationMetadataFilters` (optional) - -- Any optional [metadata](https://docs.lens.xyz/docs/use-publications#publicationmetadatafilters) to filter publications by - -### Returns - -```typescript -{ - data: PublicationFragment[], - loading: boolean, - hasMore: boolean, // whether there are more publications after the current batch - next(): () => void, // fetches the next publications and appends to the data -} -``` - - - -### PublicationMetadataFilters - -```typescript -{ - restrictPublicationMainFocusTo?: PublicationMainFocus[]; - restrictPublicationLocaleTo?: string; - showPublicationsWithContentWarnings?: { - oneOf: PublicationContentWarning[]; - }; - restrictPublicationTagsTo?: - | { - all: string[]; - } - | { - oneOf: string[]; - }; -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-reaction.md b/documents/React Hooks SDK/sdk-publication/use-reaction.md deleted file mode 100644 index da222b3..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-reaction.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: "useReaction" -slug: "use-reaction" -hidden: false -createdAt: "2023-01-05T10:32:36.600Z" -updatedAt: "2023-03-20T06:55:34.248Z" ---- -`useReaction` is a React Hook that lets you react to a publication. The only reaction type supported currently is `UPVOTE`. With `useReaction` hook you can add, remove reaction or check if a publication has a reaction. - -```typescript -const { addReaction, removeReaction, hasReaction, isPending, error } = useReaction(args); -``` - - - -## Usage - -`useReaction` hook requires a `profileId` and later a `publication` object. It is important to provide `observerId` when querying for publication to know if the observer profile has reacted to that publication. See the example below: - -```typescript -import { - ReactionType, - usePublication, - useReaction, -} from '@lens-protocol/react-web'; - -function Component({ profile }) { - const { data: publication, loading } = usePublication({ - publicationId: '0x1b-0x0118', - observerId: profile.id, // important! - }); - - const { addReaction, removeReaction, hasReaction, isPending, error } = useReaction({ - profileId: profile.id, - }); - - const reactionType = ReactionType.UPVOTE; - - if (loading) return ; - - const hasReactionType = hasReaction({ - reactionType, - publication, - }); - - const toggleReaction = async () => { - if (hasReactionType) { - await removeReaction({ - reactionType, - publication, - }); - } else { - await addReaction({ - reactionType, - publication, - }); - } - }; - - return ( - <> - {error &&

{error.message}

} - - - ); -} -``` - - - -## Reference - -### `useReaction(args)` - -#### Parameters - -- `profileId: string` this is the profile that will be reacting to a publication(s) and is the observer provided in `usePublication` as an `observerId`. - -#### Returns - -Returns an object with: - -- `addReaction`: a function you can use to add a new reaction. -- `removeReaction`: a function you can use to remove an existing reaction. -- `hasReaction`: a function you can use to check if a publication has already a reaction from a profile -- `isPending`: a boolean notifying you if any of the operations is in progress. -- `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `addReaction` function - -You can use the `addReaction` function to add a new reaction. - -#### Parameters - -- `reactionType: ReactionType` type of reaction to be added, currently, there is only one reaction supported, `ReactionType.UPVOTE`, but we plan to offer more in the future. -- `publication: PublicationFragment` this is a publication returned from any publication query - -#### Returns - -- `Promise` - -### `removeReaction` function - -You can use the `removeReaction` function to remove an existing reaction. Make sure that reaction exists before removing it. You can use `hasReaction` function for that. - -#### Parameters - -- `reactionType: ReactionType` type of reaction to be removed, currently, there is only one reaction supported, `ReactionType.UPVOTE`, but we plan to offer more in the future. -- `publication: PublicationFragment` this is a publication returned from any publication query - -#### Returns - -- `Promise` - -### `hasReaction` function - -You can use the `hasReaction` function to check if a publication has already a reaction from a profile provided as an argument to the hook. - -#### Parameters - -- `reactionType: ReactionType` type of reaction to be checked. -- `publication: PublicationFragment` this is a publication returned from any publication query - -#### Returns - -- `boolean` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-report-publication.md b/documents/React Hooks SDK/sdk-publication/use-report-publication.md deleted file mode 100644 index e942b29..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-report-publication.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: "useReportPublication" -slug: "use-report-publication" -hidden: false -createdAt: "2023-01-16T10:05:55.977Z" -updatedAt: "2023-03-20T06:55:54.932Z" ---- -`useReportPublication` is a React hook that allows you to report a publication with a reason. - -```typescript -const { report, isPending, error } = useReportPublication() -``` - - - -## Usage - -```typescript -import { useReportPublication, ReportReason } from '@lens-protocol/react-web'; - -export function ReportPublication() { - const { report, isPending, error } = useReportPublication(); - - const handleClick = async () => { - await report({ - publicationId: '0x15-0x0271', - reason: ReportReason.SCAM, - additionalComments: '', - }); - }; - - return ( -
- {error &&

{error.message}

} - -
- ); -} - -``` - - - -## Reference - -### `useReportPublication()` - -#### Returns - -The hook returns an object with: - -- `report`: a function you can use to report a publication. -- `isPending`: a boolean indicating whether the operation is still in progress. -- `error`: any error that might occur in normal operating conditions will be returned via this property. - -### `report(request: ReportPublicationRequest)` function - -You can use the `report` function to report a publication. - -#### Parameters - -- `request: ReportPublicationRequest` read below for details - -#### Returns - -- `Promise` - -### ReportPublicationRequest - -This is an object that contains the following properties: - -- `publicationId: string`: the id of the publication to be reported. -- `reason: ReportReason`: the reason for reporting the publication, it should be one of the values of the `ReportReason` enum. -- `additionalComments: string | null`: additional comments or information about the report. - -### ReportReason - -This is an enum that contains the possible reasons to report a publication. The possible values are: - -```Text TypeScript - -export enum ReportReason { - // Illegal - ANIMAL_ABUSE = 'animal-abuse', - HARASSMENT = 'harassment', - VIOLENCE = 'violence', - SELF_HARM = 'self-harm', - DIRECT_THREAT = 'direct-threat', - HATE_SPEECH = 'hate-speech', - - // Sensitive content - NUDITY = 'nudity', - OFFENSIVE = 'offensive', - - // Fraud - SCAM = 'scam', - UNAUTHORIZED_SALE = 'unauthorized-sale', - IMPERSONATION = 'impersonation', - - // Spam - MISLEADING = 'misleading', - MISUSE_HASHTAGS = 'misuse-hashtags', - UNRELATED = 'unrelated', - REPETITIVE = 'repetitive', - FAKE_ENGAGEMENT = 'fake-engagement', - MANIPULATION_ALGO = 'manipulation-algo', - SOMETHING_ELSE = 'something-else', -} - -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-who-collected-publication.md b/documents/React Hooks SDK/sdk-publication/use-who-collected-publication.md deleted file mode 100644 index 7ec3e61..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-who-collected-publication.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "useWhoCollectedPublication" -slug: "use-who-collected-publication" -hidden: false -createdAt: "2023-01-18T16:14:45.209Z" -updatedAt: "2023-03-20T06:55:18.650Z" ---- -`useWhoCollectedPublication` is a React hook that allows you to query for wallets and their profiles that collected a publication. - -```typescript -const { data, loading, hasMore, next } = useWhoCollectedPublication(args) -``` - - - -## Usage - -```typescript TypeScript -import { useWhoCollectedPublication } from '@lens-protocol/react-web'; - -const WhoCollectedPublication() { - const { - data, - loading, - hasMore - next, - } = useWhoCollectedPublication({ - publicationId: '0x1b-0x0118', - limit: 10, - }); -} -``` - - - -## Reference - -### `useWhoCollectedPublication(args)` - -#### Parameters - -- `publicationId` (required) - -The id of the publication to fetch reactions for. - -- `observerId` (optional) - -The id of the profile who is running the query, usually the logged in/active profile. - -- `limit: number` (optional) - -The amount of items to return. - -#### Returns - -```typescript -{ - data: WalletFragment[], - loading: boolean, - hasMore: boolean, // whether there are more results after the current batch - next(): () => void, // fetches the next batch and appends to the data -} -``` - - - -### `WalletFragment` - -```typescript -{ - address: string, - defaultProfile: ProfileFragment -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-who-mirrored-publication.md b/documents/React Hooks SDK/sdk-publication/use-who-mirrored-publication.md deleted file mode 100644 index 6acde63..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-who-mirrored-publication.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "useWhoMirroredPublication" -slug: "use-who-mirrored-publication" -hidden: false -createdAt: "2023-01-25T01:38:35.366Z" -updatedAt: "2023-03-20T06:55:25.617Z" ---- -`useWhoMirroredPublication` is a React hook that allows you to query for profiles that mirrored a publication. - -```typescript -const { data, loading, hasMore, next } = useWhoMirroredPublication(args) -``` - - - -## Usage - -```typescript TypeScript -import { useWhoMirroredPublication } from '@lens-protocol/react-web'; - -function WhoMirroredPublication() { - const { - data, - loading, - hasMore, - next, - } = useWhoMirroredPublication({ - publicationId: '0x1b-0x0118', - limit: 10, - }); -} -``` - - - -## Reference - -### `useWhoMirroredPublication(args)` - -#### Parameters - -- `publicationId` (required) - -The id of the publication to fetch mirroring profiles for. - -- `observerId` (optional) - -The id of the profile who is running the query, usually the logged in/active profile. - -- `limit: number` (optional) - -The amount of items to return. - -#### Returns - -```typescript -{ - data: ProfileFragment[], - loading: boolean, - hasMore: boolean, // whether there are more results after the current batch - next(): () => void, // fetches the next batch and appends to the data -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-publication/use-who-reacted.md b/documents/React Hooks SDK/sdk-publication/use-who-reacted.md deleted file mode 100644 index 80138a8..0000000 --- a/documents/React Hooks SDK/sdk-publication/use-who-reacted.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "useWhoReacted" -slug: "use-who-reacted" -hidden: false -createdAt: "2023-01-06T10:16:42.967Z" -updatedAt: "2023-03-20T06:55:40.487Z" ---- -`useWhoReacted` is a React hook that allows you to query for profiles that reacted to a publication. - -```typescript -const { data, loading, hasMore, next } = useWhoReacted(args) -``` - - - -## Usage - -```typescript TypeScript -import { useWhoReacted } from '@lens-protocol/react-web'; - -function WhoReacted() { - const { - data, - loading, - hasMore, - next, - } = useWhoReacted({ - publicationId: '0x1b-0x0118', - limit: 10, - }); -} -``` - - - -## Reference - -### `useWhoReacted(args)` - -#### Parameters - -- `publicationId` (required) - -The id of the publication to fetch reactions for. - -- `observerId` (optional) - -The id of the profile who is running the query, usually the logged in/active profile. - -- `limit: number` (optional) - -The amount of items to return. - -#### Returns - -```typescript -{ - data: WhoReactedResultFragment[], - loading: boolean, - hasMore: boolean, // whether there are more results after the current batch - next(): () => void, // fetches the next batch and appends to the data -} -``` - - - -### `WhoReactedResultFragment` - -```typescript -{ - reactionId: string, - reaction: ReactionType, // ie. ReactionType.UPVOTE - reactionAt: string, - profile: ProfileFragment -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-react-getting-started.md b/documents/React Hooks SDK/sdk-react-getting-started.md deleted file mode 100644 index 6531592..0000000 --- a/documents/React Hooks SDK/sdk-react-getting-started.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: "Getting Started" -slug: "sdk-react-getting-started" -hidden: false -createdAt: "2022-12-22T21:53:20.983Z" -updatedAt: "2023-05-17T07:03:36.563Z" ---- -> 🚧 Having some errors? -> -> Have a look at our [troubleshooting](https://docs.lens.xyz/docs/troubleshooting) section which highlight some well know pain points that can happen during initial setup. - -## Installation - -Install `@lens-protocol/react-web` and [ethers](https://ethers.org/) dependency. - -> For this configuration of packages we recommend installing using either **yarn** or **pnpm**. - -```shell yarn -yarn add @lens-protocol/react-web ethers@legacy-v5 -``` -```shell pnpm -pnpm add @lens-protocol/react-web ethers -``` - -> 🚧 Early adopters -> -> If you are eager to test new coming features offered by the Lens SDK, install the pre-release version via the `next` tag. -> -> ```shell yarn -> yarn add @lens-protocol/react-web@next -> ``` -> ```shell pnpm -> pnpm add @lens-protocol/react-web@next -> ``` -> -> Bear in mind that the pre-releases are not stable for production use and there could be breaking changes between different pre-releases before they get promoted into a stable release version. - -## Integrate with [wagmi](https://wagmi.sh/) - -Although `@lens-protocol/react-web` only depends on [ethers](https://ethers.org/) (and React ofc), we created a companion package called `@lens-protocol/wagmi` which makes it easier to integrate it with the popular [wagmi](https://wagmi.sh/) library. - -```shell yarn -yarn add wagmi@0.12.7 @lens-protocol/wagmi -``` -```shell pnpm -pnpm add wagmi@0.12.7 @lens-protocol/wagmi -``` - -Ensure you have Polygon in the wagmi chains configuration - -```typescript -import { configureChains, createClient, WagmiConfig } from 'wagmi'; -import { mainnet, polygon } from 'wagmi/chains'; -import { publicProvider } from 'wagmi/providers/public' -const { provider, webSocketProvider } = configureChains([polygon, mainnet], [publicProvider()]); - -const client = createClient({ - autoConnect: true, - provider, - webSocketProvider, -}); -``` - -Refer to [wagmi](https://wagmi.sh/) docs to see how to set up custom chains, providers and work with their client. - -### Create the `LensConfig` - -```typescript -import { LensConfig, development } from '@lens-protocol/react-web'; -import { bindings as wagmiBindings } from '@lens-protocol/wagmi'; - -const lensConfig: LensConfig = { - bindings: wagmiBindings(), - environment: development, -}; -``` - -The environment variables comes in 2 flavours: - -- `production` is the environment config variable to be used in the live instance of your application (real users, real profiles, real data). -- `development` is the environment config variable to be used when you develop and test your application (test users, test profiles, test data). - -**NOTE** - -Since v1.0.0 the `staging` got replaced by `development`. The `staging` environment config variable is still available as alias but flagged as deprecated. It will be removed in the next major release of the Lens SDK. - -See our [react-native integration](doc:cyan-nails-turn-react-native-integration) guide. - -## Wrap app with `LensProvider` - -```typescript -import { LensProvider } from '@lens-protocol/react-web'; -``` - -```html JSX - - - - - -``` - -It's not strictly necessary to have the `LensProvider` as a child of the `WagmiConfig`. - -You are good to go! - -> 📘 Prefer to learn from examples? -> -> That's perfect! We have a fully fledged example app showcasing the integration with wagmi. Our example app has authentication built-in and it's using pretty much all Lens SDK hooks. -> -> You can find it on GitHub: \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-react-intro.md b/documents/React Hooks SDK/sdk-react-intro.md deleted file mode 100644 index 514c5bd..0000000 --- a/documents/React Hooks SDK/sdk-react-intro.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Introduction" -slug: "sdk-react-intro" -excerpt: "The official React Hooks to interact with the Lens Protocol" -hidden: false -createdAt: "2022-12-22T20:56:24.192Z" -updatedAt: "2023-05-17T12:28:15.064Z" ---- -The Lens SDK includes a collection of React Hooks containing all you need to interact with the Lens Protocol. - -It provides a foundation that abstracts away the complexity of some low-level concepts of the Lens Protocol and Lens API. - -Some of the key aspects: - -### Type Safe - -The SDK is written in TypeScript and shipped with all the type definitions you need. It generates its underlying type definitions from the Lens API GraphQL schema so you can rely on end-to-end type safety. - -> 👍 Good to know -> -> Although it is based on the Lens GraphQL API, you don't need to learn GraphQL to use it. - -### Authentication - -The SDK takes care of the initial authentication handshake, persistence of auth tokens, renew of expired tokens and transparently retries unauthorized requests. - -### Persistence - -The SDK takes care of storing relevant informations for subsequent user sessions. It comes with out-of-the box adapters for common storage providers and will enable developers to define the storage provider solution that works best for their application needs. - -### It will guide you through breaking changes - -The core logic of the Lens SDK has been developed side-by-side with the Lens Protocol and Lens API. It is the result of early integration efforts and encapsulates the knowledge of past technical decisions as well as future development direction. - -It's the perfect place to provide support and migration strategies for protocol and API breaking changes. - -## Resources - -- [Lens SDK Reference](https://lens-protocol.github.io/lens-sdk/) -- [Lens SDK Monorepo](https://github.com/lens-protocol/lens-sdk) -- [Examples](https://github.com/lens-protocol/lens-sdk/tree/main/examples) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-revenue.md b/documents/React Hooks SDK/sdk-revenue.md deleted file mode 100644 index d7f9fed..0000000 --- a/documents/React Hooks SDK/sdk-revenue.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Revenue" -slug: "sdk-revenue" -hidden: false -createdAt: "2022-12-23T09:26:35.279Z" -updatedAt: "2023-01-30T11:32:59.707Z" ---- -- [usePublicationRevenue](doc:use-publication-revenue) -- [useProfileFollowRevenue](doc:use-profile-follow-revenue) -- [useProfilePublicationsRevenue](doc:use-profile-publication-revenue) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-revenue/use-profile-follow-revenue.md b/documents/React Hooks SDK/sdk-revenue/use-profile-follow-revenue.md deleted file mode 100644 index 93a8d3d..0000000 --- a/documents/React Hooks SDK/sdk-revenue/use-profile-follow-revenue.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "useProfileFollowRevenue" -slug: "use-profile-follow-revenue" -hidden: false -createdAt: "2023-01-13T14:34:45.832Z" -updatedAt: "2023-03-20T07:31:56.189Z" ---- -`useProfileFollowRevenue` is a React hook used to query the revenue a profile has generated through their paid follow module. - -```typescript -const { data, loading } = useProfileFollowRevenue(args) -``` - - - -## Usage - -```typescript TypeScript -import { useProfileFollowRevenue } from '@lens-protocol/react-web'; - -export function ProfileFollowRevenue({ profileId }: { profileId: string }) { - const { data, loading } = useProfileFollowRevenue({ - profileId, - }); - // ... -} -``` - - - -## Reference - -### `useProfileFollowRevenue(args)` - -### Parameters - -- `profileId` (required) - -The id of the profile of which to query the follow revenue - -### Returns - -```typescript -{ - data: RevenueAggregateFragment[], - loading: boolean -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-revenue/use-profile-publication-revenue.md b/documents/React Hooks SDK/sdk-revenue/use-profile-publication-revenue.md deleted file mode 100644 index 9fed73c..0000000 --- a/documents/React Hooks SDK/sdk-revenue/use-profile-publication-revenue.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "useProfilePublicationRevenue" -slug: "use-profile-publication-revenue" -hidden: false -createdAt: "2023-01-18T16:29:08.854Z" -updatedAt: "2023-03-20T07:32:00.102Z" ---- -`usePublicationRevenue` is a React hook used to query publications by a profile that have earned revenue. - -```typescript -const { data, loading, hasMore, next } = useProfilePublicationRevenue(args) -``` - - - -## Usage - -```typescript TypeScript -import { usePublicationRevenue } from '@lens-protocol/react-web'; - -function PublicationRevenue() { - const { data: profilePublicationRevenue, loading } = useProfilePublicationRevenue({ - profileId: '0x4f90-0x02', - }); - - if (loading) return 'Loading...'; - - return ( -
- {profilePublicationRevenue.map(publicationRevenue => ( -
-

- {publicationRevenue.publication.profile.name ?? `@${publicationRevenue.publication.profile.handle}`} -

- -

{publicationRevenue.publication.metadata.content}

- -

{`Currency: ${publicationRevenue.revenue.total.asset.name}`}

-

{`Symbol: ${publicationRevenue.revenue.total.asset.symbol}`}

-

{`Amount: ${publicationRevenue.revenue.total.value}`}

-
- )} -
- ); -} -``` - - - -## Reference - -### `useProfilePublicationRevenue(args)` - -### Parameters - -`profileId: string` (required) - -- The id of the profile that posted the revenue earning publications - -`observerId: string` (optional) - -- The id of the profile who is running the query, usually the logged in/active profile - -`limit: number` (optional) - -- The amount of items to return - -`publicationTypes: PublicationTypes[]` (optional) - -- the types of publications to query - -`sources: Source[]` (optional) - -- type sources of publications to query - -#### Returns - -```typescript -{ - data: PublicationRevenueFragment[], - loading: boolean, - hasMore: boolean, // whether there are more results after the current batch - next(): () => void // fetches the next batch and appends to the data -} -``` - - - -### `PublicationRevenueFragment` - -```typescript -{ - publication: PublicationFragment, - revenue: RevenueAggregate -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-revenue/use-publication-revenue.md b/documents/React Hooks SDK/sdk-revenue/use-publication-revenue.md deleted file mode 100644 index 25865fa..0000000 --- a/documents/React Hooks SDK/sdk-revenue/use-publication-revenue.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "usePublicationRevenue" -slug: "use-publication-revenue" -hidden: false -createdAt: "2023-01-16T10:35:41.135Z" -updatedAt: "2023-03-20T07:31:52.198Z" ---- -`usePublicationRevenue` is a React hook used to query the revenue from a publication. - -```typescript -const { data: publicationRevenue, loading } = usePublicationRevenue(args) -``` - - - -## Usage - -```typescript TypeScript -import { usePublicationRevenue } from '@lens-protocol/react-web'; - -function PublicationRevenue() { - const { data: revenue, loading } = usePublicationRevenue({ - publicationId: '0x4f90-0x02', - }); - - if (loading) return 'Loading...'; - - return ( -
-

{`Currency: ${revenue.total.asset.name}`}

-

{`Symbol: ${revenue.total.asset.symbol}`}

-

{`Amount: ${revenue.total.value}`}

-
- ); -} -``` - - - -## Reference - -### `usePublicationRevenue(args)` - -### Parameters - -- `publicationId` (required) - -The id of the publication for which to query the revenue - -### Returns - -```typescript -{ - data: RevenueAggregateFragment[], - loading: boolean -} -``` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-wallet-authentication.md b/documents/React Hooks SDK/sdk-wallet-authentication.md deleted file mode 100644 index 99c77c5..0000000 --- a/documents/React Hooks SDK/sdk-wallet-authentication.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Wallet Authentication" -slug: "sdk-wallet-authentication" -hidden: true -createdAt: "2022-12-23T09:06:46.929Z" -updatedAt: "2022-12-23T16:46:44.528Z" ---- -- [useWalletLogin](doc:use-wallet-login) -- [useWalletLogout](doc:use-wallet-logout) \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-login.md b/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-login.md deleted file mode 100644 index 89a628e..0000000 --- a/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-login.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: "useWalletLogin" -slug: "use-wallet-login" -hidden: true -createdAt: "2023-01-23T17:50:04.489Z" -updatedAt: "2023-03-10T11:03:17.934Z" ---- -`useWalletLogin` is a React Hook that lets you authenticate with the Lens API. - -```typescript -const { execute, error, isPending } = useWalletLogin(); -``` - - - -## Usage - -Although the following example uses [wagmi](https://wagmi.sh/) it can be adapted to any wallet integration that results in an [ethers](https://ethers.org/) `Signer`. - -```typescript -import { useWalletLogin } from '@lens-protocol/react'; -import { useAccount, useConnect, useDisconnect } from 'wagmi'; -import { InjectedConnector } from 'wagmi/connectors/injected'; - -function LoginButton() { - const { execute: login, error: loginError, isPending: isLoginPending } = useWalletLogin(); - - const { isConnected } = useAccount(); - const { disconnectAsync } = useDisconnect(); - - const { connectAsync } = useConnect({ - connector: new InjectedConnector(), - }); - - const onLoginClick = async () => { - if (isConnected) { - await disconnectAsync(); - } - - const { connector } = await connectAsync(); - - if (connector instanceof InjectedConnector) { - const signer = await connector.getSigner(); - await login(signer); - } - }; - - return ( -
- {error &&

{error}

} - -
- ); -} -``` - - - -> 📘 Looking for a full-fledged example? -> -> Check the [web-wagmi](https://github.com/lens-protocol/lens-sdk/tree/main/examples/web-wagmi) example in the Lens SDK monorepo. It's showcasing a full authnetication integration with some helper components to control which part of the UI should be just for logged in (or logged out) users. - -## Reference - -### `useWalletLogin` - -Call `useWalletLogin` in the component responsible to log in your users. - -```typescript -function LoginButton() { - const { execute, error, isPending } = useWalletLogin(); - // ... -``` - - - -#### Parameters - -`useWalletLogin` does not take any parameters. - -#### Returns - -Returns an object with: - -- `execute`: a function you can use to programmatically log in your user with the Lens API. -- `isPending`: a boolean notifying you when the operation is still in progress. -- `error`: any error that might occur in normal operating conditions will be returned via this property. Default value `null`. - -### `execute` function - -The `execute` function returned by the `useWalletLogin` lets you programmatically login the specified [ethers](https://ethers.org/) `Signer`. If called multiple times it will re-trigger a new login flow. If called with a different signer it will implicitly log-out the old signer and log-in the new one. - -```typescript -execute(signer) -``` - - - -#### Parameters - -- `signer: Signer`: an instance of ethers `Signer` \ No newline at end of file diff --git a/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-logout.md b/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-logout.md deleted file mode 100644 index 3feea74..0000000 --- a/documents/React Hooks SDK/sdk-wallet-authentication/use-wallet-logout.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "useWalletLogout" -slug: "use-wallet-logout" -hidden: true -createdAt: "2023-01-23T18:10:37.501Z" -updatedAt: "2023-03-10T11:04:10.778Z" ---- -`useWalletLogout` is a React Hook that lets you log out of the previously authenticated user. You have to be authenticated before calling `logout`. - -```typescript -const { execute, isPending } = useWalletLogout(); -``` - - - -## Reference - -### `useWalletLogout` - -Call `useWalletLogout` in the component responsible to log out your users. - -```typescript -function LogoutButton() { - const { execute: logout, isPending } = useWalletLogout(); - - return ( - - ); -} -``` - - - -#### Parameters - -`useWalletLogout` does not take any parameters. - -#### Returns - -Returns an object with: - -- `execute`: a function you can use to programmatically log out currently logged-in user. -- `isPending`: a boolean notifying you when the operation is still in progress. \ No newline at end of file diff --git a/documents/React Hooks SDK/self-funded-transactions.md b/documents/React Hooks SDK/self-funded-transactions.md deleted file mode 100644 index 967d119..0000000 --- a/documents/React Hooks SDK/self-funded-transactions.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Self-funded transactions" -slug: "self-funded-transactions" -excerpt: "How to use user's wallet to pay gas as fallback for a rejected operation" -hidden: true -createdAt: "2023-05-26T12:49:35.672Z" -updatedAt: "2023-05-26T14:28:37.681Z" ---- -[quick intro to let reader recognize the situation, error details, etc.] - -We are going to use `useFollow` in our example here but bear in mind it works the same exact way for: - -- `useCreatePost` -- `useCreateComment` -- `useCreateMirror` -- `useCollect` -- ... - -We are going to compose the `useFollow` hook with the `useSelfFundedFallback` hook into a new React hook. This new hook will encapsulate how we intend to communicate and handle the rejection scenario. - -```typescript useFollowWithSelfFundedFallback.tsx -import { FollowOperation, Profile, ProfileOwnedByMe, SelfFundedOperation, supportsSelfFundedFallback, useFollow, useSelfFundedFallback } from '@lens-protocol/react-web'; - -type UseFollowWithSelfFundedFallbackArgs = { - followee: Profile; - follower: ProfileOwnedByMe; -} - -type PossibleError = FollowOperation['error'] | SelfFundedOperation['error'] - -export function useFollowWithSelfFundedFallback({ followee, follower }: UseFollowWithSelfFundedFallbackArgs) { - const [error, setError] = useState(undefined); - const { execute: subsidize, error: subsidizedError, isPending: isSubsidizedPending } = useFollow({ followee, follower }); - - const { execute: selfFund, error: selfFundedError, isPending: isSelfFundedPending } = useSelfFundedFallback(); - - const execute = async () => { - // it won't ask to sign if can be performed via proxy-action - const result = await subsidize(); - - // did the gasless request fail? - if (result.isFailure()) { - - // was it rejected? is there an fallback? - if (supportsSelfFundedFallback(result.error)) { - - // ask your confirmation before using their funds - const shouldPayFor = window.confirm( - 'It was not possible to cover the gas costs at this time.\n\n' + - 'Do you wish to continue with your MATIC?' - ); - - if (shouldPayFor) { - // initiate self-funded, will require signature - await selfFund(result.error.fallback); - } - return; - } - // other result.error handling as needed - } - }; - - return { - execute, - error, - isPending: isSubsidizedPending || isSelfFundedPending, - } -} -``` - -### What's happening? - -[list] - -Now we can take our `FollowButton` and replace `useFollow` with our newly create hook. Job done! - -```typescript FollowButton.tsx -import { Profile, ProfileOwnedByMe } from '@lens-protocol/react-web'; - -import { useFollowWithSelfFundedFallback } from './useFollowWithSelfFundedFallback'; - -type FollowButtonProps = { - followee: Profile; - follower: ProfileOwnedByMe; -} - -export function FollowButton({ followee, follower }: FollowButtonProps) { - const { execute: follow, error, isPending } = useFollowWithSelfFundedFallback({ followee, follower }); - - return ( - <> - - - {error && {error.message}} - - ); -} -``` - -[notes about example shortcut and link to Follow a profile guide to more details] \ No newline at end of file diff --git a/documents/React Hooks SDK/troubleshooting.md b/documents/React Hooks SDK/troubleshooting.md deleted file mode 100644 index ea315f7..0000000 --- a/documents/React Hooks SDK/troubleshooting.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Troubleshooting" -slug: "troubleshooting" -excerpt: "These are some common issues you may run into while using `@lens-protocol/react`." -hidden: false -createdAt: "2023-03-08T22:00:53.661Z" -updatedAt: "2023-05-17T12:29:40.290Z" ---- -## Next.js build failing - -You might see your Next.js build failing with an error like this: - -``` -Error: Directory import '[...]/node_modules/@apollo/client/link/context' is not supported resolving ES modules imported from [...]/node_modules/@lens-protocol/api-bindings/dist/index.js -Did you mean to import @apollo/client/link/context/context.cjs? -``` - -The root cause is the lack of ESM support from Apollo Client which manifests itself when imported as sub-dependency of `@lens-protocol/api-bindings` (which in turn is imported by `@lens-protocol/react`). See open Apollo Client [issue](https://github.com/apollographql/apollo-feature-requests/issues/287). - -To fix it you need to edit you `next.config.js` so to make sure the Lens SDK and its sub-dependencies a transpiled by Next.js build pipeline. - -```js -const nextConfig = { - transpilePackages: ['@lens-protocol'], -}; -``` - -For further details on how to integrate Lens SDK with a Next.js app, there is a working [Next.js example](https://github.com/lens-protocol/lens-sdk/tree/main/examples/nextjs) in the Lens SDK monorepo. \ No newline at end of file diff --git a/documents/Specification/events.md b/documents/Specification/events.md deleted file mode 100644 index 5086bdd..0000000 --- a/documents/Specification/events.md +++ /dev/null @@ -1,428 +0,0 @@ ---- -title: "Events" -slug: "events" -hidden: false -createdAt: "2022-01-31T19:03:58.177Z" -updatedAt: "2022-08-16T19:54:31.440Z" ---- -Event Emissions ---------------- - -Events are emitted at every state-changing function call, in addition to standard [ERC721 events.](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4f8af2dceb0fbc36cb32eb2cc14f80c340b9022e/contracts/token/ERC721/IERC721.sol) Events often include the timestamp as a specific parameter, which allows for direct consumption using a bloom filter without needing to fetch block context on every event. - -Furthermore, collect and follow NFT transfers hook into an event emitter on the LensHub, which simplifies event consumption by tracking NFT transfers without indexing numerous follow and collect NFTs. - -The [Events library](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/libraries/Events.sol) contains a convenient list of all custom Lens Protocol events as well as explanations for each. It also references the [DataTypes library.](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/libraries/DataTypes.sol) - -See the events emitted below: - -### BaseInitialized - -`event BaseInitialized(string name, string symbol, uint256 timestamp);` - -Emitted when the NFT contract's name and symbol are set at initialization by [initialize()](doc:functions#initialize) - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------------ | -| name | string | The name given to the Lens profile NFT | -| symbol | string | The symbol given to the Lens profile NFT | -| timestamp | uint256 | The block timestamp at which the NFT contract is initialized | - -### StateSet - -`event StateSet(address indexed caller, DataTypes.ProtocolState indexed prevState, DataTypes.ProtocolState indexed newState, uint256 timestamp);` - -Emitted when the hub state is set by [setState()](doc:functions#setstate) - -| Parameter Name | Type | Description | -| -------------- | ----------------------------- | ------------------------------------------------------------------------------- | -| caller | address | The caller who sets the state | -| prevState | Enum: DataTypes.ProtocolState | The previous protocol state. Enum of `Paused,` `PublishingPaused` or `Unpaused` | -| newState | Enum: DataTypes.ProtocolState | The newly set state. Enum of `Paused,` `PublishingPaused` or `Unpaused` | -| timestamp | uint256 | The block timestamp at which state is set | - -### GovernanceSet - -`event GovernanceSet(address indexed caller, address indexed prevGovernance, address indexed newGovernance, uint256 timestamp);.` - -Emitted when the governance address is changed by [setGovernance()](doc:functions#setgovernance) - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------- | -| caller | address | The caller who set the governance address. Mostly previous governance address, but cannot guarantee due to upgradeability | -| prevGovernance | address | The previous governance address | -| newGovernance | address | The new governance address set | -| timestamp | uint256 | The block timestamp at which governance is set | - -### EmergencyAdminSet - -`event EmergencyAdminSet(address indexed caller, address indexed oldEmergencyAdmin, address indexed newEmergencyAdmin, uint256 timestamp);` - -Emitted when the emergency admin is changed by [setEmergencyAdmin()](doc:functions#setemergencyadmin) - -| Parameter Name | Type | Description | -| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ | -| caller | address | The caller who set the emergency admin address. Mostly previous governance address, but cannot guarantee due to upgradeability | -| oldEmergencyAdmin | address | The previous emergency admin address | -| newEmergencyAdmin | address | The new emergency admin address set | -| timestamp | uint256 | The block timestamp at which emergency admin is set | - -### ProfileCreatorWhitelisted - -`event ProfileCreatorWhitelisted(address indexed profileCreator, bool indexed whitelisted, uint256 timestamp);` - -Emitted when a profile creator is added to or removed from the whitelist by [whitelistProfileCreator()](doc:functions#whitelistprofilecreator) - -| Parameter Name | Type | Description | -| -------------- | ------- | -------------------------------------------------------------------------------- | -| profileCreator | address | The address of the profile creator | -| whitelisted | bool | 1 => profile creator is being added, 0 => profile creator is being removed | -| timestamp | uint256 | The block timestamp at which profile creator is added/removed from the whitelist | - -### FollowModuleWhitelisted - -`event FollowModuleWhitelisted(address indexed followModule, bool indexed whitelisted, uint256 timestamp);` - -Emitted when a follow module is added to or removed from the whitelist by [whitelistFollowModule()](doc:functions#whitelistfollowmodule) - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------------------------------ | -| followModule | address | The address of the follow module | -| whitelisted | bool | 1 => follow module is being added, 0 => follow module is being removed | -| timestamp | uint256 | The block timestamp at which follow module is added/removed from the whitelist | - -### ReferenceModuleWhitelisted - -` event ReferenceModuleWhitelisted(address indexed referenceModule, bool indexed whitelisted, uint256 timestamp);` - -Emitted when a reference module is added to or removed from the whitelist by [whitelistReferenceModule()](doc:functions#whitelistreferencemodule) - -| Parameter Name | Type | Description | -| --------------- | ------- | --------------------------------------------------------------------------------- | -| referenceModule | address | The address of the reference module | -| whitelisted | bool | 1 => reference module is being added, 0 => reference module is being removed | -| timestamp | uint256 | The block timestamp at which the reference module is added/removed from whitelist | - -### CollectModuleWhitelisted - -`event CollectModuleWhitelisted(address indexed collectModule, bool indexed whitelisted, uint256 timestamp);` - -Emitted when a collect module is added to or removed from the whitelist by [whitelistCollectModule()](doc:functions#whitelistcollectmodule) - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------------------------------- | -| collectModule | address | The address of the collect module. | -| whitelisted | bool | 1 => collect module is being added, 0 => collect module is being removed | -| timestamp | uint256 | The block timestamp at which the collect module is added/removed from whitelist | - -### ProfileCreated - -`event ProfileCreated(uint256 indexed profileId, address indexed creator, address indexed to, string handle, string imageURI, address followModule, bytes followModuleReturnData, string followNFTURI, uint256 timestamp);` - -| Parameter Name | Type | Description | -| ---------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | -| profileId | uint256 | The newly created profile's token ID | -| creator | The profile creator created the token with the given profile ID | | -| to | address | The address to which the profile with the given profile ID is minted to | -| handle | string | The handle set for the profile | -| imageURI | string | The image uri set for the profile | -| followModule | address | The profile's newly set follow module. This can be the zero address | -| followModuleReturnData | bytes | The data returned from the follow module's initialization. This is abi encoded and depends on the follow module chosen | -| followNFTURI | string | The uri set for follow NFT | -| timestamp | uint256 | The block timestamp at which profile NFT is created | - -### DispatcherSet - -` event DispatcherSet(uint256 indexed profileId, address indexed dispatcher, uint256 timestamp);` - -Emitted when a dispatcher is set for a specific profile by [setDispatcher()](doc:functions#setdispatcher) - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile for which the dispatcher is set | -| dispatcher | address | The dispatcher is set for the given profile | -| timestamp | uint256 | The block timestamp at which the dispatcher is set | - -### ProfileImageURISet - -`event ProfileImageURISet(uint256 indexed profileId, string imageURI, uint256 timestamp);` - -Emitted when a profile's URI is set by [setProfileImageURI()](doc:functions#setprofileimageuri) - -| Parameter Name | Type | Description | -| -------------- | ------- | ---------------------------------------------------- | -| profileId | uint256 | The token ID of the profile for which the URI is set | -| imageURI | string | The URI set for the given profile | -| timestamp | uint256 | The block timestamp at which URI is set | - -### FollowNFTURISet - -`event FollowNFTURISet(uint256 indexed profileId, string followNFTURI, uint256 timestamp);` - -Emitted when a follow NFT's URI is set by [setFollowNFTURI()](doc:functions#setfollownfturi) - -| Parameter Name | Type | Description | -| -------------- | ------- | --------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile for which the follow NFT URI is set | -| followNFTURI | string | The follow NFT URI is set for the given profile | -| timestamp | uint256 | The block timestamp at which NFT URI is set | - -### FollowModuleSet - -`event FollowModuleSet(uint256 indexed profileId, address followModule, bytes followModuleReturnData, uint256 timestamp);` - -Emitted when a profile's follow module is set by [setFollowModule()](doc:functions#setfollowmodule) - -| Parameter Name | Type | Description | -| ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile | -| followModule | address | The profile's newly set follow module. This CAN be the zero address | -| followModuleReturnData | address | The data returned from the follow module's initialization. This is abi encoded and depends on the follow module chosen | -| timestamp | uint256 | The block timestamp at which follow module is set | - -### PostCreated - -`event PostCreated(uint256 indexed profileId, uint256 indexed pubId, string contentURI, address collectModule, bytes collectModuleReturnData, address referenceModule, bytes referenceModuleReturnData, uint256 timestamp);` - -Emitted when a "post" is published by either [post()](doc:functions#post) or [postWithSig()](<>) - -| Parameter Name | Type | Description | -| ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile to which post is published | -| pubId | uint256 | The ID of the new post | -| contentURI | string | The URI mapped to this new post | -| collectModule | address | The collect module is mapped to this new post. This CAN NOT be the zero address | -| collectModuleReturnData | bytes | The data returned from the collect module's initialization for this given post. This is abi encoded, and totally depends on the collect module chosen | -| referenceModule | address | The reference module set for this post | -| referenceModuleReturnData | bytes | The data returned from the reference module at initialization. This is abi encoded and totally depends on the reference module chosen | -| timestamp | uint256 | The block timestamp at which this new post is created | - -### CommentCreated - -`event CommentCreated(uint256 indexed profileId, uint256 indexed pubId, string contentURI, uint256 profileIdPointed, uint256 pubIdPointed, address collectModule, bytes collectModuleReturnData, address referenceModule, bytes referenceModuleReturnData, uint256 timestamp);` - -Emitted when a "comment" is published by either [comment()](doc:functions#comment) or [commentWithSig()](<>) - -| Parameter Name | Type | Description | -| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| profileId | uint256 | The profile token ID from which comment is published | -| pubId | uint256 | The ID of the new comment | -| contentURI | string | The URI mapped to this new comment | -| profileIdPointed | uint256 | The profile token ID that this comment points to | -| pubIdPointed | uint256 | The publication ID that this comment points to | -| collectModule | address | The collect module mapped to this new comment. This CANNOT be the zero address | -| collectModuleReturnData | bytes | The data returned from the collect module's initialization for this given comment. This is abi encoded and totally depends on the collect module chosen | -| referenceModule | address | The reference module set for this comment | -| referenceModuleReturnData | bytes | The data returned from the reference module at initialization. This is abi encoded and totally depends on the reference module chosen | -| timestamp | uint256 | The block timestamp at which this comment is created | - -### MirrorCreated - -`event MirrorCreated(uint256 indexed profileId, uint256 indexed pubId, uint256 profileIdPointed, uint256 pubIdPointed, address referenceModule, bytes referenceModuleReturnData, uint256 timestamp);` - -Emitted when a "mirror" is published by either [mirror()](doc:functions#mirror) or [mirrorWithSig()](<>) - -| Parameter Name | Type | Description | -| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| profileId | uint256 | The profile token ID from which the mirror is published | -| pubId | uint256 | The ID of the new mirror | -| profileIdPointed | uint256 | The profile token ID that this mirror points to | -| pubIdPointed | uint256 | The publication ID that this mirror points to | -| referenceModule | address | The reference module set for this publication. | -| referenceModuleReturnData | bytes | The data returned from the reference module at initialization. This is abi encoded and totally depends on the reference module chosen | -| timestamp | uint256 | The block timestamp at which this mirror is created | - -### FollowNFTDeployed - -`event FollowNFTDeployed(uint256 indexed profileId, address indexed followNFT, uint256 timestamp);` - -Emitted when a `followNFT` clone is deployed using a lazy deployment pattern i.e. in case Follow NFT contract does not already exist when either [follow()](doc:functions#follow) or [followWithSig()](<>) is called. - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile to which this followNFT is associated | -| followNFT | address | The address of the newly deployed followNFT clone | -| timestamp | uint256 | The current block timestamp | - -### CollectNFTDeployed - -`event CollectNFTDeployed(uint256 indexed profileId, uint256 indexed pubId, address indexed collectNFT, uint256 timestamp);` - -Emitted when a `collectNFT` clone is deployed using a lazy deployment pattern i.e. in case collect NFT contract does not already exist when either [collect()](doc:functions#collect) or [collectWithSig()](<>) is called. - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------------------------ | -| profileId | uint256 | The profile ID of publisher | -| pubId | uint256 | The publication associated with the newly deployed collectNFT clone's ID | -| collectNFT | address | The address of the newly deployed collectNFT clone | -| timestamp | uint256 | The current block timestamp | - -### Collected - -`event Collected(address indexed collector, uint256 indexed profileId, uint256 indexed pubId, uint256 rootProfileId, uint256 rootPubId, uint256 timestamp);` - -Emitted upon a successful collect action by either [collect()](doc:functions#collect) or [collectWithSig()](<>) - -| Parameter Name | Type | Description | -| -------------- | ------- | --------------------------------------------------------------------------------------------------- | -| collector | address | The address collecting the publication | -| profileId | uint256 | The token ID of the profile that the collect was initiated towards, useful to differentiate mirrors | -| pubId | uint256 | The publication ID that the collect was initiated towards, useful to differentiate mirrors | -| rootProfileId | uint256 | The profile token ID of the profile whose publication is being collected | -| rootPubId | uint256 | The publication ID of the publication being collected | -| timestamp | uint256 | The current block timestamp | - -### FollowNFTTransferred - -`event FollowNFTTransferred(uint256 indexed profileId, uint256 indexed followNFTId, address from, address to, uint256 timestamp);` - -Emitted via callback when a followNFT is transferred. - -| Parameter Name | Type | Description | -| -------------- | ------- | --------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile associated with the followNFT being transferred | -| followNFTId | uint256 | The ID of followNFT being transferred | -| from | address | The address the followNFT is being transferred from | -| to | address | The address the followNFT is being transferred to | -| timestamp | uint256 | The current block timestamp | - -### CollectNFTTransferred - -`event CollectNFTTransferred(uint256 indexed profileId, uint256 indexed pubId, uint256 indexed collectNFTId, address from, address to, uint256 timestamp);` - -Emitted via callback when a collectNFT is transferred. - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile associated with the collectNFT being transferred. | -| pubId | uint256 | The publication ID associated with the collectNFT being transferred | -| collectNFTId | uint256 | The ID of the collectNFT being transferred | -| from | address | The address the collectNFT is being transferred from | -| to | address | The address the collectNFT is being transferred to | -| timestamp | uint256 | The current block timestamp | - -Collect/Follow NFT-Specific ---------------------------- - -### FollowNFTInitialized - -`event FollowNFTDelegatedPowerChanged(address delegate, uint256 newPower, uint256 timestamp);` - -Emitted when a newly deployed follow NFT is initialized. - -| Parameter Name | Type | Description | -| -------------- | ------- | -------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile connected to this follow NFT | -| timestamp | uint256 | The current block timestamp | - -### FollowNFTDelegatedPowerChanged - -`event FollowNFTDelegatedPowerChanged(address delegate, uint256 newPower, uint256 timestamp);` - -Emitted when delegation power in a FollowNFT is changed. - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------------------------- | -| delegate | address | The delegate whose power has been changed | -| newPower | uint256 | The new governance power mapped to the delegate | -| timestamp | uint256 | The current block timestamp | - -### CollectNFTInitialized - -`event CollectNFTInitialized(uint256 profileId, uint256 pubId, uint256 timestamp);` - - Emitted when a newly deployed collect NFT is initialized. - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile connected to the publication mapped to this collect NFT | -| pubId | uint256 | The publication ID connected to the publication mapped to this collect NFT | -| timestamp | uint256 | The current block timestamp | - -Module-Specific ---------------- - -### ModuleGlobalsGovernanceSet - -`event ModuleGlobalsGovernanceSet(address indexed prevGovernance, address indexed newGovernance, uint256 timestamp);` - -Emitted when the ModuleGlobals governance address is set. - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------- | -| prevGovernance | address | The previous governance address | -| newGovernance | address | The new governance address set | -| timestamp | uint256 | The current block timestamp | - -### ModuleGlobalsTreasurySet - -`event ModuleGlobalsTreasurySet(address indexed prevTreasury, address indexed newTreasury, uint256 timestamp);` - -Emitted when the ModuleGlobals treasury address is set. - -| Parameter Name | Type | Description | -| -------------- | ------- | ----------------------------- | -| prevTreasury | address | The previous treasury address | -| newTreasury | address | The new treasury address set | -| timestamp | uint256 | The current block timestamp | - -### ModuleGlobalsTreasuryFeeSet - -`event ModuleGlobalsTreasuryFeeSet(uint16 indexed prevTreasuryFee, uint16 indexed newTreasuryFee, uint256 timestamp);` - - Emitted when the ModuleGlobals treasury fee is set. - -| Parameter Name | Type | Description | -| --------------- | ------- | -------------------------------- | -| prevTreasuryFee | uint16 | The previous treasury fee in BPS | -| newTreasuryFee | uint16 | The new treasury fee in BPS | -| timestamp | uint256 | The current block timestamp | - -### ModuleGlobalsCurrencyWhitelisted - -`event ModuleGlobalsCurrencyWhitelisted(address indexed currency, bool indexed prevWhitelisted, bool indexed whitelisted, uint256 timestamp);` - -Emitted when a currency is added to or removed from the ModuleGlobals whitelist. - -| Parameter Name | Type | Description | -| --------------- | ------- | -------------------------------------------------------------------------------------- | -| currency | address | The currency address | -| prevWhitelisted | bool | 1 => Currency was previously whitelisted, 0 => Currency was not previously whitelisted | -| whitelisted | bool | 1 => Currency whitelisted, 0 => Currency not whitelisted | -| timestamp | uint256 | The current block timestamp | - -### FeeModuleBaseConstructed - -`event FeeModuleBaseConstructed(address indexed moduleGlobals, uint256 timestamp);` - -Emitted when a module inheriting from the `FeeModuleBase` is constructed. - -| Parameter Name | Type | Description | -| -------------- | ------- | --------------------------------------- | -| moduleGlobals | address | The ModuleGlobals contract address used | -| timestamp | uint256 | The current block timestamp | - -### ModuleBaseConstructed - -`event ModuleBaseConstructed(address indexed hub, uint256 timestamp);` - -Emitted when a module inheriting from the `ModuleBase` is constructed. - -| Parameter Name | Type | Description | -| -------------- | ------- | --------------------------------- | -| hub | address | The LensHub contract address used | -| timestamp | uint256 | The current block timestamp | - -### FollowsApproved - -`event FollowsApproved(address indexed owner, uint256 indexed profileId, address[] addresses, bool[] approved, uint256 timestamp);` - -Emitted when one or multiple addresses are approved (or disapproved) for following in the `ApprovalFollowModule`. - -| Parameter Name | Type | Description | -| -------------- | ---------- | ----------------------------------------------------------------- | -| owner | address | The profile owner who executed the approval | -| profileId | uint256 | The profile ID that the follow approvals are granted/revoked for | -| addresses | address\[] | The addresses that have had the follow approvals granted/revoked | -| approved | bool | Whether each corresponding address is now approved or disapproved | -| timestamp | uint256 | The current block timestamp | \ No newline at end of file diff --git a/documents/Specification/icollectmodulesol.md b/documents/Specification/icollectmodulesol.md deleted file mode 100644 index 8127a2d..0000000 --- a/documents/Specification/icollectmodulesol.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "Collect Modules" -slug: "icollectmodulesol" -hidden: false -createdAt: "2022-01-28T04:09:59.646Z" -updatedAt: "2023-02-26T14:30:33.056Z" ---- -# Collect Module Interface - -This is the interface all Lens Protocol Compatible Collect modules must implement. - -## initializePublicationCollectModule() - -`function initializePublicationCollectModule(uint256 profileId, uint256 pubId, bytes calldata data) external returns (bytes memory);` - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------ | -| profileId | uint256 | The token ID of the profile publishing the publication | -| pubId | uint256 | The associated publication's LensHub publication ID | -| data | bytes | Arbitrary data passed by the profile creator | - -This function initializes data for a given publication being published. This can only be called by the LensHub contract. - -It returns an ABI encoded byte array encapsulating the execution's state changes. This will be emitted by the hub alongside the collect modules address and should be consumed by the front ends. - -## processCollect() - -`function processCollect(uint256 referrerProfileId, address collector, uint256 profileId, uint256 pubId, bytes calldata data) external;` - -| Parameter Name | Type | Description | -| ----------------- | ------- | --------------------------------------------------------------------------- | -| referrerProfileId | uint256 | The token ID of the profile associated with the publication being collected | -| collector | address | The address collecting the publication | -| pubId | uint256 | The LensHub publication ID associated with the publication being collected | -| data | bytes | Arbitrary data passed by the collector to be decoded | - -This function processes a collect action for a given publication; this can only be called by the Lens Hub contract. - -# Whitelisted Collect Modules - -## Revert Collect Module - -The [Revert Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/RevertCollectModule.sol) causes all collect actions on a given post to fail, thus making the post uncollectible. - -## Free Collect Module - -The [Free Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/FreeCollectModule.sol) allows any profile to collect the publication this module is attached to. - -## Fee Collect Module - -The [Fee Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/FeeCollectModule.sol) allows for any follower to collect the associated publication provided they pay a fee set by the poster. This fee must be denominated in a whitelisted currency. Additionally, the poster can specify a portion of the fee that goes to a user who mirrors this publication, should the collect action be executed via their mirrored post. - -Lastly, governance can add a treasury fee, which will send a portion of the collect fee to a designated treasury address. - -## Limited Fee Collect Module - -The [Limited Fee Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/LimitedFeeCollectModule.sol) allows for any follower to collect the associated publication, provided they pay a fee, up to a specific limit of mints. As with the Fee Collect Module, the fee must be denominated in a whitelisted currency, a mirror fee can be specified, and governance can direct a treasury fee to a designated treasury address. - -## Timed Fee Collect Module - -The [Timed Fee Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/TimedFeeCollectModule.sol) allows for any follower to collect the associated publication, provided they pay a fee, up to a specific time limit. The present whitelisted Timed Fee Collect module only has a 24-hour time limit to reduce gas usage and optimize efficiency. - -As with the Fee Collect Module, the fee must be denominated in a whitelisted currency, a referral fee can be specified, and governance can direct a treasury fee to a designated treasury address. - -Note, if uninitialized, no fee will be specified. Only the time limit will be checked, providing functionality similar to the Free Collect Module with a time limit for mint added. - -## Limited Timed Fee Collect Module - -The [Limited Timed Fee Collect Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/collect/LimitedTimedFeeCollectModule.sol) allows for any follower to collect the associate publication, provided they pay a fee, up to a specific time limit and mint cap. It is essentially a combination of the Timed Fee Collect Module and the Limited Fee Collect Module. - -As with the base Fee Collect Module, the fee must be denominated in a whitelisted currency. A referral fee can be specified, and governance can direct a treasury fee to a designated treasury address. - -Additionally, as with the Timed Fee Collect Module, no fee will be specified if uninitialized. Only the time limit and mint cap will be checked, providing functionality similar to the Free Collect Module with a time limit for mint and mint cap added. - -## Multi Recipient Fee Collect Module - -This module supports splitting the collect fees between multiple recipients. It also supports timed and limited fee collects optionally, so you can use it to support almost every use case. You can specify fees for Charity's, Contributors, Co-creators, DAO's, Other contracts. - -e.g. - -- Contributor (sponsor,video editor)—20% -- Charity—10% -- DAO — 10% -- Creator—60% \ No newline at end of file diff --git a/documents/Specification/ifollowmodulesol.md b/documents/Specification/ifollowmodulesol.md deleted file mode 100644 index ca29d3e..0000000 --- a/documents/Specification/ifollowmodulesol.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Follow Modules" -slug: "ifollowmodulesol" -hidden: false -createdAt: "2022-01-28T04:02:45.919Z" -updatedAt: "2022-08-16T19:53:42.953Z" ---- -Follow Module Interface -======================= - -This is the interface all Lens Protocol Compatible Follow modules must implement. - -initializeFollowModule() ------------------------- - -`function initializeFollowModule(uint256 profileId, bytes calldata data) external;` - -| Parameter Name | Type | Description | -| -------------- | ------- | ---------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile to initialize this follow module for | -| data | bytes | Arbitrary data passed by the profile creator | - -This function initializes the follow module for a given Lens profile. The hub contract can only call this. - -processFollow() ---------------- - -`function processFollow(address follower, uint256 profileId, bytes calldata data) external;` - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------ | -| follower | address | The follower address | -| profileId | uint256 | The token ID of the profile being followed | -| data | bytes | Arbitrary data passed by the follower | - -This function processes a given follow; this can only be called from the LensHub contract. - -followModuleTransferHook() --------------------------- - -`followModuleTransferHook(uint256 profileId, address from, address to, uint256 followNFTTokenId) external;` - -| Parameter Name | Type | Description | -| ---------------- | ------- | ----------------------------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile associated with the follow NFT being transferred. | -| from | address | The address sending the follow NFT | -| to | address | The address receiving the follow NFT | -| followNFTTokenId | uint256 | The token ID of the follow NFT being transferred | - -This is a transfer hook that is called upon follow NFT transfer in `beforeTokenTransfer.` This can only be called from the LensHub contract. - -NOTE: Special care needs to be taken here: It is possible that follow NFTs were issued before this module was initialized if the profile's follow module was previously different. This transfer hook should consider this, especially when the module holds state associated with individual follow NFTs. - -function validateFollow() -------------------------- - -`function validateFollow(uint256 profileId, address follower, uint256 followNFTTokenId) external view;` - -| Parameter Name | Type | Description | -| ---------------- | ------- | ------------------------------------------------------- | -| profileId | uint256 | The token ID of the profile to validate the follow for. | -| follower | address | The follower address to validate the follow for. | -| followNFTTokenId | uint256 | The followNFT token ID to validate the follow for. | - -This is a helper function that could be used in conjunction with specific collect modules. - -NOTE: This function IS meant to replace a check on follower NFT ownership. - -NOTE: It is assumed that not all collect modules are aware of the token ID to pass. In these cases, this should receive a `followNFTTokenId` of 0, which is impossible regardless. - -One example of a use case for this would be a subscription-based following system: - 1. The collect module: - - Decodes a follower NFT token ID from user-passed data. - - Fetches the follow module from the hub. - - Calls `validateFollow` passing the profile ID, follower & follower token ID. - 2. The follow module: - - Validates the subscription status for that given NFT, reverting on an invalid subscription. - -Whitelisted Follow Modules -========================== - -Approval Follow Module ----------------------- - -The [Approval Follow Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/follow/ApprovalFollowModule.sol) only allows addresses that are approved for a profile by the profile owner to follow. Users can use the `approve()` function to add/remove addresses from the Approved Array. the `isApproved()` or `isApprovedArray()` functions allow applications to check which address(es) are approved by a given user. - -Fee Follow Module ------------------ - -The [Fee Follow Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/follow/FeeFollowModule.sol) only allows addresses to follow a given profile, so long as they pay a fee specified by the profile owner. Users can set the currency and amount required to be paid so long as the `currency` has been whitelisted by governance. Additionally, governance can adjust the `treasuryFee` variable to direct some of the follow fees to a specified treasury address. \ No newline at end of file diff --git a/documents/Specification/ireferencemodulesol.md b/documents/Specification/ireferencemodulesol.md deleted file mode 100644 index 7a299df..0000000 --- a/documents/Specification/ireferencemodulesol.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Reference Modules" -slug: "ireferencemodulesol" -hidden: false -createdAt: "2022-01-28T04:09:42.504Z" -updatedAt: "2023-01-11T12:16:21.482Z" ---- -Reference Module Interface -========================== - -This is the interface all Lens Protocol Compatible Reference modules must implement. - -initializeReferenceModule() ---------------------------- - -`function initializeReferenceModule(uint256 profileId, uint256 pubId, bytes calldata data) external returns (bytes memory);` - -| Parameter Name | Type | Description | -| -------------- | ------- | ------------------------------------------------------ | -| profileId | uint256 | The token ID of the profile publishing the publication | -| pubId | uint256 | The associated publication's LensHub publication ID | -| data | bytes | Arbitrary data passed by the profile creator | - -This function initializes data for a given publication being published. This can only be called by the hub. - -It returns an ABI encoded byte array encapsulating the execution's state changes. This will be emitted by the hub alongside the collect module's address and consumed by the front ends. - -processComment() ----------------- - -`function processComment(uint256 profileId, uint256 profileIdPointed, uint256 pubIdPointed) external;` - -| Parameter Name | Type | Description | -| ---------------- | ------- | ------------------------------------------------------------------------------ | -| profileId | uint256 | The token ID of the profile associated with the publication being published | -| profileIdPointed | uint256 | The profile ID of the profile associated with the publication being referenced | -| pubIdPointed | uint256 | The publication ID of the publication being referenced | - -This function processes a comment action referencing a given publication. This function can only be called by the LensHub contract. - -processMirror() ---------------- - -`function processMirror(uint256 profileId, uint256 profileIdPointed, uint256 pubIdPointed) external;` - -| Parameter Name | Type | Description | -| ---------------- | ------- | ------------------------------------------------------------------------------ | -| profileId | uint256 | The token ID of the profile associated with the publication being published | -| profileIdPointed | uint256 | The profile ID of the profile associated with the publication being referenced | -| pubIdPointed | uint256 | The publication ID of the publication being referenced | - -This function processes a mirror action referencing a given publication. This function can only be called by the LensHub contract. - -Whitelisted Reference Modules -============================= - -Follower Only Reference Module ------------------------------- - -The [Follower Only Reference Module](https://github.com/lens-protocol/lens-protocol/blob/main/contracts/core/modules/reference/FollowerOnlyReferenceModule.sol) ensures that only a profile is allowed to mirror or comment on content if that wallet contains the FollowNFT of the profile that posted the comment they are mirroring or commenting on. \ No newline at end of file diff --git a/documents/Specification/lenshub.md b/documents/Specification/lenshub.md deleted file mode 100644 index 8f84d77..0000000 --- a/documents/Specification/lenshub.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "LensHub.sol" -slug: "lenshub" -hidden: false -createdAt: "2021-12-15T21:40:16.473Z" -updatedAt: "2022-02-04T20:05:39.122Z" ---- -## Overview - -This is the core entry point contract for essentially all interactions with the Lens Protocol. It is an upgradeable contract via the standard OpenZeppelin [TransparentUpgradeabilityProxy.](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) This document elaborates on the functions of the implementation, assuming they are called via the proxy. Functions that take a struct as the sole input parameter will display struct members in the parameter table. - -Note that as a design choice, all NFTs *should not* mint a token with `tokenId == 0` in any circumstance, as this is equivalent to an uninitialized variable. Furthermore, ERC721 standard functions have been omitted from this document. \ No newline at end of file diff --git a/documents/Specification/lenshub/functions.md b/documents/Specification/lenshub/functions.md deleted file mode 100644 index 0cc5de8..0000000 --- a/documents/Specification/lenshub/functions.md +++ /dev/null @@ -1,471 +0,0 @@ ---- -title: "State Changing Functions" -slug: "functions" -excerpt: "State changing functions in the LensHub.sol contract" -hidden: false -createdAt: "2022-01-18T23:28:11.514Z" -updatedAt: "2022-11-08T09:39:25.944Z" ---- -## Meta-Transactions -All "`withSig`" meta-transaction functions have been omitted from this document, as they allow for the same functionality as their standard counterparts, only via EIP-712 meta-transactions. Also, the requirements in this specification are not presented in any order pertaining to security. - -## initialize() - -`function initialize(string calldata name, string calldata symbol, address newGovernance) external;.` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| name | string | The name to give to the Lens profile NFT. | -| symbol | string | The symbol to give to the Lens profile NFT. | -| newGovernance | address | The new governance address to set. | - -This function initializes the proxy contract. - -It should... - -1. Set the ERC721 name for the Lens profile NFT. -2. Set the ERC721 symbol for the Lens profile NFT. -3. Set the governance address. -4. Set the protocol state to `ProtocolState.Paused.` -5. Only be called once, unless the `REVISION` was incremented in a new implementation. -6. Not being called on the implementation (this has no security benefit in this specific context, but is a best practice). - -## setGovernance() - -`function setGovernance(address newGovernance) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| newGovernance | address | The new governance address to set | - -This function sets the governance address. Note that we do not implement a built-in timelock or a 2-step governance change because it is assumed that the governance role will implement the necessary mechanisms. - -It should... - -1. Set the governance address. -2. Only be called by the current governance address. - -## setEmergencyAdmin() - -`function setEmergencyAdmin(address newEmergencyAdmin) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| newEmergencyAdmin | address | The new emergency admin address to set | - -This function sets the emergency admin. - -It should... - -1. Set the emergency admin address. -2. Only be called by the current governance address. - -## setState() - -`function setState(DataTypes.ProtocolState state) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| state | Enum: DataTypes.ProtocolState | The ProtocolState to set. | - -This function sets the current protocol state, between `ProtocolState.Paused`, `ProtocolState.PublishingPaused` and `ProtocolState.Unpaused`. - -It should... - -1. Set the protocol state. -2. Only be called by the current governance or emergency admin addresses. - -## whitelistProfileCreator() - -`function whitelistProfileCreator(address profileCreator, bool whitelist) external` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileCreator | address | The profile creator to whitelist. | -| whitelist | bool | Whether to add or remove the profile creator from the whitelist | - -This function sets whether a profile creator is whitelist, allowing or disallowing profile creation from that address. - -It should... - -1. Set whether or not a profile creator is whitelisted. -2. Only be called by the current governance address. - -## whitelistFollowModule() - -`function whitelistFollowModule(address followModule, bool whitelist) external` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| followModule | address | The follow module address to whitelist | -| whitelist | bool | Whether to add or remove the module from the whitelist | - -This function sets whether a follow module is whitelisted, allowing or disallowing profiles to use it. - -It should... - -1. Set whether or not a follow module is whitelisted. -2. Only be called by the current governance address. -3. Not invalidate follow modules previously used then removed from the whitelist. - -## whitelistReferenceModule() - -`function whitelistReferenceModule(address referenceModule, bool whitelist) external` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| referenceModule | address | The reference module address to whitelist | -| whitelist | bool | Whether to add or remove the module from the whitelist | - -This function whitelists a reference module, allowing new publications to use it. - -It should... - -1. Set whether or not a reference module is whitelisted. -2. Only be called by the current governance address. -3. Not invalidate reference modules that were previously used then removed from the whitelist. - -## whitelistCollectModule() - -`function whitelistCollectModule(address collectModule, bool whitelist) external` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| collectModule | address | The collect module address to whitelist | -| whitelist | bool | Whether to add or remove the module from the whitelist | - -This function whitelists a collect module, allowing new publications to use it. - -It should... - -1. Set whether or not a collect module is whitelisted. -2. Only be called by the current governance address. -3. Not invalidate collect modules that were previously used then removed from the whitelist. - -## createProfile() - -`function createProfile(DataTypes.CreateProfileData calldata vars) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| to | address | The address to mint the profile to | -| handle | string | The handle to set for the new profile | -| imageURI | string | The URI to set for the new profile's image | -| followModule | address | The follow module to set for the new profile or the zero address | -| followModuleInitData | bytes | Arbitrary data to be decoded in the follow module for initialization | -| followNFTURI | string | The URI to set for the profile's follow NFT | - -This function creates a profile. - -It should... - -1. Revert if the handle is already taken. -2. Revert if the handle contains characters that are not standard, Latin lowercase alphabet characters, or digits from 0 to 9. -3. Revert if the follow module selected is not whitelisted and not the zero address. -4. Revert if the follow module data is invalid when decoded in the follow module. -5. Revert if the caller is not a whitelisted profile creator. -6. Mint a profile NFT to the 'to' address with the id equal to the profile ID Counter + 1. -7. Increment the profile ID counter. -8. Map the handle, image URI and follow NFT URI to the profile NFT token ID (profileId). -9. Map the profile NFT token ID to the handle hash. -10. Set and initialize the selected follow module with the given data for the given profile. - -## setFollowModule() - -`function setFollowModule(uint256 profileId, address followModule, bytes calldata followModuleData) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The token ID of the profile to set the follow module for | -| followModule | address | The follow module to set for the profile | -| followModuleData | bytes | The arbitrary data to be decoded in the selected follow module for initialization | - -This function sets the follow module for the specified profile. - -It should... - -1. Revert if the caller is not the profile owner. -2. Revert if the follow module selected is not whitelisted. -3. Revert if the follow module data is invalid when decoded in the follow module. -4. Set and initialize the selected follow module with the given data for the given profile. - -## setDispatcher() - -`function setDispatcher(uint256 profileId, address dispatcher) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The token ID of the profile to set the dispatcher for | -| dispatcher | address | The dispatcher to set for the profile | - -This function sets the dispatcher for a given profile. Note that a profile's dispatcher can publish and set the URI on behalf of the profile above. Dispatchers should be invalidated if the profile NFT is owned by an address other than the one that set the dispatcher. - -It should... - -1. Revert if the caller is not the profile owner. -2. Set the dispatcher for the given profile. - -## setProfileImageURI() - -`function setProfileImageURI(uint256 profileId, string calldata imageURI) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The token ID of the profile to set the URI for. | -| imageURI | string | The URI to set for the profile image. | - -This function sets the profile image URI, used to build the on-chain SVG returned on calls to `tokenURI()` in the hub. - -It should... - -1. Revert if the caller is not the profile owner or the profile's dispatcher. -2. Set the image URI for the given profile. - -## setFollowNFTURI() - -`function setFollowNFTURI(uint256 profileId, string calldata followNFTURI) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The token ID of the profile to set the follow NFT URI for | -| followNFTURI | string | The URI to set for the follow NFT | - -This function sets the given profile's follow NFT URI, which is returned on calls to `tokenURI()` on the follow NFT. This must return a URI that points to a standardized JSON metadata. - -It should... - -1. Revert if the caller is not the profile owner or the profile's dispatcher. -2. Set the follow NFT URI for the given profile's follow NFT. - -## post() - -`function post(DataTypes.PostData calldata vars) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to publish the post to | -| contentURI | string | The URI to set for this publication | -| collectModule | address | The collect module to set for this publication | -| collectModuleData | bytes | The arbitrary data to be decoded in the selected collect module for publication initialization | -| referenceModule | address | The reference module to set for this publication | -| referenceModuleData | bytes | The arbitrary data to be decoded in the selected reference module for publication initialization | - -This function publishes a post to the given profile. - -It should... - -1. Revert if the caller is not the profile owner or the profile's dispatcher. -2. Revert if the collect module is not whitelisted. -3. Revert if the reference module is not whitelisted and not the zero address. -4. Revert if the collect module data is invalid when decoded in the collect module. -5. Revert if the reference module data is invalid when decoded in the reference module. -6. Create a publication mapped to the profile via the latest profile publication ID counter + 1. - 1. The publication should have no pointer; all other fields should be non-zero, bar the reference module (though an empty URI is pointless, possible). -7. Increment the profile's publication ID counter. -8. Set and initialize the selected collect module with the given data for the given publication. -9. If it is not the zero address, set and initialize the selected reference module with the given data for the given publication. - -## comment() - -`function comment(DataTypes.CommentData calldata vars) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to publish the comment to | -| contentURI | string | The URI to set for this publication | -| profileIdPointed | uint256 | The profile ID to point the comment to | -| pubIdPointed | uint256 | The publication ID to point the comment to | -| collectModule | address | The collect module to set for this publication | -| collectModuleData | bytes | The arbitrary data to be decoded in the selected collect module for publication initialization | -| referenceModule | address | The reference module to set for this publication | -| referenceModuleData | bytes | The arbitrary data to be decoded in the selected reference module for publication initialization | - -This function publishes a comment to the given profile. - -It should... - -1. Revert if the caller is not the profile owner or the profile's dispatcher. -2. Revert if the collect module is not whitelisted. -3. Revert if the reference module is not whitelisted and not the zero address. -4. Revert if the collect module data is invalid when decoded in the collect module. -5. Revert if the reference module data is invalid when decoded in the reference module. -6. Create a publication with a pointer to the specified publication being "commented on" mapped to the profile via the latest profile publication ID counter + 1. - 1. All publication fields should be non-zero, bar the reference module (though an empty URI is pointless, but possible). -7. Execute any reference module logic mapped to the pointed publication (even if it is a mirror). -8. Increment the profile's publication ID counter. -9. Set and initialize the selected collect module with the given data for the given publication. -10. If it is not the zero address, set and initialize the selected reference module with the given data for the given publication. - -## commentWithSig() -`function commentWithSig(DataTypes.CommentWithSigData calldata vars) external;` - -CommentWithSigData Struct Params: - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to publish the comment to | -| contentURI | string | The URI to set for this publication | -| profileIdPointed | uint256 | The profile ID to point the comment to | -| pubIdPointed | uint256 | The publication ID to point the comment to | -| collectModule | address | The collect module to set for this publication | -| collectModuleData | bytes | The arbitrary data to be decoded in the selected collect module for publication initialization | -| referenceModule | address | The reference module to set for this publication | -| referenceModuleData | bytes | The arbitrary data to be decoded in the selected reference module for publication initialization | -| sig | EIP712Signature | The EIP712Signature struct containing the profile owner's signature | - -Message Params and Types used for EIP712 signature passed above: - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to publish the comment to | -| contentURI | string | The URI to set for this publication | -| profileIdPointed | uint256 | The profile ID to point the comment to | -| pubIdPointed | uint256 | The publication ID to point the comment to | -| collectModule | address | The collect module to set for this publication | -| collectModuleData | bytes | The arbitrary data to be decoded in the selected collect module for publication initialization | -| referenceModule | address | The reference module to set for this publication | -| referenceModuleData | bytes | The arbitrary data to be decoded in the selected reference module for publication initialization | -| nonce | uint256 | The profile owner signature nonce | -| deadline | uint256 | The unix timestamp by when signature expires | - - -This function publishes a comment to the given profile signed by the owner or dispatcher of the profile. - -It should... - -1. Revert if the recovered signature is not of the profile owner or the profile's dispatcher. -2. Revert if the signature deadline is before the `block.timestamp` in which tx is included. -3. Revert if the signature is not compliant with EIP712 and based on the current contract and chain ID. -4. Revert if the collect module is not whitelisted. -5. Revert if the reference module is not whitelisted and not the zero address. -6. Revert if the collect module data is invalid when decoded in the collect module. -7. Revert if the reference module data is invalid when decoded in the reference module. -8. Create a publication with a pointer to the specified publication being "commented on" mapped to the profile via the latest profile publication ID counter + 1. - 1. All publication fields should be non-zero, bar the reference module (though an empty URI is pointless, but possible). -9. Execute any reference module logic mapped to the pointed publication (even if it is a mirror) -10. Increment the profile's publication ID counter. -11. Set and initialize the selected collect module with the given data for the given publication. -12. If it is not the zero address, set and initialize the selected reference module with the given data for the given publication. - -## mirror() - -`function mirror(DataTypes.MirrorData calldata vars) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to publish the mirror to | -| profileIdPointed | uint256 | The profile ID to point the mirror to | -| pubIdPointed | uint256 | The publication ID to point the mirror to | -| referenceModuleData | bytes | The arbitrary data passed to the reference module | -| referenceModule | address | The reference module to set for this publication | -| referenceModuleInitData | bytes | The arbitrary data to be decoded in the selected reference module for publication initialization | - -This function publishes a mirror to the given profile. - -It should... - -1. Revert if the caller is not the profile owner or the profile's dispatcher. -2. Revert if the reference module is not whitelisted and not the zero address. -3. Revert if the reference module data is invalid when decoded in the reference module. -4. Create a publication with a pointer to the specified publication being "mirrored" mapped to the profile via the latest profile publication ID counter + 1. - 1. The publication should have no content URI and no collect module, all other fields should be non-zero, bar the reference module. -5. Execute any reference module logic mapped to the pointed publication (**if it is a mirror, execute the logic on the original publication being mirrored in the first place**). -6. Increment the profile's publication ID counter. -7. If it is not the zero address, set and initialize the selected reference module with the given data for the given publication. - -## burn() - -`function burn(uint256 profileId) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the token to burn. | - -This function burns a profile NFT. Burned profiles should not be able to be followed. - -It should... - -1. Revert if the caller is not the profile owner. -2. Burn the profile NFT. -3. Prevent the burned profile from being followed. -4. Have no effect on previous publications made by the burned profile. -5. Have no effect on the profile ID counter (i.e. the next profile created should have an ID that is unaffected whether profiles were or were not burned previously). -6. Release the handle mapped to the previous publication, allowing it to be claimed by a new profile. - -## follow() - -`function follow(uint256[] calldata profileIds, bytes[] calldata datas) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileIds | uint256[] | The array of profile IDs to follow | -| datas | bytes[] | The array of arbitrary data to pass to each profile being followed's follow module | - -This function follows the given profiles, minting one of each profile's follow NFTs to the follower. Note that there is no issue with following the same profile multiple times. - -It should... - -1. Revert if the `profileIds` and `datas` arrays are of different length. -2. Revert if a profile ID passed as input does not have a corresponding profile (a profile followed does not exist). -3. Execute any follow module logic mapped to the profile being followed, if any, passing the data parameter at the same index as the profile ID in the input arrays. -4. If it does not exist for the given profile, clone the follow NFT implementation and initialize it. -5. Mint follow NFTs for each profile to the follower with ID equal to the given follow NFT's token ID counter + 1 in each case. -6. Increment the token ID counter in each follow NFT. - -## collect() - -`function collect(uint256 profileId, uint256 pubId, bytes calldata data) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication being collected | -| pubId | uint256 | The publication ID of the publication being collected | -| data | bytes | The arbitrary data being passed to the publication's collect module | - -This function collects the given publication. - -It should... - -1. Revert if the profile ID passed as input does not have a corresponding profile (the profile does not exist). -2. Revert if the publication ID passed as input does not have a corresponding publication (the publication does not exist). -3. Execute collect module logic mapped to the publication being collected, passing the data parameter as input. -4. If it does not exist for the given publication, clone the collect NFT implementation and initialize it. -5. Mint a collect NFT pointing to the publication to the follower with ID equal to the given collect NFT's token ID counter + 1. -6. Increment the token ID counter in the collect NFT. - -## emitFollowNFTTransferEvent() - -`function emitFollowNFTTransferEvent(uint256 profileId, uint256 followNFTId, address from, address to) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID mapped to the follow NFT being transferred. | -| followNFTId | uint256 | The follow NFT ID of the follow NFT being transferred. | -| from | address | The address the follow NFT is being transferred from. | -| to | address | The address the follow NFT is being transferred to. | - -This function emits an event when a follow NFT is transferred, to be more easily consumed by clients. - -It should... - -1. Revert if the caller is not the follow NFT mapped to the given profile ID. -2. Only be called when a follow NFT is being transferred via `beforeTokenTransfer().` - -## emitCollectNFTTransferEvent() - -`function emitCollectNFTTransferEvent(uint256 profileId, uint256 pubId, uint256 collectNFTId, address from, address to) external;` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID mapped to the collect NFT being transferred | -| pubId | uint256 | The publication ID mapped to the collect NFT being transferred | -| collectNFTId | uint256 | The collect NFT ID of the collect NFT being transferred | -| from | address | The address the collect NFT is being transferred from | -| to | address | The address the collect NFT is being transferred to | - -This function emits an event when a follow NFT is transferred, to be more easily consumed by clients. - -It should... - -1. Revert if the caller is not the collect NFT mapped to the given profile ID and publication ID. -2. Only be called when a collect NFT is being transferred via `beforeTokenTransfer().` \ No newline at end of file diff --git a/documents/Specification/lenshub/view-functions.md b/documents/Specification/lenshub/view-functions.md deleted file mode 100644 index 916bb56..0000000 --- a/documents/Specification/lenshub/view-functions.md +++ /dev/null @@ -1,418 +0,0 @@ ---- -title: "View Functions" -slug: "view-functions" -excerpt: "View functions in the LensHub.sol contract" -hidden: false -createdAt: "2022-01-27T18:03:51.731Z" -updatedAt: "2022-02-10T01:26:54.858Z" ---- -### isFollowModuleWhitelisted() - -`function isFollowModuleWhitelisted(address followModule) external view returns (bool);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| followModule | address | The follow module to fetch whitelist status for | - -**Returns** - -| Type | Description | -| --- | --- | -| bool | Whether the queried follow module is whitelisted | - -This function returns whether a follow module is whitelisted. - -It should... - -1. Return `true` if a follow module is whitelisted, `false` otherwise. - -### isReferenceModuleWhitelisted() - -`function isReferenceModuleWhitelisted(address referenceModule) external view returns (bool);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| referenceModule | address | The reference module to fetch whitelist status for | - -**Returns** - -| Type | Description | -| --- | --- | -| bool | Whether the queried reference module is whitelisted | - -This function returns whether a reference module is whitelisted. - -It should... - -1. Return `true` if a reference module is whitelisted, `false` otherwise. - -### isCollectModuleWhitelisted() - -`function isCollectModuleWhitelisted(address collectModule) external view returns (bool);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| collectModule | address | The collect module to fetch whitelist status for | - -**Returns** - -| Type | Description | -| --- | --- | -| bool | Whether the queried collect module is whitelisted | - -This function returns whether a collect module is whitelisted. - -It should... - -1. Return `true` if a collect module is whitelisted, `false` otherwise. - -### getGovernance() - -`function getGovernance() external view returns (address);` - -**Returns** - -| Type | Description | -| --- | --- | -| address | The current governance address | - -This function returns the current governance address. - -It should... - -1. Return the current governance address. - -### getDispatcher() - -`function getDispatcher(uint256 profileId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile to fetch the dispatcher for | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The dispatcher for the queried address, if any | - -This function returns the dispatcher for the given profile if any. - -It should... - -1. Return the dispatcher address set for a given profile if it exists (which can be the zero address). -2. Return the zero address if the profile does not exist - -### getPubCount() - -`function getPubCount(uint256 profileId) external view returns (uint256);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile to fetch the publication count for | - -**Returns** - -| Type | Description | -| --- | --- | -| uint256 | The publication count for the given profile, or zero | - -This function returns the publication count for the given profile. - -It should... - -1. Return the publication count for the given profile if the profile exists (which can be zero). -2. Return zero if the profile does not exist. - -### getFollowNFT() - -`function getFollowNFT(uint256 profileId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile to fetch the follow NFT for | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The follow NFT mapped to the given profile, if any | - -This function returns the follow NFT for the given profile, if any. - -It should... - -1. Return the follow NFT for the given profile if the profile exists (which can be the zero address). -2. Return the zero address if the profile does not exist. - -### getCollectNFT() - -`function getCollectNFT(uint256 profileId, uint256 pubId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the collect NFT for | -| pubId | uint256 | The publication ID to fetch the collect NFT for. | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The collect NFT mapped to the given publication if any | - -This function returns the collect NFT for the given publication, if any. - -It should... - -1. Return the collect NFT for the given publication if the publication exists (which can be the zero address). -2. Return the zero address if the publication does not exist. - -### getFollowNFTURI() - -`function getFollowNFTURI(uint256 profileId) external view returns (string memory);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile to fetch the follow NFT URI for | - -**Returns** - -| Type | Description | -| --- | --- | -| string memory | The follow NFT URI mapped to the given profile | - -This function returns the follow NFT URI for the given profile. - -It should... - -1. Return the follow NFT URI for the given profile (which can be an empty string). - -### getFollowModule() - -`function getFollowModule(uint256 profileId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile to fetch the follow module for | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The follow module mapped to the given profile, if any | - -This function returns the follow module for the given profile, if any. - -It should... - -1. Return the follow module for the given profile if the profile exists (which can be the zero address). -2. Return the zero address if the profile does not exist. - -### getCollectModule() - -`function getCollectModule(uint256 profileId, uint256 pubId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the collect module for. | -| pubId | uint256 | The publication ID to fetch the collect module for | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The collect module mapped to the given publication | - -This function returns the collect module for the given publication. Note that a publication should not have the zero address as a collect module. - -It should... - -1. Return the collect module for the given publication if the publication exists. -2. Return the zero address if the publication does not exist. - -### getReferenceModule() - -`function getReferenceModule(uint256 profileId, uint256 pubId) external view returns (address);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the reference module for. | -| pubId | uint256 | The publication ID to fetch the reference module for | - -**Returns** - -| Type | Description | -| --- | --- | -| address | The reference module mapped to the given publication, if any | - -This function returns the reference module for the given publication, if any. - -It should... - -1. Return the reference module for the given publication if the publication exists (which can be the zero address). -2. Return the zero address if the publication does not exist. - -### getHandle() - -`function getHandle(uint256 profileId) external view returns (string memory);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to fetch the handle for | - -**Returns** - -| Type | Description | -| --- | --- | -| string | The handle mapped to the given profile, if any | - -This function returns the handle for the given profile. - -It should... - -1. Return the handle for the given profile if the profile exists. -2. Return an empty string if the profile does not exist. - -### getPubPointer() - -`function getPubPointer(uint256 profileId, uint256 pubId) external view returns (uint256, uint256);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the publication pointer fo | -| pubId | uint256 | The publication ID to fetch the publication pointer for | - -**Returns** - -| Type | Description | -| --- | --- | -| uint256 | The profile ID pointed by the given publication, if any | -| uint256 | The publication ID pointed by the given publication, if any | - -This function returns the publication pointer mapped to the given publication, if any. Pointers only exist for mirrors and comments; they indicate the publication being "mirrored" or "commented" on and should never be non-zero for posts. - -It should... - -1. Return the profile and publication IDs pointed by the given publication if the publication exists (which can both be zero, but neither should ever be zero if the other is zero) -2. Return both values as zero if the publication does not exist - -### getContentURI() - -`function getContentURI(uint256 profileId, uint256 pubId) external view returns (string memory);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the content URI for. | -| pubId | uint256 | The publication ID to fetch the content URI for | - -**Returns** - -| Type | Description | -| --- | --- | -| string | The URI mapped to the given publication, if any | - -This function returns the content URI mapped to the given publication, if any. Note that content URIs only exist for posts and comments and should always be empty for mirrors. - -It should... - -1. Return the content URI mapped to the given publication if the publication exists (which can be an empty string) -2. Return the content URI mapped to the pointed publication if the given publication is a mirror. -3. Return an empty string if the publication does not exist - -### getProfileIdByHandle() - -`function getProfileIdByHandle(string calldata handle) external view returns (uint256);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| handle | string | The handle to use to query the profile ID | - -**Returns** - -| Type | Description | -| --- | --- | -| uint256 | The profile ID of the profile with the given handle, if any | - -This function returns the profile ID of the profile mapped to a given handle, if any. - -It should... - -1. Return the profile ID of the profile mapped to the given handle. -2. Return zero if there is no profile with this handle. - -### getProfile() - -`function getProfile(uint256 profileId) external view returns (DataTypes.ProfileStruct memory);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID to query the profile struct for | - -**Returns** - -| Struct Member Name | Type | Description | -| --- | --- | --- | -| pubCount | uint256 | The publication count associated with this profile | -| followModule | address | The follow module associated with this profile, if any | -| followNFT | address | The follow NFT associated with this profile, if any | -| handle | string | The handle associated with this profile | -| imageURI | string | The URI associated with this profile's image | -| followNFTURI | string | The URI associated with this profile's follow NFT | - -This function returns the profile struct of the profile mapped to a given token ID. - -It should... - -1. Return the profile struct for a given profile if the profile exists. -2. Return an empty struct if the profile doesn't exist. - -### getPub() - -`function getPub(uint256 profileId, uint256 pubId) external view returns (DataTypes.PublicationStruct memory);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the publication struct for. | -| pubId | uint256 | The publication ID to fetch the publication struct for | - -**Returns** - -| Struct Member Name | Type | Description | -| --- | --- | --- | -| ProfileIdPointed | uint256 | The profile ID of the profile that created the publication pointed to by this publication, if any | -| PubIdPointed | uint256 | The publication ID pointed to by this publication, if any | -| contentURI | string | The content URI mapped to this publication, if any | -| referenceModule | address | The reference module mapped to this publication, if any | -| collectModule | address | The collect module mapped to this publication | -| collectNFT | address | The collect NFT mapped to this publication, if any | - -This function returns the publication struct for a given profile ID and publication ID. - -It should... - -1. Return the publication struct if the publication exists. -2. Return an empty struct if the publication does not exist. - -### getPubType() - -`function getPubType(uint256 profileId, uint256 pubId) external view returns (DataTypes.PubType);` - -| Parameter Name | Type | Description | -| --- | --- | --- | -| profileId | uint256 | The profile ID of the profile that created the publication to fetch the publication type for | - -**Returns** - -| Enum Member Name | Type | Description | -| --- | --- | --- | -| Post | enum member (technically uint8) | An indicator stating that the queried publication is a post | -| Comment | enum member (technically uint8) | An indicator stating that the queried publication is a comment | -| Mirror | enum member (technically uint8) | An indicator stating that the queried publication is a mirror | -| Nonexistant | enum member (technically uint8) | An indicator stating that the queried publication does not exist | - -This function returns the publication type for a given profile ID and publication ID. - -It should... - -1. Return one of the `PubType` enum members: `Post`, `Comment` or `Mirror` if the publication exists. -2. Return the `PubType` enum member `Nonexistant` if the publication does not exist. \ No newline at end of file diff --git a/documents/dids/authorization.md b/documents/dids/authorization.md new file mode 100644 index 0000000..0e7328b --- /dev/null +++ b/documents/dids/authorization.md @@ -0,0 +1,40 @@ +# Authorization + +Authorize and then use DIDs where needed. At the moment, Ethereum and Solana accounts +are supported. Reference the chain/network specific libraries for more info on how to +use each. Additional accounts will be supported in the future. + +Authorize with an Ethereum account using [@didtools/pkh-ethereum](https://did.js.org/docs/api/modules/pkh_ethereum): + +```js +import { DIDSession } from 'did-session' +import { EthereumWebAuth, getAccountId } from '@didtools/pkh-ethereum' + +const ethProvider = // import/get your web3 eth provider +const addresses = await ethProvider.request({ method: 'eth_requestAccounts' }) +const accountId = await getAccountId(ethProvider, addresses[0]) +const authMethod = await EthereumWebAuth.getAuthMethod(ethprovider, accountId) + +const session = await DIDSession.get(accountId, authMethod, { resources: [...]}) +``` + +Authorize with a Solana account using [@didtools/pkh-solana](https://did.js.org/docs/api/modules/pkh_solana): + +```js +import { DIDSession } from 'did-session' +import { SolanaWebAuth, getAccountIdByNetwork } from '@didtools/pkh-solana' + +const solProvider = // import/get your Solana provider (ie: window.phantom.solana) +const address = await solProvider.connect() +const accountId = getAccountIdByNetwork('mainnet', address.publicKey.toString()) +const authMethod = await SolanaWebAuth.getAuthMethod(solProvider, accountId) + +const session = await DIDSession.get(accountId, authMethod, { resources: [...]}) +``` + +With your session, use DIDs in composedb, ceramic & glaze libraries: + +```js +const ceramic = new CeramicClient() +ceramic.did = session.did +``` diff --git a/documents/dids/configuration.md b/documents/dids/configuration.md new file mode 100644 index 0000000..14a63bd --- /dev/null +++ b/documents/dids/configuration.md @@ -0,0 +1,35 @@ +# Configuration + +When creating a DID session, you need to pass an array of string identifiers for resources you want to authorize +for. In the context of the Ceramic Network, resources are an array of Model Stream Ids or Streams Ids. Typically +you will just pass resources from the `@composedb` libraries as you will already manage your Composites and Models +there. For example: + +```js +import { ComposeClient } from '@composedb/client' + +//... Reference above and `@composedb` docs for additional configuration here + +const client = new ComposeClient({ceramic, definition}) +const resources = client.resources +const session = await DIDSession.get(accountId, authMethod, { resources }) +client.setDID(session.did) +``` + +If you are still using `@glazed` libraries and tile document streams you will typically pass a wildcard resource, +this all allows 'access all'. While not ideal, there is technical limits in `@glazed` libraries and tile document +streams that make it difficult to offer more granular permission access to sets of stream. Authorization was mostly +designed with model document streams and `@composedb` libraries in mind. Wildcard resource may not be supported in +the future. + +```js +const session = await DIDSession.get(accountId, authMethod, { resources: [`ceramic://*`]}) +``` + +By default a session will expire in 1 week. You can change this time by passing the `expiresInSecs` option to +indicate how many seconds from the current time you want this session to expire. + +```js +const oneDay = 60 * 60 * 24 +const session = await DIDSession.get(accountId, authMethod, { resources: [...], expiresInSecs: oneDay }) +``` diff --git a/documents/dids/guides/add-chain-support.md b/documents/dids/guides/add-chain-support.md new file mode 100644 index 0000000..3c2bfbf --- /dev/null +++ b/documents/dids/guides/add-chain-support.md @@ -0,0 +1,57 @@ +# Add Support for a Blockchain + +The standard use of [SIWX](https://github.com/ChainAgnostic/CAIPs/pull/122), [CACAO](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-74.md) and [DID:PKH](https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md) allows anyone to implement support for another blockchain or account type to authenticate and authorize writes to the Ceramic Network. Additionally a few standard interfaces enables you to implement an auth and verification library that allows anyone to use it with [`did-session`](https://github.com/ceramicnetwork/js-did/tree/main/packages/did-session), the primary library to use DID based accounts with Ceramic. There is just a few steps you have to take, outlined below. + +### CASA Standards Support + +First make sure your blockchain has the necessary standards specification in the [Chain Agnostic Standards Alliance (CASA)](https://github.com/ChainAgnostic/CASA). CASA creates blockchain agnostic standards which support interoperability and facilitate communication between blockchain protocols, software and companies. Standards are submitted as [Chain Agnostic Improvement Proposals (CAIPs)](https://github.com/ChainAgnostic/CAIPs). Support in Ceramic requires a spec for the following CAIPs in the CASA namespace for your chain. + +1) CAIP2 - [Blockchain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) + +2) CAIP10 - [Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) + +3) CAIP122 - [Sign in With X (SIWx)](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md) + +The CASA namespaces can be found [here](https://github.com/ChainAgnostic/namespaces). If your blockchain already exists and has the prior 3 CAIPs, then you can move on to the next steps. If not, then you can define these specs yourself by following the instructions in the namespace readme and opening a PR. You can look at other blockchain namespaces for how to format and specify your specs and reference your own ecosystem standards for some if they exist already. You can reach out to the 3Box Labs team for reviews and help if needed. + +### DID:PKH Standards Support + +With accounts defined through CAIP10 you can now add standards support in DID:PKH for your blockchain. To add support simply add a test vector in the [did-pkh repo](https://github.com/w3c-ccg/did-pkh) that shows what a DID document resolution would look like for an example DID:PKH account for your blockchain. Reference other test vectors for examples and open a PR once ready. + +### CACAO Support + +[CACAO](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-74.md) is a chain-agnostic Object Capability ([OCAP](https://en.wikipedia.org/wiki/Object-capability_model)). CACAO allows us to create DID sessions by transferring the rights to write/update specific Ceramic streams from a DID:PKH (blockchain account) to a browser session key. Session keys then can sign all Ceramic writes, needing to only sign with your blockchain account once. To add support for your blockchain we need be able to translate from SIWX messages to a CACAO (and back) and describe how to sign a SIWX. The library [`@didtools/cacao`](https://github.com/ceramicnetwork/js-did/tree/main/packages/cacao) implements this. + +To add support, first implement a SIWX class specific to your blockchain, based on the CAIP122 spec defined above. The file should be added to `src/siwx/siw(name).ts` and extend `SiwxMessage`. Typically you should only have to implement the function `signMessage()` which encodes a SIWX message in the format needed to sign message payloads in your ecosystem. Reference the Solana (SIWS) and Ethereum (SIWE) implementations for example. + +Lastly in `src/cacao.ts` implement a `fromSiw(name)Message` function for your blockchain which translates a given SIWX message to a CACAO. Again reference both SIWS and SIWE for example implementations. + +Once added, open a PR. You can reach out to the 3Box Labs team for reviews and help if needed. + +### DID-Session and Ceramic Support + +To support your blockchain account as DID:PKH in Ceramic you need to be able to both sign and verify CACAOs. Signing and verifying is often specific to a chain depending on the ecosystem wallets, cryptography used and ecosystem standards. Each blockchain adds support by implementing an AuthMethod and Verifier in a blockchain specific library in the [`js-did` monorepo](https://github.com/ceramicnetwork/js-did). Reference existing chains, both Solana and Ethereum for example. + +Authmethods are the primary interface used by [`did-session`](https://github.com/ceramicnetwork/js-did/tree/main/packages/did-session). It has the following interface: + +```tsx +type AuthMethod = (opts: AuthMethodOpts) => Promise +``` + +Typically you will write a function or class that returns a configured AuthMethod and provides any specific helper functions that help a developer use your blockchain with an AuthMethod. + +Verifiers are used by Ceramic nodes to verify signed commits by a DID:PKH and CACAO. Nodes must register the verifiers needed for the blockchains and accounts they want to support. Right now most are included by default, once implemented. Verifers have the following interface. + +```tsx +export type Verifiers = Record + +export type CacaoVerifier = (cacao: Cacao, opts: VerifyOptions) => Promise +``` + +To add support you create a `@didtools/pkh-(namespace)` package in the [`js-did` monorepo](https://github.com/ceramicnetwork/js-did). Use the existing `@didtools/pkh-ethereum` and `@didtools/pkh-solana` libraries as a template to implement similar naming, functionality, documentation and testing. But primarily the library should export a `Verifier` and a function or class the gives the developer a configured `AuthMethod`. Once ready open a PR. You can reach out to the 3Box Labs team for reviews and help if needed. + +### Ready, Set, Go + +Once your library and PR are accepted, we will release them for everyone to use and add verifier support for them in Ceramic. We aim to have each maintained by their respective ecosystems when possible, as we dont have the knowledge of all details and specifications in each ecosystem to best support each and every one. If they fall out of date, or tests begin to fail, we may not be able to maintain them ourselves. + +Congrats, now everyone can auth and write to Ceramic directly with their blockchain account of your choice. diff --git a/documents/dids/guides/concepts-overview.md b/documents/dids/guides/concepts-overview.md new file mode 100644 index 0000000..08aa66f --- /dev/null +++ b/documents/dids/guides/concepts-overview.md @@ -0,0 +1,11 @@ +# Concepts overview + +Ceramic uses the [Decentralized Identifier (DID)](https://w3c.github.io/did-core/) standard for users accounts. DIDs require no central authority - users control their data and whom they share it with. + +## DID Methods + +We encourage using the `did:pkh` DID method which generates a persistent id from a wallet address’s public key hash. This enables one-click sign-on with your wallet to many apps on Ethereum, and soon on many other chains including Solana. + +## DID Sessions + +DID-Sessions is a library for providing a familiar, "web session"-like experience. Users no longer have to sign every single action they take within an app - during a timebound period of time they can authorize the app developer to act on their behalf. DID-Sessions outputs verifiable, serializable objects that store information about which DIDs authenticated them, what capabilities they are authorized with and for how long. diff --git a/documents/dids/guides/upgrading-did-session.md b/documents/dids/guides/upgrading-did-session.md new file mode 100644 index 0000000..7ebce89 --- /dev/null +++ b/documents/dids/guides/upgrading-did-session.md @@ -0,0 +1,55 @@ +--- +title: "Upgrading DID Session" +--- + +## Upgrading from `did-session@0.x.x` to `did-session@1.x.x` + +AuthProviders change to AuthMethod interfaces. Similarly you can import the auth libraries you need. How you configure and manage +these AuthMethods may differ, but each will return an AuthMethod function to be used with did-session. + +```js +// Before with v0.x.x +//... +import { EthereumAuthProvider } from '@ceramicnetwork/blockchain-utils-linking' + +const ethProvider = // import/get your web3 eth provider +const addresses = await ethProvider.request({ method: 'eth_requestAccounts' }) +const authProvider = new EthereumAuthProvider(ethProvider, addresses[0]) +const session = new DIDSession({ authProvider }) +const did = await session.authorize() + +// Now did-session@1.0.0 +... +import { EthereumWebAuth, getAccountId } from '@didtools/pkh-ethereum' + +const ethProvider = // import/get your web3 eth provider +const addresses = await ethProvider.request({ method: 'eth_requestAccounts' }) +const accountId = await getAccountId(ethProvider, addresses[0]) +const authMethod = await EthereumWebAuth.getAuthMethod(ethProvider, accountId) +const session = await DIDSession.authorize(authMethod, { resources: [...]}) +const did = session.did +``` + +# Upgrading From `@glazed/did-session` to `did-session` + +`authorize` changes to a static method which returns a did-session instance and `getDID()` becomes a `did` getter. For example: + +```js +// Before @glazed/did-session +const session = new DIDSession({ authProvider }) +const did = await session.authorize() + +// Now did-session +const session = await DIDSession.authorize(authProvider, { resources: [...]}) +const did = session.did +``` + +Requesting resources are required now when authorizing, before wildcard (access all) was the default. You can continue to use +wildcard by passing the following * below. Wildcard is typically only used with `@glazed` libraries and/or tile documents and +it is best to switch over when possible, as the wildcard option may be * deprecated in the future. When using with +composites/models you should request the minimum needed resources instead. + +```js +const session = await DIDSession.authorize(authProvider, { resources: [`ceramic://*`]}) +const did = session.did +``` diff --git a/documents/dids/guides/using-with-composedb-client.md b/documents/dids/guides/using-with-composedb-client.md new file mode 100644 index 0000000..198bb0d --- /dev/null +++ b/documents/dids/guides/using-with-composedb-client.md @@ -0,0 +1,80 @@ +# Using With ComposeDB Client + +[ComposeDB](https://composedb.js.org) is a set of TypeScript libraries and tools to interact with the [Dataverse](https://blog.ceramic.network/into-the-dataverse/) using the [Ceramic network](https://ceramic.network/). + +First, you should start with creating your instance of `ComposeClient` from `@composedb/client` package, passing it the +url to the ceramic node you want to use and the runtime composite definition of the composite you want to use in your App. + +```js +import { ComposeClient } from '@composedb/client' +import { definition } from './__generated__/definition.js' + +const compose = new ComposeClient({ ceramic: 'http://localhost:7007', definition }) +``` + +Next, you can create a DID Session, passing it the resources from your client instance. The resources are a list of model +stream IDs from your runtime composite definition: + +```js +import { DIDSession } from 'did-session' +import type { AuthMethod } from '@didtools/cacao' +import { EthereumWebAuth, getAccountId } from '@didtools/pkh-ethereum' + +const ethProvider = // import/get your web3 eth provider +const addresses = await ethProvider).request({ method: 'eth_requestAccounts' }) +const accountId = await getAccountId(ethProvider, addresses[0]) +const authMethod = await EthereumWebAuth.getAuthMethod(ethProvider, accountId) + +const loadSession = async(authMethod: AuthMethod, resources: Array):Promise => { + return DIDSession.authorize(authMethod, { resources }) +} + +const session = await loadSession(authMethod, compose.resources) +``` + +Next, you can assign the authorized did from your session to your client. + +```js +compose.setDID(session.did) + +// use the compose instance to make queries in ComposeDB graph +``` + +Before you start making mutations with the client instance, you should make sure that the session is not expired +```js +// before compose mutations, check if session is still valid, if expired, create new +if (session.isExpired) { + const session = loadSession(authMethod) + compose.setDID(session.did) +} + +// continue to make mutations +``` + +A typical pattern is to store a serialized session in local storage and load on use if available. + +:::caution Warning +LocalStorage is used for illustrative purposes here and may not be best for your app, as +there is a number of known issues with storing secret material in browser storage. The session string +allows anyone with access to that string to make writes for that user for the time and resources that +session is valid for. How that session string is stored and managed is the responsibility of the application. +::: + +```js +// An updated version of loadSession(...) +const loadSession = async(authMethod: AuthMethod, resources: Array):Promise => { + const sessionStr = localStorage.getItem('didsession') + let session + + if (sessionStr) { + session = await DIDSession.fromSession(sessionStr) + } + + if (!session || (session.hasSession && session.isExpired)) { + session = await DIDSession.authorize(authMethod, { resources }) + localStorage.setItem('didsession', session.serialize()) + } + + return session +} +``` diff --git a/documents/dids/installation.mdx b/documents/dids/installation.mdx new file mode 100644 index 0000000..a80ad77 --- /dev/null +++ b/documents/dids/installation.mdx @@ -0,0 +1,144 @@ +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +# Installation + +### did-session + +We encourage you to use `did-sessions` to manage all your DID-related needs: + + + + +```sh +pnpm add did-session +``` + + + + +```sh +npm install did-session +``` + + + + +```sh +yarn add did-session +``` + + + + +### @didtools/pkh-ethereum + +Add if you want to use did:pkh Ethereum accounts with `did-session`. + + + + +```sh +pnpm add @didtools/pkh-ethereum +``` + + + + +```sh +npm install @didtools/pkh-ethereum +``` + + + + +```sh +yarn add @didtools/pkh-ethereum +``` + + + + +### @didtools/pkh-solana + +Add if you want to use did:pkh Solana accounts with `did-session`. + + + + +```sh +pnpm add @didtools/pkh-solana +``` + + + + +```sh +npm install @didtools/pkh-solana +``` + + + + +```sh +yarn add @didtools/pkh-solana +``` + + + + +### dids + +You can also just use `dids`, if you want to manage a DID at a lower level or access additional functionality. + + + + +```sh +pnpm add dids +``` + + + + +```sh +npm install dids +``` + + + + +```sh +yarn add dids +``` + + + diff --git a/documents/dids/introduction.md b/documents/dids/introduction.md new file mode 100644 index 0000000..2fc8a8c --- /dev/null +++ b/documents/dids/introduction.md @@ -0,0 +1,3 @@ +# Welcome to Decentralized Identifiers + +A suite of tools and APIs to interact with and manage decentralized identifiers (DIDs). diff --git a/documents/dids/managing-sessions.md b/documents/dids/managing-sessions.md new file mode 100644 index 0000000..1f46469 --- /dev/null +++ b/documents/dids/managing-sessions.md @@ -0,0 +1,60 @@ +# Managing Sessions + +A session can be managed in a few different ways. All sessions consist of a session key in the form of a `did:key` and a CACAO object-capability. + +## Automatically persisted sessions + +By default (when using `DIDSession.get(...)`) sessions are persisted to [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) in the background. The private key for this session is always a [non-extractable](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey/extractable) key, which means that they key itself can't be stolen by a malicious browser extension or script. + +You can check if there already exists an authorized session for any given account using the `hasSessionFor` method. This can be useful if you want to know if the `DIDSession.get` call with result in a wallet interaction from the user, which will happen if `hasSessionFor` returns `false`. + +```js +if (await DIDSession.hasSessionFor(accountId, resources: [...])) { + console.log(`There is an active session for ${accountId}`) +} +``` + +### Removing a persisted session + +If you want to remove a persisted session that was created using `DIDSession.get(...)`, you can use the static function `remove`. This will permanently remove the persisted session for a given account, and the user would need to reauthenticate in order to establish a new session. + +```js +await DIDSession.remove(accountId) +``` + + +### Session lifecycle management + +Additional helper fields are available on DIDSession instances. They can help you manage a session lifecycle and the user experience. For example, if a session has expired you might want to show a message to the user before you ask them for a new session. + +```js +// Check if authorized or created from existing session string +didsession.hasSession + +// Check if session expired +didsession.isExpired + +// Get resources session is authorized for +didsession.authorizations + +// Check number of seconds till expiration, may want to re auth user at a time before expiration +didsession.expiresInSecs +``` + + +## Manual session management + +If you don't want to rely on browsers non-extractable keys, or you are not in a browser environment you can use the `DIDSession.authorize(...)` function. This function creates a session that can be serialized to a string. You can store this for later and then re-initialize. Currently sessions are valid +for 1 week by default. + +```js +// Create session as above, store for later +const session = await DIDSession.authorize(authMethod, { resources: [...]}) +const sessionString = session.serialize() + +// write/save session string where you want (e.g. filesystem) +// ... + +// Later re initialize session +const session2 = await DIDSession.fromSession(sessionString) +``` diff --git a/lib/litUtils.ts b/lib/litUtils.ts new file mode 100644 index 0000000..465425e --- /dev/null +++ b/lib/litUtils.ts @@ -0,0 +1,160 @@ +import * as LitJsSdk from "@lit-protocol/lit-node-client"; +import { Wallet } from "ethers"; +import { + LitAccessControlConditionResource, + createSiweMessageWithRecaps, + generateAuthSig, + LitAbility, +} from "@lit-protocol/auth-helpers"; + +const accessControlConditions = [ + { + contractAddress: "", + standardContractType: "", + chain: "ethereum", + method: "eth_getBalance", + parameters: [":userAddress", "latest"], + returnValueTest: { + comparator: ">=", + value: "1000000000000", // 0.000001 ETH + }, + }, +]; + +const chain = "ethereum"; + +export class Lit { + litNodeClient; + chain; + + constructor() { + this.chain = chain; + this.litNodeClient = new LitJsSdk.LitNodeClientNodeJs({ + alertWhenUnauthorized: false, + litNetwork: "datil-dev", + debug: true, + }); + } + + async connect() { + return await this.litNodeClient.connect(); + } + async disconnect() { + return await this.litNodeClient.disconnect(); + } + async encrypt(message) { + await this.connect(); + // Encrypt the message + const { ciphertext, dataToEncryptHash } = await LitJsSdk.encryptString( + { + accessControlConditions, + dataToEncrypt: message, + }, + this.litNodeClient + ); + await this.disconnect(); + + // Return the ciphertext and dataToEncryptHash + return { + ciphertext, + dataToEncryptHash, + }; + } + + async decrypt(ciphertext, dataToEncryptHash) { + // Get the session signatures + await this.connect(); + const sessionSigs = await this.getSessionSignatures(); + + // Decrypt the message + const decryptedString = await LitJsSdk.decryptToString( + { + accessControlConditions, + chain: this.chain, + ciphertext, + dataToEncryptHash, + sessionSigs, + }, + this.litNodeClient + ); + + await this.disconnect(); + // Return the decrypted string + return decryptedString; + } + + async getDelegationAuthSig() { + try { + const wallet = new Wallet(process.env.ETHEREUM_PRIVATE_KEY); + const { capacityDelegationAuthSig } = + await this.litNodeClient.createCapacityDelegationAuthSig({ + dAppOwnerWallet: wallet, + uses: "1", + signer: wallet, + capacityTokenId: process.env.LIT_TOKEN_ID, + }); + return capacityDelegationAuthSig; + } catch (error) { + console.error("Error connecting to LitContracts:", error); + } + } + async getSessionSignatures() { + // Connect to the wallet + const ethWallet = new Wallet(process.env.ETHEREUM_PRIVATE_KEY); + + // Get the latest blockhash + const latestBlockhash = await this.litNodeClient.getLatestBlockhash(); + + // Define the authNeededCallback function + const authNeededCallback = async (params) => { + if (!params.uri) { + throw new Error("uri is required"); + } + if (!params.expiration) { + throw new Error("expiration is required"); + } + + if (!params.resourceAbilityRequests) { + throw new Error("resourceAbilityRequests is required"); + } + + // Create the SIWE message + const toSign = await createSiweMessageWithRecaps({ + uri: params.uri, + expiration: params.expiration, + resources: params.resourceAbilityRequests, + walletAddress: ethWallet.address, + nonce: latestBlockhash, + litNodeClient: this.litNodeClient, + }); + + // Generate the authSig + const authSig = await generateAuthSig({ + signer: ethWallet, + toSign, + }); + + return authSig; + }; + + // Define the Lit resource + const litResource = new LitAccessControlConditionResource("*"); + + // Get the delegation auth sig + const capacityDelegationAuthSig = await this.getDelegationAuthSig(); + + // Get the session signatures + const sessionSigs = await this.litNodeClient.getSessionSigs({ + chain: this.chain, + resourceAbilityRequests: [ + { + resource: litResource, + ability: LitAbility.AccessControlConditionDecryption, + }, + ], + authNeededCallback, + capacityDelegationAuthSig, + }); + return sessionSigs; + } +} diff --git a/next.config.cjs b/next.config.cjs new file mode 100644 index 0000000..295898b --- /dev/null +++ b/next.config.cjs @@ -0,0 +1,10 @@ + + +/** @type {import('next').NextConfig} */ +const nextConfig = { + transpilePackages: [ + "@lit-protocol/bls-sdk", + ], +}; + +export default nextConfig; diff --git a/next.config.js b/next.config.js deleted file mode 100644 index 767719f..0000000 --- a/next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {} - -module.exports = nextConfig diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index ce53d61..0000000 --- a/package-lock.json +++ /dev/null @@ -1,4263 +0,0 @@ -{ - "name": "langchain-pinecone", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "langchain-pinecone", - "version": "0.1.0", - "dependencies": { - "@types/node": "20.2.5", - "@types/react": "18.2.7", - "@types/react-dom": "18.2.4", - "autoprefixer": "10.4.14", - "eslint": "8.41.0", - "eslint-config-next": "13.4.4", - "next": "13.4.4", - "postcss": "8.4.23", - "react": "18.2.0", - "react-dom": "18.2.0", - "tailwindcss": "3.3.2", - "typescript": "5.0.4" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/runtime": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", - "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@next/env": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.4.tgz", - "integrity": "sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.4.tgz", - "integrity": "sha512-5jnh7q6I15efnjR/rR+/TGTc9hn53g3JTbEjAMjmeQiExKqEUgIXqrHI5zlTNlNyzCPkBB860/ctxXheZaF2Vw==", - "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", - "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", - "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", - "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", - "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz", - "integrity": "sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz", - "integrity": "sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", - "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", - "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", - "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.1.tgz", - "integrity": "sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==", - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.2.12", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz", - "integrity": "sha512-IthPJsJR85GhOkp3Hvp8zFOPK5ynKn6STyHa/WZpioK7E1aYDiBzpqQPrngc14DszIUkIrdd3k9Iu0XSzlP/1w==" - }, - "node_modules/@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" - }, - "node_modules/@types/react": { - "version": "18.2.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.7.tgz", - "integrity": "sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.2.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz", - "integrity": "sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", - "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", - "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", - "dependencies": { - "@typescript-eslint/types": "5.59.7", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001489", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", - "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-equal": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", - "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.0", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.411.tgz", - "integrity": "sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/enhanced-resolve": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.4.tgz", - "integrity": "sha512-z/PMbm6L0iC/fwISULxe8IVy4DtNqZk2wQY711o35klenq70O6ns82A8yuMVCFjHC0DIyB2lyugesRtuk9u8dQ==", - "dependencies": { - "@next/eslint-plugin-next": "13.4.4", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.42.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", - "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "get-tsconfig": "^4.5.0", - "globby": "^13.1.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "synckit": "^0.8.5" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", - "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/jiti": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/next": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.4.tgz", - "integrity": "sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA==", - "dependencies": { - "@next/env": "13.4.4", - "@swc/helpers": "0.5.1", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.1.1", - "zod": "3.21.4" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=16.8.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.4", - "@next/swc-darwin-x64": "13.4.4", - "@next/swc-linux-arm64-gnu": "13.4.4", - "@next/swc-linux-arm64-musl": "13.4.4", - "@next/swc-linux-x64-gnu": "13.4.4", - "@next/swc-linux-x64-musl": "13.4.4", - "@next/swc-win32-arm64-msvc": "13.4.4", - "@next/swc-win32-ia32-msvc": "13.4.4", - "@next/swc-win32-x64-msvc": "13.4.4" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "fibers": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tailwindcss": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", - "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/package.json b/package.json index 1e40a5e..7677bec 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,37 @@ { - "name": "langchain-pinecone", + "name": "orbis-lit-langchain", "version": "0.1.0", "private": true, "scripts": { + "gen-seed": "node ./scripts/seed.mjs", + "deploy-model": "node ./scripts/deploy-model.mjs", "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { - "@pinecone-database/pinecone": "^0.1.6", + "@lit-protocol/bls-sdk": "^6.11.3", + "@lit-protocol/contracts-sdk": "^7.0.2", + "@lit-protocol/lit-node-client": "^6.11.3", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-slot": "^1.0.2", "@types/node": "20.2.5", "@types/react": "18.2.7", "@types/react-dom": "18.2.4", + "dids": "^4.0.4", + "@useorbis/db-sdk": "0.0.60-alpha", "autoprefixer": "10.4.14", + "axios": "^1.7.9", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "eslint": "8.41.0", "eslint-config-next": "13.4.4", + "ethers": "^6.13.4", "langchain": "^0.0.84", - "next": "13.4.4", + "next": "14.2.4", "pdf-parse": "^1.1.1", + "pino-pretty": "^13.0.0", "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", @@ -30,5 +39,10 @@ "tailwindcss": "3.3.2", "tailwindcss-animate": "^1.0.7", "typescript": "5.0.4" + }, + "devDependencies": { + "key-did-provider-ed25519": "^3.0.2", + "uint8arrays": "^4.0.2", + "key-did-resolver": "^3.0.0" } } diff --git a/scripts/deploy-model.mjs b/scripts/deploy-model.mjs new file mode 100644 index 0000000..1041629 --- /dev/null +++ b/scripts/deploy-model.mjs @@ -0,0 +1,55 @@ +import { OrbisDB } from "@useorbis/db-sdk"; +import { OrbisKeyDidAuth } from "@useorbis/db-sdk/auth"; + +const db = new OrbisDB({ + ceramic: { + gateway: "https://ceramic-orbisdb-mainnet-direct.hirenodes.io/", + }, + nodes: [ + { + gateway: "http://localhost:7008", + }, + ], +}); + +const embeddingModel = { + version: "2.0", + name: "EmbeddingModel", + description: "Embedding model", + accountRelation: { type: "list" }, + interface: false, + implements: [], + schema: { + type: "object", + properties: { + embedding: { + type: "array", + items: { + type: "number", + }, + }, + content: { + type: "string", + }, + contenthash: { + type: "string", + }, + }, + additionalProperties: false, + }, +}; + +const run = async () => { + const seed = await OrbisKeyDidAuth.generateSeed(); + + // Initiate the authenticator using the generated (or persisted) seed + const auth = await OrbisKeyDidAuth.fromSeed(seed); + + // Authenticate the user + await db.connectUser({ auth }); + const model = await db.ceramic.createModel(embeddingModel); + console.log({ + model, + }); +}; +run(); diff --git a/scripts/seed.mjs b/scripts/seed.mjs new file mode 100644 index 0000000..95a8d68 --- /dev/null +++ b/scripts/seed.mjs @@ -0,0 +1,9 @@ +import { OrbisKeyDidAuth } from "@useorbis/db-sdk/auth"; + +const run = async () => { + const seed = OrbisKeyDidAuth.generateSeed(); + console.log({ + seed + }) +} +run(); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index ca20633..1c93dc7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,22 @@ { "compilerOptions": { - "target": "es5", + "moduleResolution": "bundler", // Explicitly set to "bundler" + "strict": false, + "target": "ES2022", + "module": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, + "checkJs": true, "skipLibCheck": true, - "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noImplicitAny": false, "jsx": "preserve", "incremental": true, + "baseUrl": ".", + "noImplicitAny": false, "plugins": [ { "name": "next" diff --git a/utils.ts b/utils.ts index dfd4be6..061a738 100644 --- a/utils.ts +++ b/utils.ts @@ -1,94 +1,97 @@ -import { OpenAIEmbeddings } from 'langchain/embeddings/openai' -import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter' -import { OpenAI } from 'langchain/llms/openai' -import { loadQAStuffChain } from 'langchain/chains' -import { Document } from 'langchain/document' -import { timeout } from './config' - -export const queryPineconeVectorStoreAndQueryLLM = async ( - client, - indexName, - question -) => { - // 1. Start query process - console.log('Querying Pinecone vector store...'); - // 2. Retrieve the Pinecone index - const index = client.Index(indexName); - // 3. Create query embedding - const queryEmbedding = await new OpenAIEmbeddings().embedQuery(question) - // 4. Query Pinecone index and return top 10 matches - let queryResponse = await index.query({ - queryRequest: { - topK: 10, - vector: queryEmbedding, - includeMetadata: true, - includeValues: true, - }, - }); - // 5. Log the number of matches - console.log(`Found ${queryResponse.matches.length} matches...`); - // 6. Log the question being asked - console.log(`Asking question: ${question}...`); - if (queryResponse.matches.length) { - // 7. Create an OpenAI instance and load the QAStuffChain - const llm = new OpenAI({}); - const chain = loadQAStuffChain(llm); - // 8. Extract and concatenate page content from matched documents - const concatenatedPageContent = queryResponse.matches - .map((match) => match.metadata.pageContent) - .join(" "); - // 9. Execute the chain with input documents and question - const result = await chain.call({ - input_documents: [new Document({ pageContent: concatenatedPageContent })], - question: question, - }); - // 10. Log the answer - console.log(`Answer: ${result.text}`); - return result.text +import { OpenAIEmbeddings } from "langchain/embeddings/openai"; +import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; +import { OrbisDB } from "@useorbis/db-sdk"; +import { OrbisKeyDidAuth } from "@useorbis/db-sdk/auth"; +import crypto from "crypto"; +import axios from "axios"; +import { Lit } from "@/lib/litUtils"; + +export const queryLLM = async (question, context) => { + if (context.rows.length) { + const decryptedRows = await Promise.all( + context.rows.map(async (row) => { + const lit = new Lit(); + const { ciphertext, dataToEncryptHash } = JSON.parse(row.content); + const decryptedContent = await lit.decrypt( + ciphertext, + dataToEncryptHash + ); + return decryptedContent; + }) + ); + + // Concatenate the decrypted rows into a single string + const concatenatedContext = decryptedRows.join(" "); + + // Prepare prompt + const prompt = ` + Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know. Don't make up an answer. + + Context: + ${concatenatedContext} + + Question: ${question} + + Helpful Answer:`; + + // Send request to OpenAI API + const response = await axios.post( + "https://api.openai.com/v1/chat/completions", + { + model: "gpt-3.5-turbo", // or "gpt-4" based on your API key's availability + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: prompt }, + ], + max_tokens: 1000, // Adjust based on your needs + temperature: 0.7, // Adjust for creativity vs. determinism + }, + { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, + }, + } + ); + + if (response.status !== 200) { + // Log the full response object if the request failed + console.error("Error response from API:", response); + throw new Error(`HTTP error! status: ${response.status}`); + } + + // Log the raw response text for debugging + const text = response.data; + + console.log("API response:", text.choices[0].message.content); + + return text.choices[0].message.content; } else { // 11. Log that there are no matches, so GPT-3 will not be queried - console.log('Since there are no matches, GPT-3 will not be queried.'); + console.log("Since there are no matches, GPT-3 will not be queried."); } }; -export const createPineconeIndex = async ( - client, - indexName, - vectorDimension -) => { - // 1. Initiate index existence check - console.log(`Checking "${indexName}"...`); - // 2. Get list of existing indexes - const existingIndexes = await client.listIndexes(); - // 3. If index doesn't exist, create it - if (!existingIndexes.includes(indexName)) { - // 4. Log index creation initiation - console.log(`Creating "${indexName}"...`); - // 5. Create index - await client.createIndex({ - createRequest: { - name: indexName, - dimension: vectorDimension, - metric: 'cosine', + +export const updateOrbis = async (docs, context, table) => { + const lit = new Lit(); + + const db = new OrbisDB({ + ceramic: { + gateway: "https://ceramic-orbisdb-mainnet-direct.hirenodes.io/", + }, + nodes: [ + { + gateway: "http://localhost:7008", }, - }); - // 6. Log successful creation - console.log(`Creating index.... please wait for it to finish initializing.`); - // 7. Wait for index initialization - await new Promise((resolve) => setTimeout(resolve, timeout)); - } else { - // 8. Log if index already exists - console.log(`"${indexName}" already exists.`); - } -}; + ], + }); + const seed = new Uint8Array(JSON.parse(process.env.ORBIS_SEED)); + // Initiate the authenticator using the generated (or persisted) seed + const auth = await OrbisKeyDidAuth.fromSeed(seed); + // Authenticate the user + await db.connectUser({ auth }); -export const updatePinecone = async (client, indexName, docs) => { - console.log('Retrieving Pinecone index...'); - // 1. Retrieve Pinecone index - const index = client.Index(indexName); - // 2. Log the retrieved index name - console.log(`Pinecone index retrieved: ${indexName}`); - // 3. Process each document in the docs array for (const doc of docs) { console.log(`Processing document: ${doc.metadata.source}`); const txtPath = doc.metadata.source; @@ -97,7 +100,7 @@ export const updatePinecone = async (client, indexName, docs) => { const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, }); - console.log('Splitting text into chunks...'); + console.log("Splitting text into chunks..."); // 5. Split text into chunks (documents) const chunks = await textSplitter.createDocuments([text]); console.log(`Text split into ${chunks.length} chunks`); @@ -108,13 +111,11 @@ export const updatePinecone = async (client, indexName, docs) => { const embeddingsArrays = await new OpenAIEmbeddings().embedDocuments( chunks.map((chunk) => chunk.pageContent.replace(/\n/g, " ")) ); - console.log('Finished embedding documents'); + console.log("Finished embedding documents"); console.log( `Creating ${chunks.length} vectors array with id, values, and metadata...` ); // 7. Create and upsert vectors in batches of 100 - const batchSize = 100; - let batch:any = []; for (let idx = 0; idx < chunks.length; idx++) { const chunk = chunks[idx]; const vector = { @@ -127,19 +128,44 @@ export const updatePinecone = async (client, indexName, docs) => { txtPath: txtPath, }, }; - batch = [...batch, vector] - // When batch is full or it's the last item, upsert the vectors - if (batch.length === batchSize || idx === chunks.length - 1) { - await index.upsert({ - upsertRequest: { - vectors: batch, - }, - }); - // Empty the batch - batch = []; + function generateHash(content) { + return crypto.createHash("sha256").update(content).digest("hex"); + } + + const encryptedContent = await lit.encrypt(vector.metadata.pageContent); + const encryptedStringified = JSON.stringify(encryptedContent); + + // wait one second + await new Promise((resolve) => setTimeout(resolve, 1000)); + // first check if the vector already exists + const query = `SELECT * FROM ${table} WHERE contenthash = '${generateHash( + encryptedStringified + )}'`; + const res = await db.select().raw(query).run(); + if (res.rows.length) { + console.log("Vector already exists, updating..."); + const result = await db + .update(`${res?.rows[0].stream_id}`) + .set({ + embedding: vector.values, + content: encryptedStringified, + }) + .run(); + console.log(result); + } else { + const createQuery = await db + .insert(table) + .value({ + embedding: vector.values, + content: encryptedStringified, + contenthash: generateHash(encryptedStringified), + }) + .context(context) + .run(); + console.log(createQuery); } } // 8. Log the number of vectors updated - console.log(`Pinecone index updated with ${chunks.length} vectors`); + console.log(`Orbis index updated with ${chunks.length} vectors`); } -}; \ No newline at end of file +}; diff --git a/yarn.lock b/yarn.lock index b07c14a..30193df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,16 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + "@alloc/quick-lru@^5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" @@ -29,6 +39,395 @@ dependencies: regenerator-runtime "^0.13.11" +"@ceramicnetwork/codecs@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/codecs/-/codecs-2.4.1.tgz#345ea2857915191d563abe7b9b165075b289f644" + integrity sha512-QhdUHp7PJm+qL05f6ovlUe7K85urBt3V7JKQrmq33jCYt4YlVT2bTyUdsrgcyA+IJZnXP1KEWuSdcpE1V3Qe/A== + dependencies: + "@ceramicnetwork/streamid" "^3.4.1" + cartonne "^3.0.1" + codeco "^1.1.0" + dag-jose "^4.0.0" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + +"@ceramicnetwork/codecs@^4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/codecs/-/codecs-4.15.0.tgz#b937cad2dc8cc73afbae4d1280c028371952390b" + integrity sha512-BsFRPoVCVPUHGoMOfL+KWq2D8HFxiyUqphq9KQMiiTTsDTEiHOLgJ6x1YEMP0A10ZschTbc1wCaQbUxlz5w5Qg== + dependencies: + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + cartonne "^3.0.1" + codeco "^1.1.0" + dag-jose "^4.0.0" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + +"@ceramicnetwork/common@^3.4.1": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/common/-/common-3.4.1.tgz#47f24157742fbfb9a9137a585818fa5dc29e74ca" + integrity sha512-SVtPG6tkaDF77iM2mweXV+JSgZa3tKvuku0TIrA+pZswa1EHtnRHssSilaj4q91JNaTy2Gsk86oK6MuQp9+LKg== + dependencies: + "@ceramicnetwork/codecs" "^2.4.1" + "@ceramicnetwork/streamid" "^3.4.1" + "@didtools/cacao" "^3.0.0" + "@didtools/pkh-ethereum" "^0.2.0" + "@didtools/pkh-solana" "^0.2.0" + "@didtools/pkh-stacks" "^0.2.0" + "@didtools/pkh-tezos" "^0.3.0" + "@stablelib/random" "^1.0.1" + caip "~1.1.0" + flat "^5.0.2" + it-first "^3.0.4" + jet-logger "1.2.2" + lodash.clonedeep "^4.5.0" + logfmt "^1.3.2" + multiformats "^13.0.0" + rxjs "^7.8.1" + uint8arrays "^5.0.1" + +"@ceramicnetwork/common@^5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/common/-/common-5.15.0.tgz#f7b7e5179cf47cf39853ac14ab0354683fc51e54" + integrity sha512-yseYMFT36Ty9FAUuYv5yqygQ4H1jGGfxcjKEYSNDBwczMjVKYsPm77/txzpFDDjOWiVM4hHlM15bPiRVXW4L4w== + dependencies: + "@ceramicnetwork/node-metrics" "^1.0.3" + "@ceramicnetwork/streamid" "^5.4.0" + "@didtools/cacao" "^3.0.0" + "@didtools/key-webauthn" "^2.0.2" + "@didtools/pkh-ethereum" "^0.2.0" + "@didtools/pkh-solana" "^0.2.0" + "@didtools/pkh-stacks" "^0.2.0" + "@didtools/pkh-tezos" "^0.3.0" + "@ipld/dag-cbor" "^9.1.0" + "@stablelib/random" "^1.0.1" + caip "~1.1.0" + flat "^5.0.2" + it-first "^3.0.4" + jet-logger "1.2.2" + lodash.clonedeep "^4.5.0" + logfmt "^1.3.2" + multiformats "^13.0.0" + rxjs "^7.8.1" + uint8arrays "^5.0.1" + +"@ceramicnetwork/http-client@^5.16.0": + version "5.16.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/http-client/-/http-client-5.16.0.tgz#a4d7ccd9bc2644e321a810ce4563af3eb1c4b8cc" + integrity sha512-5oUim/t/nxzSXRJdEAhVtm+1ymCXOg5skVgzgR6BC8wkXE/qIorHBxLyWSo00F0Q7T0Z5HsqmQpexcw/ThIGnA== + dependencies: + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/stream-caip10-link" "^5.15.0" + "@ceramicnetwork/stream-model" "^4.15.0" + "@ceramicnetwork/stream-model-instance" "^4.16.0" + "@ceramicnetwork/stream-tile" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + "@scarf/scarf" "^1.1.1" + query-string "^7.1.0" + rxjs "^7.8.1" + +"@ceramicnetwork/node-metrics@^1.0.3": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/node-metrics/-/node-metrics-1.0.5.tgz#f7b53282f5a69b3587fd8703661e7c619c93273c" + integrity sha512-2PcMKitsE+J+uOfVk25RtZliZoQAE26qCAadQsUqTSCQn1QZOnrMXpexWtNnzyxW0jVKtmQ6/05qYPkYZ5jl3w== + dependencies: + "@ceramicnetwork/stream-model-instance" "^2.3.0" + "@ceramicnetwork/streamid" "^3.3.0" + dids "^5.0.2" + fs "0.0.1-security" + key-did-provider-ed25519 "^3.0.2" + key-did-resolver "^4.0.0" + uint8arrays "^5.0.1" + +"@ceramicnetwork/stream-caip10-link@^5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/stream-caip10-link/-/stream-caip10-link-5.15.0.tgz#52991955f625737043216fa2e6f665f5fe1e6a63" + integrity sha512-txZQvb3NHcvpikzMUCPjUdBtQmKrbm859nCaGCafNo1nJkM3yLRA1h0ZvRSYT516PXC6COut4DKnPNJMeM68fw== + dependencies: + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + caip "~1.1.0" + did-resolver "^4.0.1" + lodash.clonedeep "^4.5.0" + +"@ceramicnetwork/stream-model-instance@^2.3.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/stream-model-instance/-/stream-model-instance-2.4.1.tgz#d680d926cb90719f30c0e8c2cb29c336cd77a900" + integrity sha512-vp+oY27BFM64pXN2l4riwK3/3rN1DCEZe/iBrWWJ79SC99S9jFsSnx2TB0RLkBF+n87IsWi+t1WA+FR1KNIe/Q== + dependencies: + "@ceramicnetwork/common" "^3.4.1" + "@ceramicnetwork/streamid" "^3.4.1" + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/random" "^1.0.1" + fast-json-patch "^3.1.0" + object-sizeof "^2.6.1" + uint8arrays "^5.0.1" + +"@ceramicnetwork/stream-model-instance@^4.15.0", "@ceramicnetwork/stream-model-instance@^4.16.0": + version "4.16.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/stream-model-instance/-/stream-model-instance-4.16.0.tgz#7646c8fd6cbaed991646fc094fa603f8504882b4" + integrity sha512-kq0Uv3/oAikj1ZHNYZzhVtEPhSpf6JXoIiCF60h1X7IqEc5/Fb6EarLyhuETFCVa+xFqhAsJpahtPW0YR5tJ+w== + dependencies: + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/random" "^1.0.1" + fast-json-patch "^3.1.0" + object-sizeof "^2.6.1" + uint8arrays "^5.0.1" + +"@ceramicnetwork/stream-model@^4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/stream-model/-/stream-model-4.15.0.tgz#6a8f7c5a20e21bb599c95174537ac8c49692b914" + integrity sha512-lUeoTfKHLARYiz9KNxYJaZUgy6KlkJL8oXpDgkE65sZIzGl0zXedtmLmiS8xKwgjYQwUMsAOmW8v4D4HSztAvg== + dependencies: + "@ceramicnetwork/codecs" "^4.15.0" + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/random" "^1.0.1" + ajv "^8.8.2" + ajv-formats "^2.1.1" + codeco "^1.1.0" + fast-json-patch "^3.1.0" + json-schema-typed "^8.0.1" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + +"@ceramicnetwork/stream-tile@^5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/stream-tile/-/stream-tile-5.15.0.tgz#dffcf82e958ae7f5cd1472501323bf248c164169" + integrity sha512-BzHIhfQfCXdGGSykoeKpxEhJ811BZWCYOHR98UXAguzQdPbMR1uXLoxnu08bMMrcSd8KhO1BZ3kl2BWC5gbqkA== + dependencies: + "@ceramicnetwork/common" "^5.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/random" "^1.0.1" + dids "^5.0.0" + fast-json-patch "^3.1.0" + lodash.clonedeep "^4.5.0" + uint8arrays "^5.0.1" + +"@ceramicnetwork/streamid@^3.3.0", "@ceramicnetwork/streamid@^3.4.1": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/streamid/-/streamid-3.4.1.tgz#41e44cc9e3ac0603dfd6666f1dae07ac3cf2d837" + integrity sha512-m6uZjcdMdwzyO6TIVTJF4IJYjuceflmYDrlRxDcXrZySBNNKnL40tSHbzpcTfOy5YcIsTqJFxqUZQrFrC0mlDA== + dependencies: + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/sha256" "^1.0.1" + cborg "^1.10.2" + mapmoize "^1.2.1" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + varint "^6.0.0" + +"@ceramicnetwork/streamid@^5.4.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ceramicnetwork/streamid/-/streamid-5.6.0.tgz#5120ca2076bda264415734b7266622c1b43f9460" + integrity sha512-at9lTm993U1K3yzZ2cuQUPQ26d+Ws0OlrfVyvnrAgalRmmqjdOew9pH8U51TWN/ZdLwcDwo8duXdipeisaQHdw== + dependencies: + "@ipld/dag-cbor" "^7.0.0" + "@stablelib/sha256" "^1.0.1" + cborg "^4.0.8" + mapmoize "^1.2.1" + multiformats "~13.1.3" + uint8arrays "^5.0.1" + varint "^6.0.0" + +"@cosmjs/amino@0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.30.1.tgz#7c18c14627361ba6c88e3495700ceea1f76baace" + integrity sha512-yNHnzmvAlkETDYIpeCTdVqgvrdt1qgkOXwuRVi8s27UKI5hfqyE9fJ/fuunXE6ZZPnKkjIecDznmuUOMrMvw4w== + dependencies: + "@cosmjs/crypto" "^0.30.1" + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + +"@cosmjs/crypto@0.30.1", "@cosmjs/crypto@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.30.1.tgz#21e94d5ca8f8ded16eee1389d2639cb5c43c3eb5" + integrity sha512-rAljUlake3MSXs9xAm87mu34GfBLN0h/1uPPV6jEwClWjNkAMotzjC0ab9MARy5FFAvYHL3lWb57bhkbt2GtzQ== + dependencies: + "@cosmjs/encoding" "^0.30.1" + "@cosmjs/math" "^0.30.1" + "@cosmjs/utils" "^0.30.1" + "@noble/hashes" "^1" + bn.js "^5.2.0" + elliptic "^6.5.4" + libsodium-wrappers "^0.7.6" + +"@cosmjs/encoding@0.30.1", "@cosmjs/encoding@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.30.1.tgz#b5c4e0ef7ceb1f2753688eb96400ed70f35c6058" + integrity sha512-rXmrTbgqwihORwJ3xYhIgQFfMSrwLu1s43RIK9I8EBudPx3KmnmyAKzMOVsRDo9edLFNuZ9GIvysUCwQfq3WlQ== + dependencies: + base64-js "^1.3.0" + bech32 "^1.1.4" + readonly-date "^1.0.0" + +"@cosmjs/math@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.30.1.tgz#8b816ef4de5d3afa66cb9fdfb5df2357a7845b8a" + integrity sha512-yaoeI23pin9ZiPHIisa6qqLngfnBR/25tSaWpkTm8Cy10MX70UF5oN4+/t1heLaM6SSmRrhk3psRkV4+7mH51Q== + dependencies: + bn.js "^5.2.0" + +"@cosmjs/utils@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.30.1.tgz#6d92582341be3c2ec8d82090253cfa4b7f959edb" + integrity sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g== + +"@didtools/cacao@3.0.1", "@didtools/cacao@^3.0.0", "@didtools/cacao@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@didtools/cacao/-/cacao-3.0.1.tgz#4a705b583bde6d3a85bec33622d03ed1acfcb2b9" + integrity sha512-vV1JirxqVsBf2dqdvoS/msNN8fabvMfseZB0kf1FG8TbosrHd81+hgDOlQMZit7zJbTk5g3CGkZg3b7iYKkynw== + dependencies: + "@didtools/codecs" "^3.0.0" + "@didtools/siwx" "2.0.0" + "@ipld/dag-cbor" "^9.0.7" + caip "^1.1.0" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + viem "^1.21.4" + +"@didtools/cacao@^2.0.0", "@didtools/cacao@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@didtools/cacao/-/cacao-2.1.0.tgz#5ce7bbae0abf6cce0631b8e5df657052065b9d40" + integrity sha512-35gopj+mOmAlA3nHoHiYMvNMXJtbJDJnVpIlCf/Wf/+/x+uG9aIQefXfF35D6JuaTCZ0apabjpT2umL5h3EXcw== + dependencies: + "@didtools/codecs" "^1.0.1" + "@didtools/siwx" "1.0.0" + "@ipld/dag-cbor" "^9.0.1" + caip "^1.1.0" + multiformats "^11.0.2" + uint8arrays "^4.0.3" + +"@didtools/codecs@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@didtools/codecs/-/codecs-1.0.1.tgz#2f0372e618ffb563c1b56279f1f5e79f59a2d48b" + integrity sha512-6PYXOCX7mwVWUcudKQ3eW5LtI8v5esozazbf2q2F01PE+LoeEvTytvgU9FEspj4pATpq3hPx1eenX2uLirDJ8w== + dependencies: + codeco "^1.1.0" + multiformats "^11.0.1" + uint8arrays "^4.0.3" + +"@didtools/codecs@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@didtools/codecs/-/codecs-3.0.0.tgz#860e74e7762f8d1cb630d3ceb87a4e728455e797" + integrity sha512-TemoVySZrs1XflMtOkwVTATtZEs42Mh2yk9SoYvBXES6Mz30PBJCm8v7U/2y1N5lrjb2cAPWs48Ryc7paetSxQ== + dependencies: + codeco "^1.2.0" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + +"@didtools/key-webauthn@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@didtools/key-webauthn/-/key-webauthn-2.0.2.tgz#37d36d8a6015610a4d3ab9ccec9d86c42ea4a7c5" + integrity sha512-MkOqAiRBcRO64PMVfSFAB0SUIJMk+L8QyymE9dknjmfSKgD/ZKz7cw4pFV6IUNin75/DLrlDSfmCIIjYokivvQ== + dependencies: + "@didtools/cacao" "3.0.1" + "@ipld/dag-cbor" "^9.0.6" + "@noble/curves" "^1.2.0" + caip "^1.1.0" + cborg "^4.0.5" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + varint "^6.0.0" + +"@didtools/key-webcrypto@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@didtools/key-webcrypto/-/key-webcrypto-0.1.2.tgz#8a9da10367ace17c1616a297577b40137c15f97e" + integrity sha512-ZDlwl2TnITDA6R/FpZVh3YbgRIIaJ9rCzA49wUd/EYlK0CGD8d6HQSB9hMdX0ht+paRE+9AD/YNewkppktEUKQ== + dependencies: + fast-json-stable-stringify "^2.1.0" + rpc-utils "^0.6.2" + uint8arrays "^4.0.9" + varint "^6.0.0" + +"@didtools/pkh-ethereum@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@didtools/pkh-ethereum/-/pkh-ethereum-0.2.1.tgz#8c03a56f34c824fa83db6161362f7fa45dd2b5e9" + integrity sha512-apQefbOqqy8HQMDNVG0ITxHLr9I5iZrjADX+mPB+ie1ue8MO8pOHMifLQ3j0R6RjS2einCd+hEZ4Ib4AKs3Xlw== + dependencies: + "@didtools/cacao" "^2.0.0" + "@ethersproject/wallet" "^5.7.0" + "@stablelib/random" "^1.0.2" + caip "^1.1.0" + +"@didtools/pkh-ethereum@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@didtools/pkh-ethereum/-/pkh-ethereum-0.4.1.tgz#b03472bf0196d2ece6a64d5f01aa96c866cdccb7" + integrity sha512-oE5bbyTauJ/WddaWnDK7bWns2E2LG4Ut33ICEcEQdlMoXM0902/vnGm8+6QE/yuLOyAllgf7DnDKvERF5IY6uQ== + dependencies: + "@didtools/cacao" "^2.1.0" + "@noble/curves" "^1.1.0" + "@noble/hashes" "^1.3.1" + "@stablelib/random" "^1.0.2" + caip "^1.1.0" + +"@didtools/pkh-ethereum@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@didtools/pkh-ethereum/-/pkh-ethereum-0.6.0.tgz#7322e50f03dac300da08b0e511c06fe972b6035a" + integrity sha512-9lYcQmiI+8D5zv438H/6oweMi7UbKk9ch5ZOHkdAuCZYIP/sBP6ItMe/Nim34MZKV4emCuuHeZ1Z0xwXOLXF8A== + dependencies: + "@didtools/cacao" "^3.0.0" + "@noble/curves" "^1.2.0" + "@noble/hashes" "^1.3.2" + "@stablelib/random" "^1.0.2" + caip "^1.1.0" + +"@didtools/pkh-solana@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@didtools/pkh-solana/-/pkh-solana-0.2.0.tgz#b66d7dd642306a9808d275871de408f2e3583e6f" + integrity sha512-wOfa+hbWo1ok8YnR8tq2mZKbcyEv9qrxtTR5jXOuhOqCkz30/qu9e2Wib/byx7Kx5/ik/2z1nd2YPL0vrA+TxQ== + dependencies: + "@didtools/cacao" "^3.0.0" + "@noble/curves" "^1.2.0" + "@stablelib/random" "^1.0.2" + caip "^1.1.0" + uint8arrays "^5.0.1" + +"@didtools/pkh-stacks@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@didtools/pkh-stacks/-/pkh-stacks-0.2.0.tgz#6dc7b546ca9ad458574a7270300c0663aac4727a" + integrity sha512-lXe8ZURCYCDQXrjaM7A4p1RCKrVsQ+NbO7bI70pRfjven82BPLDiqEJbhRGnWKbjQD1CQe9MJXLy3AuStKc7qw== + dependencies: + "@didtools/cacao" "^3.0.0" + "@stablelib/random" "^1.0.2" + "@stacks/common" "^6.10.0" + "@stacks/encryption" "^6.10.0" + "@stacks/transactions" "^6.10.0" + caip "^1.1.0" + jsontokens "^4.0.1" + +"@didtools/pkh-tezos@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@didtools/pkh-tezos/-/pkh-tezos-0.3.0.tgz#21d766f4b492c5acd30ce8710585dee479fc68ae" + integrity sha512-AB8drOnBkDSE9KolsiSShPwVOVbRXM2G5T//b+GgX9potVRTcRsD0z59x/6mU1e9g2kxpScOhjRrZsC0c+SQNw== + dependencies: + "@didtools/cacao" "^3.0.0" + "@noble/curves" "^1.2.0" + "@noble/hashes" "^1.3.2" + "@stablelib/random" "^1.0.2" + caip "^1.1.0" + uint8arrays "^5.0.1" + +"@didtools/siwx@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@didtools/siwx/-/siwx-1.0.0.tgz#18eacb098a3a1f69253a8216fa5071ad9c2c7ec1" + integrity sha512-b7sPDTNHdySoJ+Rp2p06x3rg1iTxI4yPTTA3PrPh40xcvFJ0K/YhdIb/Rzff13t92arcJ+VYGFhqtJorauV91g== + dependencies: + codeco "^1.1.0" + +"@didtools/siwx@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@didtools/siwx/-/siwx-2.0.0.tgz#95225f57888bff821baa182dee2d7860ee51940a" + integrity sha512-eqBtI5dZrptXTCyadnhvU0di/KvumoByT7F8KB/8BLU7M1lltfEmvf/c5AnsyrWO9338ygCs2u5mKz1p1Zdj5A== + dependencies: + codeco "^1.2.0" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -61,6 +460,348 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.41.0.tgz#080321c3b68253522f7646b55b577dd99d2950b3" integrity sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA== +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@fortaine/fetch-event-source@^3.0.6": version "3.0.6" resolved "https://registry.yarnpkg.com/@fortaine/fetch-event-source/-/fetch-event-source-3.0.6.tgz#b8552a2ca2c5202f5699b93a92be0188d422b06e" @@ -85,6 +826,22 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@ipld/dag-cbor@^7.0.0", "@ipld/dag-cbor@^7.0.1": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@ipld/dag-cbor/-/dag-cbor-7.0.3.tgz#aa31b28afb11a807c3d627828a344e5521ac4a1e" + integrity sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA== + dependencies: + cborg "^1.6.0" + multiformats "^9.5.4" + +"@ipld/dag-cbor@^9.0.0", "@ipld/dag-cbor@^9.0.1", "@ipld/dag-cbor@^9.0.6", "@ipld/dag-cbor@^9.0.7", "@ipld/dag-cbor@^9.1.0": + version "9.2.2" + resolved "https://registry.yarnpkg.com/@ipld/dag-cbor/-/dag-cbor-9.2.2.tgz#e6f5f5bd1e4f290f2285b51fc969ef806484603a" + integrity sha512-uIEOuruCqKTP50OBWwgz4Js2+LhiBQaxc57cnP71f45b1mHEAo1OCR1Zn/TbvSW/mV1x+JqhacIktkKyaYqhCw== + dependencies: + cborg "^4.0.0" + multiformats "^13.1.0" + "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -122,10 +879,630 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@next/env@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.4.tgz#46b620f6bef97fe67a1566bf570dbb791d40c50a" - integrity sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg== +"@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz#2f3a8f1d688935c704dbc89132394a41029acbb8" + integrity sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ== + +"@lit-protocol/access-control-conditions@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/access-control-conditions/-/access-control-conditions-6.11.3.tgz#005c0d5387ca9eea84cc8aaafd7b3bb950fa0263" + integrity sha512-Rm5heGZA8qEMpJx4J7XFLUHz3RZohKKtOj620NOdiuYVWadjYqo2YNS8jWn3Xn65xBK+Vhjny4/cPVQXccp+3A== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/accs-schemas@^0.0.19": + version "0.0.19" + resolved "https://registry.yarnpkg.com/@lit-protocol/accs-schemas/-/accs-schemas-0.0.19.tgz#74216243d1208f62ee593d9e06c29ea433709ec0" + integrity sha512-O7hrDPUA6x5fgOx8HKRAV1k/8VMzwehfNHUwb2UGMbw4g3kKpokbR/ne7OPdIUYMgvRATc0WjL5gbh/w33pkOQ== + dependencies: + ajv "^8.12.0" + +"@lit-protocol/accs-schemas@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@lit-protocol/accs-schemas/-/accs-schemas-0.0.20.tgz#64d1151002f63aa0a54ba2be92bf44edefb0eb1e" + integrity sha512-JHHX0q45nq1uQ4olkg4VIGLW9lzMnRRldeTDuOrOaoPVztz+2iSOjwzb+QmuSuKFQpP5SOej2zoQB+K8b22KDw== + dependencies: + ajv "^8.12.0" + +"@lit-protocol/auth-browser@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/auth-browser/-/auth-browser-6.11.3.tgz#da16ba9d9463e1bfba965f05ff7627cbb6d9463e" + integrity sha512-DjfPYkHEF1vkTfW1Ownt01oHdtY27Dw7dh7bYrcxK7Xs35JWb3xf8wn3l0NoQdWgVoiqng/ivdutaiDohKaESQ== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/strings" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/misc-browser" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + ethers "^5.7.1" + jszip "^3.10.1" + tslib "1.14.1" + +"@lit-protocol/auth-helpers@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/auth-helpers/-/auth-helpers-6.11.3.tgz#5e1dca3e25a054d1b24f9039f367a33887479ec1" + integrity sha512-aVDyH3At3rv+S8dAmDp3/jq47+yb8wBahGaLDmbdOjoXS80sLVJ/o38Ni1j+uQaDu/l/OeVd3Avgs7QUFYJQVw== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/access-control-conditions" "6.11.3" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + siwe-recap "0.0.2-alpha.0" + tslib "2.6.0" + util "0.12.5" + +"@lit-protocol/bls-sdk@6.11.3", "@lit-protocol/bls-sdk@^6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/bls-sdk/-/bls-sdk-6.11.3.tgz#7b926f456aeb30c39e8870ee3ef3f89c58f1a2f8" + integrity sha512-LUwJ2ppy13l1lO/9+75Vaa443AZRb8CVh9NUbTqdsbcM0M0JVMYD+iGFw55KxvbRFdLlqO0Z6kV+X8V7qIlqow== + dependencies: + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/constants@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/constants/-/constants-6.11.3.tgz#ceaa1b2f208b32fd8f1f6514a2fbd0e4afa354cb" + integrity sha512-sd+jRWlXd9RMBsqXewLU4rU0dGuwgVDghsWHQlVRKTCePb4Hm0PPLit0bTZ9X+d14PF9p/jnbml0rLACqw2kWg== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/types" "6.11.3" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + +"@lit-protocol/constants@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@lit-protocol/constants/-/constants-7.0.2.tgz#2c642aa7feff0b667cef06a8cbb59c7044ef3801" + integrity sha512-A2tpsB7pCGHiC+VrPAHBaEGyb/9crCkcSIj8BtGPrLRszFZO8EHKWziM7WiMM2c2mYb+B4dKtGGUkxxCAarqaQ== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.20" + "@lit-protocol/contracts" "^0.0.74" + "@lit-protocol/types" "7.0.2" + "@openagenda/verror" "^3.1.4" + depd "^2.0.0" + ethers "^5.7.1" + siwe "^2.3.2" + tslib "1.14.1" + +"@lit-protocol/contracts-sdk@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/contracts-sdk/-/contracts-sdk-6.11.3.tgz#b32557cffd08b7cf5f99315003f558b826f8d7cb" + integrity sha512-5vwdMRVSo+SDD6ZFWNm4m4kLuyDj4pX6gwXw2lj6trD66zT2ODby2lRv8K7m0OVk0HnWONDhWe3933bgu4ltQQ== + dependencies: + "@cosmjs/amino" "0.30.1" + "@cosmjs/crypto" "0.30.1" + "@cosmjs/encoding" "0.30.1" + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/types" "6.11.3" + ajv "^8.12.0" + bitcoinjs-lib "^6.1.0" + ethers "^5.7.1" + jose "^4.14.4" + jszip "^3.10.1" + process "0.11.10" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/contracts-sdk@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@lit-protocol/contracts-sdk/-/contracts-sdk-7.0.2.tgz#5192071b32f54cceb11aff6b8661e5cbbf3864f2" + integrity sha512-EQs0l3v+tRdItuRamo675obkAPHGmQnef0WZ1cY0nNn97zRBGbkYPfkHMBxrUoGwbcsFQPMHDynrGTzAiUM7Zw== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.20" + "@lit-protocol/constants" "7.0.2" + "@lit-protocol/contracts" "^0.0.74" + "@lit-protocol/logger" "7.0.2" + "@lit-protocol/misc" "7.0.2" + "@lit-protocol/types" "7.0.2" + "@openagenda/verror" "^3.1.4" + ajv "^8.12.0" + bech32 "^2.0.0" + depd "^2.0.0" + ethers "^5.7.1" + jose "^4.14.4" + process "0.11.10" + siwe "^2.3.2" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/contracts@^0.0.63": + version "0.0.63" + resolved "https://registry.yarnpkg.com/@lit-protocol/contracts/-/contracts-0.0.63.tgz#8700c37df9d2422e9c97aa27871fb64de6186f6c" + integrity sha512-CAorNt72ybIY/g//dDeR837izNGuYQR99XwPSK2X2AJ6c+aZX1kdXCrOnxsbY40BzFrOk/dIFo+ymJ9E3qh48w== + +"@lit-protocol/contracts@^0.0.74": + version "0.0.74" + resolved "https://registry.yarnpkg.com/@lit-protocol/contracts/-/contracts-0.0.74.tgz#e726a9190c86b10cc6df3a392cd04d19057be27d" + integrity sha512-8uV038gzBp7ew7a4884SVt9Zhu8CtiTb+A8dKNnByxVoT1kFt4O4DmsaniV8p9AGjNR13IWfpU1NFChmPHVIpQ== + +"@lit-protocol/core@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/core/-/core-6.11.3.tgz#af97465ac671d86411e199099062b48fa3154efc" + integrity sha512-BdOvaxe/cmoxpjcCJ5SE0ttL1Ibvz5HpCcYaV+rjJH8LaoUF18f+eOudfR7JFxSp49+qzMrpL+aK5XkDsL7U/A== + dependencies: + "@cosmjs/amino" "0.30.1" + "@cosmjs/crypto" "0.30.1" + "@cosmjs/encoding" "0.30.1" + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/access-control-conditions" "6.11.3" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/bls-sdk" "6.11.3" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/contracts-sdk" "6.11.3" + "@lit-protocol/crypto" "6.11.3" + "@lit-protocol/ecdsa-sdk" "6.11.3" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/nacl" "6.11.3" + "@lit-protocol/sev-snp-utils-sdk" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + bitcoinjs-lib "^6.1.0" + bs58 "^5.0.0" + cross-fetch "3.1.4" + date-and-time "^2.4.1" + ethers "^5.7.1" + jose "^4.14.4" + jszip "^3.10.1" + multiformats "^9.7.1" + pako "1.0.11" + process "0.11.10" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/crypto@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/crypto/-/crypto-6.11.3.tgz#61e43394e2da4491ed07c1244f3eae65923d65e3" + integrity sha512-RRvUAMN6KDD3dk+K5ZGjNIwX9gbnnJSC/jkF7dLpvLh0/YpRi4FT6SYqUSfz7X4VWPWTOSyDgvUYqPOUPyZIlw== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/bls-sdk" "6.11.3" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/ecdsa-sdk" "6.11.3" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/nacl" "6.11.3" + "@lit-protocol/sev-snp-utils-sdk" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + cross-fetch "3.1.4" + ethers "^5.7.1" + jszip "^3.10.1" + pako "1.0.11" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/ecdsa-sdk@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/ecdsa-sdk/-/ecdsa-sdk-6.11.3.tgz#f8a1da2680feda4e567ce344951880830c635725" + integrity sha512-8R0/ulpcw6K3MjP+wTJr2aXx9zE/aHeLoziZg6S6tXRAWqwzrl00oJ9ge9bBNWCCwjNH/VgeMNMh8nw9VYNXRA== + dependencies: + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/encryption@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/encryption/-/encryption-6.11.3.tgz#84e6bb6dc2f39b80df58c6af3d481fc43d58e41c" + integrity sha512-MDpaTiNMypZ22ZsrupUINQnkIp9roJncFAnD94LsKAmY0LHHniGy5SC93lmMRZD/Sk4Yb7cmrpWergpQ4q007w== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/bls-sdk" "6.11.3" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/crypto" "6.11.3" + "@lit-protocol/ecdsa-sdk" "6.11.3" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/nacl" "6.11.3" + "@lit-protocol/sev-snp-utils-sdk" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + cross-fetch "3.1.4" + ethers "^5.7.1" + jszip "^3.10.1" + pako "1.0.11" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/lit-node-client-nodejs@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/lit-node-client-nodejs/-/lit-node-client-nodejs-6.11.3.tgz#6be13cbde0fb5a05bca687a2d4993e9eadc00d79" + integrity sha512-Cza5JpTIG5RGieJ+WpL2Rm79sAw9JwRel3ImR6ntUHWs854D8fjEzypnk3oxF4WYp7KM9CBH6XBW7tcq0sZqWA== + dependencies: + "@cosmjs/amino" "0.30.1" + "@cosmjs/crypto" "0.30.1" + "@cosmjs/encoding" "0.30.1" + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/transactions" "5.7.0" + "@lit-protocol/access-control-conditions" "6.11.3" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/auth-helpers" "6.11.3" + "@lit-protocol/bls-sdk" "6.11.3" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/contracts-sdk" "6.11.3" + "@lit-protocol/core" "6.11.3" + "@lit-protocol/crypto" "6.11.3" + "@lit-protocol/ecdsa-sdk" "6.11.3" + "@lit-protocol/encryption" "6.11.3" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/misc-browser" "6.11.3" + "@lit-protocol/nacl" "6.11.3" + "@lit-protocol/sev-snp-utils-sdk" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ajv "^8.12.0" + bitcoinjs-lib "^6.1.0" + bs58 "^5.0.0" + cross-fetch "3.1.4" + date-and-time "^2.4.1" + ethers "^5.7.1" + jose "^4.14.4" + jszip "^3.10.1" + multiformats "^9.7.1" + pako "1.0.11" + process "0.11.10" + siwe "^2.0.5" + siwe-recap "0.0.2-alpha.0" + tslib "^2.3.0" + util "0.12.5" + +"@lit-protocol/lit-node-client@^6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/lit-node-client/-/lit-node-client-6.11.3.tgz#7b9e1147b738bee18a4a3cfdd281a7388c2d68bb" + integrity sha512-WBojLz8pXXf6PdOq9OOasiX4YNFHut978v2vXTMLpNY+MQJ6FZaNoS8ssYC/78nU0WboDtQInySvtjdKXzqggA== + dependencies: + "@cosmjs/amino" "0.30.1" + "@cosmjs/crypto" "0.30.1" + "@cosmjs/encoding" "0.30.1" + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@lit-protocol/access-control-conditions" "6.11.3" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/auth-browser" "6.11.3" + "@lit-protocol/auth-helpers" "6.11.3" + "@lit-protocol/bls-sdk" "6.11.3" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/contracts-sdk" "6.11.3" + "@lit-protocol/core" "6.11.3" + "@lit-protocol/crypto" "6.11.3" + "@lit-protocol/ecdsa-sdk" "6.11.3" + "@lit-protocol/encryption" "6.11.3" + "@lit-protocol/lit-node-client-nodejs" "6.11.3" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/misc" "6.11.3" + "@lit-protocol/misc-browser" "6.11.3" + "@lit-protocol/nacl" "6.11.3" + "@lit-protocol/sev-snp-utils-sdk" "6.11.3" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + "@walletconnect/ethereum-provider" "2.9.2" + "@walletconnect/modal" "2.6.1" + ajv "^8.12.0" + bitcoinjs-lib "^6.1.0" + bs58 "^5.0.0" + cross-fetch "3.1.4" + date-and-time "^2.4.1" + ethers "^5.7.1" + jose "^4.14.4" + jszip "^3.10.1" + multiformats "^9.7.1" + pako "1.0.11" + process "0.11.10" + siwe "^2.0.5" + siwe-recap "0.0.2-alpha.0" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + util "0.12.5" + +"@lit-protocol/logger@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/logger/-/logger-6.11.3.tgz#3989422b8a1385b81101c0e00fcd580327651a3a" + integrity sha512-vyi/8Jkij1HFpZB0QSWgt72Oxm7C5fg3HjlHY3FQW0KbYWALpaeWeqNHEXt7jH6bxDp/wjyg4Qf1rvFKlHan6g== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/types" "6.11.3" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + +"@lit-protocol/logger@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@lit-protocol/logger/-/logger-7.0.2.tgz#2d28eb73ed3a0771655e03efe75bc27ccf3b7c1a" + integrity sha512-44VsSlLWVxIVG9m5GIkvdXSfd4gyCNToNN0uor41cQTYLbyvasgTfyi12XPNwfFZU7FNMrYpt+Jgig2SqrzXVg== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.20" + "@lit-protocol/constants" "7.0.2" + "@lit-protocol/contracts" "^0.0.74" + "@lit-protocol/types" "7.0.2" + "@openagenda/verror" "^3.1.4" + depd "^2.0.0" + ethers "^5.7.1" + siwe "^2.3.2" + tslib "1.14.1" + +"@lit-protocol/misc-browser@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/misc-browser/-/misc-browser-6.11.3.tgz#abc66f59e81cec70cb71d9a5e42858211eaafdf1" + integrity sha512-lJlWB7vMmHX11S/2xqdPKRlETkV3Baf1eBaN97fRwnw+y8AZpYfD1pxge5dF+ZpmxEk2gvXvO1KZHj2dCK/1eA== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/types" "6.11.3" + "@lit-protocol/uint8arrays" "6.11.3" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + +"@lit-protocol/misc@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/misc/-/misc-6.11.3.tgz#4662a92f505bab67280130bf8327cd88243a6b26" + integrity sha512-ige9iE8/M6ZT4VSsRzehjgcjPL7gHdRU9iCddrBYrEixMaKdV+cfIXKS9txfVeAcfK0JHjbOTRKhtp/DWRAB2g== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/constants" "6.11.3" + "@lit-protocol/contracts" "^0.0.63" + "@lit-protocol/logger" "6.11.3" + "@lit-protocol/types" "6.11.3" + ajv "^8.12.0" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/misc@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@lit-protocol/misc/-/misc-7.0.2.tgz#b8da1cb4107d84c8d37391d8c2992960a438f1c9" + integrity sha512-ZUU4j3E+VnCY11oPLGop95UkAUzTiBmPfiCXwFYGmh6PDvHXZlRC1Qc+3aC5lFpocoBTTJ/uE2MQZpHyN0kRlQ== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@lit-protocol/accs-schemas" "^0.0.20" + "@lit-protocol/constants" "7.0.2" + "@lit-protocol/contracts" "^0.0.74" + "@lit-protocol/logger" "7.0.2" + "@lit-protocol/types" "7.0.2" + "@openagenda/verror" "^3.1.4" + ajv "^8.12.0" + bech32 "^2.0.0" + depd "^2.0.0" + ethers "^5.7.1" + siwe "^2.3.2" + tslib "1.14.1" + util "0.12.5" + +"@lit-protocol/nacl@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/nacl/-/nacl-6.11.3.tgz#0102c1e8e4fc526485e70b0bcfb7afa8f7b97a3e" + integrity sha512-Qs3lIjP1gQB+JOBwpNdZ9N0lUBquwYY2rcgITtOnENTZXI8hspmNOC2QWmji7kIRzM7jaiMdJC/YO5airxDfQg== + dependencies: + tslib "1.14.1" + +"@lit-protocol/sev-snp-utils-sdk@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/sev-snp-utils-sdk/-/sev-snp-utils-sdk-6.11.3.tgz#fafc827585c52226c1dd7b59fabc0c6d9295a7f4" + integrity sha512-TR86ONpBK/oo4z51aJW0Jo/GJUZt/zmbIeduOyjnks7t0GHthkBbwA4/vE0uehJZH/xl+v+H3Zc9SkHUASKGuw== + dependencies: + cross-fetch "3.1.4" + tslib "1.14.1" + +"@lit-protocol/types@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/types/-/types-6.11.3.tgz#bd23e3560d07101a508aa6fedd73f10369d7bbcf" + integrity sha512-Yi8XJxc1erQdRg9DVInpIUm4yRKPvi40bY/ptWHq7zX1fzK+bSejZUQPMdBezluaOQitYc4PNJajBzfum7Wcnw== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + +"@lit-protocol/types@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@lit-protocol/types/-/types-7.0.2.tgz#2c4c0032a4210ab31f47d25e4266b8731234c8de" + integrity sha512-rEBZoeSByaMxXiP7w3g6/d180d8AbL4xpLqIlZchfJfAcSFkTseByV1d4h/J3LHl+3Q10wQsJT0N+qIi9kZbqA== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.20" + depd "^2.0.0" + ethers "^5.7.1" + siwe "^2.3.2" + tslib "1.14.1" + +"@lit-protocol/uint8arrays@6.11.3": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@lit-protocol/uint8arrays/-/uint8arrays-6.11.3.tgz#ebe877ecbc8dcd335a4c6b5209ba92bd0972b71c" + integrity sha512-TA7M9j3dEmaRctf3lhaY65n0cMCPaZV2KW8hfvB8rv6EnPpV9jr+KH4YjKyxs9MsaeDFzesocg2PRAWzZdSAPg== + dependencies: + "@ethersproject/abstract-provider" "5.7.0" + "@lit-protocol/accs-schemas" "^0.0.19" + "@lit-protocol/contracts" "^0.0.63" + ethers "^5.7.1" + jszip "^3.10.1" + siwe "^2.0.5" + tslib "1.14.1" + +"@lit/reactive-element@^1.3.0", "@lit/reactive-element@^1.6.0": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.6.3.tgz#25b4eece2592132845d303e091bad9b04cdcfe03" + integrity sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.0.0" + +"@motionone/animation@^10.15.1", "@motionone/animation@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.18.0.tgz#868d00b447191816d5d5cf24b1cafa144017922b" + integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== + dependencies: + "@motionone/easing" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/dom@^10.16.2", "@motionone/dom@^10.16.4": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.18.0.tgz#7fd25dac04cab72def6d2b92b8e0cdc091576527" + integrity sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A== + dependencies: + "@motionone/animation" "^10.18.0" + "@motionone/generators" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.18.0.tgz#7b82f6010dfee3a1bb0ee83abfbaff6edae0c708" + integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== + dependencies: + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/generators@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.18.0.tgz#fe09ab5cfa0fb9a8884097feb7eb60abeb600762" + integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== + dependencies: + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/svelte@^10.16.2": + version "10.16.4" + resolved "https://registry.yarnpkg.com/@motionone/svelte/-/svelte-10.16.4.tgz#5daf117cf5b2576fc6dd487c5e0500938a742470" + integrity sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA== + dependencies: + "@motionone/dom" "^10.16.4" + tslib "^2.3.1" + +"@motionone/types@^10.15.1", "@motionone/types@^10.17.1": + version "10.17.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.17.1.tgz#cf487badbbdc9da0c2cb86ffc1e5d11147c6e6fb" + integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== + +"@motionone/utils@^10.15.1", "@motionone/utils@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.18.0.tgz#a59ff8932ed9009624bca07c56b28ef2bb2f885e" + integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== + dependencies: + "@motionone/types" "^10.17.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/vue@^10.16.2": + version "10.16.4" + resolved "https://registry.yarnpkg.com/@motionone/vue/-/vue-10.16.4.tgz#07d09e3aa5115ca0bcc0076cb9e5322775277c09" + integrity sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg== + dependencies: + "@motionone/dom" "^10.16.4" + tslib "^2.3.1" + +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + +"@next/env@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.4.tgz#5546813dc4f809884a37d257b254a5ce1b0248d7" + integrity sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg== "@next/eslint-plugin-next@13.4.4": version "13.4.4" @@ -134,50 +1511,99 @@ dependencies: glob "7.1.7" -"@next/swc-darwin-arm64@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz#8c14083c2478e2a9a8d140cce5900f76b75667ff" - integrity sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw== +"@next/swc-darwin-arm64@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz#da9f04c34a3d5f0b8401ed745768420e4a604036" + integrity sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg== + +"@next/swc-darwin-x64@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz#46dedb29ec5503bf171a72a3ecb8aac6e738e9d6" + integrity sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg== + +"@next/swc-linux-arm64-gnu@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz#c9697ab9eb422bd1d7ffd0eb0779cc2aefa9d4a1" + integrity sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ== + +"@next/swc-linux-arm64-musl@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz#cbbceb2008571c743b5a310a488d2e166d200a75" + integrity sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A== + +"@next/swc-linux-x64-gnu@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz#d79184223f857bacffb92f643cb2943a43632568" + integrity sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q== + +"@next/swc-linux-x64-musl@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz#6b6c3e5ac02ca5e63394d280ec8ee607491902df" + integrity sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ== + +"@next/swc-win32-arm64-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz#dbad3906e870dba84c5883d9d4c4838472e0697f" + integrity sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A== + +"@next/swc-win32-ia32-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz#6074529b91ba49132922ce89a2e16d25d2ec235d" + integrity sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag== + +"@next/swc-win32-x64-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz#e65a1c6539a671f97bb86d5183d6e3a1733c29c7" + integrity sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg== + +"@noble/ciphers@^0.4.0": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.4.1.tgz#977fc35f563a4ca315ebbc4cbb1f9b670bd54456" + integrity sha512-QCOA9cgf3Rc33owG0AYBB9wszz+Ul2kramWN8tXG44Gyciud/tbkEqvxRF/IpqQaBpRBNi9f4jdNxqB2CQCIXg== -"@next/swc-darwin-x64@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz#5fe01c65c80fcb833c8789fd70f074ea99893864" - integrity sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg== +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" -"@next/swc-linux-arm64-gnu@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz#f2e071f38e8a6cdadf507cc5d28956f73360d064" - integrity sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA== +"@noble/curves@^1.0.0", "@noble/curves@^1.1.0", "@noble/curves@^1.2.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" -"@next/swc-linux-arm64-musl@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz#23bf75c544e54562bc24ec1be036e4bd9cf89e2c" - integrity sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A== +"@noble/hashes@1.1.5", "@noble/hashes@~1.1.1": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" + integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== -"@next/swc-linux-x64-gnu@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz#bd42590950a01957952206f89cf5622e7c9e4196" - integrity sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ== +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== -"@next/swc-linux-x64-musl@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz#907d81feb1abec3daec0ecb61e3f39b56e7aeafe" - integrity sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA== +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== -"@next/swc-win32-arm64-msvc@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz#1d754d2bb10bdf9907c0acc83711438697c3b5fe" - integrity sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A== +"@noble/hashes@^1", "@noble/hashes@^1.1.2", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.2", "@noble/hashes@^1.3.3": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== -"@next/swc-win32-ia32-msvc@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz#77b2c7f7534b675d46e46301869e08d504d23956" - integrity sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg== +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@next/swc-win32-x64-msvc@13.4.4": - version "13.4.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz#faab69239f8a9d0be7cd473e65f5a07735ef7b0e" - integrity sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw== +"@noble/secp256k1@1.7.1", "@noble/secp256k1@^1.6.3": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -200,12 +1626,113 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pinecone-database/pinecone@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@pinecone-database/pinecone/-/pinecone-0.1.6.tgz#13374ae9462c8eea0dc26683cafeddc4e7c0375f" - integrity sha512-tCnVc28udecthhgSBTdcMhYEW+xsR++AdZasp+ZE/AvUD1hOR2IR3edjk9m0sDxZyvXbno2KeqUbLIOZr7sCTw== +"@openagenda/verror@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@openagenda/verror/-/verror-3.1.4.tgz#a3560168e91dc35ae8c0823af70556a5a0bb8d60" + integrity sha512-+V7QuD6v5sMWez7cu+5DXoXMim+iQssOcspoNgbWDW8sEyC54Mdo5VuIkcIjqhPmQYOzBWo5qlbzNGEpD6PzMA== + dependencies: + assertion-error "^1.1.0" + depd "^2.0.0" + inherits "^2.0.4" + sprintf-js "^1.1.2" + +"@parcel/watcher-android-arm64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz#e32d3dda6647791ee930556aee206fcd5ea0fb7a" + integrity sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ== + +"@parcel/watcher-darwin-arm64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz#0d9e680b7e9ec1c8f54944f1b945aa8755afb12f" + integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw== + +"@parcel/watcher-darwin-x64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz#f9f1d5ce9d5878d344f14ef1856b7a830c59d1bb" + integrity sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA== + +"@parcel/watcher-freebsd-x64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz#2b77f0c82d19e84ff4c21de6da7f7d096b1a7e82" + integrity sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw== + +"@parcel/watcher-linux-arm-glibc@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz#92ed322c56dbafa3d2545dcf2803334aee131e42" + integrity sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA== + +"@parcel/watcher-linux-arm-musl@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz#cd48e9bfde0cdbbd2ecd9accfc52967e22f849a4" + integrity sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA== + +"@parcel/watcher-linux-arm64-glibc@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz#7b81f6d5a442bb89fbabaf6c13573e94a46feb03" + integrity sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA== + +"@parcel/watcher-linux-arm64-musl@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz#dcb8ff01077cdf59a18d9e0a4dff7a0cfe5fd732" + integrity sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q== + +"@parcel/watcher-linux-x64-glibc@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz#2e254600fda4e32d83942384d1106e1eed84494d" + integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw== + +"@parcel/watcher-linux-x64-musl@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz#01fcea60fedbb3225af808d3f0a7b11229792eef" + integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA== + +"@parcel/watcher-wasm@^2.4.1": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz#81fad1e10957f08a532eb4fc0d4c353cd8901a50" + integrity sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ== dependencies: - cross-fetch "^3.1.5" + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" + +"@parcel/watcher-win32-arm64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz#87cdb16e0783e770197e52fb1dc027bb0c847154" + integrity sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig== + +"@parcel/watcher-win32-ia32@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz#778c39b56da33e045ba21c678c31a9f9d7c6b220" + integrity sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA== + +"@parcel/watcher-win32-x64@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz#33873876d0bbc588aacce38e90d1d7480ce81cb7" + integrity sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw== + +"@parcel/watcher@^2.4.1": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.0.tgz#5c88818b12b8de4307a9d3e6dc3e28eba0dfbd10" + integrity sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.0" + "@parcel/watcher-darwin-arm64" "2.5.0" + "@parcel/watcher-darwin-x64" "2.5.0" + "@parcel/watcher-freebsd-x64" "2.5.0" + "@parcel/watcher-linux-arm-glibc" "2.5.0" + "@parcel/watcher-linux-arm-musl" "2.5.0" + "@parcel/watcher-linux-arm64-glibc" "2.5.0" + "@parcel/watcher-linux-arm64-musl" "2.5.0" + "@parcel/watcher-linux-x64-glibc" "2.5.0" + "@parcel/watcher-linux-x64-musl" "2.5.0" + "@parcel/watcher-win32-arm64" "2.5.0" + "@parcel/watcher-win32-ia32" "2.5.0" + "@parcel/watcher-win32-x64" "2.5.0" "@pkgr/utils@^2.3.1": version "2.4.1" @@ -244,23 +1771,284 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz#f5635b36fc0dad96ef1e542a302cd914230188c0" integrity sha512-IthPJsJR85GhOkp3Hvp8zFOPK5ynKn6STyHa/WZpioK7E1aYDiBzpqQPrngc14DszIUkIrdd3k9Iu0XSzlP/1w== -"@swc/helpers@0.5.1": - version "0.5.1" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.1.tgz#e9031491aa3f26bfcc974a67f48bd456c8a5357a" - integrity sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg== +"@scarf/scarf@^1.1.1": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.4.0.tgz#3bbb984085dbd6d982494538b523be1ce6562972" + integrity sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ== + +"@scure/base@^1.1.3": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== + +"@scure/base@~1.1.0", "@scure/base@~1.1.2": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/bip32@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== + dependencies: + "@noble/curves" "~1.2.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.2" + +"@scure/bip39@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" + integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== + dependencies: + "@noble/hashes" "~1.1.1" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@spruceid/siwe-parser@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz#3e13e7d3ac0bfdaf109a07342590eb21daee2fc3" + integrity sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ== + dependencies: + "@noble/hashes" "^1.1.2" + apg-js "^4.3.0" + uri-js "^4.4.1" + valid-url "^1.0.9" + +"@stablelib/aead@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3" + integrity sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg== + +"@stablelib/binary@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" + integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== + dependencies: + "@stablelib/int" "^1.0.1" + +"@stablelib/bytes@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/bytes/-/bytes-1.0.1.tgz#0f4aa7b03df3080b878c7dea927d01f42d6a20d8" + integrity sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ== + +"@stablelib/chacha20poly1305@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz#de6b18e283a9cb9b7530d8767f99cde1fec4c2ee" + integrity sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA== + dependencies: + "@stablelib/aead" "^1.0.1" + "@stablelib/binary" "^1.0.1" + "@stablelib/chacha" "^1.0.1" + "@stablelib/constant-time" "^1.0.1" + "@stablelib/poly1305" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/chacha@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/chacha/-/chacha-1.0.1.tgz#deccfac95083e30600c3f92803a3a1a4fa761371" + integrity sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/constant-time@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/constant-time/-/constant-time-1.0.1.tgz#bde361465e1cf7b9753061b77e376b0ca4c77e35" + integrity sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg== + +"@stablelib/ed25519@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/ed25519/-/ed25519-1.0.3.tgz#f8fdeb6f77114897c887bb6a3138d659d3f35996" + integrity sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg== + dependencies: + "@stablelib/random" "^1.0.2" + "@stablelib/sha512" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hash@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" + integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== + +"@stablelib/hkdf@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hkdf/-/hkdf-1.0.1.tgz#b4efd47fd56fb43c6a13e8775a54b354f028d98d" + integrity sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g== + dependencies: + "@stablelib/hash" "^1.0.1" + "@stablelib/hmac" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hmac@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hmac/-/hmac-1.0.1.tgz#3d4c1b8cf194cb05d28155f0eed8a299620a07ec" + integrity sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/int@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" + integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== + +"@stablelib/keyagreement@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz#4612efb0a30989deb437cd352cee637ca41fc50f" + integrity sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg== dependencies: + "@stablelib/bytes" "^1.0.1" + +"@stablelib/poly1305@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/poly1305/-/poly1305-1.0.1.tgz#93bfb836c9384685d33d70080718deae4ddef1dc" + integrity sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/random@^1.0.1", "@stablelib/random@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" + integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha256@1.0.1", "@stablelib/sha256@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha256/-/sha256-1.0.1.tgz#77b6675b67f9b0ea081d2e31bda4866297a3ae4f" + integrity sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha512@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha512/-/sha512-1.0.1.tgz#6da700c901c2c0ceacbd3ae122a38ac57c72145f" + integrity sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/wipe@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" + integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== + +"@stablelib/x25519@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/x25519/-/x25519-1.0.3.tgz#13c8174f774ea9f3e5e42213cbf9fc68a3c7b7fd" + integrity sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw== + dependencies: + "@stablelib/keyagreement" "^1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/wipe" "^1.0.1" + +"@stacks/common@^6.10.0", "@stacks/common@^6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@stacks/common/-/common-6.16.0.tgz#1b980acf29fd66f34b26757e85d45c6abd2e4d32" + integrity sha512-PnzvhrdGRMVZvxTulitlYafSK4l02gPCBBoI9QEoTqgSnv62oaOXhYAUUkTMFKxdHW1seVEwZsrahuXiZPIAwg== + dependencies: + "@types/bn.js" "^5.1.0" + "@types/node" "^18.0.4" + +"@stacks/encryption@^6.10.0": + version "6.17.0" + resolved "https://registry.yarnpkg.com/@stacks/encryption/-/encryption-6.17.0.tgz#b2a914f064f6ea5ca74e90be2ad0bff3661c69bf" + integrity sha512-c0+ZOjrAiB1fDCjXO6XqHdYgpeBeMYyeH+dWahpD1VQUDor2PE5Q47qyuibWmx36rLWt1M6wlaLdeVm6HlKGzw== + dependencies: + "@noble/hashes" "1.1.5" + "@noble/secp256k1" "1.7.1" + "@scure/bip39" "1.1.0" + "@stacks/common" "^6.16.0" + "@types/node" "^18.0.4" + base64-js "^1.5.1" + bs58 "^5.0.0" + ripemd160-min "^0.0.6" + varuint-bitcoin "^1.1.2" + +"@stacks/network@^6.17.0": + version "6.17.0" + resolved "https://registry.yarnpkg.com/@stacks/network/-/network-6.17.0.tgz#9e0eefb8d72cb2243744beaf1e17673737290a49" + integrity sha512-numHbfKjwco/rbkGPOEz8+FcJ2nBnS/tdJ8R422Q70h3SiA9eqk9RjSzB8p4JP8yW1SZvW+eihADHfMpBuZyfw== + dependencies: + "@stacks/common" "^6.16.0" + cross-fetch "^3.1.5" + +"@stacks/transactions@^6.10.0": + version "6.17.0" + resolved "https://registry.yarnpkg.com/@stacks/transactions/-/transactions-6.17.0.tgz#01a77e919c4c8f638b9ddb5ac593eaff3e25f96b" + integrity sha512-FUah2BRgV66ApLcEXGNGhwyFTRXqX5Zco3LpiM3essw8PF0NQlHwwdPgtDko5RfrJl3LhGXXe/30nwsfNnB3+g== + dependencies: + "@noble/hashes" "1.1.5" + "@noble/secp256k1" "1.7.1" + "@stacks/common" "^6.16.0" + "@stacks/network" "^6.17.0" + c32check "^2.0.0" + lodash.clonedeep "^4.5.0" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" + integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== + dependencies: + "@swc/counter" "^0.1.3" tslib "^2.4.0" +"@types/bn.js@^5.1.0": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== + dependencies: + "@types/node" "*" + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/node@*": + version "22.10.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" + integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== + dependencies: + undici-types "~6.20.0" + "@types/node@20.2.5": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@^18.0.4": + version "18.19.68" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.68.tgz#f4f10d9927a7eaf3568c46a6d739cc0967ccb701" + integrity sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw== + dependencies: + undici-types "~5.26.4" + "@types/prop-types@*": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" @@ -292,6 +2080,11 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== +"@types/trusted-types@^2.0.2": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + "@typescript-eslint/parser@^5.42.0": version "5.59.7" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.7.tgz#02682554d7c1028b89aa44a48bf598db33048caa" @@ -336,16 +2129,345 @@ "@typescript-eslint/types" "5.59.7" eslint-visitor-keys "^3.3.0" +"@useorbis/db-sdk@0.0.60-alpha": + version "0.0.60-alpha" + resolved "https://registry.yarnpkg.com/@useorbis/db-sdk/-/db-sdk-0.0.60-alpha.tgz#7951b2b1ac6e99202b12a66aba6cc81db1f77491" + integrity sha512-aosCH/6I+9oAFAYO8aS6/ig1wNNbKQCnPWXhhXAUEEM7SppjI1aOeoH7quRqGONW+PTnreKLOpuzOby9OS6zog== + dependencies: + "@ceramicnetwork/http-client" "^5.16.0" + "@ceramicnetwork/stream-model" "^4.15.0" + "@ceramicnetwork/stream-model-instance" "^4.15.0" + "@ceramicnetwork/streamid" "^5.4.0" + "@didtools/cacao" "^2.0.0" + "@noble/hashes" "^1.3.1" + "@stablelib/random" "^1.0.2" + ajv "^8.17.1" + ajv-formats "^3.0.1" + did-session "^2.0.1" + dids "^4.0.3" + uint8arrays "^4.0.3" + +"@walletconnect/core@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.9.2.tgz#c46734ca63771b28fd77606fd521930b7ecfc5e1" + integrity sha512-VARMPAx8sIgodeyngDHbealP3B621PQqjqKsByFUTOep8ZI1/R/20zU+cmq6j9RCrL+kLKZcrZqeVzs8Z7OlqQ== + dependencies: + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-provider" "1.0.13" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.13" + "@walletconnect/keyvaluestorage" "^1.0.2" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/relay-auth" "^1.0.4" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.9.2" + "@walletconnect/utils" "2.9.2" + events "^3.3.0" + lodash.isequal "4.5.0" + uint8arrays "^3.1.0" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" + integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== + dependencies: + tslib "1.14.1" + +"@walletconnect/ethereum-provider@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.9.2.tgz#fb3a6fca279bb4e98e75baa2fb9730545d41bb99" + integrity sha512-eO1dkhZffV1g7vpG19XUJTw09M/bwGUwwhy1mJ3AOPbOSbMPvwiCuRz2Kbtm1g9B0Jv15Dl+TvJ9vTgYF8zoZg== + dependencies: + "@walletconnect/jsonrpc-http-connection" "^1.0.7" + "@walletconnect/jsonrpc-provider" "^1.0.13" + "@walletconnect/jsonrpc-types" "^1.0.3" + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/sign-client" "2.9.2" + "@walletconnect/types" "2.9.2" + "@walletconnect/universal-provider" "2.9.2" + "@walletconnect/utils" "2.9.2" + events "^3.3.0" + +"@walletconnect/events@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" + integrity sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/heartbeat@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz#afaa3a53232ae182d7c9cff41c1084472d8f32e9" + integrity sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-http-connection@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz#2f4c3948f074960a3edd07909560f3be13e2c7ae" + integrity sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.1" + cross-fetch "^3.1.4" + events "^3.3.0" + +"@walletconnect/jsonrpc-provider@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b" + integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-provider@^1.0.13": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz#696f3e3b6d728b361f2e8b853cfc6afbdf2e4e3e" + integrity sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-types@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c" + integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz#ce1a667d79eadf2a2d9d002c152ceb68739c230c" + integrity sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ== + dependencies: + events "^3.3.0" + keyvaluestorage-interface "^1.0.0" + +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" + integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.3" + tslib "1.14.1" + +"@walletconnect/jsonrpc-ws-connection@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.13.tgz#23b0cdd899801bfbb44a6556936ec2b93ef2adf4" + integrity sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + tslib "1.14.1" + ws "^7.5.1" + +"@walletconnect/keyvaluestorage@^1.0.2": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" + integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== + dependencies: + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" + +"@walletconnect/logger@^2.0.1": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.1.2.tgz#813c9af61b96323a99f16c10089bfeb525e2a272" + integrity sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw== + dependencies: + "@walletconnect/safe-json" "^1.0.2" + pino "7.11.0" + +"@walletconnect/modal-core@2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.6.1.tgz#bc76055d0b644a2d4b98024324825c108a700905" + integrity sha512-f2hYlJ5pwzGvjyaZ6BoGR5uiMgXzWXt6w6ktt1N8lmY6PiYp8whZgqx2hTxVWwVlsGnaIfh6UHp1hGnANx0eTQ== + dependencies: + valtio "1.11.0" + +"@walletconnect/modal-ui@2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.6.1.tgz#200c54c8dfe3c71321abb2724e18bb357dfd6371" + integrity sha512-RFUOwDAMijSK8B7W3+KoLKaa1l+KEUG0LCrtHqaB0H0cLnhEGdLR+kdTdygw+W8+yYZbkM5tXBm7MlFbcuyitA== + dependencies: + "@walletconnect/modal-core" "2.6.1" + lit "2.7.6" + motion "10.16.2" + qrcode "1.5.3" + +"@walletconnect/modal@2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.6.1.tgz#066fdbfcff83b58c8a9da66ab4af0eb93e3626de" + integrity sha512-G84tSzdPKAFk1zimgV7JzIUFT5olZUVtI3GcOk77OeLYjlMfnDT23RVRHm5EyCrjkptnvpD0wQScXePOFd2Xcw== + dependencies: + "@walletconnect/modal-core" "2.6.1" + "@walletconnect/modal-ui" "2.6.1" + +"@walletconnect/relay-api@^1.0.9": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.11.tgz#80ab7ef2e83c6c173be1a59756f95e515fb63224" + integrity sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q== + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + +"@walletconnect/relay-auth@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz#0b5c55c9aa3b0ef61f526ce679f3ff8a5c4c2c7c" + integrity sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ== + dependencies: + "@stablelib/ed25519" "^1.0.2" + "@stablelib/random" "^1.0.1" + "@walletconnect/safe-json" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + uint8arrays "^3.0.0" + +"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" + integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA== + dependencies: + tslib "1.14.1" + +"@walletconnect/sign-client@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.9.2.tgz#ff4c81c082c2078878367d07f24bcb20b1f7ab9e" + integrity sha512-anRwnXKlR08lYllFMEarS01hp1gr6Q9XUgvacr749hoaC/AwGVlxYFdM8+MyYr3ozlA+2i599kjbK/mAebqdXg== + dependencies: + "@walletconnect/core" "2.9.2" + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.9.2" + "@walletconnect/utils" "2.9.2" + events "^3.3.0" + +"@walletconnect/time@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" + integrity sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g== + dependencies: + tslib "1.14.1" + +"@walletconnect/types@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.9.2.tgz#d5fd5a61dc0f41cbdca59d1885b85207ac7bf8c5" + integrity sha512-7Rdn30amnJEEal4hk83cdwHUuxI1SWQ+K7fFFHBMqkuHLGi3tpMY6kpyfDxnUScYEZXqgRps4Jo5qQgnRqVM7A== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/keyvaluestorage" "^1.0.2" + "@walletconnect/logger" "^2.0.1" + events "^3.3.0" + +"@walletconnect/universal-provider@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.9.2.tgz#40e54e98bc48b1f2f5f77eb5b7f05462093a8506" + integrity sha512-JmaolkO8D31UdRaQCHwlr8uIFUI5BYhBzqYFt54Mc6gbIa1tijGOmdyr6YhhFO70LPmS6gHIjljwOuEllmlrxw== + dependencies: + "@walletconnect/jsonrpc-http-connection" "^1.0.7" + "@walletconnect/jsonrpc-provider" "1.0.13" + "@walletconnect/jsonrpc-types" "^1.0.2" + "@walletconnect/jsonrpc-utils" "^1.0.7" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/sign-client" "2.9.2" + "@walletconnect/types" "2.9.2" + "@walletconnect/utils" "2.9.2" + events "^3.3.0" + +"@walletconnect/utils@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.9.2.tgz#035bdb859ee81a4bcc6420f56114cc5ec3e30afb" + integrity sha512-D44hwXET/8JhhIjqljY6qxSu7xXnlPrf63UN/Qfl98vDjWlYVcDl2+JIQRxD9GPastw0S8XZXdRq59XDXLuZBg== + dependencies: + "@stablelib/chacha20poly1305" "1.0.1" + "@stablelib/hkdf" "1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/sha256" "1.0.1" + "@stablelib/x25519" "^1.0.3" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.9.2" + "@walletconnect/window-getters" "^1.0.1" + "@walletconnect/window-metadata" "^1.0.1" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "^3.1.0" + +"@walletconnect/window-getters@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" + integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" + integrity sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA== + dependencies: + "@walletconnect/window-getters" "^1.0.1" + tslib "1.14.1" + +abitype@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.8.tgz#1f120b6b717459deafd213dfbf3a3dd1bf10ae8c" + integrity sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + acorn@^8.8.0: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -356,12 +2478,22 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.12.0, ajv@^8.17.1, ajv@^8.8.2: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -378,7 +2510,7 @@ any-promise@^1.0.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== -anymatch@~3.1.2: +anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -386,6 +2518,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +apg-js@^4.3.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/apg-js/-/apg-js-4.4.0.tgz#09dcecab0731fbde233b9f2352fdd2d07e56b2cf" + integrity sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q== + arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" @@ -458,6 +2595,11 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -468,6 +2610,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + autoprefixer@10.4.14: version "10.4.14" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" @@ -485,6 +2632,13 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + axe-core@^4.6.2: version "4.7.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" @@ -497,6 +2651,15 @@ axios@^0.26.0: dependencies: follow-redirects "^1.14.8" +axios@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" + integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -509,16 +2672,36 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.5.1: +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + +base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bech32@1.1.4, bech32@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + big-integer@^1.6.44: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== +bigint-mod-arith@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.3.1.tgz#8ed33dc9f7886e552a7d47c239e051836e74cfa8" + integrity sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w== + binary-extensions@^2.0.0, binary-extensions@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -529,6 +2712,33 @@ binary-search@^1.3.5: resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c" integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA== +bip174@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.1.tgz#ef3e968cf76de234a546962bcf572cc150982f9f" + integrity sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ== + +bitcoinjs-lib@^6.1.0: + version "6.1.7" + resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz#0f98dec1333d658574eefa455295668cfae38bb0" + integrity sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg== + dependencies: + "@noble/hashes" "^1.2.0" + bech32 "^2.0.0" + bip174 "^2.1.1" + bs58check "^3.0.1" + typeforce "^1.11.3" + varuint-bitcoin "^1.1.2" + +bn.js@^4.11.9: + version "4.12.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" + integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== + +bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + bplist-parser@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" @@ -551,6 +2761,11 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + browserslist@^4.21.5: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" @@ -561,6 +2776,29 @@ browserslist@^4.21.5: node-releases "^2.0.8" update-browserslist-db "^1.0.10" +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + +bs58check@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-3.0.1.tgz#2094d13720a28593de1cba1d8c4e48602fdd841c" + integrity sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ== + dependencies: + "@noble/hashes" "^1.2.0" + bs58 "^5.0.0" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + bundle-name@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" @@ -575,6 +2813,27 @@ busboy@1.6.0: dependencies: streamsearch "^1.1.0" +c32check@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/c32check/-/c32check-2.0.0.tgz#b9365618b2fb135c0783d03f00605b7b0f90c659" + integrity sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA== + dependencies: + "@noble/hashes" "^1.1.2" + base-x "^4.0.0" + +caip@^1.1.0, caip@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/caip/-/caip-1.1.1.tgz#c2c2b598b5e052d72c35c8d81b31f864e19c61e3" + integrity sha512-a3v5lteUUOoyRI0U6qe5ayCCGkF2mCmJ5zQMDnOD2vRjgRg6sm9p8TsRC2h4D4beyqRN9RYniphAPnj/+jQC6g== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" + integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -583,6 +2842,24 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -593,11 +2870,46 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: version "1.0.30001489" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz#ca82ee2d4e4dbf2bd2589c9360d3fcc2c7ba3bd8" integrity sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ== +caniuse-lite@^1.0.30001579: + version "1.0.30001689" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz#67ca960dd5f443903e19949aeacc9d28f6e10910" + integrity sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g== + +canonicalize@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-2.0.0.tgz#32be2cef4446d67fd5348027a384cae28f17226a" + integrity sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w== + +cartonne@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cartonne/-/cartonne-3.0.1.tgz#70aea12530b7ca400630326edb7cbbd02031883d" + integrity sha512-Y8DH//DthEUbfvOMGYj/9K3F1RcWkiVu2dB9tGkiBnMqojAXTpu+TUs9FNNx202H0TQdJgbPsQl7Q6NuJ48dCw== + dependencies: + "@ipld/dag-cbor" "^9.0.7" + multiformats "^13.0.0" + multihashes-sync "^2.0.0" + varintes "^2.0.5" + +cborg@^1.10.2, cborg@^1.6.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/cborg/-/cborg-1.10.2.tgz#83cd581b55b3574c816f82696307c7512db759a1" + integrity sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug== + +cborg@^4.0.0, cborg@^4.0.5, cborg@^4.0.8: + version "4.2.7" + resolved "https://registry.yarnpkg.com/cborg/-/cborg-4.2.7.tgz#19769ecaf201461eeef69ca215cf3cbda0a695bd" + integrity sha512-zHTUAm+HAoRLtGEQ1b28HXBm8d/5YP+7eiSKzEu/mpFkptGYaMQCHv15OiQBuyNlIgbCBXvBbZQPl3xvcZTJXg== + chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -621,6 +2933,28 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +citty@^0.1.5, citty@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.6.tgz#0f7904da1ed4625e1a9ea7e0fa780981aab7c5e4" + integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ== + dependencies: + consola "^3.2.3" + class-variance-authority@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" @@ -633,11 +2967,34 @@ client-only@0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +clipboardy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" + integrity sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w== + dependencies: + execa "^8.0.1" + is-wsl "^3.1.0" + is64bit "^2.0.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clsx@2.0.0, clsx@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== +codeco@^1.1.0, codeco@^1.2.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/codeco/-/codeco-1.4.3.tgz#ff904b921519a1d42a0ba3f4012cf0de9e62153b" + integrity sha512-NG2kuhCtCNVKWYEwhVb6yg1QU/hYbMUIsaJkxXGEypHQIBClAvMGQhiheEX6c4C9Dwi9L/UuzeO66Us3KrK1rA== + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -650,6 +3007,16 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +colors@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" + integrity sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -667,6 +3034,40 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +consola@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" + integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== + +cookie-es@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.2.2.tgz#18ceef9eb513cac1cb6c14bcbf8bdb2679b34821" + integrity sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-fetch@3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" + integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== + dependencies: + node-fetch "2.6.1" + +cross-fetch@^3.1.4: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-fetch@^3.1.5: version "3.1.6" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" @@ -683,6 +3084,13 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +"crossws@>=0.2.0 <0.4.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.3.1.tgz#7980e0b6688fe23286661c3ab8deeccbaa05ca86" + integrity sha512-HsZgeVYaG+b5zA+9PbIPGq4+J/CJynJuearykPsXx4V/eMhyQ5EDVg3Ak2FBZtVXCiOLu/U7IiwDHTr9MA+IKw== + dependencies: + uncrypto "^0.1.3" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -693,11 +3101,45 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== +dag-jose-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dag-jose-utils/-/dag-jose-utils-3.0.0.tgz#38a0fb1e17c0af5ea148fdd50a8b77671fe329fa" + integrity sha512-gu+XutOTy3kD8fDcA1SMjZ2U0mUOb/hxoRVZaMCizXN7Ssbc5dKOzeXQ4GquV4BdQzs3w5Y7irOpn2plFPIJfg== + dependencies: + "@ipld/dag-cbor" "^7.0.1" + multiformats "^11.0.1" + +dag-jose-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/dag-jose-utils/-/dag-jose-utils-4.0.0.tgz#0cdecb555e6dbff2f023f36beee5b2a14d93d337" + integrity sha512-bmmXtVdEKp/zYH8El4GGkMREJioUztz8fzOErfy5dTbyKIVOF61C5sfsZLYCB/wiT/I9+SPNrQeo/Cx6Ik3wJQ== + dependencies: + "@ipld/dag-cbor" "^9.0.7" + multiformats "^13.0.0" + +dag-jose@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/dag-jose/-/dag-jose-4.0.0.tgz#4e65f62af58dd5203b2b094eb52142ffe0cdec1d" + integrity sha512-tw595L3UYoOUT9dSJPbBEG/qpRpw24kRZxa5SLRnlnr+g5L7O8oEs1d3W5TiVA1oJZbthVsf0Vi3zFN66qcEBA== + dependencies: + "@ipld/dag-cbor" "^9.0.0" + multiformats "^11.0.0" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +date-and-time@^2.4.1: + version "2.4.3" + resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-2.4.3.tgz#116963998a8cecd478955ae053f31a6747a988df" + integrity sha512-xkS/imTmsyEdpp9ie5oV5UWolg3XkYWNySbT2W4ESWr6v4V8YrsHbhpk9fIeQcr0NFTnYbQJLXlgU1zrLItysA== + +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -712,6 +3154,16 @@ debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + deep-equal@^2.0.5: version "2.2.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.1.tgz#c72ab22f3a7d3503a4ca87dde976fe9978816739" @@ -759,6 +3211,15 @@ default-browser@^4.0.0: execa "^7.1.1" titleize "^3.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" @@ -772,16 +3233,113 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +depd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destr@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.3.tgz#7f9e97cb3d16dbdca7be52aca1644ce402cfe449" + integrity sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ== + +detect-browser@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" + integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +did-jwt@^7.2.0, did-jwt@^7.4.7: + version "7.4.7" + resolved "https://registry.yarnpkg.com/did-jwt/-/did-jwt-7.4.7.tgz#44105fb0a0cdfd78c087de52087422075c674700" + integrity sha512-Apz7nIfIHSKWIMaEP5L/K8xkwByvjezjTG0xiqwKdnNj1x8M0+Yasury5Dm/KPltxi2PlGfRPf3IejRKZrT8mQ== + dependencies: + "@noble/ciphers" "^0.4.0" + "@noble/curves" "^1.0.0" + "@noble/hashes" "^1.3.0" + "@scure/base" "^1.1.3" + canonicalize "^2.0.0" + did-resolver "^4.1.0" + multibase "^4.0.6" + multiformats "^9.6.2" + uint8arrays "3.1.1" + +did-resolver@^4.0.1, did-resolver@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-4.1.0.tgz#740852083c4fd5bf9729d528eca5d105aff45eb6" + integrity sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA== + +did-session@^2.0.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/did-session/-/did-session-2.1.2.tgz#563576b581fe31b6d01234b8b7603afd2926003e" + integrity sha512-6tMGZ6Q4gRJYjH5bocwL4Te55UF0MIA+fNOaEAhK0Xbq4PAYxCnL1e0zhe4jwSbTqU8ilaoUoE2r6McAFZTDMQ== + dependencies: + "@didtools/key-webcrypto" "^0.1.2" + "@stablelib/random" "^1.0.1" + caip "^1.1.0" + dids "^4.0.3" + key-did-provider-ed25519 "^3.0.1" + key-did-resolver "^3.0.0" + uint8arrays "^4.0.9" + +dids@^4.0.3, dids@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/dids/-/dids-4.0.4.tgz#b84e10f0d41554c91cfe9f06f731bfc1f70cfe60" + integrity sha512-PKxQP0QFqgeMe0dbL7LCRdPJVhZU2ejj8RWCfJ6vro3a+o5o32cWNM1X6YXpdIWq6G5fTJw9KO2dHj2ZzYDc7w== + dependencies: + "@didtools/cacao" "^2.1.0" + "@didtools/codecs" "^1.0.1" + "@didtools/pkh-ethereum" "^0.4.1" + "@stablelib/random" "^1.0.1" + codeco "^1.1.0" + dag-jose-utils "^3.0.0" + did-jwt "^7.2.0" + did-resolver "^4.1.0" + multiformats "^11.0.2" + rpc-utils "^0.6.1" + uint8arrays "^4.0.3" + +dids@^5.0.0, dids@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/dids/-/dids-5.0.3.tgz#a29699877611ec64feaf4f8e4f0160e3a724d2d2" + integrity sha512-VAgMnoD/DA8hZBZ9Km3M45jaeD3uRVo+GLT8dg8+SPECDPCzCqX/0eVSAHgEnppbP6+p297H2d826cS2Qmd6wg== + dependencies: + "@didtools/cacao" "^3.0.1" + "@didtools/codecs" "^3.0.0" + "@didtools/pkh-ethereum" "^0.6.0" + "@stablelib/random" "^1.0.2" + codeco "^1.2.0" + dag-jose-utils "^4.0.0" + did-jwt "^7.4.7" + did-resolver "^4.1.0" + multiformats "^13.0.0" + rpc-utils "^0.6.2" + uint8arrays "^5.0.1" + didyoumean@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== +dijkstrajs@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" + integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -808,16 +3366,78 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dunder-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.0.tgz#c2fce098b3c8f8899554905f4377b6d85dabaa80" + integrity sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexify@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + electron-to-chromium@^1.4.284: version "1.4.411" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.411.tgz#8cb7787f0442fcb4209590e9951bdb482caa93b2" integrity sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg== +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +elliptic@^6.5.4: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encode-utf8@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + enhanced-resolve@^5.12.0: version "5.14.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3" @@ -866,6 +3486,16 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: unbox-primitive "^1.0.2" which-typed-array "^1.1.9" +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-get-iterator@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" @@ -881,6 +3511,13 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -1121,11 +3758,65 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +ethers@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^6.13.4: + version "6.13.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.4.tgz#bd3e1c3dc1e7dc8ce10f9ffb4ee40967a651b53c" + integrity sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -1156,11 +3847,31 @@ execa@^7.1.1: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + expr-eval@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expr-eval/-/expr-eval-2.0.2.tgz#fa6f044a7b0c93fde830954eb9c5b0f7fbc7e201" integrity sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg== +fast-copy@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" + integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1177,7 +3888,12 @@ fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: +fast-json-patch@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947" + integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ== + +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -1187,6 +3903,21 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-redact@^3.0.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-uri@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" + integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -1208,6 +3939,19 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1239,6 +3983,11 @@ follow-redirects@^1.14.8: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -1265,6 +4014,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fs@0.0.1-security: + version "0.0.1-security" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== + fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -1275,6 +4029,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -1290,6 +4049,11 @@ functions-have-names@^1.2.2, functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" @@ -1300,11 +4064,37 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-proto "^1.0.1" has-symbols "^1.0.3" +get-intrinsic@^1.2.4, get-intrinsic@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" + integrity sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA== + dependencies: + call-bind-apply-helpers "^1.0.1" + dunder-proto "^1.0.0" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + function-bind "^1.1.2" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.0.0" + +get-port-please@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49" + integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ== + get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1412,7 +4202,12 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.2.4: +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1422,6 +4217,22 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +h3@^1.12.0, h3@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.13.0.tgz#b5347a8936529794b6754b440e26c0ab8a60dceb" + integrity sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg== + dependencies: + cookie-es "^1.2.2" + crossws ">=0.2.0 <0.4.0" + defu "^6.1.4" + destr "^2.0.3" + iron-webcrypto "^1.2.1" + ohash "^1.1.4" + radix3 "^1.1.2" + ufo "^1.5.4" + uncrypto "^0.1.3" + unenv "^1.10.0" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -1439,6 +4250,13 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -1449,6 +4267,11 @@ has-symbols@^1.0.2, has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -1456,6 +4279,13 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1463,6 +4293,45 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-shutdown@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" + integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -1473,11 +4342,31 @@ human-signals@^4.3.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + +idb-keyval@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" + integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -1499,7 +4388,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1513,11 +4402,24 @@ internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" +iron-webcrypto@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f" + integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg== + is-any-array@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-2.0.1.tgz#9233242a9c098220290aa2ec28f82ca7fa79899e" integrity sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ== +is-arguments@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -1591,6 +4493,18 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -1687,6 +4601,13 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" +is-typed-array@^1.1.3: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -1714,21 +4635,77 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + +is64bit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is64bit/-/is64bit-2.0.0.tgz#198c627cbcb198bbec402251f88e5e1a51236c07" + integrity sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw== + dependencies: + system-architecture "^0.1.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + +it-first@^3.0.4: + version "3.0.6" + resolved "https://registry.yarnpkg.com/it-first/-/it-first-3.0.6.tgz#f532f0f36fe9bf0c291e0162b9d3375d59fe8f05" + integrity sha512-ExIewyK9kXKNAplg2GMeWfgjUcfC1FnUXz/RPfAvIXby+w7U4b3//5Lic0NV03gXT8O/isj5Nmp6KiY0d45pIQ== + +jet-logger@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jet-logger/-/jet-logger-1.2.2.tgz#f3866c0a34b6dc43f03bf4479ca677a1110156bc" + integrity sha512-Kbw4G3BC45+Umz5XBnsE50pHplruJTVKGRy5X1YfCu3Te7f8ggTL8Tm10YegAD2QP41MVQ3o/Y9MFAZzfythqw== + dependencies: + colors "1.3.0" + jiti@^1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== +jiti@^2.1.2: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.1.tgz#4de9766ccbfa941d9b6390d2b159a4b295a52e6b" + integrity sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g== + +jose@^4.14.4: + version "4.15.9" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-tiktoken@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.6.tgz#f32f4b9b3c33d11f12b5cf016b3c729370817ee9" @@ -1753,6 +4730,16 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema-typed@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-8.0.1.tgz#826ee39e3b6cef536f85412ff048d3ff6f19dfa0" + integrity sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -1770,6 +4757,15 @@ jsonpointer@^5.0.1: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== +jsontokens@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsontokens/-/jsontokens-4.0.1.tgz#c3edf74a01160b2ca6d62b021b288edd59d1184a" + integrity sha512-+MO415LEN6M+3FGsRz4wU20g7N2JA+2j9d9+pGaNJHviG4L8N0qzavGyENw6fJqsq9CcrHOIL6iWX5yeTZ86+Q== + dependencies: + "@noble/hashes" "^1.1.2" + "@noble/secp256k1" "^1.6.3" + base64-js "^1.5.1" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" @@ -1778,6 +4774,55 @@ jsonpointer@^5.0.1: array-includes "^3.1.5" object.assign "^4.1.3" +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +key-did-provider-ed25519@^3.0.1, key-did-provider-ed25519@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/key-did-provider-ed25519/-/key-did-provider-ed25519-3.0.2.tgz#5c336954680db2ae03e9d4a25cdbde30b72062b5" + integrity sha512-4Yw0CeO1hKRaUsh9NIz4tn4Ysr09CdoJItyT0vHjd5iedJ+FvVt7pTbNr7IY0/+8mWvYslutAK5LFrwu5agpsA== + dependencies: + "@noble/curves" "^1.1.0" + did-jwt "^7.2.0" + dids "^4.0.4" + fast-json-stable-stringify "^2.1.0" + rpc-utils "^0.6.2" + uint8arrays "^4.0.3" + +key-did-resolver@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/key-did-resolver/-/key-did-resolver-3.0.0.tgz#c1cc4ebeb41e7959db5d4f3d90fd96bf89507315" + integrity sha512-IyEq64AdS6lUwtn3YSvGpu7KAGA2x5+fjRCUIa8+ccSLmWrODV/ICM5aa6hHV/19EPWef8/e322r9sQJJ6/3qA== + dependencies: + "@stablelib/ed25519" "^1.0.2" + bigint-mod-arith "^3.1.0" + multiformats "^11.0.1" + nist-weierstrauss "^1.6.1" + uint8arrays "^4.0.3" + varint "^6.0.0" + +key-did-resolver@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/key-did-resolver/-/key-did-resolver-4.0.0.tgz#011910ef2db7db82977466ac6850b4976f8cd761" + integrity sha512-+U2nd/0rjO4Yqe2hnHBD7ygcLRfT43Oje9IIjv1BlBi0lopwxZpIFQ7GekguOHK02r+JGdl8mpJVNHs5lvXVOA== + dependencies: + "@noble/curves" "^1.2.0" + multiformats "^13.0.0" + uint8arrays "^5.0.1" + varint "^6.0.0" + +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" + integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== + langchain@^0.0.84: version "0.0.84" resolved "https://registry.yarnpkg.com/langchain/-/langchain-0.0.84.tgz#fa9c6ed0641d90250438b3a46b66cedaded33996" @@ -1820,6 +4865,25 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +libsodium-wrappers@^0.7.6: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz#53f13e483820272a3d55b23be2e34402ac988055" + integrity sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ== + dependencies: + libsodium "^0.7.15" + +libsodium@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.15.tgz#ac284e3dcb1c29ae9526c5581cdada6a072f6d20" + integrity sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw== + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lilconfig@^2.0.5, lilconfig@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" @@ -1830,6 +4894,62 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listhen@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.9.0.tgz#59355f7e4fc1eefda6bc494ae7e9ed13aa7658ef" + integrity sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg== + dependencies: + "@parcel/watcher" "^2.4.1" + "@parcel/watcher-wasm" "^2.4.1" + citty "^0.1.6" + clipboardy "^4.0.0" + consola "^3.2.3" + crossws ">=0.2.0 <0.4.0" + defu "^6.1.4" + get-port-please "^3.1.2" + h3 "^1.12.0" + http-shutdown "^1.2.2" + jiti "^2.1.2" + mlly "^1.7.1" + node-forge "^1.3.1" + pathe "^1.1.2" + std-env "^3.7.0" + ufo "^1.5.4" + untun "^0.1.3" + uqr "^0.1.2" + +lit-element@^3.3.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.3.tgz#10bc19702b96ef5416cf7a70177255bfb17b3209" + integrity sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.0" + "@lit/reactive-element" "^1.3.0" + lit-html "^2.8.0" + +lit-html@^2.7.0, lit-html@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.8.0.tgz#96456a4bb4ee717b9a7d2f94562a16509d39bffa" + integrity sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q== + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@2.7.6: + version "2.7.6" + resolved "https://registry.yarnpkg.com/lit/-/lit-2.7.6.tgz#810007b876ed43e0c70124de91831921598b1665" + integrity sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg== + dependencies: + "@lit/reactive-element" "^1.6.0" + lit-element "^3.3.0" + lit-html "^2.7.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -1837,11 +4957,29 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.isequal@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +logfmt@^1.3.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/logfmt/-/logfmt-1.4.0.tgz#6cb1e62cf65143a3248aa0f2823c3bd436e2251f" + integrity sha512-p1Ow0C2dDJYaQBhRHt+HVMP6ELuBm4jYSYNHPMfz0J5wJ9qA6/7oBOlBZBfT1InqguTYcvJzNea5FItDxTcbyw== + dependencies: + split "0.2.x" + through "2.3.x" + loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -1849,6 +4987,11 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1856,6 +4999,16 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +mapmoize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/mapmoize/-/mapmoize-1.2.1.tgz#a491a01dfc9f851478120057d98af9b160edf4d7" + integrity sha512-LK8ArSM1wbfRPTnl+LpdxW1pwkfY6GxtM9p+STr6aDtM7ImR8jLuf4ekei43/AN0f7XDSrohzwwK57eGHSDAuA== + +math-intrinsics@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.0.0.tgz#4e04bf87c85aa51e90d078dac2252b4eb5260817" + integrity sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -1886,6 +5039,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -1896,6 +5054,16 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1944,6 +5112,28 @@ ml-tree-similarity@^1.0.0: binary-search "^1.3.5" num-sort "^2.0.0" +mlly@^1.7.1, mlly@^1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.3.tgz#d86c0fcd8ad8e16395eb764a5f4b831590cee48c" + integrity sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A== + dependencies: + acorn "^8.14.0" + pathe "^1.1.2" + pkg-types "^1.2.1" + ufo "^1.5.4" + +motion@10.16.2: + version "10.16.2" + resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" + integrity sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ== + dependencies: + "@motionone/animation" "^10.15.1" + "@motionone/dom" "^10.16.2" + "@motionone/svelte" "^10.16.2" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + "@motionone/vue" "^10.16.2" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -1954,6 +5144,46 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multibase@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== + dependencies: + "@multiformats/base-x" "^4.0.1" + +multiformats@^11.0.0, multiformats@^11.0.1, multiformats@^11.0.2: + version "11.0.2" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-11.0.2.tgz#b14735efc42cd8581e73895e66bebb9752151b60" + integrity sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg== + +multiformats@^12.0.1: + version "12.1.3" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-12.1.3.tgz#cbf7a9861e11e74f8228b21376088cb43ba8754e" + integrity sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw== + +multiformats@^13.0.0, multiformats@^13.1.0: + version "13.3.1" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.3.1.tgz#ea30d134b5697dcf2036ac819a17948f8a1775be" + integrity sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g== + +multiformats@^9.4.2, multiformats@^9.5.4, multiformats@^9.6.2, multiformats@^9.6.5, multiformats@^9.7.1: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +multiformats@~13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.1.3.tgz#36d312401ff424948ef90746fbda9dd798cffa09" + integrity sha512-CZPi9lFZCM/+7oRolWYsvalsyWQGFo+GpdaTmjxXXomC+nP/W1Rnxb9sUgjvmNmRZ5bOPqRAl4nuK+Ydw/4tGw== + +multihashes-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/multihashes-sync/-/multihashes-sync-2.0.0.tgz#777c6ab4b32862075a775cec15f09c1e69d426df" + integrity sha512-hoBamCqXuVmeo4NAY52dbYuUIKHy3/FcqxyKZSbhqicR2SbUjgiY4FoDvE8BV40dPfAJTT6pQpqYeuKxqKwOLQ== + dependencies: + "@noble/hashes" "^1.3.3" + multiformats "^13.0.0" + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -1963,44 +5193,77 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.4, nanoid@^3.3.6: +nanoid@^3.3.1: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + +nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +napi-wasm@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.3.tgz#7bb95c88e6561f84880bb67195437b1cfbe99224" + integrity sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@13.4.4: - version "13.4.4" - resolved "https://registry.yarnpkg.com/next/-/next-13.4.4.tgz#d1027c8d77f4c51be0b39f671b4820db03c93e60" - integrity sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA== +next@14.2.4: + version "14.2.4" + resolved "https://registry.yarnpkg.com/next/-/next-14.2.4.tgz#ef66c39c71e2d8ad0a3caa0383c8933f4663e4d1" + integrity sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ== dependencies: - "@next/env" "13.4.4" - "@swc/helpers" "0.5.1" + "@next/env" "14.2.4" + "@swc/helpers" "0.5.5" busboy "1.6.0" - caniuse-lite "^1.0.30001406" - postcss "8.4.14" + caniuse-lite "^1.0.30001579" + graceful-fs "^4.2.11" + postcss "8.4.31" styled-jsx "5.1.1" - zod "3.21.4" optionalDependencies: - "@next/swc-darwin-arm64" "13.4.4" - "@next/swc-darwin-x64" "13.4.4" - "@next/swc-linux-arm64-gnu" "13.4.4" - "@next/swc-linux-arm64-musl" "13.4.4" - "@next/swc-linux-x64-gnu" "13.4.4" - "@next/swc-linux-x64-musl" "13.4.4" - "@next/swc-win32-arm64-msvc" "13.4.4" - "@next/swc-win32-ia32-msvc" "13.4.4" - "@next/swc-win32-x64-msvc" "13.4.4" + "@next/swc-darwin-arm64" "14.2.4" + "@next/swc-darwin-x64" "14.2.4" + "@next/swc-linux-arm64-gnu" "14.2.4" + "@next/swc-linux-arm64-musl" "14.2.4" + "@next/swc-linux-x64-gnu" "14.2.4" + "@next/swc-linux-x64-musl" "14.2.4" + "@next/swc-win32-arm64-msvc" "14.2.4" + "@next/swc-win32-ia32-msvc" "14.2.4" + "@next/swc-win32-x64-msvc" "14.2.4" + +nist-weierstrauss@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/nist-weierstrauss/-/nist-weierstrauss-1.6.1.tgz#ce1acd81d09f83289bc5113f14c9790920935176" + integrity sha512-FpjCOnPV/s3ZVIkeldCVSml2K4lruabPbBgoEitpCK1JL0KTVoWb56CFTU6rZn5i6VqAjdwcOp0FDwJACPmeFA== + dependencies: + multiformats "^9.6.5" + uint8arrays "^2.1.4" + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== node-ensure@^0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" integrity sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw== +node-fetch-native@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e" + integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ== + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-fetch@^2.6.11: version "2.6.11" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" @@ -2008,6 +5271,18 @@ node-fetch@^2.6.11: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-releases@^2.0.8: version "2.0.12" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" @@ -2070,6 +5345,13 @@ object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-sizeof@^2.6.1: + version "2.6.5" + resolved "https://registry.yarnpkg.com/object-sizeof/-/object-sizeof-2.6.5.tgz#84ea0760e38876532ab811987dab58a6bbf61230" + integrity sha512-Mu3udRqIsKpneKjIEJ2U/s1KmEgpl+N6cEX1o+dDl2aZ+VW5piHqNgomqAk5YMsDoSkpcA8HnIKx1eqGTKzdfw== + dependencies: + buffer "^6.0.3" + object.assign@^4.1.3, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -2115,7 +5397,31 @@ object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" -once@^1.3.0: +ofetch@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" + integrity sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw== + dependencies: + destr "^2.0.3" + node-fetch-native "^1.6.4" + ufo "^1.5.4" + +ohash@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.4.tgz#ae8d83014ab81157d2c285abf7792e2995fadd72" + integrity sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g== + +on-exit-leak-free@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" + integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -2171,6 +5477,13 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -2178,6 +5491,13 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -2208,6 +5528,16 @@ p-timeout@^3.2.0: dependencies: p-finally "^1.0.0" +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@1.0.11, pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2245,6 +5575,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.1, pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + pdf-parse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pdf-parse/-/pdf-parse-1.1.1.tgz#745e07408679548b3995ff896fd38e96e19d14a7" @@ -2268,11 +5603,86 @@ pify@^2.3.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== +pino-abstract-transport@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== + dependencies: + split2 "^4.0.0" + +pino-abstract-transport@v0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" + integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== + dependencies: + duplexify "^4.1.2" + split2 "^4.0.0" + +pino-pretty@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.0.0.tgz#21d57fe940e34f2e279905d7dba2d7e2c4f9bf17" + integrity sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.2" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pump "^3.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^4.0.1" + strip-json-comments "^3.1.1" + +pino-std-serializers@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" + integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== + +pino@7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" + integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.15.1" + pirates@^4.0.1: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== +pkg-types@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.2.1.tgz#6ac4e455a5bb4b9a6185c1c79abd544c901db2e5" + integrity sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw== + dependencies: + confbox "^0.1.8" + mlly "^1.7.2" + pathe "^1.1.2" + +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== + +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + postcss-import@^15.1.0: version "15.1.0" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" @@ -2317,15 +5727,6 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.4.14: - version "8.4.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== - dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - postcss@8.4.23, postcss@^8.4.23: version "8.4.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" @@ -2335,11 +5736,35 @@ postcss@8.4.23, postcss@^8.4.23: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + +process@0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2349,16 +5774,64 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +proxy-compare@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600" + integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +pump@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +qrcode@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" + integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^15.3.1" + +query-string@7.1.3, query-string@^7.1.0: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +radix3@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.2.tgz#fd27d2af3896c6bf4bcdfab6427c69c2afc69ec0" + integrity sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA== + react-dom@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -2386,6 +5859,28 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +readable-stream@^3.1.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -2393,6 +5888,16 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +readonly-date@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/readonly-date/-/readonly-date-1.0.0.tgz#5af785464d8c7d7c40b9d738cbde8c646f97dcd9" + integrity sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ== + +real-require@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" + integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== + regenerator-runtime@^0.13.11: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" @@ -2412,6 +5917,21 @@ regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0: define-properties "^1.2.0" functions-have-names "^1.2.3" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -2452,6 +5972,18 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160-min@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/ripemd160-min/-/ripemd160-min-0.0.6.tgz#a904b77658114474d02503e819dcc55853b67e62" + integrity sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A== + +rpc-utils@^0.6.1, rpc-utils@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rpc-utils/-/rpc-utils-0.6.2.tgz#3cab779f93048eda69ff198c58b1a2c2e35e3fa6" + integrity sha512-kzk1OflbBckfDBAo8JwsmtQSHzj+6hxRt5G+u8A8ZSmunBw1nhWvRkSq8j1+EvWBqBRLy1aiGLUW5644CZqQtA== + dependencies: + nanoid "^3.3.1" + run-applescript@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" @@ -2466,6 +5998,23 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.1.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -2475,6 +6024,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-stable-stringify@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -2482,6 +6036,16 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secure-json-parse@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -2494,6 +6058,28 @@ semver@^7.3.7: dependencies: lru-cache "^6.0.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2520,6 +6106,30 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +siwe-recap@0.0.2-alpha.0: + version "0.0.2-alpha.0" + resolved "https://registry.yarnpkg.com/siwe-recap/-/siwe-recap-0.0.2-alpha.0.tgz#75a0902c10a8ba5b4471f40e4eafb0afb2f8db59" + integrity sha512-xqFUnvrACWW/Q4s5HQ02avg8IyH2RcgkUzfvN4scYaaHErotLVtTGDZkSS0sn/oNK4MXRt83lTqredsvXgt8iA== + dependencies: + canonicalize "^2.0.0" + multiformats "^11.0.2" + siwe "^2.1.4" + +siwe@^2.0.5, siwe@^2.1.4, siwe@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/siwe/-/siwe-2.3.2.tgz#0794ae25f734f3068de0ab093ddd2f7867bc2d67" + integrity sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA== + dependencies: + "@spruceid/siwe-parser" "^2.1.2" + "@stablelib/random" "^1.0.1" + uri-js "^4.4.1" + valid-url "^1.0.9" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -2530,11 +6140,52 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +sonic-boom@^2.2.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== + dependencies: + atomic-sleep "^1.0.0" + +sonic-boom@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== + dependencies: + atomic-sleep "^1.0.0" + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +split@0.2.x: + version "0.2.10" + resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" + integrity sha512-e0pKq+UUH2Xq/sXbYpZBZc3BawsfDZ7dgv+JtRTUPNcvF5CMR4Y9cvJqkMY0MoxWzTHvZuz1beg6pNEKlszPiQ== + dependencies: + through "2" + +sprintf-js@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + +std-env@^3.7.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" + integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== + stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -2542,11 +6193,30 @@ stop-iteration-iterator@^1.0.0: dependencies: internal-slot "^1.0.4" +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string.prototype.matchall@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" @@ -2588,7 +6258,21 @@ string.prototype.trimstart@^1.0.6: define-properties "^1.1.4" es-abstract "^1.20.4" -strip-ansi@^6.0.1: +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -2655,6 +6339,11 @@ synckit@^0.8.5: "@pkgr/utils" "^2.3.1" tslib "^2.5.0" +system-architecture@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d" + integrity sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA== + tailwind-merge@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.2.0.tgz#b6bb1c63ef26283c9e6675ba237df83bbd554688" @@ -2720,6 +6409,18 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +thread-stream@^0.15.1: + version "0.15.2" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" + integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== + dependencies: + real-require "^0.1.0" + +through@2, through@2.3.x: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + titleize@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" @@ -2752,11 +6453,26 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@1.14.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^2.4.0, tslib@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" @@ -2769,6 +6485,16 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -2790,11 +6516,49 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" +typeforce@^1.11.3: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + typescript@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +ufo@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" + integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== + +uint8arrays@3.1.1, uint8arrays@^3.0.0, uint8arrays@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== + dependencies: + multiformats "^9.4.2" + +uint8arrays@^2.1.4: + version "2.1.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== + dependencies: + multiformats "^9.4.2" + +uint8arrays@^4.0.2, uint8arrays@^4.0.3, uint8arrays@^4.0.9: + version "4.0.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-4.0.10.tgz#3ec5cde3348903c140e87532fc53f46b8f2e921f" + integrity sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA== + dependencies: + multiformats "^12.0.1" + +uint8arrays@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-5.1.0.tgz#14047c9bdf825d025b7391299436e5e50e7270f1" + integrity sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww== + dependencies: + multiformats "^13.0.0" + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -2805,11 +6569,67 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + +unenv@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.10.0.tgz#c3394a6c6e4cfe68d699f87af456fe3f0db39571" + integrity sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ== + dependencies: + consola "^3.2.3" + defu "^6.1.4" + mime "^3.0.0" + node-fetch-native "^1.6.4" + pathe "^1.1.2" + +unstorage@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.13.1.tgz#090b30de978ee8755b3ad7bbc00acfade124ac13" + integrity sha512-ELexQHUrG05QVIM/iUeQNdl9FXDZhqLJ4yP59fnmn2jGUh0TEulwOgov1ubOb3Gt2ZGK/VMchJwPDNVEGWQpRg== + dependencies: + anymatch "^3.1.3" + chokidar "^3.6.0" + citty "^0.1.6" + destr "^2.0.3" + h3 "^1.13.0" + listhen "^1.9.0" + lru-cache "^10.4.3" + node-fetch-native "^1.6.4" + ofetch "^1.4.1" + ufo "^1.5.4" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== +untun@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6" + integrity sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ== + dependencies: + citty "^0.1.5" + consola "^3.2.3" + pathe "^1.1.1" + update-browserslist-db@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" @@ -2818,23 +6638,88 @@ update-browserslist-db@^1.0.10: escalade "^3.1.1" picocolors "^1.0.0" -uri-js@^4.2.2: +uqr@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" + integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== + +uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" -util-deprecate@^1.0.2: +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + uuid@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +valid-url@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== + +valtio@1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.11.0.tgz#c029dcd17a0f99d2fbec933721fe64cfd32a31ed" + integrity sha512-65Yd0yU5qs86b5lN1eu/nzcTgQ9/6YnD6iO+DDaDbQLn1Zv2w12Gwk43WkPlUBxk5wL/6cD5YMFf7kj6HZ1Kpg== + dependencies: + proxy-compare "2.5.1" + use-sync-external-store "1.2.0" + +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + +varintes@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/varintes/-/varintes-2.0.5.tgz#e5e2e53b10300ca4d5c0bacae2a826f7b3b2cab5" + integrity sha512-iF3jlHLko9NrYjaUZvT3VwypP3V20KNNhT1tzqblyIyrVjNiW7HseGOhuP+apgZBp9X/8+5pxa7kNikhJeZlIw== + +varuint-bitcoin@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92" + integrity sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw== + dependencies: + safe-buffer "^5.1.1" + +viem@^1.21.4: + version "1.21.4" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.21.4.tgz#883760e9222540a5a7e0339809202b45fe6a842d" + integrity sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "0.9.8" + isows "1.0.3" + ws "8.13.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -2869,6 +6754,22 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.14, which-typed-array@^1.1.2: + version "1.1.16" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.16.tgz#db4db429c4706feca2f01677a144278e4a8c216b" + integrity sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" @@ -2893,11 +6794,45 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@^7.5.1: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" @@ -2908,6 +6843,31 @@ yaml@^2.1.1, yaml@^2.2.1: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" @@ -2918,7 +6878,7 @@ zod-to-json-schema@^3.20.4: resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.21.1.tgz#a24b2737bf361fc516c92421eb59988b6e2fc046" integrity sha512-y5g0MPxDq+YG/T+cHGPYH4PcBpyCqwK6wxeJ76MR563y0gk/14HKfebq8xHiItY7lkc9GDFygCnkvNDTvAhYAg== -zod@3.21.4, zod@^3.21.4: +zod@^3.21.4: version "3.21.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==