-
Custom Address
Send an asset across chains and optionally attach destination logic in one transaction. Use the same Omnisea entrypoint for a simple transfer, a Morpho borrow, or your own cross-chain action.

// sendOriginal pulls the token into OmniseaVault
IERC20(token).approve(address(omnisea), amt);
// A plain transfer: no composer, no compose gas
ComposeParams memory compose = ComposeParams({
composer: address(0),
gasLimit: 0,
message: ""
});
// Quote and send must stay byte-identical
uint256 fee = omnisea.quoteSendOriginal(
dstEid, token, amt, to, false, compose, opts
);
// EndpointV2 chains require exact msg.value
omnisea.sendOriginal{value: fee}(
dstEid, token, amt, to, false, compose, opts
);
Use wagmi and viem to transfer Omniassets or attach Omnihooks—composers that run application logic after an asset arrives. Connect to destination protocols without operating a relayer or backend.

// Canonical token, or an Omniasset already?
const identity = await client.readContract({
address: omnisea,
abi: omniseaAbi,
functionName: "oftToOriginal",
args: [token],
});
const isRepresentation = identity[3];
// A zero address means this deploys the token
const representation = await client.readContract({
address: omnisea,
abi: omniseaAbi,
functionName: "representationFor",
args: [originalChainId, 1, pad(token)],
});
const isFirst = representation === zeroAddress;
// Canonical → sendOriginal, representation → sendOFT
const fn = isRepresentation
? "sendOFT" : "sendOriginal";