Skip to content

agorapp-dao/agorapp-react-utils

Repository files navigation

AgorApp Web3 IDE Editor

NPM version Build npm-typescript License

The AgorApp Web3 IDE Editor can be seamlessly integrated into partner websites with this package.

Live Demo

Installation:

pnpm add agorapp-react-utils

or

yarn add agorapp-react-utils

Basic usage:

Add EmbeddedEditor to your component:

export const YourComponent = () => {
  return (
    <EmbeddedEditor
      aspectRatio={'4:3'}
      courseSlug={'solidity'}
      lessonSlug={'optimized-array-sum'}
    />
  )
}

courseSlug

The courseSlug parameter specifies the course that the IDE should open. The value of the parameter is the slug of the course.

lessonSlug

The lessonSlug parameter specifies the lesson that the IDE should open. The value of the parameter is the slug of the lesson.

Customizing the appearance of the IDE

You can customize the behavior of the IDE by specifying parameters to <EmbeddeedEditor />.

  <EmbeddedEditor
    ref={ref}
    aspectRatio={'4:3'}
    courseSlug={'solidity'}
    lessonSlug={'optimized-array-sum'}
    brand={'rareSkills'}
    hideTheory={true}
    style={{ border: '1px solid orange', borderRadius: '15px' }}
  />

aspectRatio

Supported values: 16:9, 4:3, 3:2, 1:1. If no value is specified, the component will adjust to the size of the parent.

brand

Supported valued: agorapp, rareSkills. If no value is specified, the default value is agorapp.

hideTheory

You can hide theory panel by setting hideTheory to true.

style

You can customize the appearance of the IDE by specifying the style parameter. The style is applied to wrapper of <iframe /> element.

Advanced usage - MetaMask integration

AgorApp IDE can be integrated with MetaMask wallet.

Based on a prior agreement with AgorApp, you can transfer information about your user to the IDE, in order to match the solution with the user later.

Communication is based on Window: postMessage() method.

IDE verify the user by requiring him to sign the messages sent to AgorApp iframe with his MetaMask wallet.

Sample code to pass the MetaMask towards the IDE.

export const YourComponent = () => {
  const ref = useRef<HTMLIFrameElement | null>(null)
  const publicKey = 'PUBLIC_KEY_OF_THE_USER'
  
  const { setIdentity } = useEmbeddedEditorMessage(
    async (message: AgorAppMessage) => {
      switch (message.type) {
        case 'ready':
          console.log(`AgorApp IDE is ready`)
          setIdentity('metamask', publicKey)
          break
        case 'sign-request':
          console.log(`AgorApp IDE requires sign-request: `, message)
          // your code to sign the message
          break
      }
    },
    { ref },
  )
  
  return (
    <EmbeddedEditor
      ref={ref}
      aspectRatio={'4:3'}
      courseSlug={'solidity'}
      lessonSlug={'optimized-array-sum'}
    />
  )
}

As the first argument of useEmbeddedEditorMessage is Message handler function. Over this function you will handle the messages sent from the IDE.

Complete code with example of signing the message with MetaMask wallet: Live Demo

Message format

Each Message received by Message handler will follow this structure:

{
  "type": "<message type>",
  "payload": "<message>",
  "signature": "signature of the message"
}

Message flow

This section describes what the typical interaction between AgorApp and Partner will look like:

  1. User goes to the Partner website that embeds AgorApp iframe over <EmbeddedEditor ... /> component.
  2. AgoraApp iframe sends a ready Message to the Partner window:
{
  "type": "ready"
}
  1. Partner window creates payload with user identity. Partner window sends the message to the AgoraApp iframe.

To send the response back to the IDE, the Partner calls the function setIdentity function from useEmbeddedEditorMessage hook.

setIdentity('metamask', '<metamask public key>');
  1. AgorApp iframe remembers the user identity and will apply it to the messages it wants to verify from Partner.
  2. User submits a solution in the AgorApp iframe.
  3. AgoraApp iframe sends a sign request Message to the Partner window for signing.
{
  "type": "sign-request",
  "payload": {
    "action": "submit-solution",
    "identity": {
      "type": "metamask",
      "value": "<metamask public key>"
    },
    "solution": "<solution>"
  }
}
  1. Partner window will sign payload with the MetaMask Wallet and get the signature of the message.

To sign the message with MetaMask wallet, Partner will sign message:

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = await provider.getSigner();
const signature = await signer.signMessage("<message>");

To send the response back to the IDE, the Partner calls the function signResponse function from useEmbeddedEditorMessage hook:

signResponse(message.payload, signature);
  1. This signed message is sent back to the AgorApp iframe. AgoraApp backend verifies the signature, evaluates the solution and stores the result in the leaderboard.

Payload

The payload in the examples above is presented as JSON for readability. In reality, payload will be a string. The real message will look something like this:

{
  "type": "set-identity",
  "payload": "{\"action\": \"set-identity\", \"type\": \"metamask\", \"value\": \"<metamask public key>\"}",
  "signature": "<signature of the payload>"
}