Skip to main content
A complete submission is two artifacts with different confidentiality levels:
  • The on-chain intent, public, passed as arguments to BridgeIntentV2.createIntent on the source chain. Solver-facing.
  • The encrypted recipient bundle, stored off-chain on the relayer via POST /store-recipients, ECIES-encrypted to the relayer’s public key. Recipient-facing.

Public (on-chain) fields

These are the arguments to createIntent. Visible to anyone watching the source chain:
function createIntent(
  address _tokenA,
  address _tokenB,
  uint256 _amountA,
  uint256 _expectedAmountB,
  uint256 _reward,
  uint256 _destChainId,
  uint256 _auctionDuration
)
_tokenA
address
required
ERC-20 address on source chain. Must be a supported asset.
_tokenB
address
required
ERC-20 address on destination chain.
_amountA
uint256
required
Amount of _tokenA the user is offering. The user’s approval to the bridge contract must cover _amountA + _reward.
_expectedAmountB
uint256
required
Minimum acceptable amount of _tokenB delivered to the recipient(s). Acts as a slippage floor.
_reward
uint256
required
Reward paid to the winning solver, in _tokenA. Deducted from the user’s approval alongside _amountA.
_destChainId
uint256
required
Numeric destination chain ID. Must be a directly supported chain.
_auctionDuration
uint256
required
Seconds the solver auction stays open after intent creation. Minimum 20 seconds (enforced by the TWAP service; tighter minimums may be enforced on BridgeIntentV2).
The contract also emits an encrypted blob in the same event, containing recipient-side metadata recoverable only with the relayer’s private key. This is the on-chain recovery anchor, if the relayer is ever lost, the key holder can reconstruct intent state from on-chain history. Integrators never construct this blob; the protocol handles it.

Encrypted (off-chain) fields

Posted to POST /store-recipients after createIntent mines:
interface RecipientBundle {
  recipients: Address[];   // destination addresses (one or many)
  amounts:    string[];    // per-recipient amounts on destination, sum <= expectedAmountB
}
The bundle is JSON-serialized and ECIES-encrypted with the relayer’s public key (fetched from GET /ecies-pubkey), then posted hex-encoded. The relayer decrypts in its trusted environment and never writes plaintext anywhere persistent. Only the winning solver receives the bundle, re-encrypted to the solver’s own keypair.

Planned SDK shape

The SDK (WIP) will accept a single object and split it into the two artifacts internally:
interface IntentParams {
  sourceChain: ChainId;
  destChain:   ChainId;
  tokenIn:     Address;
  tokenOut:    Address;
  amountIn:    bigint;
  minAmountOut: bigint;
  reward:      bigint;
  deadline:    number;      // unix seconds, maps to auctionDuration when contract is called
  recipients:  { address: Address; amount: bigint }[];
  metadata?:   Record<string, string>;   // off-chain only, never published
  viewers?:    Address[];                // scoped read access, off-chain only
}
The SDK will:
  1. Call createIntent with the public fields above.
  2. Encrypt { recipients, amounts } and POST /store-recipients.
  3. Store metadata and viewers against the intent in the relayer (off-chain only).

Field semantics

sourceChain / destChain
ChainId
Source chain the user funds from; destination chain the recipient receives on. See supported chains.
amountIn + reward
bigint
The user’s approval to the bridge contract must be at least amountIn + reward. The bridge pulls this on createIntent; the reward pays the winning solver, the remainder is what the solver delivers on destination.
minAmountOut
bigint
Solvers need to deliver at least this much (summed across all recipients) for their bid to be valid at settlement.
deadline / auctionDuration
number
Seconds of auction window. Longer = more solver participation (better rates); shorter = faster commitment.
  • UI flows: 60–120 seconds
  • Batch / payroll: 60–300 seconds per intent
  • Server-to-server backfill: 300–600 seconds
  • TWAP tranche: period / 2 (service default, minimum 20 seconds)
recipients
{ address, amount }[]
One or many. Amounts are in tokenOut’s base units on the destination chain. Their sum must not exceed minAmountOut; it can be less if solvers are expected to deliver more than the minimum (any slippage cushion stays with the recipient).
metadata
Record<string, string>
Integrator-defined key/value data. Stored off-chain only, never published on any chain. Useful for correlation with your internal records (invoice IDs, payroll periods, etc.).
viewers
Address[]
Addresses granted scoped read access to this intent’s decrypted details (via the relayer, after the intent settles). See viewing permissions. Cannot be modified after submission.

Allowed ChainId values

type ChainId =
  | "horizen_mainnet"
  | "base_mainnet"
  | "polygon_mainnet"
  | "ethereum_mainnet"
  | "optimism_mainnet"
  | "rari_mainnet"
  // and their testnet variants, see /concepts/supported-chains
  | string;
Numeric chain IDs are used on-chain (the _destChainId arg). Call POST /get-routes to enumerate live source–destination pairs at any time.

What observers actually see

DataOn-chain (source)Relayer broadcast (to solvers, pre-bid)Relayer (post-bid, to winning solver)
Token pair✓ (batched)
AmountAggregated across batch
Reward / fees✓ (batched)
Destination chain
Sender address✓ (calls createIntent)
Recipient addressesEncrypted blob only✓ (re-encrypted to solver)
Permit signatures✓ (re-encrypted to solver)
See privacy guarantees for the full threat model.

SDK API reference

Method signatures and return types.