Skip to main content

OIF Provider

The OIF (Open Intents Framework) provider enables direct integration with any OIF-compliant solver. If you have access to a solver's API endpoint, you can integrate cross-chain functionality directly into your application using this provider.

Configuration

FieldTypeRequiredDescription
solverIdstringYesSolver identifier
urlstringYesSolver API endpoint URL
headersobjectNoCustom HTTP headers
adapterMetadataobjectNoAdditional metadata for the solver
providerIdstringNoCustom provider identifier
supportedLocksstring[]NoLock mechanisms to request (e.g. ["oif-escrow"], ["compact-resource-lock"]). Default: ["oif-escrow"]
submissionModesstring[]NoExecution modes: ["user-transaction"], ["gasless"], or both. Default: all modes
OIF defaults to all submission modes

Unlike Relay and Bungee, the OIF provider enables both submission modes when submissionModes is not set — "user-transaction" (user pays gas) and "gasless" (solver executes on behalf of the user). The exact order types available also depend on supportedLocks (default: ["oif-escrow"]).

"user-transaction" maps to oif-user-open-v0; "gasless" maps to escrow-based order types (oif-escrow-v0, oif-3009-v0, oif-resource-lock-v0).

To restrict to a specific mode, set it explicitly:

// User-pays-gas quotes only
submissionModes: ["user-transaction"]

// Gasless quotes only
submissionModes: ["gasless"]

Lock Mechanism Mapping

The supportedLocks option controls which OIF order types the solver returns:

Lock MechanismOIF Order Types
oif-escrowoif-escrow-v0, oif-3009-v0
compact-resource-lockoif-resource-lock-v0

oif-user-open-v0 (user-pays-gas) is controlled by submissionModes independently.

oif-escrow-v0 Permit2 approval not auto-handled

oif-escrow-v0 quotes rely on Permit2 and require a one-time approve(PERMIT2, ...) per token before the solver can pull funds. The OIF wire format does not surface this in order.checks.allowances, so the approval service cannot prepend the step automatically for these quotes.

Workaround until the OIF adapter is updated: either handle the Permit2 approval yourself, or restrict the provider to submissionModes: ["user-transaction"] (which uses oif-user-open-v0, where approvals are declared correctly). oif-3009-v0 and oif-resource-lock-v0 do not need ERC-20 approvals and are unaffected.

Creating the Provider

import { createCrossChainProvider } from "@wonderland/interop-cross-chain";

// Default: oif-escrow lock type, all submission modes
const oifProvider = createCrossChainProvider("oif", {
solverId: "my-solver",
url: "https://oif-api.example.com",
});

// Gasless only (escrow-based)
const gaslessProvider = createCrossChainProvider("oif", {
solverId: "my-solver",
url: "https://oif-api.example.com",
supportedLocks: ["oif-escrow"],
submissionModes: ["gasless"],
});

// User-pays-gas only
const userTxProvider = createCrossChainProvider("oif", {
solverId: "my-solver",
url: "https://oif-api.example.com",
submissionModes: ["user-transaction"],
});

Execution Modes

The provider offers intent-based cross-chain operations with two execution modes:

Protocol Mode (Gasless)

User signs EIP-712 message, solver executes on their behalf:

import { createCrossChainProvider, getSignatureSteps } from "@wonderland/interop-cross-chain";
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";

const quotes = await oifProvider.getQuotes({
user: "0xYourAddress",
input: {
chainId: 1,
assetAddress: "0xInputTokenAddress",
amount: "1000000",
},
output: {
chainId: 42161,
assetAddress: "0xOutputTokenAddress",
},
swapType: "exact-input",
});

const quote = quotes[0];
const walletClient = createWalletClient({ account, chain: base, transport: http() });
const step = getSignatureSteps(quote.order)[0];
const { signatureType, ...typedData } = step.signaturePayload;
const signature = await walletClient.signTypedData(typedData);
await oifProvider.submitOrder(quote, signature);

User Mode (User Pays Gas)

User executes transaction directly:

import { getTransactionSteps } from "@wonderland/interop-cross-chain";

const quotes = await oifProvider.getQuotes({
user: "0xYourAddress",
input: {
chainId: 1,
assetAddress: "0xInputTokenAddress",
amount: "1000000",
},
output: {
chainId: 42161,
assetAddress: "0xOutputTokenAddress",
},
swapType: "exact-input",
});

const quote = quotes[0];
const step = getTransactionSteps(quote.order)[0];
// walletClient: a viem WalletClient connected to the user's wallet
await walletClient.sendTransaction({
to: step.transaction.to,
data: step.transaction.data,
value: step.transaction.value ? BigInt(step.transaction.value) : undefined,
});

Approvals

Access approval information from the order checks:

// Allowance requirements from order checks
const allowances = quote.order.checks?.allowances ?? [];
for (const { spender, tokenAddress, required } of allowances) {
// Approve token spend if needed
}

Next Step

See a complete working example: Execute Intent

References