حالیہ برسوں میں ڈیفی تصور کی مقبولیت کے ساتھ ، یونیسوپ وی 3 غیر مرکزی مالیاتی (ڈی فائی) کے میدان میں سب سے زیادہ مقبول موضوعات میں سے ایک ہے۔ ایک معروف غیر مرکزی تبادلہ پروٹوکول کے طور پر ، یونیسوپ وی 3 زیادہ موثر ، محفوظ اور بہتر صارف کا تجربہ فراہم کرتا ہے۔ اب ، کوڈ کی صرف 200 لائنوں کے ساتھ ، تاجر اور ڈویلپر ایف ایم زیڈ پلیٹ فارم پر آسانی سے یونیسوپ وی 3 تک رسائی حاصل کرسکتے ہیں۔
ایف ایم زیڈ ایک مقداری تجارتی پلیٹ فارم ہے جو مقداری تجارتی حکمت عملیوں کی ترقی ، بیک ٹیسٹنگ اور حقیقی مارکیٹ کی تعیناتی کی حمایت کرتا ہے۔ اس کے استعمال میں آسان انٹرفیس اور طاقتور افعال کو سمجھنا مشکل نہیں ہے کہ ایف ایم زیڈ ڈی ایف آئی تاجروں اور ڈویلپرز کی پہلی پسند کیوں بن رہا ہے۔
Uniswap V3 کو FMZ میں ضم کرنے کا عمل آسان اور سمجھنے میں آسان ہے ، مکمل کرنے کے لئے صرف 200 لائنوں کے کوڈ کی ضرورت ہے۔ اس کا مطلب یہ ہے کہ یہاں تک کہ اگر آپ کوڈ کرنے میں نئے ہیں تو ، آپ آسانی سے FMZ پر Uniswap V3 سے رابطہ قائم کرسکتے ہیں اور فوری طور پر تجارت شروع کرسکتے ہیں۔
ایف ایم زیڈ نے ویب 3 کے بنیادی افعال کا ایک سلسلہ شامل کیا ہے۔ یونیسوپ کے علاوہ ، یہ کچھ کوڈز کے ساتھ دیگر ڈی ای ایکس ایکسچینجز کو بھی شامل کرسکتا ہے۔ اگلا ، میں آپ کو ڈیفی ایپلی کیشن میں تصورات اور ٹیکنالوجیز کو شروع سے سیکھنے کے لئے لے جاؤں گا۔ جگہ کی وجہ سے ، مندرجہ ذیل تفصیل جتنا ممکن ہو آسان ہے۔ یہ بہت عین مطابق نہیں ہوسکتا ہے ، لیکن سمجھنا آسان ہے۔
Uniswap V3 ٹریڈ ٹیمپلیٹایف ایم زیڈ پلیٹ فارم کے ذریعہ ظاہر کیا گیا
کوڈ مندرجہ ذیل ہے:
/* jshint esversion: 7 */
const ABI_Route = '[{"inputs":[{"internalType":"address","name":"_factoryV2","type":"address"},{"internalType":"address","name":"factoryV3","type":"address"},{"internalType":"address","name":"_positionManager","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"approveMax","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"approveMaxMinusOne","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"approveZeroThenMax","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"approveZeroThenMaxMinusOne","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"callPositionManager","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"paths","type":"bytes[]"},{"internalType":"uint128[]","name":"amounts","type":"uint128[]"},{"internalType":"uint24","name":"maximumTickDivergence","type":"uint24"},{"internalType":"uint32","name":"secondsAgo","type":"uint32"}],"name":"checkOracleSlippage","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint24","name":"maximumTickDivergence","type":"uint24"},{"internalType":"uint32","name":"secondsAgo","type":"uint32"}],"name":"checkOracleSlippage","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactInputParams","name":"params","type":"tuple"}],"name":"exactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IV3SwapRouter.ExactInputSingleParams","name":"params","type":"tuple"}],"name":"exactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IV3SwapRouter.ExactOutputSingleParams","name":"params","type":"tuple"}],"name":"exactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getApprovalType","outputs":[{"internalType":"enum IApproveAndCall.ApprovalType","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"}],"internalType":"struct IApproveAndCall.IncreaseLiquidityParams","name":"params","type":"tuple"}],"name":"increaseLiquidity","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IApproveAndCall.MintParams","name":"params","type":"tuple"}],"name":"mint","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"previousBlockhash","type":"bytes32"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"positionManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"pull","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"refundETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowed","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowedIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"}],"name":"sweepToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"sweepTokenWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"sweepTokenWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"unwrapWETH9","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"}],"name":"unwrapWETH9","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"unwrapWETH9WithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"unwrapWETH9WithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"wrapETH","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]';
const ABI_Pool = '[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"name\":\"Collect\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"name\":\"CollectProtocol\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paid0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paid1\",\"type\":\"uint256\"}],\"name\":\"Flash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"observationCardinalityNextOld\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"observationCardinalityNextNew\",\"type\":\"uint16\"}],\"name\":\"IncreaseObservationCardinalityNext\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"indexed\":false,\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"}],\"name\":\"Initialize\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol0Old\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol1Old\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol0New\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol1New\",\"type\":\"uint8\"}],\"name\":\"SetFeeProtocol\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"amount0\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"amount1\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"liquidity\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"}],\"name\":\"Swap\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount0Requested\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Requested\",\"type\":\"uint128\"}],\"name\":\"collect\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"amount0Requested\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Requested\",\"type\":\"uint128\"}],\"name\":\"collectProtocol\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGrowthGlobal0X128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGrowthGlobal1X128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"flash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"observationCardinalityNext\",\"type\":\"uint16\"}],\"name\":\"increaseObservationCardinalityNext\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidity\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLiquidityPerTick\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"observations\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"blockTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"int56\",\"name\":\"tickCumulative\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityCumulativeX128\",\"type\":\"uint160\"},{\"internalType\":\"bool\",\"name\":\"initialized\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"secondsAgos\",\"type\":\"uint32[]\"}],\"name\":\"observe\",\"outputs\":[{\"internalType\":\"int56[]\",\"name\":\"tickCumulatives\",\"type\":\"int56[]\"},{\"internalType\":\"uint160[]\",\"name\":\"secondsPerLiquidityCumulativeX128s\",\"type\":\"uint160[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"positions\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"liquidity\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthInside0LastX128\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthInside1LastX128\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"tokensOwed0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"tokensOwed1\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"token0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"token1\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"feeProtocol0\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"feeProtocol1\",\"type\":\"uint8\"}],\"name\":\"setFeeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slot0\",\"outputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"},{\"internalType\":\"uint16\",\"name\":\"observationIndex\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"observationCardinality\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"observationCardinalityNext\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"feeProtocol\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"unlocked\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"}],\"name\":\"snapshotCumulativesInside\",\"outputs\":[{\"internalType\":\"int56\",\"name\":\"tickCumulativeInside\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityInsideX128\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"secondsInside\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"int256\",\"name\":\"amountSpecified\",\"type\":\"int256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"swap\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"amount0\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int16\",\"name\":\"\",\"type\":\"int16\"}],\"name\":\"tickBitmap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tickSpacing\",\"outputs\":[{\"internalType\":\"int24\",\"name\":\"\",\"type\":\"int24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"\",\"type\":\"int24\"}],\"name\":\"ticks\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"liquidityGross\",\"type\":\"uint128\"},{\"internalType\":\"int128\",\"name\":\"liquidityNet\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthOutside0X128\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthOutside1X128\",\"type\":\"uint256\"},{\"internalType\":\"int56\",\"name\":\"tickCumulativeOutside\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityOutsideX128\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"secondsOutside\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"initialized\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]'
const ABI_Factory = '[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickSpacing\",\"type\":\"int24\"}],\"name\":\"FeeAmountEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"int24\",\"name\":\"tickSpacing\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"PoolCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"}],\"name\":\"createPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"internalType\":\"int24\",\"name\":\"tickSpacing\",\"type\":\"int24\"}],\"name\":\"enableFeeAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"feeAmountTickSpacing\",\"outputs\":[{\"internalType\":\"int24\",\"name\":\"\",\"type\":\"int24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"getPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"parameters\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"internalType\":\"int24\",\"name\":\"tickSpacing\",\"type\":\"int24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]'
let ContractV3Factory = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
let ContractV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
[decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt);
const TWO = BigInt(2);
const TEN = BigInt(10);
const SIX_TENTH = BigInt(1000000);
const Q192 = (TWO ** BigInt(96)) ** TWO;
return (
Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /
Number(SIX_TENTH)
);
}
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(n, decimals) {
return (BigDecimal(n)*BigDecimal(Math.pow(10,decimals))).toFixed(0)
}
$.NewUniswapV3 = function(e) {
e = e || exchange
if (e.GetName() !== 'Web3') {
panic("only support Web3 exchange")
}
let self = {
tokenInfo: {},
walletAddress: e.IO("address"),
pool: {}
}
// register
e.IO("abi", ContractV3Factory, ABI_Factory)
e.IO("abi", ContractV3SwapRouterV2, ABI_Route)
self.addToken = function(name, address) {
let ret = e.IO("api", address, "decimals")
if (!ret) {
throw "get token decimals failed"
}
let decimals = Number(ret)
self.tokenInfo[name] = {
name: name,
decimals: decimals,
address: address
}
}
self.waitMined = function(tx) {
while (true) {
Sleep(1000)
let info = e.IO("api", "eth", "eth_getTransactionReceipt", tx)
if (info && info.gasUsed) {
return true
}
Log('Transaction not yet mined', tx)
}
}
self.swapToken = function(tokenIn, amountInDecimal, tokenOut, options) {
// options like {gasPrice: 11, gasLimit: 111, nonce: 111}
let tokenInInfo = self.tokenInfo[tokenIn]
let tokenOutInfo = self.tokenInfo[tokenOut]
if (!tokenInInfo) {
throw "not found token info " + tokenIn
}
if (!tokenOutInfo) {
throw "not found token info " + tokenOut
}
let amountIn = toInnerAmount(amountInDecimal, tokenInInfo.decimals)
let recipientAddress = self.walletAddress
if (tokenInInfo.name != 'ETH') {
let allowanceAmount = e.IO("api", tokenInInfo.address, "allowance", self.walletAddress, ContractV3SwapRouterV2);
let realAmount = toAmount(allowanceAmount, tokenInInfo.decimals)
if (realAmount < toAmount(amountIn, tokenInInfo.decimals)) {
Log("realAmount is", realAmount, "too small, try to approve large amount")
if (tokenInInfo.name == 'USDT') {
// As described in Tether code: To change the approve amount you first have to reduce the addresses allowance to 0 calling approve(spender, 0)
let txApprove = e.IO("api", tokenInInfo.address, "approve", ContractV3SwapRouterV2, 0)
if (!txApprove) {
throw "approve error"
}
Log("wait reduce approve", txApprove)
self.waitMined(txApprove)
}
let txApprove = e.IO("api", tokenInInfo.address, "approve", ContractV3SwapRouterV2, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
if (!txApprove) {
throw "approve error"
}
Log("wait approve", txApprove)
self.waitMined(txApprove)
Log("approve success amountIn", amountIn)
} else {
Log("allowance", realAmount, "no need to approve")
}
}
if (tokenOutInfo.name == 'ETH' || tokenOutInfo.address.toLowerCase() == '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') {
/*
ADDRESS_THIS https://degencode.substack.com/p/uniswapv3-multicall
https://etherscan.io/address/0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45#code
*/
recipientAddress = '0x0000000000000000000000000000000000000002'
}
let swapToken = e.IO("encode", ContractV3SwapRouterV2, "swapExactTokensForTokens", amountIn, 1, [tokenInInfo.address, tokenOutInfo.address], recipientAddress)
let data = [swapToken]
if (tokenOutInfo.name == 'ETH') {
data.push(e.IO("encode", ContractV3SwapRouterV2, "unwrapWETH9(uint256,address)", 1, self.walletAddress))
}
let tx = e.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", (tokenInInfo.name == 'ETH' ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})
if (tx) {
Log("tx: ", tx)
self.waitMined(tx)
Log("swap", tokenInInfo.name, "to", tokenOutInfo.name, "success")
return true
} else {
Log("trans error")
return false
}
}
self.getETHBalance = function(address) {
return toAmount(e.IO("api", "eth", "eth_getBalance", address || self.walletAddress, "latest"), 18)
}
self.balanceOf = function(token, address) {
let tokenInfo = self.tokenInfo[token]
if (!tokenInfo) {
throw "not found token info " + token
}
return toAmount(e.IO("api", tokenInfo.address, "balanceOf", address || self.walletAddress), tokenInfo.decimals)
}
self.sendETH = function(to, amount, options) {
return e.IO("api", "eth", "send", to, toInnerAmount(amount, 18), options || {})
}
self.getPrice = function(pair) {
let arr = pair.split('_')
let token0 = self.tokenInfo[arr[0]]
if (!token0) {
throw "token " + arr[0] + "not found"
}
let token1 = self.tokenInfo[arr[1]]
if (!token1) {
throw "token " + arr[1] + "not found"
}
let reverse = false
if (BigInt(token0.address) > BigInt(token1.address)) {
let tmp = token0
token0 = token1
token1 = tmp
reverse = true
}
let key = token0.address + '/' + token1.address
if (typeof(self.pool[key]) == 'undefined') {
let pool = e.IO("api", ContractV3Factory, "getPool", token0.address, token1.address, 3000)
if (pool) {
self.pool[key] = pool
// register pool address
e.IO("abi", pool, ABI_Pool)
}
}
if (typeof(self.pool[key]) == 'undefined') {
throw "pool " + pair + " not found"
}
let slot0 = e.IO("api", self.pool[key], "slot0")
if (!slot0) {
return null
}
let price = computePoolPrice(token0.decimals, token1.decimals, slot0.sqrtPriceX96)
if (reverse) {
price = 1 / price
}
return price
}
return self
}
$.testUniswap = function() {
let ex = $.NewUniswapV3()
Log("walletAddress: ", ex.walletAddress)
let tokenAddressMap = {
"ETH": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH
"USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"1INCH": "0x111111111117dC0aa78b770fA6A738034120C302",
}
for (let name in tokenAddressMap) {
ex.addToken(name, tokenAddressMap[name])
}
Log(ex.getPrice('ETH_USDT'))
Log(ex.getPrice('1INCH_USDT'))
// swap 0.01 ETH to USDT
Log(ex.swapToken('ETH', 0.01, 'USDT'))
let usdtBalance = ex.balanceOf('USDT')
Log("balance of USDT", usdtBalance)
// swap reverse
Log(ex.swapToken('USDT', usdtBalance, 'ETH'))
Log("balance of ETH", ex.getETHBalance())
// Log(ex.sendETH('0x11111', 0.02))
}
ایتھرئم نیٹ ورک کو سافٹ ویئر انفراسٹرکچر کے طور پر سمجھا جاسکتا ہے ، جس پر مختلف سمارٹ معاہدوں کو تعینات اور چلانے کے قابل بنایا جاسکتا ہے۔ اسمارٹ معاہدوں میں مختلف افعال اور ایپلی کیشنز کے منظرنامے ہیں۔ ایتھرئم کلائنٹ چلانے والے آلات ایتھرئم نیٹ ورک میں نوڈس تشکیل دیتے ہیں۔
طالب علموں کو جو اس سے واقف نہیں ہیںUniswap V3
پروٹوکول پہلے کچھ تصورات کو سمجھنے کی ضرورت ہے.Uniswap V3
یہ ایک سمارٹ معاہدہ بھی ہے جو ایتھریم پر چل رہا ہے۔
token
.ایک بار جب اسمارٹ معاہدہ ایتھریم پر تعینات کیا جاتا ہے، تو ایک پتہ ہوگا.
Uniswap V3 ٹریڈنگ کلاس لائبریری کا کوڈ بنیادی طور پر چار حصوں میں تقسیم ہے، جو ہم ایک ایک کرکے وضاحت کریں گے۔
const ABI_Route = '[{"inputs":[{"internalType":"address...
const ABI_Pool = '[{\"inputs\":[],\"stateMutability\":\"nonpayable...
const ABI_Factory = '[{\"inputs\":[],\"stateMutability\":\"...
let ContractV3Factory = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
let ContractV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
مندرجہ بالا بنیادی تصور پیش نظارہ کے ساتھ، یہ یہاں سمجھنے کے لئے آسان ہے.
ABI_Route
اس مسلسل کی طرف سے محفوظ تار روٹنگ سمارٹ معاہدے کی ABI ہے.ABI_Pool
پولنگ معاہدے کا اے بی آئی محفوظ کرتا ہے۔ABI_Factory
فیکٹری کے معاہدے کا اے بی آئی۔
چونکہ یہ تار لمبی ہیں ، لہذا وہ صرف اقتباسات ہیں۔ یہ مواد پروگرام کے لئے سمارٹ معاہدے کے طریقہ کار کو کال کرنے کے لئے ایک معیار فراہم کرتے ہیں (مثال کے طور پر ، سمارٹ معاہدہ انٹرفیس کے پیرامیٹرز کیا ہیں ، کتنے پیرامیٹرز ، وہ کس قسم کے ہیں ، اور واپس آنے والے ڈیٹا کی قسم کیا ہے) ۔
جیسا کہ ہم نے ابھی ذکر کیا، ایک بار جب اسمارٹ معاہدہ ایتھریم میں تعینات کیا جاتا ہے، تو ایک پتہ ہوگا.
ContractV3Factory
: فیکٹری کے معاہدے کا پتہ ریکارڈ کیا جاتا ہے.ContractV3SwapRouterV2
: Uniswap V3 کا روٹر V2 ایڈریس۔ نوٹ کریں کہ Uniswap میں V1 اور V2 ہیں۔ Uniswap V3 کے روٹر میں بھی V1 اور V2 ہیں۔ مختلف معاہدے کے پتے مختلف ہیں۔
computePoolPrice
فنکشن پول میں ٹوکن کی قیمت کا حساب کرنے کے لئے استعمال کیا جاتا ہے.function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
[decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt); // Use the BigInt function for processing. Because of the precision of JavaScript language values, it is necessary to use one of FMZ's underlying processing functions, BigInt, to process.
const TWO = BigInt(2); // Define constant 2 to calculate
const TEN = BigInt(10); // Define constant 10 to calculate
const SIX_TENTH = BigInt(1000000); // Define the 6th power of constant 10, i.e. 1e6
const Q192 = (TWO ** BigInt(96)) ** TWO; // 2^192
return (
Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /
Number(SIX_TENTH)
);
}
اگر ٹریڈنگ جوڑی ہےETH_USDT
پھرtoken0
ہےETH
، اورtoken1
ہےUSDT
. decimals0
کی صحت سے متعلق اعداد و شمار ہےtoken0
، اورdecimals1
کی صحت سے متعلق اعداد و شمار ہےtoken1
. SqrtPriceX96
قیمت سے متعلق اعداد و شمار ہیں (براہ راست قیمت کی قیمت نہیں) ، جوslot0
گروپ معاہدے کا طریقہ کار۔
sqrtPriceX96: ایک sqrt ((ٹوکن1/ٹوکن0) Q64.96 قدر کے طور پر پول کی موجودہ قیمت Q64.96 ڈیٹا پروسیسنگ اور اسٹوریج کا ایک معیار ہے۔
یہ تین اعداد و شمارdecimals0
, decimals1
, sqrtPriceX96
میں منتقل کر رہے ہیںcomputePoolPrice
تجارتی جوڑی کی قیمت کا حساب کرنے کے لئے پیرامیٹرز کے طور پر کامETH_USDT
. گزشتہ میں الگورتھمreturn
اس تقریب کے بیان کی بحالی کے عمل ہےsqrtPriceX96
کرنے کے لئےtoken1/token0
مثال کے طور پر، پول میں ٹوکن 0 (ETH) کی تعداد 1 ہے، اور ٹوکن 1 (USDT) کی تعداد 1100 ہے۔ تو1100/1=1100
، موجودہ قیمت میںETH_USDT
پول 1100 ہے.
toAmount
فنکشن کا استعمال سلسلہ میں عددی ڈیٹا کو پڑھنے کے قابل ڈیٹا میں تبدیل کرنے کے لئے کیا جاتا ہے۔function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}
اس کو آسان طریقے سے بیان کرنے کے لئے ، مثال کے طور پر ، ایک ETH ٹوکن 1e18 ہوتا ہے جب تعداد کو زنجیر پر پیش کیا جاتا ہے ، یعنی ، 10 کی 18 ویں طاقت ، کیونکہ ETH کا صحت سے متعلق ڈیٹا 18 ہے۔ تمام ٹوکنز کی صحت سے متعلق 18 نہیں ہوتی ہے ، اور USDT کی صحت سے متعلق ETH کی طرح نہیں ہے۔toAmount
فنکشن 1e18 کو 1 میں تبدیل کرنا ہے۔
toInnerAmount
فنکشن کے برعکس ہےtoAmount
فنکشن، جو پڑھنے کے قابل اعداد و شمار کو زنجیر میں استعمال ہونے والی اقدار میں تبدیل کرتا ہے۔function toInnerAmount(n, decimals) {
return (BigDecimal(n)*BigDecimal(Math.pow(10,decimals))).toFixed(0)
}
اگلا، آئیے
اس ٹیمپلیٹ کلاس لائبریری کا بنیادی یونیسوپ وی 3 آپریشن آبجیکٹ ہے ، جو یونیسوپ وی 3 پر بنیادی آپریشنز کو نافذ کرتا ہے۔ مستقبل میں مزید افعال کو اپ گریڈ کیا جاسکتا ہے۔ اس کوڈ مثال کا تجزیہ کرکے ، یہاں تک کہ اگر آپ ایف ایم زیڈ پلیٹ فارم استعمال نہیں کرتے ہیں تو ، آپ یونیسوپ ڈی ای ایکس کے ہر لنک کے عمل اور تفصیلات کے بارے میں اپنے علم اور تفہیم میں اضافہ کریں گے۔ اب آئیے سیکھیں کہ یہ بنیادی افعال ایف ایم زیڈ پر کس طرح ڈیزائن اور نافذ کیے گئے ہیں۔
Uniswap V3 آپریشن آبجیکٹ کا کنسٹرکٹر کوڈ:
$.NewUniswapV3 = function(e) {
e = e || exchange // If the parameter e is not passed, the exchange object exchange is used, that is, the first exchange added in the strategy.
if (e.GetName() !== 'Web3') { // Determine if the exchange object is Web3, because this template only supports Web3 exchange objects.
panic("only support Web3 exchange")
}
let self = { // The current function is a constructor, and the constructed object is the object self.
tokenInfo: {}, // Member variable of the self object, used to record the registration information of the token.
walletAddress: e.IO("address"), // Record the address of the wallet to which the current exchange object is bound.
pool: {} // Used to record registered pool information.
}
// register
e.IO("abi", ContractV3Factory, ABI_Factory) // ABI for registered factory contracts
e.IO("abi", ContractV3SwapRouterV2, ABI_Route) // ABI for registered routing contracts
self.addToken = function(name, address) { // Used to register token
let ret = e.IO("api", address, "decimals") // Call the decimals method to get token precision information
if (!ret) {
throw "get token decimals failed"
}
let decimals = Number(ret)
self.tokenInfo[name] = {
name: name,
decimals: decimals,
address: address
}
}
self.waitMined = function(tx) { // It is used to wait for the result of an operation on Ethereum. The hash is a tx parameter.
while (true) {
Sleep(1000)
let info = e.IO("api", "eth", "eth_getTransactionReceipt", tx) // Query results using eth_getTransactionReceipt method, if it's not found, loop to continue query.
if (info && info.gasUsed) {
return true
}
Log('Transaction not yet mined', tx)
}
}
self.swapToken = function(tokenIn, amountInDecimal, tokenOut, options) { // For token exchange
// options like {gasPrice: 11, gasLimit: 111, nonce: 111}
let tokenInInfo = self.tokenInfo[tokenIn] // Get the information of the exchanged token
let tokenOutInfo = self.tokenInfo[tokenOut] // Get the information of the converted token
if (!tokenInInfo) {
throw "not found token info " + tokenIn
}
if (!tokenOutInfo) {
throw "not found token info " + tokenOut
}
let amountIn = toInnerAmount(amountInDecimal, tokenInInfo.decimals) // Convert to data used on smart contracts
let recipientAddress = self.walletAddress
if (tokenInInfo.name != 'ETH') {
let allowanceAmount = e.IO("api", tokenInInfo.address, "allowance", self.walletAddress, ContractV3SwapRouterV2); // Query the number of authorizations
let realAmount = toAmount(allowanceAmount, tokenInInfo.decimals)
if (realAmount < toAmount(amountIn, tokenInInfo.decimals)) { // If the number of licenses is insufficient
Log("realAmount is", realAmount, "too small, try to approve large amount")
if (tokenInInfo.name == 'USDT') {
// As described in Tether code: To change the approve amount you first have to reduce the addresses allowance to 0 calling approve(spender, 0)
let txApprove = e.IO("api", tokenInInfo.address, "approve", ContractV3SwapRouterV2, 0) // If the authorized token is USDT, it needs to be authorized to 0 first.
if (!txApprove) {
throw "approve error"
}
Log("wait reduce approve", txApprove)
self.waitMined(txApprove)
}
let txApprove = e.IO("api", tokenInInfo.address, "approve", ContractV3SwapRouterV2, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); // Authorize Router contracts to operate the wallet's tokens
if (!txApprove) {
throw "approve error"
}
Log("wait approve", txApprove)
self.waitMined(txApprove)
Log("approve success amountIn", amountIn)
} else {
Log("allowance", realAmount, "no need to approve")
}
}
if (tokenOutInfo.name == 'ETH' || tokenOutInfo.address.toLowerCase() == '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') {
/*
ADDRESS_THIS https://degencode.substack.com/p/uniswapv3-multicall
https://etherscan.io/address/0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45#code
*/
recipientAddress = '0x0000000000000000000000000000000000000002'
// When exchanging other coins for WETH, you have to let