### Installation Source: https://github.com/plebbit/plebbit-js/blob/master/docs/testing.md Installs the project dependencies using npm. ```bash npm install ``` -------------------------------- ### Editing and Starting a Subplebbit Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Shows how to edit the information of an existing subplebbit and how to start publishing its updates. This includes updating the title, description, and pubsub topic, and then initiating the publishing process. ```javascript // edit the subplebbit info in the database await subplebbit.edit({ title: 'Memes', description: 'Post your memes here.', pubsubTopic: '12D3KooW...' }) // start publishing updates every 5 minutes await subplebbit.start() ``` -------------------------------- ### Create and Manage Subplebbit Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Demonstrates how to create a new subplebbit, edit its properties like title, description, and pubsub topic, and then start publishing updates. ```js const options = { title: 'Your subplebbit title' } const subplebbit = await plebbit.createSubplebbit(options) // edit the subplebbit info in the database await subplebbit.edit({ title: 'Memes', description: 'Post your memes here.', pubsubTopic: '12D3KooW...' }) // start publishing updates/new posts await subplebbit.start() ``` -------------------------------- ### Plebbit API Documentation Source: https://github.com/plebbit/plebbit-js/blob/master/README.md API documentation for the plebbit-js library, detailing methods for creating multisubs and subplebbits, including their options, parameters, return types, and usage examples. ```APIDOC plebbit.createMultisub(createMultisubOptions) Create a multisub instance. A multisub is a list of subplebbits curated by the creator of the multisub. E.g. 'plebbit.eth/#/m/john.eth' would display a feed of the multisub subplebbits curated by 'john.eth' (multisub Address 'john.eth'). Parameters: createMultisubOptions: CreateMultisubOptions | Options for the Multisub instance CreateMultisubOptions: address: string | undefined | Address of the multisub signer: Signer | undefined | (Multisub owners only) Optional Signer of the subplebbit to create a multisub with a specific private key title: string | undefined | Title of the multisub description: string | undefined | Description of the multisub subplebbits: MultisubSubplebbit[] | undefined | List of MultisubSubplebbit of the multisub Returns: Promise | A Multisub instance Example: const multisubOptions = {signer} const multisub = await plebbit.createMultisub(multisubOptions) // edit the multisub info in the database (only in Node and if multisub.signer is defined) await multisub.edit({ address: 'funny-subs.eth', title: 'Funny subplebbits', description: 'The funniest subplebbits', }) // add a list of subplebbits to the multisub in the database (only in Node and if multisub.signer is defined) const multisubSubplebbit1 = {address: 'funny.eth', title: 'Funny things', tags: ['funny']} const multisubSubplebbit2 = {address: 'even-more-funny.eth'} await multisub.edit({subplebbits: [multisubSubplebbit1, multisubSubplebbit2]}) // start publishing updates to your multisub (only in Node and if multisub.signer is defined) await multisub.start() // stop publishing updates to your multisub await multisub.stop() plebbit.createSubplebbit(createSubplebbitOptions) Create a subplebbit instance. Should update itself on update events after Subplebbit.update() is called if CreateSubplebbitOptions.address exists. If the subplebbit database corresponding to subplebbit.address exists locally, can call Subplebbit.edit(subplebbitEditOptions) to edit the subplebbit as the owner, and Subplebbit.start() to listen for new posts on the pubsub and publish updates as the owner. Parameters: createSubplebbitOptions: CreateSubplebbitOptions | Options for the Subplebbit instance CreateSubplebbitOptions: address: string | undefined | undefined | Address of the subplebbit signer: Signer | undefined | undefined | (Subplebbit owners only) Optional Signer of the subplebbit to create a subplebbit with a specific private key ...subplebbit: any | undefined | CreateSubplebbitOptions can also initialize any property on the Subplebbit instance Returns: Promise | A Subplebbit instance ``` -------------------------------- ### Plebbit Default Settings Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Outlines the default configuration settings loaded when the application starts. This includes mappings of default multisub names to their addresses, used for initial content display and search. ```APIDOC PlebbitDefaults { // fetched once when app first load, a dictionary of default settings multisubAddresses: {[multisubName: string]: Address} // plebbit has 3 default multisubs multisubAddresses.all: Address // the default subplebbits to show at url plebbit.eth/p/all multisubAddresses.crypto: Address // the subplebbits to show at url plebbit.eth/p/crypto multisubAddresses.search: Address // list of thousands of semi-curated subplebbits to "search" for in the client (only search the Multisub metadata, don't load each subplebbit) } ``` -------------------------------- ### Create Comment Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Creates a new comment instance. This function handles the initial setup of a comment, including optional properties like content, author, and associated metadata. It returns a Promise that resolves to a Comment instance, which can then be used to publish the comment or handle challenge events. ```APIDOC plebbit.createComment(createCommentOptions) Parameters: createCommentOptions: Object subplebbitAddress: string - Address of the subplebbit. timestamp: number | undefined - Time of publishing in seconds. Defaults to current time if undefined. author: Author - Author of the comment. signer: Signer - Signer of the comment. parentCid: string | undefined - CID of the parent comment. Undefined for top-level posts. content: string | undefined - Content of the comment. Link posts may not have content. title: string | undefined - Title for posts. link: string | undefined - URL for link posts. spoiler: boolean | undefined - Whether the comment thumbnail is hidden by a spoiler warning. flair: Flair | undefined - Author or mod chosen label for the comment. challengeRequest: ChallengeRequest | undefined - Optional properties for ChallengeRequestPubsubMessage. cid: string | undefined - (Not for publishing) Used to access Comment.on('update') for fetched comments. ...comment: any - Initializes any property on the Comment instance. Returns: Promise - A Promise that resolves to a Comment instance. Example: ```js const comment = await plebbit.createComment(createCommentOptions) comment.on('challenge', async (challengeMessage) => { const challengeAnswers = await askUserForChallengeAnswers(challengeMessage.challenges) comment.publishChallengeAnswers(challengeAnswers) }) comment.on('challengeverification', console.log) await comment.publish() // Initialize any property on the Comment instance const comment = await plebbit.createComment({ cid: 'Qm...', content: 'My first post', locked: true, upvoteCount: 100, replies: { pages: { topAll: { nextCid: 'Qm...', comments: [{content: 'My first reply', ...reply}] } }, pageCids: {new: 'Qm...', old: 'Qm...', ...pageCids} } }) console.log(comment.content) // prints 'My first post' console.log(comment.locked) // prints true console.log(comment.upvoteCount) // prints 100 console.log(comment.replies.pages.topAll.comments[0].content) // prints 'My first reply' ``` ``` -------------------------------- ### Start Subplebbit Updates Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Initiates polling for new posts on the pubsub and publishes them every 5 minutes. This functionality is only available if the corresponding subplebbit database exists locally, indicating ownership. ```js await subplebbit.start() ``` -------------------------------- ### Subplebbit 'startedstatechange' Event Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Fired when the `Subplebbit.startedState` property changes. The emitted value indicates the new started state, which can be 'stopped', 'fetching-ipns', 'publishing-ipns', 'failed', or 'succeeded'. ```APIDOC startedstatechange: Emits: 'stopped' | 'fetching-ipns' | 'publishing-ipns' | 'failed' | 'succeeded' The Subplebbit.startedState property ``` -------------------------------- ### Making Client Requests with JSON-RPC Websocket Source: https://github.com/plebbit/plebbit-js/blob/master/src/rpc/README.md This code example shows how to establish a connection to the Plebbit websocket server and make JSON-RPC calls. It utilizes the 'rpc-websockets' library and includes logic for handling subscription messages and managing listeners for real-time updates. It demonstrates fetching a comment and subscribing to comment updates. ```javascript const WebSocketClient = require('rpc-websockets').Client // or any JSON RPC websocket compatible library const webSocketClient = new WebSocketClient(`ws://localhost:${port}`) // debug raw JSON RPC messages in console (optional) webSocketClient.socket.on('message', (message) => console.log('from server:', message.toString())) // wait for websocket connection to open await new Promise((resolve) => webSocketClient.on('open', resolve)) // save all subscription messages (ie json rpc messages without 'id', also called json rpc 'notifications') // NOTE: it is possible to receive a subscription message before receiving the subscription id const subscriptionsMessages = {} webSocketClient.socket.on('message', (jsonMessage) => { const message = JSON.parse(jsonMessage) const subscriptionId = message?.params?.subscription if (subscriptionId) { if (!subscriptionsMessages[subscriptionId]) { subscriptionsMessages[subscriptionId] = [] } subscriptionsMessages[subscriptionId].push(message) // delete the message after 1 minute to not cause memory leak setTimeout(() => subscriptionsMessages[subscriptionId].shift(), 60000) } }) class Subscription extends EventEmitter { constructor(subscriptionId) { super() let emittingMessages = false this.on('newListener', (eventName) => { // emit all subscription messages received before the listener started if (eventName === 'message') { for (const message of subscriptionsMessages[subscriptionId] || []) { this.emit('message', message) } } // emit all new messages if (!emittingMessages) { emittingMessages = true webSocketClient.socket.on('message', emitMessage) } }) // stop listening if listener is removed this.on('removeListener', (eventName) => { if (eventName === 'message' && this.listenerCount('message') === 0) { emittingMessages = false webSocketClient.socket.off('message', emitMessage) } }) function emitMessage(jsonMessage) { const message = JSON.parse(jsonMessage) if (subscriptionId === message?.params?.subscription) { this.emit('message', message) } } } } // get comment const commentCid = 'Qm...' const comment = await webSocketClient.call('getComment', [commentCid]) console.log(comment) // get comment updates const subscriptionId = await webSocketClient.call('commentUpdateSubscribe', [comment.cid]) new Subscription(subscriptionId).on('message', console.log) ``` -------------------------------- ### Subplebbit API Methods Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Provides methods for managing and interacting with a specific subplebbit, including editing, starting, stopping, and updating its state. ```APIDOC subplebbit.edit(subplebbitEditOptions) - Edits the subplebbit. - Parameters: - subplebbitEditOptions: Options for editing the subplebbit. - Returns: A Promise that resolves when the edit is complete. subplebbit.start() - Starts the subplebbit. - Returns: A Promise that resolves when the subplebbit is started. subplebbit.stop() - Stops the subplebbit. - Returns: A Promise that resolves when the subplebbit is stopped. subplebbit.update() - Updates the subplebbit. - Returns: A Promise that resolves when the subplebbit is updated. subplebbit.delete() - Deletes the subplebbit. subplebbit.address - Property: The address of the subplebbit. subplebbit.shortAddress - Property: The short address of the subplebbit. subplebbit.roles - Property: The roles associated with the subplebbit. subplebbit.posts - Property: The posts within the subplebbit. subplebbit.lastPostCid - Property: The CID of the last post. subplebbit.pubsubTopic - Property: The Pub/Sub topic for the subplebbit. subplebbit.rules - Property: The rules of the subplebbit. subplebbit.flairs - Property: The flairs available in the subplebbit. subplebbit.suggested - Property: Suggested content for the subplebbit. subplebbit.features - Property: Enabled features for the subplebbit. subplebbit.settings - Property: Settings for the subplebbit. subplebbit.createdAt - Property: The creation timestamp of the subplebbit. subplebbit.updatedAt - Property: The last update timestamp of the subplebbit. subplebbit.statsCid - Property: The CID for subplebbit statistics. subplebbit.updateCid - Property: The CID for subplebbit updates. subplebbit.signer - Property: The signer associated with the subplebbit. subplebbit.started - Property: Boolean indicating if the subplebbit has started. subplebbit.state - Property: The current state of the subplebbit. subplebbit.updatingState - Property: The updating state of the subplebbit. subplebbit.startedState - Property: The started state of the subplebbit. ``` -------------------------------- ### Plebbit Get Defaults Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Retrieves the default global plebbit settings, including default multisub addresses. This is useful for accessing common plebbit configurations. ```js const plebbitDefaults = await plebbit.getDefaults() const allMultisub = await plebbit.getMultisub(plebbitDefaults.multisubAddresses.all) const allSubplebbitAddresses = allMultisub.map(subplebbit => subplebbit.address) console.log(allSubplebbitAddresses) ``` -------------------------------- ### Plebbit API Documentation Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Detailed API documentation for Plebbit functionalities including creating comment moderation and votes. It outlines parameters, options, return types, and provides usage examples. ```APIDOC plebbit.createCommentModeration(createCommentModerationOptions) Description: Create a CommentModeration instance, which can be used by moderators to remove comments. A CommentModeration must still be published and go through a challenge handshake. Parameters: createCommentModerationOptions: CreateCommentModerationOptions - The comment moderation to create CreateCommentModerationOptions: subplebbitAddress: string - Address of the subplebbit commentCid: string - The comment CID to be edited timestamp: number | undefined - Time of publishing in ms, Math.round(Date.now() / 1000) if undefined author: Author - Author of the CommentModeration publication, must be moderator signer: Signer - Signer of the edit, must be moderator commentModeration: CommentModerationOptions - The comment moderation options challengeRequest: ChallengeRequest | undefined - Optional properties to pass to ChallengeRequestPubsubMessage CommentModerationOptions: flair: Flair | undefined - Edited flair of the comment spoiler: boolean | undefined - Edited spoiler of the comment reason: string | undefined - Reason of the edit pinned: boolean | undefined - Edited pinned status of the comment locked: boolean | undefined - Edited locked status of the comment removed: boolean | undefined - Edited removed status of the comment author: CommentModerationAuthorOptions | undefined - Edited author property of the comment CommentModerationAuthorOptions: banExpiresAt: number | undefined - Comment author was banned for this comment flair: Flair | undefined - Edited flair of the comment author Returns: Promise - A CommentModeration instance Example: const commentModeration = await plebbit.createCommentModeration(createCommentModerationOptions) commentModeration.on('challenge', async (challengeMessage, _commentModeration) => { const challengeAnswers = await askUserForChallengeAnswers(challengeMessage.challenges) _commentModeration.publishChallengeAnswers(challengeAnswers) }) commentModeration.on('challengeverification', console.log) await commentModeration.publish() plebbit.createVote(createVoteOptions) Description: Create a Vote instance. Vote inherits from Publication, like Comment, so has the same API. Parameters: createVoteOptions: CreateVoteOptions - The vote to create CreateVoteOptions: subplebbitAddress: string - Address of the subplebbit commentCid: string - The comment or post to vote on timestamp: number | undefined - Time of publishing in ms, Math.round(Date.now() / 1000) if undefined author: Author - Author of the comment, will be needed for voting with NFTs or tokens vote: 1 | 0 | -1 - 0 is for resetting a vote signer: Signer - Signer of the vote challengeRequest: ChallengeRequest | undefined - Optional properties to pass to ChallengeRequestPubsubMessage ChallengeRequest: challengeAnswers: string[] | undefined - Optional pre-answers to subplebbit.challenges challengeCommentCids: string[] | undefined - Optional comment cids for subplebbit.challenges related to author karma/age in other subs Returns: Promise - A Vote instance ``` -------------------------------- ### JSON-RPC Pubsub Websocket API Documentation Source: https://github.com/plebbit/plebbit-js/blob/master/src/rpc/README.md This section provides comprehensive documentation for the JSON-RPC Pubsub Websocket API. It covers various methods for subscribing to real-time updates, publishing content, and managing subscriptions. Each method includes its purpose, parameters, expected results, request/response examples, and notification formats. ```APIDOC JSON-RPC Pubsub Websocket API This API allows clients to subscribe to real-time updates for comments and subplebbits, publish new comments and votes, and manage these subscriptions. ## Methods: ### commentUpdateSubscribe - **Description**: Subscribe to a comment update to receive notifications when the comment is updated (e.g., has a new reply). - **Parameters**: - `cid` (string): The CID of the comment to subscribe to. - **Result**: - `number`: Subscription ID, used for unsubscribing. - **Request Example**: ```json { "jsonrpc": "2.0", "id": 1, "method": "commentUpdateSubscribe", "params": [ "Qm..." ] } ``` - **Response Example**: ```json { "jsonrpc": "2.0", "result": 23784, "id": 1 } ``` - **Notification Formats**: - `update` event: ```json { "jsonrpc": "2.0", "method": "commentUpdateNotification", "params": { "result": { "cid": "Qm...", "upvoteCount": 1, "downvoteCount": 0, "replyCount": 0, "updatedAt": 1689886478 }, "event": "update", "subscription": 23784 } } ``` - `updatingstatechange` event: ```json { "jsonrpc": "2.0", "method": "commentUpdateNotification", "params": { "result": "fetching-ipfs", "event": "updatingstatechange", "subscription": 23784 } } ``` ### subplebbitUpdateSubscribe - **Description**: Subscribe to a subplebbit update to receive notifications when the subplebbit is updated (e.g., has a new post). - **Parameters**: - `address` (string): The address of the subplebbit to subscribe to. - **Result**: - `number`: Subscription ID, used for unsubscribing. - **Request Example**: ```json { "jsonrpc": "2.0", "id": 1, "method": "subplebbitUpdateSubscribe", "params": [ "memes.eth" ] } ``` - **Response Example**: ```json { "jsonrpc": "2.0", "result": 23784, "id": 1 } ``` - **Notification Formats**: - `update` event: ```json { "jsonrpc": "2.0", "method": "subplebbitUpdateNotification", "params": { "result": { "title": "Memes", "description": "Publish memes here", "updatedAt": 1689886478 }, "event": "update", "subscription": 23784 } } ``` - `updatingstatechange` event: ```json { "jsonrpc": "2.0", "method": "subplebbitUpdateNotification", "params": { "result": "fetching-ipfs", "event": "updatingstatechange", "subscription": 23784 } } ``` ### publishComment - **Description**: Publish a comment and subscribe to receive notifications of the challenge pubsub message received and other publishing state changes. - **Parameters**: - `comment` (Comment): The comment object to publish. - `challengeAnswers` (array of strings): Answers to the challenge. - **Result**: - `number`: Subscription ID, used for unsubscribing and publishing challenge answers. - **Request Example**: ```json { "jsonrpc": "2.0", "id": 1, "method": "publishComment", "params": [{ "comment": { "title": "Hello", "content": "World", "author": {"address": "john.eth"}, "signature": { "signature": "...", "publicKey": "...", "type": "ed25519", "signedPropertyNames": ["title", "content", "author"] } }, "challengeAnswers": ["some answer"] }] } ``` - **Response Example**: ```json { "jsonrpc": "2.0", "result": 23784, "id": 1 } ``` ### publishVote - **Description**: Publish a vote. - **Parameters**: - `vote` (object): The vote object. - `challengeAnswers` (array of strings): Answers to the challenge. - `challengeCommentCids` (array of strings): CIDs of challenged comments. ### publishCommentEdit - **Description**: Publish an edited comment. - **Parameters**: - `commentEdit` (object): The comment edit object. - `challengeAnswers` (array of strings): Answers to the challenge. - `challengeCommentCids` (array of strings): CIDs of challenged comments. ### publishCommentModeration - **Description**: Publish comment moderation status. - **Parameters**: - `commentModeration` (object): The comment moderation object. - `challengeAnswers` (array of strings): Answers to the challenge. - `challengeCommentCids` (array of strings): CIDs of challenged comments. ### publishChallengeAnswers - **Description**: Publish answers to a challenge. - **Parameters**: - `subscriptionId` (number): The ID of the subscription. - `challengeAnswers` (object): The challenge answers. ### startSubplebbit - **Description**: Start a subplebbit. - **Parameters**: - `address` (string): The address of the subplebbit to start. ### subplebbitsSubscribe - **Description**: Subscribe to all subplebbit updates. - **Parameters**: None. - **Result**: - `number`: Subscription ID. ### settingsSubscribe - **Description**: Subscribe to settings updates. - **Parameters**: None. - **Result**: - `number`: Subscription ID. ### unsubscribe - **Description**: Unsubscribe from a subscription. - **Parameters**: - `subscriptionId` (number): The ID of the subscription to unsubscribe from. ``` -------------------------------- ### Pages API: Get Page Instance Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Retrieves a Page instance using an IPFS CID. This is used for fetching paginated content like posts or replies, sorted by different criteria. It depends on the existence of pageCIDs for the desired sort type. ```APIDOC pages.getPage(pageCid) Parameters: pageCid (string): The IPFS CID of the page. Returns: Promise: A Promise that resolves to a Page instance. Example: // Get sorted posts in a subplebbit const subplebbit = await plebbit.getSubplebbit(subplebbitAddress) const pageSortedByTopYear = await subplebbit.posts.getPage(subplebbit.posts.pageCids.topYear) const postsSortedByTopYear = pageSortedByTopYear.comments console.log(postsSortedByTopYear) // Get sorted replies to a post or comment const post = await plebbit.getComment(commentCid) post.on('update', async updatedPost => { let replies // try to get sorted replies by sort type 'new' // sorted replies pages are not always available, for example if the post only has a few replies if (updatedPost.replies?.pageCids?.new) { const repliesPageSortedByNew = await updatedPost.replies.getPage(updatedPost.replies.pageCids.new) replies = repliesPageSortedByNew.comments } else { // the 'topAll' sort type is always preloaded by default on replies and can be used as fallback // on subplebbits.posts only 'hot' is preloaded by default replies = updatedPost.replies.pages.topAll.comments } console.log(replies) }) ``` -------------------------------- ### Example NFT Data Structures Source: https://github.com/plebbit/plebbit-js/blob/master/docs/nft.md Demonstrates the structure of NFT objects used within the project, including chain ticker, contract address, token ID, and timestamp. These objects are used as input for NFT resolution and signature functions. ```javascript const avatarNft = { chainTicker: 'eth', address: '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d', // the contract address of the nft timestamp: Math.round(Date.now() / 1000), id: 100 // the nft number 100 in the colletion } const avatarNft2 = { chainTicker: 'matic', address: '0xf6d8e606c862143556b342149a7fe0558c220375', // the contract address of the nft timestamp: Math.round(Date.now() / 1000), id: 100 // the nft number 100 in the colletion } const author = { address: 'some test address...', avatar: avatarNft } ``` -------------------------------- ### Test Preparation Source: https://github.com/plebbit/plebbit-js/blob/master/docs/testing.md Steps to prepare the environment for running tests, including setting up environment variables and running build processes. ```bash # Create a .env file and add CHROME_BIN=/usr/bin/chromium (replace the path with your chrome path) # In a new terminal run npm run build:watch to compile typescript # In a new terminal run npm run webpack:watch to compile the browser tests # In a new terminal run npm run test:server to start an ipfs node and the test subplebbits # (Optional) run all the scripts at the same time with scripts/build-watch-all ``` -------------------------------- ### Resolve ENS Names with Plebbit JS Source: https://github.com/plebbit/plebbit-js/blob/master/docs/ens.md This code snippet demonstrates how to resolve ENS names for author and subplebbit addresses using the ethers.js library within the plebbit-js project. It includes functions to get blockchain providers, resolve ENS text records, and then use these to resolve author and subplebbit addresses. The example shows how to call these functions with a sample ENS name. ```js const ethers = require('ethers') // the user can edit these blockchains settings in the account or plebbit-js settings const chainProviders = { avax: { url: 'https://api.avax.network/ext/bc/C/rpc', chainId: 43114 }, matic: { url: 'https://polygon-rpc.com', chainId: 137 } } // cache the blockchain providers because only 1 should be running at the same time const cachedChainProviders = {} const getChainProvider = (chainTicker) => { if (cachedChainProviders[chainTicker]) { return cachedChainProviders[chainTicker] } if (chainProviders[chainTicker]) { cachedChainProviders[chainTicker] = new ethers.providers.JsonRpcProvider({url: chainProviders[chainTicker].url}, chainProviders[chainTicker].chainId) return cachedChainProviders[chainTicker] } if (chainTicker === 'eth') { cachedChainProviders['eth'] = ethers.getDefaultProvider() return cachedChainProviders['eth'] } throw Error(`no chain provider settings for chain ticker '${chainTicker}'`) } const resolveEnsTxtRecord = async (ensName, txtRecordName) => { const chainProvider = getChainProvider('eth') const resolver = await chainProvider.getResolver(ensName) const txtRecordResult = await resolver.getText(txtRecordName) return txtRecordResult } const resolveAuthorAddress = async (authorAddress) => { if (authorAddress.endsWith('.eth')) { return resolveEnsTxtRecord(authorAddress, 'plebbit-author-address') } return authorAddress } const resolveSubplebbitAddress = async (subplebbitAddress) => { if (subplebbitAddress.endsWith('.eth')) { return resolveEnsTxtRecord(subplebbitAddress, 'subplebbit-address') } return subplebbitAddress } ;(async () => { // resolve ens name (replace 'plebbit.eth' with 'john.eth' or whatever the address is) // this needs to be called when verifying the comment.signature, but not the nft.signature const authorAddressPublicKeyHash = await resolveAuthorAddress('plebbit.eth') const subplebbitAddressPublicKeyHash = await resolveSubplebbitAddress('plebbit.eth') console.log({authorAddressPublicKeyHash, subplebbitAddressPublicKeyHash}) })() ``` -------------------------------- ### Build Process Source: https://github.com/plebbit/plebbit-js/blob/master/docs/testing.md Command to build the project. ```bash npm run build ``` -------------------------------- ### Plebbit Get Defaults Return Type Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Specifies the return type for `plebbit.getDefaults`, which is a `Promise` resolving to a `PlebbitDefaults` instance. ```APIDOC PlebbitDefaults: Promise Description: A `PlebbitDefaults` instance. ``` -------------------------------- ### Plebbit Initialization and Subplebbit Creation Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Demonstrates how to initialize the Plebbit library with custom options and create new subplebbits. It covers creating subplebbits with default settings, custom titles and descriptions, and using pre-made signers. It also shows how to instantiate an existing subplebbit and access its properties. ```javascript const Plebbit = require('@plebbit/plebbit-js') const plebbitOptions = { ipfsGatewayUrls: ['https://cloudflare-ipfs.com'], kuboRpcClientsOptions: ['http://localhost:5001/api/v0'], // optional, must run an IPFS node to use localhost:5001/api/v0 dataPath: __dirname } const plebbit = await Plebbit(plebbitOptions) plebbit.on('error', console.log) // create a new local subplebbit as the owner const subplebbit = await plebbit.createSubplebbit() // create a new local subplebbit as the owner, already with settings const subplebbit = await plebbit.createSubplebbit({title: 'Memes', description: 'Post your memes here.'}) // create a new local subplebbit as the owner with a premade signer const signer = await plebbit.createSigner() const subplebbit = await plebbit.createSubplebbit({signer}) // signer.address === subplebbit.address // create a new local subplebbit as the owner with a premade signer, already with settings const signer = await plebbit.createSigner() const subplebbit = await plebbit.createSubplebbit({signer, title: 'Memes', description: 'Post your memes here.'}) // instantiate an already existing subplebbit instance const subplebbitOptions = {address: '12D3KooW...',} const subplebbit = await plebbit.createSubplebbit(subplebbitOptions) // instantiate an already existing subplebbit instance and initialize any property on it const subplebbit = await plebbit.createSubplebbit({ address: '12D3KooW...', title: 'Memes', posts: { pages: { hot: { nextCid: 'Qm...', comments: [{content: 'My first post', ...post}] } }, pageCids: {topAll: 'Qm...', new: 'Qm...', ...pageCids} } }) console.log(subplebbit.title) // prints 'Memes' console.log(subplebbit.posts.pages.hot.comments[0].content) // prints 'My first post' ``` -------------------------------- ### Plebbit Initialization Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Initializes a new Plebbit instance with customizable options. Supports configuring IPFS gateways, Kubo RPC clients, pubsub clients, plebbit RPC clients, data paths, chain providers, and address resolution. ```javascript const Plebbit = require('@plebbit/plebbit-js') const options = { ipfsGatewayUrls: ['https://cloudflare-ipfs.com'], kuboRpcClientsOptions: ['http://localhost:5001/api/v0'], // optional, must run an IPFS node to use localhost:5001/api/v0 dataPath: __dirname } const plebbit = await Plebbit(options) // should be independent instance, not singleton plebbit.on('error', console.log) ``` -------------------------------- ### Subplebbit 'statechange' Event Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Fired when the `Subplebbit.state` property changes. The emitted value indicates the new state, which can be 'stopped', 'updating', or 'started'. ```APIDOC statechange: Emits: 'stopped' | 'updating' | 'started' The Subplebbit.state property ``` -------------------------------- ### Running the Plebbit JSON-RPC Websocket Server Source: https://github.com/plebbit/plebbit-js/blob/master/src/rpc/README.md This snippet demonstrates how to initialize and run the Plebbit JSON-RPC websocket server. It includes setting up the server with specified options and handling connection and error events. Dependencies include the '@plebbit/plebbit-js/rpc' module. ```javascript const {PlebbitWsServer} = require('@plebbit/plebbit-js/rpc') const port = 8080 const plebbitOptions = {ipfsHttpClientsOptions: ['http://localhost:5001/api/v0']} const plebbitWebSocketServer = await PlebbitWsServer({port, plebbitOptions}) // debug raw JSON RPC messages in console (optional) plebbitWebSocketServer.ws.on('connection', (socket, request) => { console.log('connection') socket.on('message', (message) => console.log(message.toString())) }) // handle plebbit and wss errors plebbitWebSocketServer.on('error', console.log) console.log(`test server plebbit wss listening on port ${port}`) ``` -------------------------------- ### Running Tests Source: https://github.com/plebbit/plebbit-js/blob/master/docs/testing.md Commands to execute different types of tests within the project. ```bash npm run test:node npm run test:browser npm test DEBUG=plebbit-js:* npm test ``` -------------------------------- ### Stop Subplebbit Operations Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Halts the polling of the network for new subplebbit updates initiated by `subplebbit.update()`. It also stops listening for new posts on the pubsub and publishing updates started by `subplebbit.start()`. ```js subplebbit.stop() ``` -------------------------------- ### Plebbit Options Schema Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Defines the structure and types for Plebbit initialization options, including IPFS gateway URLs, Kubo RPC client configurations, pubsub client configurations, plebbit RPC client URLs, data path, chain providers, and author address resolution settings. ```APIDOC PlebbitOptions: ipfsGatewayUrls: strings[] | undefined (default: ['https://cloudflare-ipfs.com']) Optional URLs of IPFS gateways kuboRpcClientsOptions: (string | kuboRpcClientsOptions)[] | undefined (default: undefined) Optional URLs of Kubo IPFS APIs or [kuboRpcClientsOptions](https://www.npmjs.com/package/kubo-rpc-client#options), 'http://localhost:5001/api/v0' to use a local Kubo IPFS node pubsubKuboRpcClientsOptions: (string | kuboRpcClientsOptions)[] | undefined (default: ['https://pubsubprovider.xyz/api/v0']) Optional URLs or [kuboRpcClientsOptions](https://www.npmjs.com/package/kubo-rpc-client#options) used for pubsub publishing when `kuboRpcClientsOptions` isn't available, like in the browser plebbitRpcClientsOptions: string[] | undefined (default: undefined) Optional websocket URLs of plebbit RPC servers, required to run a sub from a browser/electron/webview dataPath: string | undefined (default: .plebbit folder in the current working directory) (Node only) Optional folder path to create/resume the user and subplebbit databases chainProviders: {[chainTicker: string]: ChainProvider} | undefined (default: default providers for supported chains) Optional provider RPC URLs and chain IDs resolveAuthorAddresses: boolean | undefined (default: true) Optionally disable resolving crypto domain author addresses, which can be done lazily later to save time ChainProvider: urls: string[] URLs of the provider RPCs chainId: number ID of the EVM chain if any ``` -------------------------------- ### Subplebbit Settings Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Configuration options for a Subplebbit. Includes settings for fetching thumbnail URLs and a proxy URL for fetching them. Note that fetching thumbnail URLs might reveal IP addresses. ```APIDOC SubplebbitSettings: fetchThumbnailUrls: boolean | undefined Fetch the thumbnail URLs of comments comment.link property, could reveal the IP address of the subplebbit node fetchThumbnailUrlsProxyUrl: string | undefined The HTTP proxy URL used to fetch thumbnail URLs ``` -------------------------------- ### Update and Poll for Comment Updates Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Starts polling the network for comment updates such as replies, upvotes, and edits. It updates the comment instance and emits an 'update' event. This method requires the comment to have a 'cid' or exist. ```APIDOC comment.update() - Start polling the network for comment updates (replies, upvotes, edits, etc), update itself and emit the update event. - Only usable if comment.cid or exists. - Example: const commentCid = 'Qm...' const comment = await plebbit.getComment(commentCid) comment.on('update', (updatedCommentInstance) => { console.log(updatedCommentInstance) comment.stop() }) comment.update() const commentDataFetchedEarlier = {content, author, cid, ...comment} const comment = await plebbit.createComment(commentDataFetchedEarlier) comment.on('update', () => { console.log('the comment instance updated itself:', comment) }) comment.update() ``` -------------------------------- ### Plebbit Signer Creation Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Illustrates the creation of a Signer instance, which is used for creating comments. It shows how to create a signer with a new random private key or by providing an existing private key and type. ```js const newRandomSigner = await plebbit.createSigner() const signerFromPrivateKey = await plebbit.createSigner({privateKey: 'AbCd...', type: 'ed25519'}) ``` -------------------------------- ### Build Commands Source: https://github.com/plebbit/plebbit-js/blob/master/docs/building.md Commands to build the Node.js and browser distributions, and to bundle Karma test files. These commands utilize npm scripts for watch mode compilation. ```bash npm run build:node:watch npm run build:browser:watch npm run webpack:watch ``` -------------------------------- ### Get Comment and Related Data Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Demonstrates how to fetch a comment using its CID, listen for updates, and retrieve its parent post, subplebbit, and previous comment. It also shows how to access the comment's parent CID to determine if it's a post. ```js const commentCid = 'Qm...' const comment = await plebbit.getComment(commentCid) console.log('comment:', comment) comment.on('update', updatedComment => console.log('comment with latest data', updatedComment)) if (comment.parentCid) { // comment with no parent cid is a post plebbit.getComment(comment.parentCid).then(parentPost => console.log('parent post:', parentPost)) } plebbit.getSubplebbit(comment.subplebbitAddress).then(subplebbit => console.log('subplebbit:', subplebbit)) plebbit.getComment(comment.previousCid).then(previousComment => console.log('previous comment:', previousComment)) /* Prints: { ...TODO } */ ``` -------------------------------- ### Get Challenge Answers and Verification Source: https://github.com/plebbit/plebbit-js/blob/master/src/runtime/node/subplebbit/challenges/README.md Demonstrates how to retrieve challenge answers from a user and verify challenge completion using the `getChallengeVerification` function. It includes error handling for misconfigured challenges, emitting an error event, and returning a failure status. ```js const {getChallengeVerification} = require('./challenges') // NOTE: publishing challenge pubsub message and waiting for challenge answer message go inside the getChallengeAnswers callback // because they are sometimes skipped const getChallengeAnswers = async (challenges) => { // ...get challenge answers from user. e.g.: // step 1. subplebbit publishes challenge pubsub message with `challenges` provided in argument of `getChallengeAnswers` // step 2. subplebbit waits for challenge answer pubsub message with `challengeAnswers` and then returns `challengeAnswers` return challengeAnswers } // NOTE: we try to get challenge verification immediately after receiving challenge request // because some challenges are automatic and skip the challenge message let challengeVerification try { challengeVerification = await getChallengeVerification(challengeRequest, subplebbit, getChallengeAnswers) } // getChallengeVerification will throw if one of the getChallenge function throws, which indicates a bug with the challenge script catch (e) { // notify the sub owner that that one of his challenge is misconfigured via an error event subplebbit.emit('error', e.message) // notify the author that his publication wasn't published because the subplebbit is misconfigured challengeVerification = { challengeSuccess: false, reason: `One of the subplebbit challenges is misconfigured: ${e.message}` } } ``` -------------------------------- ### Subplebbit Suggested Settings Source: https://github.com/plebbit/plebbit-js/blob/master/README.md Optional settings suggested by the subplebbit owner, such as primary/secondary colors, avatar/banner URLs, and language. Clients can ignore these suggestions. ```APIDOC SubplebbitSuggested { primaryColor?: string secondaryColor?: string avatarUrl?: string bannerUrl?: string backgroundUrl?: string language?: string // TODO: menu links, wiki pages, sidebar widgets } ```