Skip to main content

Partner integration (SDK)

This guide is for teams that run their own swap or treasury tool (for example a vault rebalancing console) and want to route orders through Ophis, charge the Ophis fee, and earn a rebate, signing with a smart-contract wallet (a Safe via EIP-1271, or an MPC signer behind EIP-1271).

If you want to embed the Ophis swap UI instead, use the widget. The widget cannot carry a partner fee or a rebate code, so to earn attribution you must use the SDK path described here.

The whole integration is a standard CoW Protocol order built with @cowprotocol/cow-sdk, with a few values overridden from @ophis/sdk. If your tool already places CoW orders, the changes are small.

Install

npm i @cowprotocol/cow-sdk @ophis/sdk
# plus an EVM util lib for keccak256 + EIP-712 (ethers v6 or viem)

@ophis/sdk is dependency-free and provides only the Ophis-specific values. It does not bundle cow-sdk, so install both. No Ophis-side deployment is required: the Optimism orderbook and settlement already exist and are live.

Two cases: Optimism vs CoW-hosted chains

Ophis serves two kinds of chain, and they differ only in where the order is posted and which settlement contract signs:

Optimism (self-hosted)CoW-hosted chains (Mainnet, Base, Arbitrum, Gnosis, Polygon, Avalanche, BNB, Linea, Plasma, Ink)
Orderbook hostoptimism-mainnet.ophis.fi (Ophis)api.cow.fi/<chain> (cow-sdk default)
Settlement (EIP-712 verifyingContract)Ophis 0x310784c7FCE12d578dA6f53460777bAc9718B859CoW canonical 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 (cow-sdk default)
Partner feebuildOphisAppDataPartnerFee(chainId)buildOphisAppDataPartnerFee(chainId)
Fee enforcementEnforced floor at settlementCarried in appData, validated by CoW

On CoW-hosted chains you change nothing about host or settlement (cow-sdk defaults are correct); you only add the Ophis partnerFee fragment. On Optimism you also override the host and the settlement contract.

Optimism integration

1. Point the orderbook at the Ophis host

import { OrderBookApi } from '@cowprotocol/cow-sdk';
import { getOphisOrderbookUrl } from '@ophis/sdk';

const orderBookApi = new OrderBookApi({
chainId: 10,
// optimism-mainnet.ophis.fi, NOT api.cow.fi. The CoW host does not serve
// Ophis on Optimism: it would bypass our solver and charge no Ophis fee.
baseUrls: { 10: getOphisOrderbookUrl(10) },
});

2. Build the appData with the Ophis partner fee

import { MetadataApi, stringifyDeterministic } from '@cowprotocol/cow-sdk';
import { keccak256, toUtf8Bytes } from 'ethers';
import { buildOphisAppDataPartnerFee, ophisVolumeBpsForPair, OPHIS_PARTNER_FEE_RECIPIENT } from '@ophis/sdk';

// The standard fragment is { volumeBps: 10, recipient }, the CIP-75 Volume shape:
// const partnerFee = buildOphisAppDataPartnerFee(10);
// On a SAME-CHAIN STABLECOIN pair, charge the reduced 1 bp rate instead. The SDK
// is chain-only and cannot detect the pair, so you decide isStablePair and pass it
// to ophisVolumeBpsForPair (1 bp stable-stable, else 10 bps):
const partnerFee = {
recipient: OPHIS_PARTNER_FEE_RECIPIENT,
volumeBps: ophisVolumeBpsForPair(isStablePair),
};

const doc = await new MetadataApi().generateAppDataDoc({
appCode: 'YourApp',
metadata: { partnerFee, hooks: {} },
});
const fullAppData = await stringifyDeterministic(doc); // deterministic, never JSON.stringify
const appDataHash = keccak256(toUtf8Bytes(fullAppData)); // bytes32 -> order.appData

On Optimism the fee is an enforced floor. The backend rejects (HTTP 400) any order to the Ophis recipient whose partner fee is below the floor, or that uses a Surplus or PriceImprovement policy. Always charge at least the applicable floor: 10 bps, or 1 bp for a same-chain stablecoin pair. Do not set the bps below that, and do not drop the fee.

3. Sign with the Ophis EIP-712 domain

import { getOphisOrderDomain } from '@ophis/sdk';

// { name: 'Gnosis Protocol', version: 'v2', chainId: 10,
// verifyingContract: '0x310784c7FCE12d578dA6f53460777bAc9718B859' }
const domain = getOphisOrderDomain(10);

The verifyingContract is the Ophis self-deployed GPv2Settlement on Optimism, not CoW's canonical address. Signing against the canonical address produces a domain separator the deployed contract rejects, so every order would fail.

4. Pin the receiver to your vault

import { assertReceiverIsOwner, ophisOrderReceiver } from '@ophis/sdk';

// For a vault, owner = the vault Safe. assertReceiverIsOwner throws unless
// order.receiver === owner (undefined / zero are treated as owner and pass), so
// proceeds land back in the vault. ophisOrderReceiver(owner) resolves it for you.
order.receiver = ophisOrderReceiver(vaultSafe);
assertReceiverIsOwner(vaultSafe, order.receiver);

5. Sign via the vault Safe (EIP-1271) and submit

The Ophis Optimism orderbook supports the eip1271 signing scheme, so a Safe (or an MPC signer behind EIP-1271) can sign:

  1. Compute the EIP-712 order digest over the domain from step 3 and the Order struct (the 12 GPv2 fields: sellToken, buyToken, receiver, sellAmount, buyAmount, validTo, appData, feeAmount, kind, partiallyFillable, sellTokenBalance, buyTokenBalance).
  2. Have the vault Safe produce the EIP-1271 signature (isValidSignature).
  3. orderBookApi.sendOrder({ ...order, from: vaultSafe, signingScheme: 'eip1271', signature }).

Your tool already does steps like this against CoW Swap. The only deltas are the three overrides above (host, verifyingContract, partnerFee).

Other (CoW-hosted) chains

Use cow-sdk exactly as you do today (its default api.cow.fi host and canonical settlement are correct), and add only the Ophis partner-fee fragment:

import { buildOphisAppDataPartnerFee, ophisVolumeBpsForPair, OPHIS_PARTNER_FEE_RECIPIENT, OPHIS_FEE_CHAIN_IDS } from '@ophis/sdk';

if (OPHIS_FEE_CHAIN_IDS.includes(chainId)) {
// Standard rate: buildOphisAppDataPartnerFee(chainId). For a same-chain
// stablecoin pair use the reduced 1 bp rate, same as on Optimism:
const partnerFee = {
recipient: OPHIS_PARTNER_FEE_RECIPIENT,
volumeBps: ophisVolumeBpsForPair(isStablePair),
};
// ...put it in metadata.partnerFee, sign with the CoW canonical domain
}

The fee recipient is one CREATE2-deterministic Safe on every chain, so the fragment is identical everywhere; only the host and settlement differ (and only on Optimism). CoW-hosted chains do not enforce the floor, so the 1 bp stable rate there is your choice, kept consistent with Optimism.

Earning a rebate (the partner discount)

The fee is the same flat 10 bps everywhere, but partners earn a rebate on top. On CoW-hosted chains the fee cannot be lowered at settlement, so the partner benefit is delivered as a post-hoc WETH rebate: tag each order with your referral code and Ophis pays you monthly.

import { ophisVolumeBpsForPair, OPHIS_PARTNER_FEE_RECIPIENT, buildOphisReferrerMetadata } from '@ophis/sdk';

const doc = await new MetadataApi().generateAppDataDoc({
appCode: 'YourApp',
metadata: {
// Same partner-fee fragment as above: reduced 1 bp for a same-chain
// stablecoin pair, else 10 bps. The rebate is on top of the fee.
partnerFee: { recipient: OPHIS_PARTNER_FEE_RECIPIENT, volumeBps: ophisVolumeBpsForPair(isStablePair) },
...buildOphisReferrerMetadata('your-code'), // -> metadata.ophisReferrer.code
hooks: {},
},
});

The rebate indexer reads metadata.ophisReferrer.code from every settled order, credits your referred USD volume across all served chains, and pays out monthly in WETH from a single Gnosis Safe. Your code must exist before you tag orders with it. Higher tiers earn a larger share. See the Affiliate program for rates and tiers.

A future option for Optimism is an enforced lower fee at settlement (rather than a post-hoc rebate), via a signed fee credential. That is a separate, not-yet-shipped capability; talk to us if you want it.

Caveats

  • Use the SDK path, not the widget. The embed cannot carry a partnerFee or a referral code.
  • Optimism is the only self-hosted chain. Other chains are CoW-hosted, where Ophis charges the fee but cannot enforce a floor or an on-chain discount.
  • Do not use the api.cow.fi host on Optimism. It silently bypasses the Ophis solver and charges no Ophis fee.

Quick reference

StepOptimismCoW-hosted chains
Orderbook hostgetOphisOrderbookUrl(10)cow-sdk default api.cow.fi/<chain>
EIP-712 domaingetOphisOrderDomain(10)cow-sdk default (canonical settlement)
Partner feevolumeBps: ophisVolumeBpsForPair(isStablePair) to the Ophis recipient (>= floor on OP)same; buildOphisAppDataPartnerFee(chainId) for the flat 10 bps
Rebate tagbuildOphisReferrerMetadata(code)buildOphisReferrerMetadata(code)
ReceiverassertReceiverIsOwner(vault, receiver)assertReceiverIsOwner(vault, receiver)
SigningEIP-1271 (Safe / MPC)EIP-1271 (Safe / MPC)