Skip to content

How to support DAO DAO's Apps interface

noah edited this page May 7, 2024 · 22 revisions

In order to become an app in DAO DAO's Apps interface, follow this guide. This allows DAOs to use your app natively right from DAO DAO!

Here is an example of a DAO interacting with Osmosis to perform swaps:

Screenshot 2024-05-07 at 17 24 15

Integration

Iframe wallet connection is powered by the Cosmiframe package.

If you need a logo to display in your wallet connection modal, you can use https://daodao.zone/daodao.svg or https://daodao.zone/daodao.png.

Wallet adapter

The following wallet adapter libraries support Cosmiframe as a wallet option, so if you use one of them, you're already good to go!

Cosmos Kit

Cosmos Kit with @cosmos-kit/core version >= 2.9.3

The iframe wallet connection is automatically attempted if it detects it's being used within an iframe. You should not have to do anything other than install and set up the package.

Graz

Graz version >= v0.1.12

Make sure to add a way to connect to the WalletType.COSMIFRAME wallet type wherever you display/register wallets. Ideally you set up auto-connect, which is described below.

Manual integration

If you don't use one of the above adapters, you will need to integrate the iframe connection library directly. Cosmiframe includes instructions in its README.

Security

It is very important to trust the outer app, since supporting this functionality opens up the possibility for the outer app to manipulate messages before asking the user to sign them. DAO DAO needs this functionality in order to wrap requested messages in a proposal creation message. This is an unavoidable consequence.

At the end of the day, everything still needs to be approved by a wallet, so a malicious app wrapping your app only has so much power, but relying on user intelligence as a line of defense is definitely not a good idea, especially because most users don't have the tools to validate that the smart contract messages they're seeing are correct.

DAO DAO makes it easy to validate. Add the following logic to your app, and only enable Cosmiframe connection inside the listener's if statement:

const listener = ({ origin, data }: MessageEvent) => {
  // Only trust messages coming from a valid DAO DAO domain.
  if ((origin === 'https://daodao.zone' || origin === 'https://dao.daodao.zone') && data === 'amDaoDao') {
    // ENABLE COSMIFRAME CONNECTION
  }
}

window.addEventListener('message', listener)

// Ask if parent is DAO DAO.
window.parent.postMessage('isDaoDao', 'https://daodao.zone')
window.parent.postMessage('isDaoDao', 'https://dao.daodao.zone')

This code will ask the outer app if it is DAO DAO, to which DAO DAO responds that it is. Crucially, modern browsers ensure that the messages can only be sent to or received from the specified domains. Only once verifying this should you support a Cosmiframe connection.

Auto connect

Ideally your app detects when it's being used within DAO DAO and automatically uses Cosmiframe or connects to the Cosmiframe wallet in your adapter library. There are two mechanisms that are helpful here:

  1. To detect if your app is being used within an iframe, you can simply check window.self !== window.parent.

  2. To detect if your app is being used within DAO DAO specifically, you should perform the call-and-response check in the security section above. Really, you should always be performing the security check, even if you don't want to auto-connect.

React example

In a React app, using the security check and auto-connecting to DAO DAO using Cosmiframe will look something like this:

useEffect(() => {
  // Do nothing if not in a browser (Next.js server-side rendering) or if not inside of an iframe.
  if (typeof window === 'undefined' || window.self === window.parent) {
    return
  }

  const listener = ({ origin, data }: MessageEvent) => {
    // Only trust messages coming from a valid DAO DAO domain.
    if ((origin === 'https://daodao.zone' || origin === 'https://dao.daodao.zone') && data === 'amDaoDao') {
      // ENABLE COSMIFRAME AND AUTO-CONNECT
    }
  }

  window.addEventListener('message', listener)

  // Ask if parent is DAO DAO.
  window.parent.postMessage('isDaoDao', 'https://daodao.zone')
  window.parent.postMessage('isDaoDao', 'https://dao.daodao.zone')

  return () => {
    window.removeEventListener('message', listener)
  }
}, [])

Testing

You can test your integration by visiting a DAO on a chain your app supports, visiting the Apps tab, and entering your app's URL in the Custom URL field.

Once you get it working, reach out to us on our Discord to request being added to our Apps library!