Skip to Content
SDKSwaps

Swaps

The Zodiac Roles SDK provides built-in support for token swaps through COW Protocol, enabling efficient trading secured by tightly scoped role permissions.

Swaps incur a small fee of 0.25% of the swap value, in addition to the network fee. This fee is automatically collected by COW Protocol only for successful swaps.

Zodiac OS Enterprise customers can reach out for custom pricing.

Overview

The SDK offers a dedicated entrypoint zodiac-roles-sdk/swaps allowing you to:

  • Generate permissions for token swaps
  • Get quotes from swaps from the COW API
  • Sign orders using your role permissions
  • Post signed orders to COW API

Example

Configure permissions

Before your role can execute swaps, you need to configure the appropriate permissions. The SDK provides allowCowOrderSigning to generate the necessary permissions for COW swaps:

import { allowCowOrderSigning, processPermissions, applyTargets, } from "zodiac-roles-sdk/swaps"; // Define the tokens your role should be able to swap const permissions = allowCowOrderSigning({ sell: [ "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH "0xA0b86a33E6441b8dB4B2b6b0b0b6B0b0b0b0b0b0", // USDC ], buy: [ "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH "0xA0b86a33E6441b8dB4B2b6b0b0b6B0b0b0b0b0b0", // USDC "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", // COW ], // Optional: specify custom receiver (defaults to avatar address) // receiver: "0x...", });

Permission Parameters

  • sell: Array of token addresses that the role can sell
  • buy: Array of token addresses that the role can buy
  • receiver (optional): Address that can receive the bought tokens. Defaults to the avatar address of the Roles Modifier

What Permissions Are Created

The allowCowOrderSigning function creates permissions for:

  1. ERC20 Approvals: Allows approving the specified sell tokens to the COW Protocol Vault Relayer (0xC92E8bdf79f0507f65a392b0ab4667716BFE0110)
  2. Order Signing: Allows calling signOrder on the COW Order Signer contract (0x23dA9AdE38E4477b23770DeD512fD37b12381FAB) with the specified token constraints
  3. Order Unsigning: Allows calling unsignOrder to cancel orders if needed

Apply Permissions to Your Roles Modifier

Once you have the permissions, apply them to a role in your Roles Modifier:

import { planExtendRole, processPermissions, encodeKey, } from "zodiac-roles-sdk"; // Convert permissions to targets const { targets } = processPermissions(permissions); // Plan the role extension (this fetches current state and calculates the diff) // `planExtendRole` is strictly additive, for replacing permissions that have been applied earlier, use `planApplyRole`. const calls = await planExtendRole( { key: encodeKey("trader-role"), targets, // The swap permissions }, { chainId: 1, // Ethereum mainnet address: "0x27d8bb2e33Bc38A9CE93fdD90C80677b8436aFfb", // Your Roles Modifier address log: true, // Optional: log the planned changes } ); // Execute the calls (requires owner permissions on the Roles Modifier) for (const call of calls) { await signer.sendTransaction(call); }

Once permissions are applied, you can make swaps using your role.

Make a swap using your role

Use getCowQuote to get a price quote for a token swap:

import { getCowQuote, SupportedChainId } from "zodiac-roles-sdk/swaps"; const quote = await getCowQuote({ // Order type and side kind: "sell", // Token addresses sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH buyToken: "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", // COW // Amount to sell (1 ETH in wei) sellAmountBeforeFee: BigInt("1000000000000000000"), // Order validity (30 minutes from now) validTo: Math.floor(Date.now() / 1000) + 30 * 60, // Network and Roles Modifier configuration chainId: SupportedChainId.MAINNET, rolesModifier: "0x27d8bb2e33Bc38A9CE93fdD90C80677b8436aFfb", roleKey: "trader-role", }); console.log("Quote:", quote); // { // sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // buyToken: "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", // sellAmount: "1000000000000000000", // buyAmount: "4000000000000000000", // // ... other quote fields // }

Quote Request Parameters

Required Parameters
  • kind: Order type - "sell" or "buy"
  • sellToken: Address of the token to sell
  • buyToken: Address of the token to buy
  • chainId: Network chain ID (see SupportedChainId enum)
  • rolesModifier: Address of your Roles Modifier instance
  • roleKey: Identifier for the role making the swap
Amount Parameters

For sell orders, provide:

  • sellAmountBeforeFee: Amount to sell (before fees) as bigint

For buy orders, provide:

  • buyAmountAfterFee: Desired amount to buy (after fees) as bigint
Optional Parameters
  • receiver: Recipient address (defaults to the avatar address of the Roles Modifier)
  • validTo: Order expiration timestamp (defaults to 30 minutes from now)
  • partiallyFillable: Allow partial fills (defaults to false)
  • sellTokenBalance: Token balance source ("erc20", "external", "internal")
  • buyTokenBalance: Token balance destination ("erc20", "internal")
  • priceQuality: Quote quality ("fast", "optimal")

Signing the Order

After getting a quote, you need to sign the order. The SDK provides signCowOrder to generate the transaction that will mark the order as signed through your role:

import { signCowOrder } from "zodiac-roles-sdk/swaps"; // Generate the signing transaction const signingTx = signCowOrder(quote); // Execute the signing transaction using the role member wallet await roleSigner.sendTransaction(signingTx);

The Signing Transaction

The signCowOrder function returns a transaction object with:

{ to: "0x27d8bb2e33Bc38A9CE93fdD90C80677b8436aFfb", // Your Roles Modifier address data: "0x...", // Encoded call to sign the order value: 0, chainId: 1, // The network chain ID }

Role Signer Requirements

The signer executing the transaction must:

  • Be a member of the role that has swap permissions
  • Have sufficient ETH for gas fees
  • Be connected to the correct network

The signing process uses the COW Protocol’s presign mechanism, which means the order is marked as “signed” on-chain without requiring an actual cryptographic signature from the avatar.

Posting the Order

In addition to marking the order as signed, you need to post it to the COW API to be executed:

import { postCowOrder } from "zodiac-roles-sdk/swaps"; // Assume you have a signed quote const orderId = await postCowOrder(quote); console.log("Order posted with ID:", orderId); // "0x1234567890abcdef..."
Last updated on