Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@dao-dao/cosmiframe

Package Overview
Dependencies
Maintainers
4
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dao-dao/cosmiframe

Facilitate iframe message passthrough for Cosmos wallets

  • 1.0.0-rc.0
  • latest
  • npm
  • Socket score

Version published
Maintainers
4
Created
Source

cosmiframe

Cosmiframe assists in establishing a Cosmos wallet connection through an iframe. An outer (parent) window can act as a wallet for an iframe.

Installation

npm install @dao-dao/cosmiframe @cosmjs/amino @cosmjs/proto-signing

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.

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.

Cosmiframe enforces security by requiring you to specify allowed origins in the constructor on client instantiation (seen in the examples below). Though it's possible to work around this, I urge you not to. I made it slightly harder than just passing in '*' in the constructor, which is the best I can do (and I'm not telling you how 😡). Don't be lazy and risk your user's money.

All requests verify origin on message sending and receiving, which should automatically prevent any messages being sent to or received from an origin you haven't explicitly allowed. If you want to perform an additional security check which also validates that Cosmiframe is in fact listening from one of the allowed origins, you can use isReady from the client.

import { Cosmiframe } from '@dao-dao/cosmiframe'

const client = new Cosmiframe([
  'https://daodao.zone',
  'https://dao.daodao.zone',
])

// If this is true, we know that:
// - The current app is being used in an iframe.
// - The parent window is running Cosmiframe.
// - The parent window is one of the allowed origins above.
const readyAndSafeToUse = await client.isReady()

App integration

Integrating Cosmiframe to allow your app to be used inside iframes on another app or apps is very straightforward. To retrieve an offline signer for use in a signing client, which you would normally get from a wallet, get it from the Cosmiframe client instead:

import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { Cosmiframe } from '@dao-dao/cosmiframe'

const signer = new Cosmiframe([
  "https://daodao.zone",
  "https://dao.daodao.zone",
]).getOfflineSigner("cosmoshub-4")

const client = await SigningCosmWasmClient.connectWithSigner(
  'https://rpc...',
  signer
)

await client.sendTokens(...)
await client.execute(...)

If you are used to interacting with Keplr's interface (e.g. maybe you've created a wallet adapter system based on Keplr's functions), which is shared by many wallets, you can retrieve a client that conforms to Keplr's interface and simply proxies requests to the parent. Then, any parent that adds support for functions defined in Keplr's interface should be supported:

import { Cosmiframe } from '@dao-dao/cosmiframe'

const keplr = new Cosmiframe([
  "https://daodao.zone",
  "https://dao.daodao.zone",
]).getKeplrClient()

// Connect

await keplr.experimentalSuggestChain(...)
await keplr.enable('cosmoshub-4')
const key = await keplr.getKey('cosmoshub-4')

// Get signing client

const signer = await keplr.getOfflineSignerOnlyAmino('cosmoshub-4')
const client = await SigningCosmWasmClient.connectWithSigner(
  'https://rpc...',
  signer
)

await client.sendTokens(...)
await client.execute(...)

Because wallet interfaces vary slightly depending on wallet and adapter library, it's up to the parent to properly support and redirect requests. Some parents may pass requests directly through to a connected wallet, and some may handle message signature requests manually, wrapping them with other messages.

Example

This example allows an iframe to interact with Keplr connected to DAO DAO (this is unrelated to the Keplr-like client support mentioned above). The first step is performed in the parent app (DAO DAO), and the second step is performed in the iframe app.

  1. Begin listening from the parent window:
import { Cosmiframe } from '@dao-dao/cosmiframe'

Cosmiframe.listen({
  iframe: document.getElementById('iframe'),
  target: window.keplr,
  getOfflineSignerDirect: window.keplr.getOfflineSigner.bind(window.keplr),
  getOfflineSignerAmino: window.keplr.getOfflineSignerOnlyAmino.bind(
    window.keplr
  ),
  // Pass some metadata for the iframe to display about the parent.
  metadata: {
    name: 'DAO DAO',
    imageUrl: 'https://daodao.zone/daodao.png',
  },
})
  1. Request method calls from the iframe:
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { Cosmiframe } from '@dao-dao/cosmiframe'

const cosmiframe = new Cosmiframe([
  "https://daodao.zone",
  "https://dao.daodao.zone",
])

// `cosmiframe.p` can be used to proxy any method call to the `target` set by
// the parent. This should call Keplr's `enable` function. This proxying only
// works for methods that accept and receive JSON-serializable parameters and
// results. Since most wallet messages are requests for signatures, this covers
// most cases.
await cosmiframe.p.enable('cosmoshub-4')

// In most cases, you will need an instance of an offline signer to pass to
// another signing client, such as SigningCosmWasmClient. This is done through
// the `getOfflineSigner`, `getOfflineSignerAmino`, and `getOfflineSignerDirect`
// functions, which wrap the proxy calls above and implements the necessary
// interfaces.
const directAndAminoSigner = cosmiframe.getOfflineSigner('cosmoshub-4')
const directSigner = cosmiframe.getOfflineSignerDirect('cosmoshub-4')
const aminoSigner = cosmiframe.getOfflineSignerAmino('cosmoshub-4')

const signingClient = await SigningCosmWasmClient.connectWithSigner(
  'https://rpc...',
  aminoSigner
)

// If you're familiar with Keplr's interface...
const keplr = cosmiframe.getKeplrClient()

await keplr.experimentalSuggestChain(...)
await keplr.enable('cosmoshub-4')
const key = await keplr.getKey('cosmoshub-4')

FAQs

Package last updated on 06 Aug 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc