Aragon Connect 0.5.0
This version introduces a series of changes to the API of Connect, aiming to make it easier to use while reducing the amount of boilerplate.
Contributors for this release: @0xGabi, @ajsantander, @bpierre, @onbjerg, @pengiundev 🎉
Breaking changes 🔨
- New API to initiate an app connection (see next section).
- New API to implement app connectors (see next section).
- The
@aragon/connect-thegraph-voting
package is now@aragon/connect-voting
. - The
@aragon/connect-thegraph-tokens
package is now@aragon/connect-tokens
. - The
chainId
option of theconnect()
function is nownetwork
, and accepts a chain ID (e.g.4
), a network name (e.g."rinkeby"
), or a network object. - The
readProvider
option of theconnect()
function is nowethereum
.
New app connectors API 🔌
This version is adding important changes to the way we interact with app connectors.
Before the new API
To illustrate these changes, let’s have a look at how a list of votes could get fetch with Connect 0.4.2:
import connect from '@aragon/connect'
import { Voting } from '@aragon/connect-thegraph-voting'
// Connect to an organization on mainnet via The Graph.
const org = await connect('myorg.aragonid.eth', 'thegraph')
// Get the voting app.
const voting = await org.app('voting')
// Instantiate the Voting class, and pass the URL for mainnet.
const votingConnected = new Voting(
voting.address,
'https://api.thegraph.com/subgraphs/name/aragon/aragon-voting-mainnet'
)
// Fetch the votes from the votingConnected object.
const votes = await votingConnected.votes()
The example above contains a few things that we wanted to improve:
- The network (mainnet here) has to be set again on the app connector. The organization and the app live on the same network, so it shouldn’t be necessary.
- The app connector is specific to a data source (The Graph here). The main library will eventually include several data sources, and app connectors should follow the same direction.
- We are dealing with two different objects:
voting
andvotingConnected
. They might seem similar but are doing different things: one is anApp
instance, while the other one is coming from the app connector and allows to fetch data.
With the new API
This is how the same example looks with the new API:
import connect from '@aragon/connect'
import connectVoting from '@aragon/connect-voting'
// Connect to an organization on mainnet via The Graph.
const org = await connect('myorg.aragonid.eth', 'thegraph')
// Get and connect to the voting app.
const voting = await connectVoting(org.app('voting'))
// Fetch the votes from voting.
const votes = await voting.votes()
A few things about this last example:
- The app connector function knows about the current network (mainnet), there is no need to specifiy the URL for The Graph (but it can be done optionally).
- The app connector is now universal. You might have noticed that
@aragon/connect-thegraph-voting
is now@aragon/connect-voting
. This is because a connector can now support any number of data sources it wants, and we plan to support the same data sources in@aragon/connect
and the core app connectors. - We are now only using one object:
voting
. With this new API, the object returned by the app connector gets extended byApp
, rather than being separate. It means that the API ofApp
is available on this object. - connectVoting() accepts either an
App
or a promise resolving to anApp
. This is why we can directly passorg.app('voting')
to it.
This new API should make app connectors feel more similar to the connect()
function, while keeping the boilerplate and code repetition to a minimum, without compromising on the expressiveness as everything can be configured as before − except it’s optional now.
Usage with React
This is how the example presented above looks like with the React library:
import { createAppHook, useApp } from '@aragon/connect-react'
import connectVoting from '@aragon/connect-voting'
// We start by creating a hook for the app connector.
const useVoting = createAppHook(connectVoting)
function Votes() {
// We fetch the voting app.
const [voting] = useApp('voting')
// And we pass the voting app to the useVoting() hook.
// The second parameter is a callback that returns the data we want.
const [votes] = useVoting(voting, app => app.votes())
return (
<ul>
{votes ? (
votes.map(vote => <li key={vote.id}>{formatVote(vote)}</li>)
) : (
<li>Loading votes…</li>
)}
</ul>
)
}
As you can see, we are using the exact same function, connectVoting, to create a React Hook. This means that authors of app connectors don’t have to do anything specific for their connector to work with @aragon/connect-react
.
Note: this doesn’t support subscriptions yet. The next version will enable subscriptions using the exact same syntax as above.
Authoring app connectors with the new API
This is how an app connector can get implemented in the simplest way:
import { createAppConnector } from '@aragon/connect-core'
export default createAppConnector(() => ({
total: () => fetchTotal(),
}))
The createAppConnector()
utility takes care of doing the necessary checks, and passing contextual information to the callback.
This is how the connector for the Voting app is implemented using createAppConnector()
:
import { createAppConnector } from '@aragon/connect-core'
import Voting from './entities/Voting'
import VotingConnectorTheGraph, {
subgraphUrlFromChainId,
} from './thegraph/connector'
export default createAppConnector(
({ app, config, connector, network, verbose }) => {
if (connector !== 'thegraph') {
console.warn(
`Connector unsupported: ${connector}. Using "thegraph" instead.`
)
}
return new MyAppConnector(
new VotingConnectorTheGraph(
config.subgraphUrl ?? subgraphUrlFromChainId(network.chainId),
verbose
),
app.address
)
}
)
Pull request
- connectApp() (#135)
New app connector: Finance 📊
A new app connector has been added, for the Finance app. It uses the new connector API, and you can use it this way:
const org = await connect(env.location, 'thegraph')
const finance = await connectFinance(org.app('finance'))
const transactions = await finance.transactions()
Pull requests
ES modules exports 📦
Every Connect package is now exported in two formats: CommonJS and standard ES Modules, rather than CommonJS only. Your preferred bundler should detect the most appropriate format, or you should be able to configure it to choose either the main
or module
field from the package.json file. Nothing will change for Node.js apps, as the CommonJS export is still going to get imported by Node.
If you are using a tool like SnowPack, the integration with Connect will be much better from now on.
Pull request
- Add ESM exports (#162)
New examples 📬
A few more examples have been added.
Karma template organization deployment
This script demonstrates how to deploy an organization using the Karma template. It doesn’t use Connect yet, but it will be updated when the possibility to deploy an organization from Connect will get added.
Minimal Setup
This example demonstrates the absolute minimum required to build a React app using Connect. Here we are using Parcel to bundle it, and nothing more.
List Votes (CLI + React)
These two examples demonstrate how the new API to connect apps can get used from Node.js or a React app.
Pull requests
Other changes 📝
connect()
now acceptsactAs
as an option (#135)connect()
now acceptsverbose
as an option (#135)- The
ipfs
option ofconnect()
now also accepts an URL template, containing{cid}
and{path}
. - Documentation tweaks (#134)
- Handle stranger cases in TokenManager (#130)
- Types: remove some non-null assertion operators (!) (#128)
- Types: add SubscriptionHandler, Address (#136)
- Rename ConnectorInterface to IOrganizationConnector (#137)
- Connectors: make it possible to close the connection (#140)
- Examples: connect-react-intro: move to SnowPack (#160, #163)
- Add GRAPHKEY to the deploy scripts and documentation (#145)
- Subgraph: deployment data of Tokens and Voting on xDai (#155)
- Add app installation count to
Repo
entity (#150) - Fix: ethers overloads (#158)
- Connectors: Use official aragon subgraphs url (#167)