SDK
Getting Started

Getting started

This guide walks you through the basic steps of using the Roles SDK.

Installation

The Roles SDK relies on eth-sdk (opens in a new tab) for generating type-safe APIs from automatically downloaded contract ABIs. To add it to your project, run one of the following commands.

With npm:

npm i --save @gnosis-guild/eth-sdk @gnosis-guild/eth-sdk-client zodiac-roles-sdk

With yarn:

yarn add @gnosis-guild/eth-sdk @gnosis-guild/eth-sdk-client zodiac-roles-sdk

With pnpm:

pnpm add @gnosis-guild/eth-sdk @gnosis-guild/eth-sdk-client zodiac-roles-sdk

Configuration

The next step is to create a config file that lists all the contracts we want to permit calling.

Create a folder named eth-sdk in your project root (where your package.json is located). Inside this folder, create a config.ts file with the following content structure:

import { defineConfig } from "@gnosis-guild/eth-sdk";
 
export default defineConfig({
  contracts: {
    mainnet: {
      dai: "0x6b175474e89094c44da98b954eedeac495271d0f",
    },
  },
});

This example lists the DAI contract (opens in a new tab) on Ethereum mainnet. The object under the contracts field should generally list the identifiers of all chains you plan to target. For each chain entry, you can define arbitrary object structures with addresses stored at the leave values.

For custom chain configurations: refer to the eth-sdk docs (opens in a new tab) for a complete overview of the available configuration options.

Generate allow kit

Now, and after any update to the eth-sdk/config.ts file, make sure to run the following command:

yarn eth-sdk

This command will fetch the ABIs of the contracts listed in the config file and generate TypeScript types for them directly into your node_modules. If the ABI of any listed contract cannot be fetched automatically, the command will return an error code. In that case, you need to manually create a JSON file with the ABI at a location inside eth-sdk/abi matching the path of the contract in the eth-sdk/config.ts file.

The VSCode TypeScript server may not automatically pick up the type updates generated by the yarn eth-sdk command. To ensure the latest state is reflected in your IDE, press CMD+SHIFT+P and select "TypeScript: Restart TS Server".

Define permissions

You now have a typed allow kit at your disposal. Access it by importing from "zodiac-roles-sdk/kit":

import { allow } from "zodiac-roles-sdk/kit";
 
const CURVE_3POOL = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7";
 
const permissions = [allow.mainnet.dai.approve(CURVE_3POOL)];

Apply permissions

Additional SDK functions allow applying a set of permissions to a role.

import { processPermissions, applyTargets } from "zodiac-roles-sdk";
 
const { targets } = processPermissions(permissions);
 
const calls = applyTargets(MY_ROLE_KEY, targets, {
  chainId: 1,
  address: ROLES_MOD_ADDRESS,
  mode: "replace",
});

As an initial step, permissions are processed for grouping them by target address and merging multiple permissions to the same function into a single entry.

The applyTargets function fetches the current targets configured onchain for the role in the Roles Modifier and computes the set of calls required to patch it to the new set of targets.

The mode option controls how the current set of targets already configured for the role onchain is handled. It can be one of the following values:

  • "replace": The new set of targets replaces the current set.
  • "extend": The current set of targets is kept and only additional targets or functions are added.
  • "remove": All passed target that are already configured in the current set of targets will we removed.

The applyTargets function returns an array of call data hex string that can be executed to apply the update. You can execute the calls via ethers/viem or batch them as a multi-send.

ethers:

calls.forEach(async (data) => {
  await provider.call({ to: ROLES_MOD_ADDRESS, data }); // signer must be the `owner` of the roles mod
});

multi-send:

import { encodeMulti } from "ethers-multisend";
 
const multiSendTx = encodeMulti(
  calls.map((data) => ({ to: ROLES_MOD_ADDRESS, value: 0, data }))
);