MEE Bridging Plugins
Bridging plugins are modular components that enable the MEE SDK to integrate with different cross-chain bridge protocols. Each plugin encapsulates the logic for interacting with a specific bridge, allowing the SDK to optimize routes across multiple bridges and chains.
Plugin Architecture
A bridging plugin is defined by the BridgingPlugin
interface:
type BridgingPlugin = {
encodeBridgeUserOp: (params: BridgingUserOpParams) => Promise<BridgingPluginResult>;
};
The plugin takes bridging parameters and returns a user operation that can be executed by the MEE service:
type BridgingUserOpParams = {
fromChain: Chain; // Source chain
toChain: Chain; // Destination chain
multichainAccount: MultichainSmartAccount; // User's account
tokenMapping: MultichainAddressMapping; // Token addresses
bridgingAmount: bigint; // Amount to bridge
};
type BridgingPluginResult = {
userOp: MeeUserOp; // The operation to execute
receivedAtDestination?: bigint; // Expected output amount
bridgingDurationExpectedMs?: number; // Expected bridge time
};
Creating Your Own Plugin
Here's a step-by-step guide to implementing a bridge plugin, using the Across protocol as an example:
- Setup Basic Structure
export const MyBridgePlugin: BridgingPlugin = {
encodeBridgeUserOp: async (params) => {
const {
bridgingAmount,
fromChain,
toChain,
multichainAccount,
tokenMapping,
} = params;
// Your implementation here
}
};
- Get Required Addresses
// Get token addresses on both chains
const inputToken = tokenMapping.on(fromChain.id);
const outputToken = tokenMapping.on(toChain.id);
// Get user's account addresses
const depositor = multichainAccount.deploymentOn(fromChain.id).address;
const recipient = multichainAccount.deploymentOn(toChain.id).address;
- Handle Bridge-Specific Logic
// Example: Fetch bridge fees
const bridgeFees = await fetchBridgeFees({
amount: bridgingAmount,
sourceChain: fromChain.id,
destChain: toChain.id
});
// Calculate actual amount received after fees
const outputAmount = bridgingAmount - bridgeFees;
- Create Required Transactions
// Usually includes approval and bridge transactions
const approveCall: AbstractCall = {
to: inputToken,
gasLimit: 100000n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: [bridgeAddress, bridgingAmount]
})
};
const bridgeCall: AbstractCall = {
to: bridgeAddress,
gasLimit: 150000n,
data: encodeFunctionData({
abi: bridgeAbi,
functionName: "bridge",
args: [/* bridge-specific args */]
})
};
- Return Bridge Operation
const userOp = buildMeeUserOp({
calls: [approveCall, bridgeCall],
chainId: fromChain.id
});
return {
userOp,
receivedAtDestination: outputAmount,
bridgingDurationExpectedMs: expectedDuration
};
How Plugins Are Used
The MEE SDK uses plugins to optimize bridge routes:
- Route Discovery
// SDK queries all available plugins
const bridgeQueries = sourceBalances.flatMap(source =>
bridgingPlugins.map(plugin =>
queryBridge({
fromChain,
toChain,
plugin,
amount: source.balance,
multichainAccount,
tokenMapping,
})
)
);
- Route Optimization
// Results are sorted by efficiency
.sort((a, b) =>
Number((b.receivedAtDestination * 10000n) / b.amount) -
Number((a.receivedAtDestination * 10000n) / a.amount)
);
- Route Selection The SDK selects the best routes based on:
- Amount received after fees
- Bridge duration
- Bridge reliability
- Gas costs
Best Practices
- Error Handling
try {
const bridgeFees = await fetchBridgeFees(/*...*/);
} catch (error) {
// Return null to indicate bridge unavailable
return null;
}
- Gas Estimation
- Always provide conservative gas limits
- Account for varying gas costs across chains
- Include buffer for token approvals
- Amount Calculation
- Account for all fees and slippage
- Return accurate
receivedAtDestination
amounts - Consider minimum bridge amounts
- Bridge Duration
- Provide accurate
bridgingDurationExpectedMs
when possible - This helps the MEE service optimize operation timing
Integration Example
Here's how to register your plugin with the SDK:
const quote = await supertransaction()
.injectAccount(mcNexus)
.addInstructions(
await requireErc20Balance({
amount: supplyAmount,
chain: base,
token: xUSDC,
bridgingPlugins: [MyBridgePlugin, AcrossPlugin]
})
)
.getQuote(meeService);
The SDK will automatically evaluate your plugin alongside others to find the optimal bridging route.