Submit Proportional Exit
POST /intents/submit (type: "exitProportional")
Submit a signed proportional exit intent. The user burns LP shares and receives pool tokens proportionally.
Full Example (viem)
javascript
const MULTIHOP_ROUTER = '0x662F15226f5b6Bf8aA10512374Af3115412C04bA';
const RELAYER_URL = 'https://mainnet.relayer.ryze.pro/api/v1';
// 1. Read nonce
const nonce = await publicClient.readContract({
address: MULTIHOP_ROUTER,
abi: [{ name: 'exitProportionalNonces', type: 'function', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }], stateMutability: 'view' }],
functionName: 'exitProportionalNonces',
args: [account.address],
});
// 2. Build intent
const deadline = BigInt(Math.floor(Date.now() / 1000) + 1800);
const sharesIn = BigInt('50000000000000000000'); // LP shares to burn
const intent = {
user: account.address,
pool: '0x7B41aA91947398CD9244AD4e314C253D9B1B5206',
sharesIn,
minAmountsOut: [
BigInt('30000000000000000'), // min WETH
BigInt('49000000'), // min USDC
],
recipient: account.address,
deadline,
nonce,
};
// 3. Sign EIP-712
const signature = await walletClient.signTypedData({
domain: {
name: 'MultiHopRouter',
version: '1',
chainId: 8453,
verifyingContract: MULTIHOP_ROUTER,
},
types: {
ExitProportionalIntent: [
{ name: 'user', type: 'address' },
{ name: 'pool', type: 'address' },
{ name: 'sharesIn', type: 'uint256' },
{ name: 'minAmountsOut', type: 'uint256[]' },
{ name: 'recipient', type: 'address' },
{ name: 'deadline', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
],
},
primaryType: 'ExitProportionalIntent',
message: intent,
});
// 4. Split signature and submit
const r = signature.slice(0, 66);
const s = '0x' + signature.slice(66, 130);
const v = parseInt(signature.slice(130, 132), 16);
const res = await fetch(`${RELAYER_URL}/intents/submit`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'exitProportional',
user: intent.user,
pool: intent.pool,
sharesIn: intent.sharesIn.toString(),
minAmountsOut: intent.minAmountsOut.map(a => a.toString()),
poolTokens: [
'0x4200000000000000000000000000000000000006', // WETH
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
],
recipient: intent.recipient,
deadline: Number(intent.deadline),
nonce: Number(intent.nonce),
signature: { v, r, s },
}),
});
const result = await res.json();
console.log('Intent ID:', result.intentId);Request Body
json
{
"type": "exitProportional",
"user": "0xYourAddress",
"pool": "0x7B41aA91947398CD9244AD4e314C253D9B1B5206",
"sharesIn": "50000000000000000000",
"minAmountsOut": [
"30000000000000000",
"49000000"
],
"poolTokens": [
"0x4200000000000000000000000000000000000006",
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
],
"recipient": "0xYourAddress",
"deadline": 1713200000,
"nonce": 0,
"signature": { "v": 27, "r": "0x...", "s": "0x..." }
}Fields
| Field | Type | Description |
|---|---|---|
type | string | Must be "exitProportional" |
user | address | Sender (must match signature) |
pool | address | Pool to exit |
sharesIn | string | LP shares to burn (18 decimals) |
minAmountsOut | string[] | Minimum amounts per token (slippage protection) |
poolTokens | string[] | Token addresses (same order as minAmountsOut) |
recipient | address | Address to receive tokens |
deadline | number | Unix timestamp expiry |
nonce | number | From exitProportionalNonces(user) on contract |
signature | object | EIP-712 signature {v, r, s} |
INFO
The minAmountsOut and poolTokens arrays must be the same length and in the same token order.
EIP-712 Types
typescript
const types = {
ExitProportionalIntent: [
{ name: 'user', type: 'address' },
{ name: 'pool', type: 'address' },
{ name: 'sharesIn', type: 'uint256' },
{ name: 'minAmountsOut', type: 'uint256[]' },
{ name: 'recipient', type: 'address' },
{ name: 'deadline', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
],
};