-
Notifications
You must be signed in to change notification settings - Fork 21
How to support DAO DAO's Apps interface
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:
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.
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 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 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.
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.
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.
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:
-
To detect if your app is being used within an iframe, you can simply check
window.self !== window.parent
. -
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.
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)
}
}, [])
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!