Getting Started
This guide will help you quickly understand how to use JAMM DEX for token swaps and liquidity management.
Prerequisites
Before you begin, please ensure you have the following:
JuChain Wallet: A Web3 wallet that supports the JuChain network.
JU Token: The native token used to pay for transaction fees.
Test Tokens: ERC-20 tokens for swapping.
Contract Addresses
Mainnet Addresses
JAMMFactory:
0x6b5d54E6F73e96Ca960DBA71D778b98221939aa6
JAMMRouter:
0x3F26fb54C28Eab026e908A9A9357a456F3c8Dc87
WJU:
0x4d1B49B424afd7075d3c063adDf97D5575E1c7E2
USDT:
0xc8e19C19479a866142B42fB390F2ea1Ff082E0D2
ETH:
0x80077F108Dd73B709C43A1a13F0EEF25e48f7D0e
BNB:
0x151b6F646Ac02Ed9877884ed9637A84f2FD8FaA6
Testnet Addresses
JAMMFactory:
0xbddd716a9d6325700d1c29562c819987e5b1f6a8
JAMMRouter:
0x3f8b0038023393009712D0051D192a8825dd02B9
WJU:
0xb8cdb16bc2b64d42638e285a691973ff10078d8e
Your First Token Swap
1. Setup
First, you need to connect to the JuChain network and prepare the tokens for swapping.
// Connect to the JuChain network
const provider = new ethers.providers.JsonRpcProvider('https://rpc.juchain.org');
const signer = new ethers.Wallet(privateKey, provider);
// JAMMRouter contract instance
const routerAddress = '0x3F26fb54C28Eab026e908A9A9357a456F3c8Dc87';
const routerABI = ['...']; // Add router ABI
const router = new ethers.Contract(routerAddress, routerABI, signer);
2. Executing a Swap
The following example shows how to swap TokenA for TokenB:
// Swap parameters
const amountIn = ethers.utils.parseEther("1.0"); // 1 TokenA
const amountOutMin = ethers.utils.parseEther("0.9"); // Minimum 0.9 TokenB to receive
const path = [tokenA_address, tokenB_address]; // Swap path
const fees = [100]; // Fee tier for the pair (1%)
const to = signer.address; // Recipient address
const referrer = ethers.constants.AddressZero; // No referrer
const deadline = Math.floor(Date.now() / 1000) + 60 * 20; // 20 minutes from now
// Execute the swap
const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
path,
fees,
to,
referrer,
deadline
);
await tx.wait();
console.log("Swap completed!");
3. Swapping with JU
If you want to swap with the native JU token, use the ETH-related functions:
// Buy tokens with JU
const tx = await router.swapExactETHForTokens(
amountOutMin,
[WJU_address, tokenB_address], // Path must start with WJU
[100], // Fee tier
to,
referrer,
deadline,
{ value: ethers.utils.parseEther("1.0") } // Send 1 JU
);
Providing Liquidity for the First Time
1. Adding Liquidity
// Liquidity parameters
const tokenA = "TOKEN_A_ADDRESS";
const tokenB = "TOKEN_B_ADDRESS";
const fee = 100; // 1% fee tier
const amountADesired = ethers.utils.parseEther("10");
const amountBDesired = ethers.utils.parseEther("10");
const amountAMin = ethers.utils.parseEther("9"); // Minimum amount of TokenA
const amountBMin = ethers.utils.parseEther("9"); // Minimum amount of TokenB
const to = signer.address;
const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
// Approve the router to spend your tokens first
const tokenAContract = new ethers.Contract(tokenA, erc20ABI, signer);
const tokenBContract = new ethers.Contract(tokenB, erc20ABI, signer);
await tokenAContract.approve(routerAddress, amountADesired);
await tokenBContract.approve(routerAddress, amountBDesired);
// Add liquidity
const tx = await router.addLiquidity(
tokenA,
tokenB,
fee,
amountADesired,
amountBDesired,
amountAMin,
amountBMin,
to,
deadline
);
const receipt = await tx.wait();
console.log("Liquidity added successfully!");
2. Removing Liquidity
// Get LP token balance
const pairAddress = await factory.getPair(tokenA, tokenB, fee);
const pairContract = new ethers.Contract(pairAddress, pairABI, signer);
const lpBalance = await pairContract.balanceOf(signer.address);
// Remove 50% of your liquidity
const liquidity = lpBalance.div(2);
// Approve the router to spend your LP tokens
await pairContract.approve(routerAddress, liquidity);
// Calculate minimum amounts to receive with 1% slippage tolerance
const { reserve0, reserve1 } = await pairContract.getReserves();
const totalSupply = await pairContract.totalSupply();
const amount0 = liquidity.mul(reserve0).div(totalSupply);
const amount1 = liquidity.mul(reserve1).div(totalSupply);
const amount0Min = amount0.mul(99).div(100);
const amount1Min = amount1.mul(99).div(100);
// Remove liquidity
const tx = await router.removeLiquidity(
tokenA,
tokenB,
fee,
liquidity,
amount0Min,
amount1Min,
to,
deadline
);
await tx.wait();
console.log("Liquidity removed successfully!");
Using the permit
Function
permit
FunctionJAMM DEX supports EIP-2612 permit
, allowing you to approve token spending with a signature, avoiding a separate approve
transaction.
// Generate permit signature
const domain = {
name: 'JAMM LPs',
version: '1',
chainId: await signer.getChainId(),
verifyingContract: pairAddress
};
const types = {
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
};
const nonce = await pairContract.nonces(signer.address);
const value = {
owner: signer.address,
spender: routerAddress,
value: liquidity,
nonce: nonce,
deadline: deadline
};
const signature = await signer._signTypedData(domain, types, value);
const { v, r, s } = ethers.utils.splitSignature(signature);
// Remove liquidity using permit
const tx = await router.removeLiquidityWithPermit(
tokenA,
tokenB,
fee,
liquidity,
amount0Min, // Use calculated min amounts
amount1Min,
to,
deadline,
false, // approveMax
v,
r,
s
);
Querying Information
Getting Pair Information
// Check if a pair exists
const pairAddress = await factory.getPair(tokenA, tokenB, fee);
if (pairAddress === ethers.constants.AddressZero) {
console.log("Pair does not exist.");
} else {
console.log("Pair address:", pairAddress);
}
// Get reserves
const pair = new ethers.Contract(pairAddress, pairABI, provider);
const { reserve0, reserve1 } = await pair.getReserves();
console.log("Reserves:", reserve0.toString(), reserve1.toString());
Calculating Swap Amounts
// Calculate output amount
const amountOut = await router.getAmountOut(
amountIn,
reserves.reserve0,
reserves.reserve1,
fee
);
console.log("Expected output:", ethers.utils.formatEther(amountOut));
// Calculate amounts for a multi-hop swap
const amounts = await router.getAmountsOut(amountIn, path, fees);
console.log("Multi-hop swap path amounts:", amounts.map(a => ethers.utils.formatEther(a)));
Common Error Handling
Common Reasons for Transaction Failure
"JAMMRouter: EXPIRED": The transaction deadline has passed.
"JAMMRouter: INSUFFICIENT_OUTPUT_AMOUNT": Slippage is too high, and the output amount is less than the minimum required.
"JAMM: INSUFFICIENT_LIQUIDITY": Not enough liquidity in the pair for the swap.
"JAMMFactory: INVALID_FEE": An unsupported fee tier was used.
Error Handling Example
try {
const tx = await router.swapExactTokensForTokens(...);
await tx.wait();
} catch (error) {
if (error.message.includes("INSUFFICIENT_OUTPUT_AMOUNT")) {
console.log("Slippage too high. Please increase your slippage tolerance.");
} else if (error.message.includes("EXPIRED")) {
console.log("Transaction expired. Please try again.");
} else {
console.log("Transaction failed:", error.message);
}
}
Next Steps
Now that you understand the basics of using JAMM DEX, you can continue learning about:
Fee Structure - Understand the fee system.
Referral System - Learn how to earn referral rewards.
Integration Guides - Integrate JAMM DEX into your application.
Getting Help
If you encounter any issues, you can get help through the following channels:
Technical Docs: Check the detailed technical reference.
Community Support:
https://t.me/jammfun
Last updated