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 host | optimism-mainnet.ophis.fi (Ophis) | api.cow.fi/<chain> (cow-sdk default) |
Settlement (EIP-712 verifyingContract) | Ophis 0x310784c7FCE12d578dA6f53460777bAc9718B859 | CoW canonical 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 (cow-sdk default) |
| Partner fee | buildOphisAppDataPartnerFee(chainId) | buildOphisAppDataPartnerFee(chainId) |
| Fee enforcement | Enforced floor at settlement | Carried 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:
- Compute the EIP-712 order digest over the
domainfrom step 3 and theOrderstruct (the 12 GPv2 fields:sellToken,buyToken,receiver,sellAmount,buyAmount,validTo,appData,feeAmount,kind,partiallyFillable,sellTokenBalance,buyTokenBalance). - Have the vault Safe produce the EIP-1271 signature (
isValidSignature). 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
partnerFeeor 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.fihost on Optimism. It silently bypasses the Ophis solver and charges no Ophis fee.
Quick reference
| Step | Optimism | CoW-hosted chains |
|---|---|---|
| Orderbook host | getOphisOrderbookUrl(10) | cow-sdk default api.cow.fi/<chain> |
| EIP-712 domain | getOphisOrderDomain(10) | cow-sdk default (canonical settlement) |
| Partner fee | volumeBps: ophisVolumeBpsForPair(isStablePair) to the Ophis recipient (>= floor on OP) | same; buildOphisAppDataPartnerFee(chainId) for the flat 10 bps |
| Rebate tag | buildOphisReferrerMetadata(code) | buildOphisReferrerMetadata(code) |
| Receiver | assertReceiverIsOwner(vault, receiver) | assertReceiverIsOwner(vault, receiver) |
| Signing | EIP-1271 (Safe / MPC) | EIP-1271 (Safe / MPC) |