Page MenuHomePhabricator

[Cashtab] MVP Social Feed
AbandonedPublic

Authored by emack on Feb 12 2022, 14:02.

Details

Reviewers
bytesofman
Group Reviewers
Restricted Project
Summary
  • An end to end functional MVP version of D10935 for initial landing.
  • This new Social component retrieves the 20 most recent social feed posts from onchain and allows the user to submit new posts which are committed onchain with embedded cashtab social hex prefixes.
  • For ease of review, I'm pushing this initial revision without the Edit Name/Photo and inline img/link/emoji rendering features, as this is already a very large initial diff within the initial MVP.
  • I'm also cognisant we'll need to refactor to align with the D10970 UI facelift at some point so let's incrementally build/review in stages even within this initial MVP release.
  • As mentioned in T2017, the libraries listed on memo cash's site are reliant on asm values and bitbox, which are not compatible with how OP_RETURN parsing is implemented in XEC, so not much direct reuse there but we'll certainly be emulating most of their feature set on XEC where possible.

Key Backend Updates:

Chronik vs bch-api:

  • To avoid mixing bch-api and chronik api calls, I've opted for sole bch-api usage.

useBCH.sendSocialTx():

  • Similar to the useBCH.sendXec() function except the output script is constructed in the following manner:

[OP_RETURN]
index 0 - [Cashtab Social Prefix Hex]
index 1 - [Social Action Prefix Hex]
index 2 - [Poster Address]
index 3 - [Message content] || [New Profile Name] || [New Profile Photo Url]

  • This function will grow as additional social actions are added.

useBCH.retrieveSocialFeed():

  • Retrieves only the txids of the social hub address' full tx history via the Electrum.getTxHistory() API call.
  • The array of txids is then sorted via the Electrum.sortAllTxs() API call.
  • The 20 (i.e. currency.socialHistoryCount) most recent txids in the array are then sent to the Electrum.txData() api call to retrieve their transaction details.
  • The OP_RETURN hex for each of these 20 txs is parsed via the cashMethods.parseOpReturn() function which returns an array consistent with the prefixes used in useBCH.sendSocialTx() above and subsequent parsing logic ignores all other permutations (unencrypted/encrypted messaging, etokens...etc)
  • If the social action is to submit a post, then the message, time and poster's address is inserted into the parsedSocialTx object, which is pushed into the parsedSocialFeedArray array and returned for frontend rendering.

Key Frontend Updates:

Social Component

  • On initial render, the hasSocialFeedChanged() function checks whether the tx count for the social feed address has increased and if so, trigger the refreshSocialFeed() function which makes the api calls via useBCH.retrieveSocialFeed() to retrieve the latest social feed. If the onchain feed is unchanged, the social feed in the local storage will be rendered.
  • A 10 second interval is set in Social.js' useEffect function which continuously polls whether the feed onchain has changed and then acts accordingly.
  • When submiting a post, the social poster's address is embedded as part of the OP_RETURN prefix hex to save the useBCH.retrieveSocialFeed() function from making extra api calls to extract the input address.
  • The limit for the social post is 148 characters due to the increased output prefix hex embedded into the transaction.
  • For mobile mode, the pull-to-refresh library from antd-mobile is used for the pull down refresh ux. Although in hindesight, it's kind of redundant given the feed auto refreshes every 10 seconds. Will potentially remove unless you think the UX factor outweights the functional redundancy.
  • Will need to refactor for the UI facelift in D10970 once that lands.

Unit tests added for:

  • isValidSocialOutputTx in Validation
  • isValidSocialMsg in Validation
  • sendSocialTx in useBCH
  • Social.js in Components

For resolution prior to landing:

  • New posts (unconfirmed txs) don't have time/block attributes in the api responses, which causes their time attribute to be undefined. Proposing to simply render their time as 'mempool'.
  • Spam protection - should this logic be frontend via cashtab or backend via cashtab's version of bch-api? Also, how do you want to manage people posting NSFW stuff on this public feed.
  • Most libraries to parse string inputs for image, url links are around half a meg. Still trying to find the best one for use in this diff.

Manifest: T2017

Dependencies:

  • D10970 UI Facelift
  • @antd-mobile/pull-to-refresh library
  • T2184 @hungsam's upcoming OP_RETURN messaging backend enhancements
Test Plan
  • on initial load, ensure the Post button is not clickable with no inputs in the Input field.
  • send a valid social post and verify it is posted onchain and gets picked up by the 10 second polling interval and updated to the social feed history.
  • send a social post with special characters and ensure it is depicted as-is on the social feed.
  • attempt to post a blank, empty string or >148 character social message and verify it is picked up by frontend validation.
  • test sending a social post with a wallet with insufficient XEC balance and ensure the app handles the dust error with a soft error notification.
  • switch between saved wallets and ensure the social feed is consistent across wallets
  • test posting and observe 10 second polling across firefox and chrome browsers
  • test posting and observe 10 second polling in extension mode
  • test posting and observe 10 second polling in mobile mode

Diff Detail

Repository
rABC Bitcoin ABC
Branch
socialmvp
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 18258
Build 36324: Build Diffcashtab-tests
Build 36323: arc lint + arc unit

Event Timeline

emack requested review of this revision.Feb 12 2022, 14:02
emack edited the test plan for this revision. (Show Details)

Collecting all posts at a constant address, like cashtabSocialHubAddr, does simplify the polling process. However, I don't think it's the correct long term approach. If the service scales and becomes more popular, then we would need to solve edge cases like bots on the address -- where we could solve them up front by having an indexer for desired OP_RETURN prefixes and having Cashtab poll that.

That said...we don't have such an indexer *rightnow* , and this approach does give us something that works right away. I think getting real world info (how popular is the feature, what issues can we expect, maybe even some parameters we will want to index for, etc) earlier is worth the trade-off of having to adjust for better indexing in the future.

New posts (unconfirmed txs) don't have time/block attributes in the api responses, which causes their time attribute to be undefined. Proposing to simply render their time as 'mempool'.

Sure -- 'unconfirmed' or 'just now' also fine

Spam protection - should this logic be frontend via cashtab or backend via cashtab's version of bch-api? Also, how do you want to manage people posting NSFW stuff on this public feed.

Ultimately, we're just a front-end for blockchain data. The point is, it can't be censored. At the same time, we don't want to go out of our way to create a bad user experience. I think best approach is

  1. Add a modal when users go to the page, "warning: this content is uncensorable and probably should not be viewed by anyone." -- would also need a way for users to opt out of seeing this every time. This could be a diff after this lands.
  2. We won't host any images. Similar to memo, if people post images, they have to upload them somewhere on the internet and include a link.
  3. We'll have to see what kind of use / attacks come in and then iterate through to do what we can to optimize the user experience. Our main goal with Cashtab here is to show what the underlying tech can do. If the feature takes off, it would take a specialized service that focuses only on this.

Most libraries to parse string inputs for image, url links are around half a meg. Still trying to find the best one for use in this diff.

the MVP doesn't need to parse these. Users can still "post images" by including the link in msgs.

Large diff will get back to additional technical review later on.

This revision now requires changes to proceed.Feb 14 2022, 22:53

Chronik implementation and better dev tools have become higher priority than social media features. This is a good proof of concept, but should be abandoned as it will not land in this form.