Getting Started with CyberConnect

Getting Started with CyberConnect

A Complete Guide

What is CyberConnect?

CyberConnect is a decentralized social network protocol that helps developers build their Web3 social applications. It has a data infrastructure that helps store and manage users’ self-sovereign social data at scale and a smart contract protocol for creating on-chain social networks. The smart contract protocol is live on BNB chain. This guide will cover the smart contract protocol with examples on the BSC testnet.

How does it work?

Profile

CyberConnect profile serves as the entry point for every on-chain action and therefore, it is just like a profile in Web2 social applications. Each profile is an ERC-721 NFT and owns its paid subscribers and content. Currently, the protocol allows people to mint profiles through cc.me on BNB Chain while minting profiles is free on testnet.

01.png

Content

After creating their profiles, users can start building their on-chain social network by creating “content”. In CyberConnect, content could be anything that a user creates, issues, or builds. This design enables dynamic use cases like:

  1. Creators posting short-form content on video platforms,

  2. Event organizers issuing reward/recognition badges for participation, or

  3. Universities issue verifiable credentials like diplomas for students.

All content is represented in the format of an ERC-721 token called EssenceNFT. The content itself can be stored on different storage platforms like IPFS or Arweave, depending on the developer’s discretion.

The protocol also offers Collect Middleware Contracts. With that, every profile owner can include custom functionality on ‘collecting’ conditions (e.g. pay to collect or hold NFT to collect) and token nature (e.g. transferable or non-transferable). A case in point would be Link3. The Web3 social network of verifiable identities utilizes EssenceNFT to enable organization profiles to issue attendance badges/SBTs. Our own demo app uses EssenceNFT to represent a post.

Screen Shot 2022-10-19 at 6.09.55 PM.png

Subscribe

With CyberConnect’s Smart Contract Protocol, Web3 users have the ability to enable paid subscriptions to their profiles. Our Subscribe Middleware Contracts will prove to be essential when setting up rules for profile subscriptions. Each subscriber will be issued a SubscribeNFT upon a successful subscription.

Screen Shot 2022-10-19 at 3.33.51 PM.png

Interaction

A general interaction is illustrated in the diagram below:

Getting started with CyberConnect API

The CyberConnect API is a GraphQL API, which can be tested on Playground easily. All available queries are clearly visible on Playground. For example, one can get profile info by the handle or profile id directly. We encourage developers to explore more queries here!

query {
  profileByHandle(handle: "ryan") {
    profileID
    owner {
      address
    }
    avatar
    metadata
    metadataInfo {
      name
      bio
      title
      organization
    }
  }
}
// response data
{
  "data": {
    "profileByHandle": {
      "profileID": 18,
      "owner": {
        "address": "0x7C04786F04c522ca664Bb8b6804E0d182eec505F"
      },
      "avatar": "https://cyberconnect.mypinata.cloud/ipfs/bafkreib22x3t2br3w2dnmkm4lpcmngqngdbiaaubasgpyqme234wblhju4",
      "metadata": "Qmapk16yCpzXcCEh6GJroj99FASi4nZv52KtQzPLPCtcML",
      "metadataInfo": {
        "name": "ryan",
        "bio": "",
        "title": "Cofounder",
        "organization": "CyberConnectHQ"
      }
    }
  }
}

It’s worth mentioning that the CyberConnect team build its own indexer to:

  • Index on-chain data and serve API queries, and

  • Act as a relayer for gasless transactions (meta transactions).

However, since all data is publicly accessible on-chain, anyone can interact with the protocol directly without using the APIs and building their own indexers/relayers to query, aggregate, and serve these data.

Build a Simple Content App with CyberConnect

Now that you have a good understanding of CyberConnect Protocol, let’s build a simple app! This app will cover the most commonly seen features of social apps such as creating a user profile, creating a post, subscribing to another user, and collecting users’ posts. You can find more detailed steps in our Developer Center.

Prerequisites

For this tutorial, you will need:

  • Basic understanding of React.js, GraphQL, and Web3.

  • Have Node.js, NPM, and MetaMask Chrome extension installed on your machine.

Quick Setup

  • Clone the GitHub repo
git clone git@github.com:cyberconnecthq/cc-content-app.git
  • Set up env variables

    • 1. NEXT_PUBLIC_API_KEY and NEXT_PUBLIC_API_SECRET are for uploading metadata using Pinata (register on Pinata).

    • 2. For the development environment, you need to set NEXT_PUBLIC_GRAPHQL_ENDPOINT to https://api.cyberconnect.dev/testnet/.

    • 3. When you call the relay mutation from the API, you need to put X-API-KEY: process.env.NEXT_PUBLIC_CYBERCONNECT_API_KEY in the request header, you can register the key from the dashboard.

    • 4. Last but not least, make sure to set NEXT_PUBLIC_CHAIN_ID to 97 which is BSC Testnet.

        # .env
        NEXT_PUBLIC_API_KEY=*** // PINATA API KEY 
        NEXT_PUBLIC_API_SECRET=*** // PINATA API SECRET 
        NEXT_PUBLIC_CYBERCONNECT_API_KEY=*** // CyberConnect API KEY   
        NEXT_PUBLIC_GRAPHQL_ENDPOINT=https://api.cyberconnect.dev/testnet/  
        NEXT_PUBLIC_CHAIN_ID=97 // BSC Testnet
      
  • Install & run locally

npm install
npm run dev

Authentication

  • Login to get an access token for authentication purposes. This can be accomplished by sending out two GraphQL mutations: LoginGetMessage and LoginVerify.
const messageResult = await loginGetMessage({
    variables: {
        input: {
            address: address,
            domain: DOMAIN
        },
    },
});
const message = messageResult?.data?.loginGetMessage?.message;

// Get the user's signature for the message
const signature = await signer.signMessage(message);

// Authenticate
const accessTokenResult = await loginVerify(...);
const accessToken = accessTokenResult?.data?.loginVerify?.accessToken;
  • Set up the ApolloClient so that whenever you make a request, it will pass the accessToken and CyberConnect API Key in the HTTP header.
...
    return {
        headers: {
            ...headers,
            Authorization: accessToken ? `bearer ${accessToken}` : "",
            "X-API-KEY": process.env.NEXT_PUBLIC_CYBERCONNECT_API_KEY,
        },
    };
...

Smart Contract ABI

To talk to an external smart contact from our application, we need:

  1. The contract addresses

  2. The contract ABI (Application Binary Interface)

  • You can find all deployed contract addresses in the cheat sheet. It’s important to note that CC Profile (Proxy) is the one you will be interacting with for most of your actions such as createProfile, collect, and subscribe(all example transactions in this tutorial will interact with this contract).
// BSC Testnet
const profileProxyAddress = "0x57e12b7a5f38a7f9c23ebd0400e6e53f2a45f271";
  • You can find CC Profile (Impl) contract's ABI on BscScan (BSC Testnet) and copy & paste the file for further usage.

07.png

Create Profile

  • Set up the metadata so that your profile information can be indexed and displayed properly on marketplaces like OpenSea.
const metadata = {
    name: name,
    bio: bio,
    handle: handle,
    version: "1.0.0",
};
  • Send our ‘create profile’ transaction. The preData and postData are used for middleware and we can safely ignore them for now.
const tx = await contract.createProfile(
    {
        to: address,
        handle: handle,
        avatar: avatar,
        metadata: metadataStr,
        operator: PROFILE_NFT_OPERATOR,
    },
    // preData
    0x0,
    // postData
    0x0
);

Subscribe to Profile

Subscribing to a profile is a three-step process and requires two GraphQL mutations: CreateSubscribeTypedData and Relay. If you’re unfamiliar with typed data, you can read more about it here.

  • Get typedData and typedDataID
/* Create typed data in a readable format */
const typedDataResult = await createSubscribeTypedData({
    variables: {
        input: {
            profileIDs: [profileID],
        },
    },
});
const typedData = typedDataResult.data?.createSubscribeTypedData?.typedData;
const message = typedData.data;
const typedDataID = typedData.id;
  • Let the user sign the message data and get signature.
/* Create typed data in a readable format */
const typedDataResult = await createSubscribeTypedData({
    variables: {
        input: {
            profileIDs: [profileID],
        },
    },
});
const typedData = typedDataResult.data?.createSubscribeTypedData?.typedData;
const message = typedData.data;
const typedDataID = typedData.id;
  • Call the relay, pass it the typedDataID and signature and get the relayActionId.
const relayResult = await relay({
  variables: {
    input: {
      typedDataID: typedDataID,
      signature: signature
    }
  }
});

const relayActionId = relayResult?.data?.relay.relayActionId;
  • Call relayActionStatus to receive txHash.
const res = await getRelayActionStatus({
  variables: {
    relayActionId: relayActionId
  },
});
console.log("txHash", res?.data?.relayActionStatus?.txHash);

Create a Post

The process of creating a post involves a step to Register an Essence. These steps are mainly for you to customize the appearance and minting logic (middleware) of the EssenceNFT.

  • Construct the metadata object for EssenceNFT

The Metadata schema is a standard template used to store data related to content and the NFT. Some of the fields are following the OpenSea Metadata Standards to ensure they can be displayed properly on OpenSea and other marketplaces. Other fields like app_id and tags are mainly used for query filter purposes.

const metadata: IEssenceMetadata = {
    metadata_id: uuidv4(),
    version: Version.V1,
    app_id: "cyberconnect",
    lang: "en",
    issue_date: new Date().toISOString(),
    content: post,
    media: [],
    tags: [],
    image: nftImageURL ? nftImageURL : "",
    image_data: !nftImageURL ? svg_data : "",
    name: `@${handle}'s post`,
    description: `@${handle}'s post on CyberConnect Content app`,
    animation_url: "",
    external_url: "",
    attributes: [],
};
  • Upload the metadata to IPFS to get the hash
const ipfsHash = await pinJSONToIPFS(metadata);
  • Create the typed data, let the user sign it, and relay the transaction

This step is exactly the same as subscribing to a profile except for the typed data field. We are using CreateRegisterEssenceTypedData when creating a post.

const typedDataResult = await createRegisterEssenceTypedData({
    variables: {
        input: {
            /* The profile id under which the Essence is registered */
            profileID: profileID,
            /* Name of the Essence */
            name: "Post",
            /* Symbol of the Essence */
            symbol: "POST",
            /* URL for the JSON object containing data about content and the Essence NFT */
            tokenURI: `https://cyberconnect.mypinata.cloud/ipfs/${ipfsHash}`,
            /* Middleware that allows users to collect the Essence NFT for free */
            middleware: {
                collectFree: true,
            },
            /* Set if the Essence should be transferable or not */
            transferable: true,
        },
    },
});

It’s worth mentioning that you can either set the middleware here when registering the EssenceNFT or later in a separate call (see Setup Customized Middleware section).

Collect a Post

Collecting a post has exactly the same procedures as subscribing to a profile except for the typed data field. We will be using CreateCollectTypedData when collecting a post.

const typedDataResult = await createCollectTypedData({
    variables: {
        input: {
            profileIDs: [profileID],
        },
    },
});

Setup Customized Middleware

The above example uses the default behavior (free to mint) when a user tries to subscribe to a profile or collect a post. But what if a user wants to set up rules like “only BAYC holder can subscribe” or “pay 1 BSC to collect my 500 limited edition post”? To enable dynamic rules, the CyberConnect protocol provides various CollectMiddleware and SubscribeMiddleware. We will go through a quick example of setting up a CollectPaidMw.

The user signing and relay process are exactly the same as in the steps in Subscribe to Profile. We are using CreateSetEssenceDataTypedData when setting middleware.

const typedDataResult = await createSetEssenceDataTypedData({
    variables: {
        input: {
            /* The id of the essence the middleware is set for */
            essenceId: essenceID,
            /* The id of the profile that created the essence */
            profileId: profileID,
            /* URL for the JSON object containing data about content and the Essence NFT */
            tokenURI: `https://cyberconnect.mypinata.cloud/ipfs/QmWeusbdbY2SEry1GEiJpmzd3Frp29wMNS3ZbNN21hLbVw`,
            /* The middleware that will be set for the essence */
            middleware: {
                collectPaid: {
                    /* Address that will receive the amount */
                    recipient: account,
                    /* Number of times the Essence can be collected */
                    totalSupply: 1000,
                    /* Amount that needs to be paid to collect essence */
                    amount: 1,
                    /* The currency for the  amount. Chainlink token contract on Goerli */
                    currency: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
                    /* If it requires that the collector is also subscribed */
                    subscribeRequired: false,
                },
            },
        },
    },
});

Conclusion

Congratulations! You’ve successfully created a social app using CyberConnect. Hope it provides a good understanding of the CyberConnect Protocol, how it works, and how to use CyberConnect APIs to create your next Web3 social app.

We strongly recommend the following on your journey in building with CyberConnect:

  • Learn more about the CyberConnect Recommendation Engine

For lots of interesting data like recommended Web2 social profiles based on trading history, or recommended tokens the address should purchased based on modeling trading behavior & holdings relative to other addresses (i.e. collaborative filtering model).

  • Extend the middleware contracts

You can create more interesting middleware contracts for other developers to use. A governance process oversees the whitelist of new middleware.

  • Join our Discord if you have any questions!