Wallchain
Search
⌃K
🤲

Integration

Integration consists of 2 steps.
  1. 1.
    Upgrading the transaction through Wallchain Service API using an access key. Request one at https://t.me/wallchain_xyz
  2. 2.
    Sending the transaction to Wallchain Router Proxy

Contents

Upgrade Transaction

Before sending a transaction to a wallet for confirmation, you need to upgrade it using Wallchain Service API at https://matic.wallchain.xyz/upgrade_txn/?key=<KEY>.
Here is an example of how it can be done:
// JavaScript Upgrade Transaction example (from Node.JS)
const fetch = require('cross-fetch');
const url = `https://matic.wallchains.com/upgrade_txn/?key=${KEY}`
fetch(url,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
value: "1000000000000000000000",
sender: "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270",
destination: "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff",
data: "0x7ff36ab5000000000000000000000000000000000000000000000065fff429ce525844fe00000000000000000000000000000000000000000000000000000000000000800000000000000000000000003d73afbb4b3de6870898ecde8d13b2d198e2f8e200000000000000000000000000000000000000000000000000000000c3810f2d00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000f239e69ce434c7fb408b05a0da416b14917d934e"
})
})
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
If the request fails for any reason you should use the original transaction. This way zero downtime is guaranteed.

Send Transaction to Wallchain Router Proxy

Wallchain Router Proxy redirects all swaps to the original DEX router and triggers Wallchain Master to capture backrunning profits.
DEX should deploy its own Router Proxy similar to the example below. The latest contract with updates to the DEX (if needed) is provided separately.
dexRouterAddress is the address of the current router used by DEX. dexAgent is the address where DEX owners want to receive profit share. To get wchainMasterAddress send a message to https://t.me/wallchain_xyz
// Smart contract exapmle for Wallchain Router Proxy
contract RouterManager {
uint256 constant UINT256_MAX = 2**256 - 1;
IUniswapV2Router02 public immutable dexRouter;
IWChainMaster public wchainMaster;
address public immutable dexAgent;
constructor(
address dexRouterAddress,
address _dexAgent,
address wchainMasterAddress
) {
dexRouter = IUniswapV2Router02(dexRouterAddress);
dexAgent = _dexAgent;
wchainMaster = IWChainMaster(wchainMasterAddress);
}
receive() external payable {}
modifier coverUp(bytes memory masterInput) {
_;
try wchainMaster.execute(masterInput, msg.sender, dexAgent) {} catch {}
}
function maybeApproveERC20(address token) private {
// approve dex router to fetch the funds for swapping
if (
IERC20(token).allowance(address(this), address(dexRouter)) == 0
) {
IERC20(token).approve(address(dexRouter), UINT256_MAX);
}
}
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
address to,
uint256 deadline,
bytes memory masterInput
) public coverUp(masterInput) returns (uint256[] memory amounts) {
amounts = dexRouter.getAmountsOut(amountIn, path);
require(
amounts[amounts.length - 1] >= amountOutMin,
"UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
address(this),
amounts[0]
);
maybeApproveERC20(path[0]);
return dexRouter.swapExactTokensForTokens(
amountIn,
amountOutMin,
path,
to,
deadline
);
}
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline,
bytes calldata masterInput
) external coverUp(masterInput) returns (uint256[] memory amounts) {
amounts = dexRouter.getAmountsIn(amountOut, path);
require(
amounts[0] <= amountInMax,
"UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"
);
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
address(this),
amounts[0]
);
maybeApproveERC20(path[0]);
return dexRouter.swapTokensForExactTokens(
amountOut,
amountInMax,
path,
to,
deadline
);
}
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline,
bytes calldata masterInput
) external payable coverUp(masterInput) returns (uint256[] memory amounts) {
return dexRouter.swapExactETHForTokens{value: msg.value}(
amountOutMin,
path,
to,
deadline
);
}
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline,
bytes calldata masterInput
) external coverUp(masterInput) returns (uint256[] memory amounts) {
require(
path[path.length - 1] == dexRouter.WETH(),
"UniswapV2Router: INVALID_PATH"
);
amounts = dexRouter.getAmountsIn(amountOut, path);
require(
amounts[0] <= amountInMax,
"UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"
);
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
address(this),
amounts[0]
);
maybeApproveERC20(path[0]);
return dexRouter.swapTokensForExactETH(
amountOut,
amountInMax,
path,
to,
deadline
);
}
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline,
bytes calldata masterInput
) external coverUp(masterInput) returns (uint256[] memory amounts) {
require(
path[path.length - 1] == dexRouter.WETH(),
"UniswapV2Router: INVALID_PATH"
);
amounts = dexRouter.getAmountsOut(amountIn, path);
require(
amounts[amounts.length - 1] >= amountOutMin,
"UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
address(this),
amounts[0]
);
maybeApproveERC20(path[0]);
return dexRouter.swapExactTokensForETH(
amountIn,
amountOutMin,
path,
to,
deadline
);
}
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline,
bytes calldata masterInput
) external payable coverUp(masterInput) returns (uint256[] memory amounts) {
require(path[0] == dexRouter.WETH(), "UniswapV2Router: INVALID_PATH");
amounts = dexRouter.getAmountsIn(amountOut, path);
require(
amounts[0] <= msg.value,
"UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"
);
dexRouter.swapETHForExactTokens{value: msg.value}(
amountOut,
path,
to,
deadline
);
// refund dust eth, if any
if (msg.value > amounts[0])
TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
}
}

Gotchas

  1. 1.
    To get the information about expected profit and use it in the frontend, send the query to Wallchain Service API before the Swap button has been clicked.
  2. 2.
    No need to approve the router before the user clicks Swap, since the router might change
  3. 3.
    It's better to delay sending the request to Wallchain Service API from the last user keystroke by 200 ms
Last modified 1mo ago