EtherEaseWithFMZ টিউটোরিয়াল
FMZ ব্যবহার করে Ethereum-ভিত্তিক ওয়েব3 বিকাশের সাথে সহজেই শুরু করুন
Ethereum হল ব্লকচেইন প্রযুক্তির উপর ভিত্তি করে একটি স্মার্ট চুক্তির প্ল্যাটফর্ম, যা স্মার্ট কন্ট্রাক্ট লিখতে এবং স্থাপন করার একটি বিকেন্দ্রীকৃত উপায় প্রদান করে। একটি স্মার্ট চুক্তি হল একটি বিশেষ কম্পিউটার প্রোগ্রাম যা ব্লকচেইনে স্বয়ংক্রিয়ভাবে কার্যকর করতে পারে এবং তৃতীয় পক্ষকে বিশ্বাস না করে বিভিন্ন ব্যবসায়িক যুক্তি প্রয়োগ করতে পারে।
উদ্ভাবক কোয়ান্টিটেটিভ ট্রেডিং প্ল্যাটফর্ম (FMZ.COM) একটি সহজে ব্যবহারযোগ্য API প্রদান করে যা ডেভেলপারদের জন্য Ethereum ব্লকচেইন এবং এর ইকোসিস্টেমের সাথে যোগাযোগ করা সহজ করে তোলে। বিকেন্দ্রীভূত এক্সচেঞ্জ অ্যাক্সেস করা (DEX), অন-চেইন ডেটা প্রাপ্ত করা এবং লেনদেন পাঠানোর মতো ফাংশনগুলি অর্জন করুন।
এই টিউটোরিয়াল ব্যবহার উদাহরণJavaScriptভাষা লেখা, পরীক্ষার পরিবেশ ব্যবহারইথেরিয়াম মেইননেট、গোয়ারলি টেস্টনেট. আপনি টিউটোরিয়ালে ব্যবহৃত API ইন্টারফেসগুলির পাশাপাশি FMZ প্ল্যাটফর্মের API ডকুমেন্টেশনে সম্পর্কিত বিবরণ এবং কোড উদাহরণগুলিও দেখতে পারেন।
FMZ দিয়ে শুরু করা
FMZ পরিমাণগত ট্রেডিং প্ল্যাটফর্ম ব্যবহার করতে শেখার আগে, আমাদের বেশ কয়েকটি মৌলিক ধারণার সাথে পরিচিত হতে হবে:
1. FMZ পরিমাণগত ট্রেডিং প্ল্যাটফর্ম কাঠামো
FMZ পরিমাণগত ট্রেডিং প্ল্যাটফর্মের (https://www.fmz.com) অফিসিয়াল ওয়েবসাইটে নিবন্ধন এবং লগ ইন করার পরে, আপনি প্ল্যাটফর্মের বিভিন্ন ফাংশন ব্যবহার করতে পারেন। FMZ ওয়েবসাইট হল পুরো সিস্টেমের ব্যবস্থাপনার দিক, এবং ব্যবহারকারীদের দ্বারা লিখিত প্রোগ্রামগুলি আসলে হোস্টে চলে। হোস্ট একটি সফ্টওয়্যার প্রোগ্রাম যা বিভিন্ন ডিভাইস যেমন সার্ভার, কম্পিউটার ইত্যাদিতে স্থাপন করা যেতে পারে। যখন একজন ব্যবহারকারী একটি চলমান উদাহরণ তৈরি করতে এফএমজেড ওয়েবসাইটে একটি প্রোগ্রাম লেখেন, তখন এফএমজেড প্ল্যাটফর্ম হোস্টের সাথে যোগাযোগ করবে এবং হোস্টে একটি প্রোগ্রাম ইনস্ট্যান্স শুরু করবে।
2. কাস্টোডিয়ান
আপনি যদি একটি প্রোগ্রামের উদাহরণ চালাতে চান, তাহলে আপনাকে অবশ্যই একজন কাস্টোডিয়ান স্থাপন করতে হবে। আপনি আপনার পক্ষে FMZ দ্বারা ভাড়া করা সার্ভারটিকে স্বয়ংক্রিয়ভাবে স্থাপন করতে FMZ-এ দেওয়া "এক-ক্লিক স্থাপনা হোস্ট" ব্যবহার করতে পারেন।
-
ব্যক্তিগত ডিভাইসে হোস্ট স্থাপন করুন
কাস্টোডিয়ান প্রোগ্রামটি সার্ভার, ব্যক্তিগত কম্পিউটার এবং অন্যান্য ডিভাইসে স্থাপন এবং চালানো যেতে পারে, যতক্ষণ না নেটওয়ার্ক স্বাভাবিক থাকে (সংশ্লিষ্ট লক্ষ্যটি অ্যাক্সেসযোগ্য হওয়া প্রয়োজন, যেমন একটি বিনিময় ইন্টারফেস, নোড ঠিকানা ইত্যাদি)। স্থাপনার প্রধান ধাপ হল:
- লগ ইন করুন বা ডিভাইস খুলুন যেখানে হোস্ট প্রোগ্রাম স্থাপন করা হবে, উদাহরণস্বরূপসার্ভারে লগ ইন করুনঅথবাকম্পিউটার চালু করুন এবং অপারেটিং সিস্টেমে প্রবেশ করুন。
- কাস্টোডিয়ান প্রোগ্রামের সংশ্লিষ্ট সংস্করণটি ডাউনলোড করুন (ডিভাইস অপারেটিং সিস্টেমের উপর নির্ভর করে), ডাউনলোড পৃষ্ঠা: https://www.fmz.com/m/add-node

- ডাউনলোডটি একটি সংকুচিত প্যাকেজ এবং এটি ডিকম্প্রেস করা প্রয়োজন৷
- কাস্টোডিয়ান প্রোগ্রাম চালান একটি প্রোগ্রাম বলা হয়
robotএক্সিকিউটেবল ফাইল। হোস্টের যোগাযোগ ঠিকানা কনফিগার করুন FMZ এ লগ ইন করার পর এই যোগাযোগের ঠিকানাটি অনন্য।https://www.fmz.com/m/add-nodeপৃষ্ঠাটি তার নিজস্ব ঠিকানা দেখতে পারে (যেমন./robot -s node.fmz.com/xxxxxঠিকানা এই স্ট্রিং, এখানেxxxxxপ্রতিটি FMZ অ্যাকাউন্টের জন্য অবস্থানের বিষয়বস্তু ভিন্নভাবে প্রদর্শিত হয়)। অবশেষে, আপনাকে FMZ অ্যাকাউন্টের পাসওয়ার্ড লিখতে হবে এইগুলি কনফিগার করার পরে, আপনি কাস্টোডিয়ান প্রোগ্রাম চালাতে পারেন।
-
FMZ প্ল্যাটফর্মের "এক-ক্লিক ডিপ্লয়মেন্ট অফ কাস্টোডিয়ান" ফাংশন ব্যবহার করুন
FMZ প্ল্যাটফর্মে হোস্ট পৃষ্ঠা যোগ করুন, ঠিকানা:
https://www.fmz.com/m/add-node
3. ডিবাগিং টুল
FMZ পরিমাণগত ট্রেডিং প্ল্যাটফর্ম একটি বিনামূল্যে ডিবাগিং টুল সরবরাহ করে যা সমর্থন করেJavaScript,TypeScript, পৃষ্ঠাটি হল: https://www.fmz.com/m/debug, কারণ একটি উদাহরণ তৈরি করা এবং এটি চালানোর জন্য বিল করা হয়। আপনি এই ডিবাগিং টুলটি প্রাথমিক সময়ের মধ্যে পরীক্ষা এবং শেখার জন্য ব্যবহার করতে পারেন। চলমান সময়কে সর্বাধিক 3 মিনিটের মধ্যে সীমিত করা ছাড়া, ডিবাগিং টুলটি অন্যান্য দিকগুলিতে একটি উদাহরণ তৈরি করা থেকে আলাদা নয়।
ব্যবহারTypeScriptভাষা, আপনাকে কোডের প্রথম লাইনে এটি লিখতে হবে// @ts-checkস্যুইচ করার জন্যTypeScriptমোড, যদি সুইচ না করা হয়, ডিফল্ট হয়JavaScriptভাষা
4. বিনিময়
FMZ-এ, CEX এক্সচেঞ্জের জন্য "এক্সচেঞ্জ" একটি সাধারণ ধারণা, এটি একটি নির্দিষ্ট এক্সচেঞ্জ অ্যাকাউন্ট কনফিগারেশনকে নির্দেশ করে। ওয়েব3-এর জন্য, এই লেনদেনটি নোড ঠিকানা এবং ব্যক্তিগত কী কনফিগারেশন সহ একটি কনফিগারেশন তথ্যকে বোঝায়।
FMZ প্ল্যাটফর্মে লগ ইন করার সময়,https://www.fmz.com/m/add-platformপৃষ্ঠা, আপনি বিনিময় তথ্য কনফিগার করতে পারেন, যেখানে বিনিময় একটি সাধারণ ধারণা বোঝায়।
চয়ন করুনWeb3, RPC নোড ঠিকানা কনফিগার করুন এবং ব্যক্তিগত কী কনফিগার করুন আপনি নীচের ডানদিকের কোণায় "সংবেদনশীল তথ্য এনক্রিপ্ট করা হয়েছে এবং একটি স্বাধীন ব্যক্তিগত কী দিয়ে সংরক্ষণ করা হয়েছে" ক্লিক করতে পারেন৷
নোডগুলি স্ব-নির্মিত নোড বা নোড পরিষেবা প্রদানকারীদের দ্বারা সরবরাহ করা নোড হতে পারে। অনেক নোড পরিষেবা প্রদানকারী আছে, যেমন:Infura. নিবন্ধন করার পরে, আপনি আপনার অ্যাকাউন্টের নোড ঠিকানা দেখতে পারেন। মেইননেট এবং টেস্টনেট উভয়ই রয়েছে, যা উপরের ছবিতে এই নোড ঠিকানাটি কনফিগার করুন।Rpc Addressনিয়ন্ত্রণে কনফিগার করা এক্সচেঞ্জ অবজেক্টগুলিকে আলাদা করতে লেবেলগুলির নামকরণ করা যেতে পারে।
ছবিতেhttps://mainnet.infura.io/v3/xxxxxxxxxxxxxএটি হল ব্যক্তিগত ইনফুরা ইটিএইচ মেইননেট আরপিসি নোড ঠিকানা।
FMZ ব্যবহার করে Ethereum এর সাথে ইন্টারঅ্যাক্ট করা
কাস্টোডিয়ান প্রোগ্রাম স্থাপন এবং এক্সচেঞ্জ অবজেক্ট কনফিগার করার পরে, আপনি পরীক্ষা করতে FMZ.COM এর "ডিবাগিং টুল" ব্যবহার করতে পারেন। Ethereum RPC পদ্ধতিতে কল করতে এবং Ethereum এর সাথে ইন্টারঅ্যাক্ট করতে, এই অধ্যায়ে তালিকাভুক্ত বেশ কয়েকটি RPC পদ্ধতি ছাড়াও, আপনি অন্যান্য RPC পদ্ধতির জন্য তথ্য অনুসন্ধান করতে পারেন, যেমনhttps://www.quicknode.com/docs。
আসুন কয়েকটি সাধারণ উদাহরণ দেওয়া যাক এবং প্রাথমিক থেকে শুরু করি। বিভিন্ন ভাষা এবং সরঞ্জামগুলির জন্য ওয়েব 3 অ্যাক্সেস করার উপায় রয়েছে, যেমন চিত্রে দেখানো হয়েছে:
RPC মেথড কলগুলি FMZ-এ এনক্যাপসুলেট করা হয়exchange.IOমাঝখানে। কলিং পদ্ধতি হলexchange.IO("api", "eth", ...). প্রথম পরামিতি সংশোধন করা হয়েছে এবং পাস করা হয়েছে"api", দ্বিতীয় প্যারামিটারটি পাস করার জন্য সংশোধন করা হয়েছে"eth", অন্যান্য পরামিতি নির্দিষ্ট RPC পদ্ধতির উপর নির্ভর করে।
তথ্য আউটপুট করতে, আমরা FMZ প্ল্যাটফর্ম ব্যবহার করিLogফাংশনLogফাংশনটি একাধিক প্যারামিটারে পাস করতে পারে এবং তারপরে FMZ প্ল্যাটফর্মের "ডিবাগিং টুলস" বা "রিয়েল ডিস্ক" পৃষ্ঠায় লগ এরিয়াতে আউটপুট করতে পারে "ডিবাগিং টুলস" পৃষ্ঠাটি আমাদের পরীক্ষার জন্য প্রধান হাতিয়ার হবে৷
eth_getBalance
ইথেরিয়ামেরeth_getBalanceএই পদ্ধতিটি Ethereum-এ একটি ঠিকানার ETH ব্যালেন্স জিজ্ঞাসা করতে ব্যবহৃত হয় এই পদ্ধতিটি 2 প্যারামিটারে পাস করা প্রয়োজন।
- ঠিকানা জিজ্ঞাসা করা হবে.
- লেবেল, সাধারণত "সর্বশেষ" ব্যবহার করুন।
আসুন Ethereum এর প্রতিষ্ঠাতা পরীক্ষা করা যাকV神ETH ওয়ালেট ঠিকানা, পরিচিত ঠিকানা হল:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045。
javascript
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
}
কাস্টোডিয়ান স্থাপন করা হয়েছে (চিত্রে: linux/amd64 ...) এবং এক্সচেঞ্জ অবজেক্টটি কনফিগার করা হয়েছে (চিত্রে: Web3 পরীক্ষা)। ডিবাগিং টুলে কোডটি পরীক্ষা করুন:
এই কোডটি চালানোর জন্য "Execute" বোতামটি ক্লিক করুন এবং ফলাফলগুলি প্রদর্শন করুন:
ethBalance: 0x117296558f185bbc4c6
Logফাংশন দ্বারা মুদ্রিতethBalanceপরিবর্তনশীল মান হল:0x117296558f185bbc4c6, একটি স্ট্রিং টাইপ। হ্যাঁহেক্সাডেসিমেল মানের ETH ব্যালেন্স,দ্বারাweiইউনিট হিসাবে,1e18 weiহল 1ETH. তাই এটি এখনও একটি পঠনযোগ্য দশমিক ETH ব্যালেন্সে রূপান্তরিত করা প্রয়োজন।
উইলethBalanceপঠনযোগ্য ডেটাতে রূপান্তর করুন:
javascript
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
// 将ethBalance转换为可读的数据
let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
Log("vitalikEthBalance:", vitalikEthBalance)
}
উপরেhttps://etherscan.io/প্রশ্ন:
যাইহোক, এই প্রক্রিয়াকরণটি ভাষার নির্ভুলতার কারণে পক্ষপাতদুষ্ট হবে, তাই FMZ প্ল্যাটফর্মে ডেটা প্রক্রিয়াকরণের জন্য দুটি অন্তর্নির্মিত ফাংশন রয়েছে:
- BigInt: একটি হেক্সাডেসিমেল স্ট্রিংকে একটি BigInt অবজেক্টে রূপান্তর করুন।
- BigDecimal: সাংখ্যিক টাইপ অবজেক্টগুলিকে BigDecimal অবজেক্টে রূপান্তর করুন যা চালানো যেতে পারে।
আবার কোড সামঞ্জস্য করুন:
javascript
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
// ETH的精度单位为1e18
let ethDecimal = 18
Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}
vitalikEthBalance: 5149.6244846875215
eth_chainId
eth_chainIdএবংnet_versionব্যবহারগুলি একই রকম, তাই আমরা একসাথে পরীক্ষা করেছি। উভয় ফাংশনই বর্তমান RPC নোড যে ব্লকচেইনের সাথে সংযুক্ত তার ID ফেরত দেয়। পার্থক্য হলnet_versionদশমিক আইডি প্রদান করে,eth_chainIdহেক্সাডেসিমেলে আইডি প্রদান করে।
চেইন আইডির সাথে সংশ্লিষ্ট নেটওয়ার্কের নাম
desc
1 - ethereum mainnet
2 - morden testnet (deprecated)
3 - ropsten testnet
4 - rinkeby testnet
5 - goerli testnet
11155111 - sepolia testnet
10 - optimism mainnet
69 - optimism kovan testnet
42 - kovan testnet
137 - matic/polygon mainnet
80001 - matic/polygon mumbai testnet
250 - fantom mainnet
100 - xdai mainnet
56 - bsc mainnet
কনফিগার করা Ethereum testnet ব্যবহার করুনgoerliনোড পরীক্ষা:
javascript
function main() {
let netVersionId = exchange.IO("api", "eth", "net_version")
let ethChainId = exchange.IO("api", "eth", "eth_chainId")
Log("netVersionId:", netVersionId)
Log("ethChainId:", ethChainId, " ,转换:", parseInt(ethChainId.substring(2), 16))
}
eth_gasPrice
কলeth_gasPriceবর্তমান চেইন জিজ্ঞাসা করার পদ্ধতিgas price。
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
Log("gasPrice:", gasPrice, " ,转换:", toAmount(gasPrice, 0))
}
এখানে আমরা একটি হেক্সাডেসিমেল স্ট্রিংকে একটি ফাংশন হিসাবে একটি পাঠযোগ্য মানের মধ্যে রূপান্তর করার অপারেশন লিখি:toAmount. আরেকটি বিষয় লক্ষণীয় যে গ্যাসপ্রাইসের একক হলwei, তাই আনুষ্ঠানিক পরামিতিdecimalsসংশ্লিষ্ট প্রকৃত পরামিতির জন্য শুধু মান 0 পাস করুন।
eth_blockNumbe
eth_blockNumbeব্লকের উচ্চতা অনুসন্ধান করতে ব্যবহৃত হয়।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(toAmount(blockNumber, 0))
}
ডিবাগিং টুলে চালান:
https://etherscan.io/প্রশ্ন:
eth_getBlockByNumber
প্রশ্ন ব্লক তথ্য.
javascript
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(blockNumber)
let blockMsg = exchange.IO("api", "eth", "eth_getBlockByNumber", blockNumber, true)
Log(typeof(blockMsg), blockMsg)
// 由于Log输出的内容过多,会自动截断,所以遍历返回的区块信息各个字段,逐个打印
for (let key in blockMsg) {
Log("key:", key, ", val:", blockMsg[key])
}
}
"ডিবাগিং টুলস" এ কার্যকর করা নিম্নলিখিত তথ্য পেতে পারে:
চুক্তির তথ্য পড়ুন
ইথেরিয়ামে প্রচুর সংখ্যক স্মার্ট চুক্তির অ্যাপ্লিকেশন চলছে।ENSএটি তাদের মধ্যে একটি।ENS, ইথেরিয়াম নাম পরিষেবা, ইথেরিয়াম ব্লকচেইনের উপর ভিত্তি করে একটি বিকেন্দ্রীকৃত ডোমেন নাম রেজোলিউশন পরিষেবা৷
আপনি কি এখনও টিউটোরিয়ালের উদাহরণটি মনে রেখেছেন যেখানে আমরা ইথেরিয়াম প্রতিষ্ঠাতা ভিটালিকের ওয়ালেট ব্যালেন্স পরীক্ষা করেছি? V ঈশ্বরের ওয়ালেট ঠিকানাগুলির মধ্যে একটি হল:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045. তাহলে আমরা কিভাবে এই ঠিকানা জানি? আসলে, এটি পাস করা যেতে পারেENSস্মার্ট চুক্তি, একটি স্বজ্ঞাত নাম ব্যবহার করুনvitalik.eth(ভিটালিক হল ভগবানের নাম) জিজ্ঞাসা করা।
এই অধ্যায়ে নিম্নলিখিত বিষয়বস্তু Ethereum মেইননেট পরিবেশ ব্যবহার করে, উপর ভিত্তি করেENSনথিটি দেখায় যে এটি Ethereum ডোমেন নামের উপর ক্যোয়ারী সম্পাদন করা প্রয়োজনHashing Names, নিম্নলিখিত কোড ব্যবহার করুনvitalik.ethনাম প্রক্রিয়া করা হয়।
javascript
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
উপরের কোড উদাহরণে, আমরা আরেকটি অপরিচিত ফাংশন দেখতে পাচ্ছিEncodeএই ফাংশনটি FMZ প্ল্যাটফর্মের API ফাংশন, যা বিশেষভাবে FMZ প্ল্যাটফর্মে এনকোডিং ক্রিয়াকলাপ সম্পাদনের জন্য ব্যবহৃত হয়। এই ফাংশনটি একাধিক এনকোডিং পদ্ধতি এবং একাধিক হ্যাশ অ্যালগরিদম সমর্থন করে।
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
ENS ডকুমেন্টেশন অনুসারে, ব্যবহার করুনsha3.keccak256অ্যালগরিদম ডেটা প্রক্রিয়া করে।
কলnameHashফাংশন, উদাহরণস্বরূপ:Log(nameHash("vitalik.eth")), আপনি পেতে পারেন:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, "0x" এর সাথে প্রিফিক্স করা দরকার।0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835একটি ENS স্মার্ট চুক্তি হিসাবেresolverপদ্ধতি পরামিতি।
javascript
let ensNode = "0x" + nameHash("vitalik.eth") // 准备好调用resolver方法的参数ensNode
ENS নথি অনুসারে, ENS স্মার্ট চুক্তির আবেদনের চুক্তির ঠিকানা হল:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e. স্মার্ট চুক্তি কল যখনresolverপদ্ধতির আগে, আমাদের চুক্তিও প্রস্তুত করতে হবেABI。
ABI নিবন্ধন করুন
এখানে অধ্যয়ন করার পরে, আপনি সাহায্য করতে পারবেন না কিন্তু জিজ্ঞাসা করুন, একটি স্মার্ট চুক্তি কি?ABIপশমী কাপড়?
desc
ABI,即应用程序二进制接口(Application Binary Interface),是智能合约与外部世界进行通信的接口标准。
智能合约的 ABI 定义了合约的函数接口、参数类型、返回值等信息,以及调用合约的方式和参数传递方式等规范。
智能合约的 ABI 通常以 JSON 格式存储,包含以下信息:
合约的函数接口:函数名、参数列表、返回值等信息。
函数参数类型:如 uint256、bool、string 等。
函数的输入参数和输出参数的编码方式:智能合约使用一种称为 Solidity ABI 的编码方式来编码函数的输入参数和输出参数,
以便与以太坊网络进行交互。
在以太坊网络中,使用智能合约的 ABI 来调用合约的函数。当需要调用合约函数时,需要提供函数名和函数参数,以及将函数参数按照 ABI 编码方式编码后的字节码。
以太坊节点会将这些信息打包成一笔交易,并将交易发送到以太坊网络中执行。
智能合约的 ABI 在 Solidity 语言中可以通过 interface 关键字来定义。以太坊开发工具如 Remix IDE、Truffle 等也提供了 ABI 编辑和生成工具,
使得开发者可以方便地创建和使用智能合约的 ABI。
ENS এর ABI বের করুনresolverপদ্ধতির অংশ, আপনি সম্পূর্ণ ABI ব্যবহার করতে পারেন, যা পাওয়া যাবেhttps://etherscan.io/চুক্তির ABI-কে অনলাইনে জিজ্ঞাসা করুন, অথবা অন্যান্য উপায়ে ABI প্রাপ্ত করুন (উদাহরণস্বরূপ: সম্পর্কিত প্রকল্পের নথি)।
javascript
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
এখানে আমাদের FMZ প্ল্যাটফর্মে একটি নতুন কলিং পদ্ধতি শিখতে হবে,exchange.IO("abi", address, abiContent), ABI নিবন্ধন করতে এই পদ্ধতি ব্যবহার করুন,addressপ্যারামিটারটি হল স্মার্ট চুক্তির ঠিকানা।abiContentপরামিতি হল সংশ্লিষ্ট স্মার্ট চুক্তি ABI (স্ট্রিং)।
javascript
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver) // 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e 是在以太坊主网上部署的ENS智能合约的地址
কিভাবে একটি স্মার্ট চুক্তি কল
এর পরে, আপনি ENS স্মার্ট চুক্তি কল করতে পারেনresolverপদ্ধতি, পদ্ধতি ফিরে আসেENS: Public Resolverচুক্তির ঠিকানা।
javascript
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
ব্যবহারENS: Public Resolverচুক্তিভিত্তিকaddrভিটালিকের ওয়ালেট ঠিকানা পাওয়ার পদ্ধতি। ফোন করতেENS: Public Resolverচুক্তিটি এখনও প্রথমে ABI-এর সাথে নিবন্ধিত হতে হবে। এই স্মার্ট চুক্তির ABI তথ্য এখনও পাওয়া যেতে পারেhttps://etherscan.io/পান।
javascript
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
শেষ কলENS: Public Resolverচুক্তিভিত্তিকaddrপদ্ধতি, পরামিতি এখনও আছেensNode。
javascript
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
লগ ফাংশন আউটপুট:
run
vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
ENS কল করার জন্য সম্পূর্ণ কোড
javascript
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
function main() {
// 计算名称
let ensNode = "0x" + nameHash("vitalik.eth")
// 注册ENS合约
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
// 注册ENS Public Resolver合约
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
}
ETH পাঠান
পূর্ববর্তী কোর্সের অধ্যায়ে, আমরা শিখেছি কিভাবে প্রাইভেট কী কনফিগার করতে হয় কিভাবে আমরা কনফিগার করা এক্সচেঞ্জ অবজেক্টের জন্য প্রাইভেট কী এর সাথে সম্পর্কিত ওয়ালেট ঠিকানা জানব? FMZ এ উপলব্ধexchange.IO("address")ফাংশনটি কনফিগার করা ব্যক্তিগত কী-এর সাথে সংশ্লিষ্ট ওয়ালেট ঠিকানা পায়।
যেহেতু এই অধ্যায়ে নিম্নলিখিত বিষয়বস্তু ব্যবহার করেGoerliনেটওয়ার্ক পরিবেশ পরীক্ষা করুন, তাই আমি যে নোডটি ব্যবহার করি তা হল:https://goerli.infura.io/v3/*******, Infura এখানে প্রতিটি নিবন্ধিত ব্যবহারকারীকে বিভিন্ন নোড ঠিকানা নির্ধারণ করে*******নির্দিষ্ট বিষয়বস্তু লুকানো হয়.
javascript
function main() {
let walletAddress = exchange.IO("address")
Log("测试网 goerli 钱包地址:", walletAddress)
}
একবার আপনি আপনার ওয়ালেটের ঠিকানা জেনে গেলে, আপনি Ethereum এর RPC পদ্ধতি ব্যবহার করতে পারেনeth_getTransactionCountওয়ালেট ঠিকানার লেনদেন গণনা জিজ্ঞাসা করুন। এই গণনাটি সাধারণত ইথেরিয়ামে ব্যবহৃত হয়, এটি হস্তান্তর ক্রিয়াকলাপের সময় পাস করা দরকার।nonceপরামিতি, ইথেরিয়ামে, প্রতিটি লেনদেন অনন্য তা নিশ্চিত করার জন্য ননসে একটি সংখ্যা ব্যবহার করা হয়। এটি একটি ক্রমবর্ধমান সংখ্যা যা প্রতিবার নতুন লেনদেন পাঠানো হলে স্বয়ংক্রিয়ভাবে বৃদ্ধি পায়। অতএব, আপনি যখন একটি স্মার্ট চুক্তিতে একটি লেনদেন পাঠান, তখন লেনদেনটি অনন্য এবং সঠিক ক্রমে তা নিশ্চিত করার জন্য আপনাকে একটি নন্স প্রদান করতে হবে। কিছু তথ্য এবং নথিতে আমরা খুঁজে পেতে পারি:
এখানে গো ভাষার ইথেরিয়াম লাইব্রেরিতেPendingNonceAtফাংশনটি আসলে কল করেeth_getTransactionCountপদ্ধতি আগের কোর্সে আমরা আরপিসি মেথডকে কল করতে শিখেছি, আমরা এখানে আবার ব্যবহার করিexchange.IO("api", "eth", ...)ফাংশন
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let walletAddress = exchange.IO("address")
Log("测试网 goerli 钱包地址:", walletAddress)
/**
* eth_getTransactionCount
* @param address - string - The address from which the transaction count to be checked.
* @param blockNumber - string - The block number as a string in hexadecimal format or tags.
* @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
*/
let nonce = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
Log("钱包地址:", walletAddress, "当前的 nonce:", nonce, ",转换为10进制:", toAmount(nonce, 0))
}
ট্রান্সফার অপারেশন ব্যাখ্যা করার আগে, আসুন কিছু ধারণা সংক্ষেপে বুঝতে পারি। ইথেরিয়ামে টাকা ট্রান্সফার করার সময়, একটি নির্দিষ্ট পরিমাণ ETH টোকেন খরচ হবে (গ্যাস ফি হিসেবে)। গ্যাস ফি দুটি পরামিতি দ্বারা নির্ধারিত হয়:
-
gasPrice
যাইহোক, Ethereum নেটওয়ার্কে গ্যাস ফি সবসময় বাজারের চাহিদা এবং ব্যবহারকারীরা কী দিতে ইচ্ছুক তার উপর ভিত্তি করে ওঠানামা করে, তাই কোডে একটি নির্দিষ্ট গ্যাস ফি লেখা কখনও কখনও আদর্শ নয়। আমরা আগে যা শিখেছি তা আপনি ব্যবহার করতে পারেন
eth_gasPriceগ্যাসের গড় মূল্য নির্ধারণের পদ্ধতি। -
gasLimit
একটি আদর্শ Ethereum স্থানান্তরের জন্য গ্যাসের সীমা হল 21,000 ইউনিট।
বুঝেছিnonce,gasPrice,gasLimitএই ধারণাগুলির সাথে, আপনি স্থানান্তর পরীক্ষা করতে পারেন। একটি খুব সহজ এবং সহজেই ব্যবহারযোগ্য স্থানান্তর ফাংশন FMZ-এ এনক্যাপসুলেট করা হয়েছে।
javascript
exchange.IO("api", "eth", "send", toAddress, toAmount)
যখন স্থানান্তর হিসাবে ব্যবহার করা হয়,exchange.IOতৃতীয় প্যারামিটারটি স্থিরভাবে "পাঠান" হিসাবে লেখা হয়েছে।toAddressপরামিতি হল স্থানান্তর করার সময় ETH পাওয়ার ঠিকানা।toAmountস্থানান্তরিত ETH পরিমাণ।
nonce,gasPrice,gasLimitএই পরামিতিগুলি FMZ-এ সিস্টেম ডিফল্ট দ্বারা স্বয়ংক্রিয়ভাবে প্রাপ্ত মানগুলি ব্যবহার করতে পারে। এছাড়াও আপনি নির্দিষ্ট করতে পারেন:
javascript
exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})
পরবর্তী, আমরা পরীক্ষা নেটওয়ার্ক goerli-এর একটি ঠিকানায় নির্দিষ্ট পরিমাণ ETH স্থানান্তর করি:
javascript
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
Log("测试网 goerli 钱包地址:", walletAddress)
let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
return ret // 返回Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}
কারণ Ethereum স্থানান্তর পরিমাণ একক হয়wei, আপনাকে একটি কাস্টম ফাংশন ব্যবহার করতে হবেtoInnerAmountহিসাবে চিকিত্সা করা হয়weiইউনিটে মান।
বিদ্যমানhttps://etherscan.io/প্রশ্ন লেনদেন হ্যাশ অন:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e。
আপনি স্থানান্তর হ্যাশ জিজ্ঞাসা করার জন্য কোড লিখতে পারেন0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e, ব্যবহার করুনeth_getTransactionReceiptপ্রশ্ন করার পদ্ধতি।
javascript
function main() {
let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
return info
}
প্রশ্নের ফলাফল:
run
{
"cumulativeGasUsed": "0x200850",
"effectiveGasPrice": "0x1748774421",
"transactionHash": "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e",
"type": "0x0",
"blockHash": "0x6bdde8b0f0453ecd24eecf7c634d65306f05511e0e8f09f9ed3f59eee2d06ac7",
"contractAddress": null,
"blockNumber": "0x868a50",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"to": "0x4d75a08e870674e68cae611f329a27f446a66813",
"status": "0x1",
"transactionIndex": "0x23",
"from": "0x6b3f11d807809b0b1e5e3243df04a280d9f94bf4",
"logs": []
}
প্রতিটি ক্ষেত্রের সাথে সম্পর্কিত বর্ণনা:
desc
blockHash - 该交易所在区块的哈希值
blockNumber - 以十六进制编码的该交易所在区块的块号
contractAddress - 如果是合约创建,该合约的地址;否则为null
cumulativeGasUsed - 该交易在区块中执行时使用的总燃气量
effectiveGasPrice - 每单位燃气的总基础费用加小费
from - 发送者的地址
gasUsed - 该特定交易使用的燃气量
logs - 生成该交易的日志对象数组
address - 生成该日志的地址
topics - 0到4个32字节索引日志参数的数据数组。在Solidity中,第一个主题是事件签名的哈希值(例如Deposit(address,bytes32,uint256)),除非你使用匿名说明符声明该事件
data - 日志的32字节非索引参数
blockNumber - 该日志所在区块的块号
transactionHash - 该日志创建时的交易哈希值。如果该日志处于待定状态,则为null
transactionIndex - 该日志创建时的交易索引位置。如果该日志处于待定状态,则为null
blockHash - 该日志所在区块的哈希值
logIndex - 该日志在区块中的索引位置,以十六进制编码的整数。如果该日志处于待定状态,则为null
removed - 如果该日志已被删除,则为true,由于链重组而被删除;如果是有效的日志,则为false
logsBloom - 用于检索相关日志的布隆过滤器
status - 以十六进制编码的值,它要么是1(成功),要么是0(失败)
to - 接收者的地址。如果是合约创建交易,则为null
transactionHash - 该交易的哈希值
transactionIndex - 以十六进制编码的该交易在区块中的索引位置
type - 值的类型
একটি Ethereum স্মার্ট চুক্তি কলিং
আমরাচুক্তির তথ্য পড়ুনএই অধ্যায়ে, একটি সম্পূর্ণ উদাহরণের মাধ্যমে, Ethereum-এ স্থাপন করা ENS চুক্তিকে কল করে Buterin-এর মানিব্যাগের ঠিকানা পাওয়া যায়। এই পদ্ধতি অন্তর্গতReadপদ্ধতি, এই পদ্ধতি কল প্রয়োজন হয় নাgas(গ্যাস সম্পর্কে আমরা আগে কী বলেছিলাম মনে আছে?) এই বিভাগে আমরা ইথেরিয়ামের কিছু স্মার্ট চুক্তির নাম বলব।Writeপদ্ধতি এবং অর্থপ্রদানgas. এই ক্রিয়াকলাপগুলি সম্পূর্ণ নেটওয়ার্কের প্রতিটি নোডের পাশাপাশি খনি শ্রমিকদের দ্বারা যাচাই করা হবে এবং ব্লকচেইনের অবস্থা পরিবর্তন করবে।
ERC20
ERC20 চুক্তির জন্য (ERC20 টোকেন চুক্তি), FMZ প্ল্যাটফর্ম ERC20 চুক্তির ABI কে একটি সাধারণভাবে ব্যবহৃত ABI হিসাবে তালিকাভুক্ত করে এবং এটিকে সরাসরি সিস্টেমে তৈরি করে, ABI নিবন্ধনের প্রয়োজনীয়তা দূর করে। আমরা আগের টিউটোরিয়ালে ABI সম্পর্কে জেনেছি যখন আমরা ENS কন্ট্রাক্ট মেথড বলি, আমরা প্রথমে ENS কন্ট্রাক্টের ABI রেজিস্টার করি।
ABI আরও স্পষ্টভাবে বোঝার জন্য, আপনি এটি ব্যবহার করার আগে এটি পরীক্ষা করতে পারেন ERC20 চুক্তির ABI:
javascript
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]
এই অধ্যায়ে নিম্নলিখিত বিষয়বস্তু ব্যবহার করা হয়Goerliটেস্টনেট পরিবেশ।
balanceOf
এর পরে, আসুন কীভাবে আবার চুক্তি কল করবেন তা অনুশীলন করি।Readচুক্তির তথ্য পড়ার এবং ERC20 চুক্তিতে কল করার পদ্ধতিbalanceOfটোকেন ব্যালেন্স জিজ্ঞাসা করার পদ্ধতি,balanceOfপদ্ধতিতে শুধুমাত্র একটি পরামিতি আছে, কিন্তু এটির নাম দেওয়া হয়নি আপনি ধরন থেকে দেখতে পাচ্ছেন যে এটি একটি ঠিকানা (অর্থাৎ জিজ্ঞাসা করা টোকেন ঠিকানা)। যেহেতু প্রত্যাবর্তিত ডেটা একটি টোকেনের এককে নয়, টোকেনের নির্ভুলতা ডেটাও রূপান্তরের জন্য প্রয়োজন হয় ERC20 চুক্তি ব্যবহার করে টোকেনের নির্ভুলতা গণনা করা যেতে পারে৷decimalsপ্রাপ্ত করার পদ্ধতি। আমরা ইথেরিয়াম টেস্টনেট ব্যবহার করিgoerliএকটি পরীক্ষা পরিচালনা করুন এবং নোট করুন যে টোকেন চুক্তির ঠিকানা বিভিন্ন চেইনে ভিন্ন হতে পারে।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let walletAddress = exchange.IO("address")
// goerli WETH address
let wethAddress = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
// goerli LINK address
let linkAddress = "0x326C977E6efc84E512bB9C30f76E30c160eD06FB"
// 由于是ERC20合约,FMZ已经内置ABI注册,所以这里不用注册ERC20 ABI
let wethDecimals = exchange.IO("api", wethAddress, "decimals")
let linkDecimals = exchange.IO("api", linkAddress, "decimals")
let wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
let linkBalance = exchange.IO("api", linkAddress, "balanceOf", walletAddress)
Log("WETH精度:", wethDecimals, "wethBalance:", toAmount(wethBalance, wethDecimals))
Log("LINK精度:", linkDecimals, "linkBalance:", toAmount(linkBalance, linkDecimals))
}
বর্তমান ওয়ালেটের WETH এবং LINK টোকেন ব্যালেন্স জিজ্ঞাসা করতে উপরের কোডটি চালান:
WETH যথার্থতা: 18 wethব্যালেন্স: 0
LINK যথার্থতা: 18 লিঙ্ক ব্যালেন্স: 51.41374973681053
deposit
আপনি দেখতে পাচ্ছেন যে এই ওয়ালেটে WETH টোকেনের ব্যালেন্স 0। এরপর, আমরা WETH টোকেনগুলির ERC20 স্মার্ট চুক্তির সাথে ইন্টারঅ্যাক্ট করতে থাকি এইবার আমরা লিখি টাইপ পদ্ধতি বলি:deposit。
depositসহজভাবে বলতে গেলে, এই পদ্ধতির কাজ হল একটি নির্দিষ্ট পরিমাণ ETH কে WETH-এ রূপান্তর করাdepositপদ্ধতিটির কোন পরামিতি নেই (যা ABI দেখে লক্ষ্য করা যায়), এবং পদ্ধতির বৈশিষ্ট্যpayableজন্যtrue, তাই কল করার সময়, জমা করা ETH-এর পরিমাণ নির্দিষ্ট করতে আপনাকে স্থানান্তর ETH (payableAmount) সেট করতে হবে।
স্মার্ট চুক্তি পদ্ধতি কল করার সময় দয়া করে নোট করুন:
যদি বলা পদ্ধতিতে প্রদেয় বৈশিষ্ট্য থাকে, তাহলে আপনাকে পদ্ধতির নামের পরে একটি স্থানান্তর ETH মান যোগ করতে হবে (এক্সচেঞ্জ.IO ফাংশনের চতুর্থ প্যারামিটার), যা একটি সংখ্যাসূচক প্রকার বা একটি স্ট্রিং আকারে একটি মান হতে পারে।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
// goerli WETH address
let wethAddress = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
// 由于是ERC20合约,FMZ已经内置ABI注册,所以这里不用注册ERC20 ABI
let wethDecimals = exchange.IO("api", wethAddress, "decimals")
let wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
Log("WETH精度:", wethDecimals, "wethBalance:", toAmount(wethBalance, wethDecimals))
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", walletAddress, "latest")
Log("ETH精度:", 18, "ethBalance:", toAmount(ethBalance, 18))
// 调用deposit方法,由于deposit是ERC20标准之外的方法,所以这里要注册这个方法的ABI
let abiWETH = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]`
exchange.IO("abi", wethAddress, abiWETH)
let payableAmount = toInnerAmount(0.01, 18)
let ret = exchange.IO("api", wethAddress, "deposit", payableAmount)
Log("Transaction Hash:", ret)
}
WETH যথার্থতা: 18 wethব্যালেন্স: 0
ETH যথার্থতা: 18 ethব্যালেন্স: 0.14333094664072302
Transaction Hash: 0xaf15b0b0e25a81eda583295e82b249e2d02e4eafebecc906470ccc2c89e23563
আবার WETH এবং ETH এর ব্যালেন্স জিজ্ঞাসা করুন:
WETH নির্ভুলতা: 18 wethব্যালেন্স: 0.01
ETH নির্ভুলতা: 18 ethব্যালেন্স: 0.1333309358060905
কলdepositআগেWETHহল 0,ETH0.14333094664072302, কল করা হচ্ছেdepositপরেWETHহল 0.01,ETHহল 0.1333309358060905। আপনি দেখতে পাচ্ছেন যে 0.01 সফলভাবে যোগ করা হয়েছেETHদ্বারা প্রতিস্থাপিতWETH。
transfer
ERC20 টোকেনগুলিও ব্যবহার করে স্থানান্তর করা যেতে পারেtransferএই ঠিকানায় পদ্ধতি স্থানান্তর0x4D75a08E870674E68cAE611f329A27f446A66813০.০১ WETH টোকেন।transferপদ্ধতিটিতে দুটি পরামিতি রয়েছে, প্রথম প্যারামিটারটিdstস্থানান্তর প্রাপকের ওয়ালেট ঠিকানা, দ্বিতীয় পরামিতিwadস্থানান্তরের পরিমাণ।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function waitMined (tx) {
for (var i = 0 ; i < 10 ; i++) {
Sleep(5000)
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", tx)
if (info && info.gasUsed) {
Log(info)
return true
}
Log('Transaction not yet mined', tx)
}
return false
}
function main() {
let walletAddress = exchange.IO("address")
// goerli WETH address
let wethAddress = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
// 由于是ERC20合约,FMZ已经内置ABI注册,所以这里不用注册ERC20 ABI
let wethDecimals = exchange.IO("api", wethAddress, "decimals")
let wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
Log("WETH精度:", wethDecimals, "wethBalance:", toAmount(wethBalance, wethDecimals))
let dst = "0x4D75a08E870674E68cAE611f329A27f446A66813"
let wad = toInnerAmount(0.01, wethDecimals)
let tx = exchange.IO("api", wethAddress, "transfer", dst, wad)
Log("Transaction Hash:", tx)
waitMined(tx)
wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
Log("WETH精度:", wethDecimals, "wethBalance:", toAmount(wethBalance, wethDecimals))
}
উপরের উদাহরণটি একটি কাস্টম ফাংশন ব্যবহার করেwaitMined, আসলে, আমরা এই ফাংশনটির সাথে অপরিচিত নইeth_getTransactionReceiptপদ্ধতি? এই waitMined কাস্টম ফাংশনের কাজ হল ইনকামিং ট্রানজেকশন হ্যাশের ফলাফলের জন্য অপেক্ষা করা।
এই WETH স্থানান্তরের জন্য, আগ্রহী পাঠকরাও লেনদেন হ্যাশকে জিজ্ঞাসা করতে পারেন0x2fafb62b548a1fffb0f3189429e3c5a4f57ddafb0acbc0678d8b3cf0a2f7c92cবিস্তারিত দেখতে আসুন (উল্লেখ্য যে এটি testnet goerli এ রয়েছে)।
withdraw
এই সময় আমরা করাWETHফিরে বিনিময়ETH, ব্যবহার করুনwithdrawপদ্ধতি, যার শুধুমাত্র একটি প্যারামিটার আছেwad, সহজভাবে বলতে গেলে, কতটা ETH বিনিময় হবে তা সেট করতে ব্যবহৃত হয়।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
// goerli WETH address
let wethAddress = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
// 由于是ERC20合约,FMZ已经内置ABI注册,所以这里不用注册ERC20 ABI
let wethDecimals = exchange.IO("api", wethAddress, "decimals")
let wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
Log("WETH精度:", wethDecimals, "wethBalance:", toAmount(wethBalance, wethDecimals))
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", walletAddress, "latest")
Log("ETH精度:", 18, "ethBalance:", toAmount(ethBalance, 18))
let abiWETH = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]`
exchange.IO("abi", wethAddress, abiWETH)
let wad = toInnerAmount(0.01, 18)
let ret = exchange.IO("api", wethAddress, "withdraw", wad)
Log("Transaction Hash:", ret)
}
Transaction Hash: 0x446423c841451a8d04428a075b556eb5564186b09926da915f5da1c9837d2af4
আপনি উপরের কোড এবং আগের কোড দেখতে পারেনdepositপদ্ধতির উদাহরণগুলি মূলত একই, শেষ ধাপে বলা পদ্ধতিটি প্রতিস্থাপিত হয়withdrawকল করার আগে:
WETH নির্ভুলতা: 18 wethব্যালেন্স: 0.01
ETH যথার্থতা: 18 ethব্যালেন্স: 0.11322979983231546
আবার প্রশ্ন:
WETH যথার্থতা: 18 wethব্যালেন্স: 0
ETH যথার্থতা: 18 ethব্যালেন্স: 0.1231207156449464
আপনি দেখতে পারেন যে অন্য 0.01WETHফিরে এসেছেETH。
Uniswap V3
Uniswap V3এটি একটি বিকেন্দ্রীকৃত ট্রেডিং প্রোটোকল যা ইথেরিয়াম ব্লকচেইনে ক্রিপ্টোকারেন্সি ট্রেডিং এবং তারল্য বিধানের জন্য তৈরি করা হয়েছে। এতে মূল চুক্তি, পুল চুক্তি, কারখানার চুক্তি, রাউটিং চুক্তি ইত্যাদি সহ একাধিক স্মার্ট চুক্তি রয়েছে।
ব্যবহারেUniswapবর্তমান বিনিময় মূল্য জিজ্ঞাসা করার সময় এবং বিনিময় ক্রিয়াকলাপ সম্পাদন করার সময় নিম্নলিখিত চুক্তিগুলি প্রধানত ব্যবহৃত হয়:
Router(রাউটিং চুক্তি)
এটি একটি চুক্তি যা লেনদেন সম্পাদন করতে ব্যবহৃত হয়, যা ব্যবহারকারীদের লেনদেনের পথ এবং পরামিতি নির্দিষ্ট করে ট্রেডিং অপারেশন করতে দেয়।Pool(পুলের চুক্তি)
পুল চুক্তি হয়Uniswapএকটি মূল উপাদান, নির্দিষ্ট সম্পদ জোড়ার তরলতা সঞ্চয় ও পরিচালনা করতে ব্যবহৃত হয়। প্রতিটি অ্যাসেট পেয়ারের একটি সংশ্লিষ্ট পুল চুক্তি থাকে, যেটিতে তহবিল, মূল্য পরিসীমা এবং তারল্য প্রদানকারীর দ্বারা প্রদত্ত ফি সেটিংসের মতো তথ্য থাকে। পুল চুক্তি লেনদেন প্রক্রিয়াকরণ, তহবিল পুলের স্থিতি গণনা এবং লেনদেনের মসৃণ সম্পাদন নিশ্চিত করার জন্য দায়ী।Factory(কারখানা চুক্তি)
কারখানার চুক্তিগুলি তৈরি এবং পরিচালনা করতে ব্যবহৃত হয়Uniswapপুল চুক্তির জন্য চুক্তি। যখন একজন ব্যবহারকারী একটি নতুন সম্পদ জোড়া তৈরি করতে চায়, তারা কারখানা চুক্তির সাথে ইন্টারঅ্যাক্ট করে একটি নতুন পুল চুক্তি স্থাপন করে। কারখানার চুক্তিটি পুল চুক্তির সৃষ্টি এবং সূচনা সমন্বয়ের জন্য দায়ী, ব্যবহারকারীদের গতিশীলভাবে নতুন সম্পদ জোড়া তৈরি করতে দেয়।
আমরা আগে যা শিখেছি তার উপর ভিত্তি করে, আসুন FMZ পরিমাণগত ট্রেডিং প্ল্যাটফর্ম কৌশল কোডে কীভাবে স্মার্ট চুক্তি নিবন্ধন করতে হয় তা পর্যালোচনা করিABI, কিভাবে স্মার্ট চুক্তির ABI প্রাপ্ত করা যায় তা পূর্ববর্তী কোর্সে ব্যাখ্যা করা হয়েছে, তাই আমরা এখানে বিশদে যাব না।
তিনটি নিবন্ধন প্রয়োজনUniswapস্মার্ট চুক্তিABI, একটি উদাহরণ হিসাবে Ethereum মেইননেট ব্যবহার করে:
javascript
var abiRoute = '[{"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"}]';
var abiPool = '[{\"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\"}]'
var abiFactory = '[{\"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\"}]'
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
var contractV3SwapRouterV2Address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
function main() {
// 注册Uniswap工厂合约的ABI
exchange.IO("abi", contractV3FactoryAddress, abiFactory)
// 测试Factory合约的owner方法
var owner = exchange.IO("api", contractV3FactoryAddress, "owner")
Log("owner:", owner) // 返回值应当为: 0x1a9C8182C09F50C8318d769245beA52c32BE35BC
// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)
// 测试Uniswap V3 Router V2合约的factory方法
var factoryOfRouter = exchange.IO("api", contractV3SwapRouterV2Address, "factory")
Log("factoryOfRouter:", factoryOfRouter) // 返回值应当为: 0x1F98431c8aD98523631AE4a59f267346ea31F984
// 获取交易对的池地址
var tokenIn = {name : "DAI", address: "0x6b175474e89094c44da98b954eedeac495271d0f"}
var tokenOut = {name : "USDT", address: "0xdac17f958d2ee523a2206206994597c13d831ec7"}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 3000)
var pair = "tokenIn:" + tokenIn.name + ", tokenOut:" + tokenOut.name + ", fee:" + 3000
Log("使用工厂合约的getPool方法获取", pair, "池地址:", poolAddress)
// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)
// 测试池合约的
var factoryOfPool = exchange.IO("api", poolAddress, "factory")
Log("factoryOfPool:", factoryOfPool) // 返回值应当为: 0x1F98431c8aD98523631AE4a59f267346ea31F984
}
উপরের কোডটি কারখানার চুক্তি, রাউটিং চুক্তি এবং পুল চুক্তির ABI নিবন্ধন করে এবং কিছু পরীক্ষা করে। এটা লক্ষ্য করা যায় যে রাউটিং চুক্তি এবং পুল চুক্তিfactoryসমস্ত পদ্ধতি ফিরে0x1F98431c8aD98523631AE4a59f267346ea31F984এই ঠিকানা, এই ঠিকানাটি Uniswap কারখানা চুক্তি (কোডেcontractV3FactoryAddressপরিবর্তনশীল) ঠিকানা।
javascript
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
স্মার্ট চুক্তির ABI নিবন্ধন করার পরে, আসুন প্রথমে এর ব্যবহারটি দেখি।Uniswap V3বিনিময় অপারেশন জন্য, আমরা নিম্নলিখিত বিষয়বস্তু ব্যবহার করুনERC20(ইথেরিয়াম মেইননেটে) টোকেন বিনিময় একটি নির্দিষ্ট পরিস্থিতি হিসেবে ব্যবহৃত হয়।
প্রশ্নUniswap V3রাউটিং চুক্তি অনুমোদন
বিদ্যমানERC20চুক্তিতে,allowanceফাংশনটি অন্যান্য ঠিকানায় অনুমোদিত টোকেনের সংখ্যা জিজ্ঞাসা করতে ব্যবহৃত হয়। এটি টোকেনের সংখ্যা জিজ্ঞাসা করতে পারে যা একটি নির্দিষ্ট ঠিকানা অন্য ঠিকানাকে (সাধারণত একটি চুক্তির ঠিকানা) তার নিজের অ্যাকাউন্ট থেকে স্থানান্তর করার অনুমতি দেয়।
জন্যUniswap V3রাউটিং চুক্তির জন্য, যদি আপনি কার্যকর করে থাকেনapproveফাংশনটি রাউটিং চুক্তির ঠিকানায় অনুমোদিত, তারপর আপনি ব্যবহার করতে পারেনERC20টোকেনallowanceঅনুমোদনের পরিমাণ জিজ্ঞাসা করার ফাংশন।
আমরা আগের টিউটোরিয়ালে যা দেখিয়েছি তা মনে রাখবেনERC20চুক্তি পদ্ধতি কল?allowance、approveসবERC20চুক্তি পদ্ধতি, এই পদ্ধতিগুলি আমরা আগে ব্যাখ্যা করেছি তাদের অনুরূপbalanceOf、transferপদ্ধতি সবই সমান মর্যাদার।
রিডিম করার আগে, প্রথমে আমাদের এটি অনুমোদিত কিনা তা পরীক্ষা করতে হবেUniswapরাউটিং চুক্তিতে বিনিময় করার জন্য পর্যাপ্ত সংখ্যক টোকেন রয়েছে যদি আমরা ক্রিয়াটি বিনিময় করতে চাই:1INCH->ETH, হার 10,000 সেট করা হয়েছে। এই হার 10000 সেট করার অর্থ হল 1%।Uniswapবিনিময় পুলে সাধারণত বিভিন্ন হার থাকতে পারেUniswapবেশ কিছু অপশন দেওয়া হয়। উদাহরণস্বরূপ, যদি হার 3000 সেট করা হয়, তাহলে এর মানে হল 0.3% আপনি বিশদটি পরীক্ষা করতে পারেন।Uniswapনথি এবং সম্পর্কিত তথ্য।
এখানে উল্লেখ্য যে প্রকৃত বিনিময় পুল1INCH/WETH, ETH এবং WETH ইথেরিয়ামে দুটি ভিন্ন টোকেন।
- ETH (ইথেরিয়াম):
ETH হল Ethereum ব্লকচেইনের নেটিভ ক্রিপ্টোকারেন্সি এবং Ethereum নেটওয়ার্কের গণনার প্রাথমিক সম্পদ এবং একক। ETH হল Ethereum-এর নেটিভ টোকেন এবং এর সার্বজনীন বাণিজ্যযোগ্যতা এবং ব্যবহারযোগ্যতা রয়েছে এটি লেনদেন ফি প্রদান, স্মার্ট চুক্তির মিথস্ক্রিয়া, স্টোর মূল্য ইত্যাদিতে ব্যবহার করা যেতে পারে। - WETH (মোড়ানো ইথার):
WETH হল ETH কে ERC20 স্ট্যান্ডার্ড টোকেনে এনক্যাপসুলেট করার একটি ফর্ম। এটি Ethereum-এ একটি স্মার্ট চুক্তি যার লক্ষ্য ETH-কে স্মার্ট চুক্তিতে ERC20 টোকেনের সাথে নির্বিঘ্নে যোগাযোগ করতে সক্ষম করা। WETH চুক্তির ঠিকানায় ETH জমা করে WETH তৈরি এবং প্রাপ্ত করা যেতে পারে, এবং WETH যে কোনো সময় ETH-এ ফেরত স্থানান্তর করা যেতে পারে। Ethereum ইকোসিস্টেমে WETH-এর প্রধান ভূমিকা হল ETH-কে অন্যান্য ERC20 টোকেনের মতো একই স্ট্যান্ডার্ড ইন্টারফেস এবং সামঞ্জস্যপূর্ণতা প্রদান করা, যা ETH-কে বিকেন্দ্রীভূত বিনিময়, লিকুইডিটি পুল এবং অন্যান্য DeFi প্রোটোকলগুলিতে অংশগ্রহণ করতে সক্ষম করে।
তাই, WETH হল ETH-এর একটি প্যাকেজড ফর্ম যা ETH-এর সাথে Ethereum স্মার্ট চুক্তিতে ERC20 টোকেন আকারে যোগাযোগ করতে সক্ষম করে। সাধারণত, যখন আপনার একটি স্মার্ট চুক্তিতে ETH ব্যবহার করার প্রয়োজন হয়, আপনি ETH-কে WETH-এ রূপান্তর করতে পারেন, লেনদেন পরিচালনা করতে পারেন বা DeFi অপারেশনে অংশগ্রহণ করতে পারেন এবং তারপর প্রয়োজন অনুসারে WETH-কে ETH-এ রূপান্তর করতে পারেন৷
ব্যবহারERC20এরallowanceঅনুমোদিত পরিমাণ প্রাপ্ত করার পদ্ধতি:
javascript
var abiRoute = '[{"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"}]';
var abiPool = '[{\"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\"}]'
var abiFactory = '[{\"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\"}]'
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
var contractV3SwapRouterV2Address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
// 注册Uniswap工厂合约的ABI
exchange.IO("abi", contractV3FactoryAddress, abiFactory)
// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)
// 获取交易对的池地址
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 10000)
// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)
// 获取当前配置的钱包地址
var walletAddress = exchange.IO("address")
// 1INCH -> ETH, tokenIn: 1INCH
var allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
}
কোডের জন্যtoAmount()আমাদের ফাংশনগুলির সাথে পরিচিত হওয়া উচিত আমরা এই কাস্টম ফাংশন কোডটি পূর্ববর্তী অধ্যায়গুলিতে ডেটা প্রক্রিয়া করার জন্য বহুবার ব্যবহার করেছি যা মানুষের পক্ষে পড়া সহজ।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
কোডটি চালানোর পরে, এটি পাওয়া যায় যে বর্তমান অনুমোদিত পরিমাণটি 0, তাই এটি খালাস করার জন্য, রাউটিং চুক্তিতে পর্যাপ্ত পরিমাণ অনুমোদিত হতে হবে।
অনুমোদন করুনUniswap V3রাউটিং চুক্তি
ব্যবহার করলেallowanceজিজ্ঞাসা করার পরে, এটি পাওয়া যায় যে অনুমোদনের সংখ্যা অপর্যাপ্ত, তাই আপনাকে ব্যবহার করতে হবেapproveঅনুমোদন করুনUniswap V3রাউটিং চুক্তিগুলি এটিকে নির্দিষ্ট সংখ্যক পরিচালনা করার অনুমতি দেয়ERC20টোকেন।
এখনও সঙ্গে1INCH -> ETHবিনিময় উদাহরণের জন্য, ব্যবহার করুনERC20এরapproveদেওয়ার পদ্ধতিUniswapরাউটিং চুক্তি বর্তমানে কনফিগার করা ওয়ালেটে ক্রিয়াকলাপ অনুমোদন করে।1INCHটোকেন।
javascript
var abiRoute = '[{"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"}]';
var abiPool = '[{\"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\"}]'
var abiFactory = '[{\"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\"}]'
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
var contractV3SwapRouterV2Address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
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)
}
function main() {
// 注册Uniswap工厂合约的ABI
exchange.IO("abi", contractV3FactoryAddress, abiFactory)
// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)
// 获取交易对的池地址
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 10000)
// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)
// 获取当前配置的钱包地址
var walletAddress = exchange.IO("address")
// 1INCH -> WETH, tokenIn: 1INCH
var allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
var balance = exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "balanceOf", walletAddress)
var balanceOf1INCH = toAmount(balance, tokenIn.decimals)
Log("balanceOf1INCH:", balanceOf1INCH)
var swapAmount = 38
if (balanceOf1INCH < swapAmount) {
Log("钱包中", tokenIn.name, "不足,数量只有:", balanceOf1INCH)
}
if (toAmount(allowanceAmount, tokenIn.decimals) < swapAmount) {
Log("授权数量不足,进行授权")
// 也可以指定授权数量为无限,即把代码中toInnerAmount(swapAmount, tokenIn.decimals) 替换为 '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
var txApprove = exchange.IO("api", tokenIn.address, "approve", contractV3SwapRouterV2Address, toInnerAmount(swapAmount, tokenIn.decimals))
if (!txApprove) {
Log("授权失败")
} else {
for (var i = 0; i < 10; i++) {
Sleep(5000)
var info = exchange.IO("api", "eth", "eth_getTransactionReceipt", txApprove)
if (info && info.gasUsed) {
Log("info:", info)
break
}
Log('Transaction not yet mined', txApprove)
}
// 再次查询授权数量
allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("再次查询授权数量,", "allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
}
}
}
যোগ করা হয়েছে একটিtoInnerAmount()একটি কাস্টম ফাংশন বাস্তবায়ন প্রায়ই আমাদের পূর্ববর্তী কোর্সে ব্যবহৃত হয় এবং এখানে বিস্তারিতভাবে বর্ণনা করা হবে না।
আপনি অনুমোদনের রেকর্ড দেখতে পারেন এবং অনুমোদনের স্থিতি পরীক্ষা করতে কোডটি আবার কল করতে পারেন:
javascript
allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("再次查询授权数量,", "allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
Uniswap ব্যবহার করে টোকেন সোয়াপ
যখন মানিব্যাগে যথেষ্ট টোকেন (অর্থাৎ: টোকেনইন) দিতে হবে, এবং অনুমোদনUniswapযদি রাউটিং চুক্তিতে পর্যাপ্ত সংখ্যক ক্রিয়াকলাপ থাকে, তাহলে বিনিময়টি কার্যকর করা যেতে পারে।
Uniswapরাউটিং চুক্তিতে একাধিক রিডেম্পশন পদ্ধতি রয়েছে, যা এখানে দেখানো হয়েছে।exactInputপদ্ধতি, প্রকৃত বিনিময় পুল হয়1INCH/WETH, রিডিম করার পর এটি ব্যবহার করুনunwrapWETH9WETH-কে ETH-এ আনপ্যাক করার পদ্ধতি। এই ধারণাটি আমরা পূর্ববর্তী ERC20 অধ্যায়ে আলোচনা করেছিwithdrawবর্ণনায় ব্যাখ্যা করা হয়েছে।
বিনিময় অপারেশন প্রধানত তিনটি পদ্ধতি ব্যবহার করে:exactInput、unwrapWETH9、multicall, প্রথম করাUniswapরাউটিং চুক্তিexactInputপদ্ধতি কল,unwrapWETH9পদ্ধতি কল এনকোডিং, এবং তারপর রাউটিং চুক্তি ব্যবহার করুনmulticallপদ্ধতিগুলি ব্যাচগুলিতে কার্যকর করা হয়।
javascript
// 兑换
var recipientAddress = "0x0000000000000000000000000000000000000002" // 如果最终兑换到手的是ETH或者WETH,需要把exactInput方法的recipient参数指定为"0x0000000000000000000000000000000000000002"
var fee = exchange.IO("encodePacked", "uint24", 10000)
var path = tokenIn.address.slice(2).toLowerCase() + fee + tokenOut.address.slice(2).toLowerCase()
var minOut = 1
var amountIn = toInnerAmount(swapAmount, tokenIn.decimals)
var swapToken = exchange.IO("encode", contractV3SwapRouterV2Address, "exactInput", {
path: path,
recipient: recipientAddress,
amountIn: amountIn,
amountOutMinimum: minOut
})
var data = [swapToken]
data.push(exchange.IO("encode", contractV3SwapRouterV2Address, "unwrapWETH9(uint256,address)", 1, walletAddress))
var tx = exchange.IO("api", contractV3SwapRouterV2Address, "multicall(uint256,bytes[])", 0, (new Date().getTime() / 1000) + 3600, data)
Log("tx:", tx)
- ব্যবহার
exchange.IO("encodePacked", ...)ফাংশনটি রেট প্যারামিটারগুলিকে এনকোড করে এবং সংকুচিত করে। - অনুযায়ী
exactInputপদ্ধতি পরামিতি প্রয়োজনীয়তা, নির্মাণ পথ পরামিতিpath。 - ব্যবহার
exchange.IO("encode", ...)ফাংশন এনকোডিংexactInputপদ্ধতি কল।
দ্রষ্টব্য: যদি চূড়ান্ত বিনিময়টি ETH বা WETH হয়, তাহলে আপনাকে "0x0000000000000000000000000000000000000000000000000000000002" হিসাবে সঠিক ইনপুট পদ্ধতির প্রাপক পরামিতি নির্দিষ্ট করতে হবে। - ব্যবহার
exchange.IO("encode", ...)ফাংশন এনকোডিংunwrapWETH9(uint256,address)পদ্ধতি কল। - ব্যবহার
multicall(uint256,bytes[])পদ্ধতিটি উপরে কোড করা ফাংশন কল করে।
বিনিময় ফলাফল অনুসন্ধান করুন:
সম্পূর্ণ কোড:
javascript
var abiRoute = '[{"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"}]';
var abiPool = '[{\"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\"}]'
var abiFactory = '[{\"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\"}]'
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
var contractV3SwapRouterV2Address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
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)
}
function main() {
// 注册Uniswap工厂合约的ABI
exchange.IO("abi", contractV3FactoryAddress, abiFactory)
// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)
// 获取交易对的池地址
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 10000)
// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)
// 获取当前配置的钱包地址
var walletAddress = exchange.IO("address")
// 1INCH -> WETH, tokenIn: 1INCH
var allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
var balance = exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "balanceOf", walletAddress)
var balanceOf1INCH = toAmount(balance, tokenIn.decimals)
Log("balanceOf1INCH:", balanceOf1INCH)
var swapAmount = 38
if (balanceOf1INCH < swapAmount) {
Log("钱包中", tokenIn.name, "不足,数量只有:", balanceOf1INCH)
}
if (toAmount(allowanceAmount, tokenIn.decimals) < swapAmount) {
Log("授权数量不足,进行授权")
// 也可以指定授权数量为无限,即把代码中toInnerAmount(swapAmount, tokenIn.decimals) 替换为 '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
var txApprove = exchange.IO("api", tokenIn.address, "approve", contractV3SwapRouterV2Address, toInnerAmount(swapAmount, tokenIn.decimals))
if (!txApprove) {
Log("授权失败")
} else {
for (var i = 0; i < 10; i++) {
Sleep(5000)
var info = exchange.IO("api", "eth", "eth_getTransactionReceipt", txApprove)
if (info && info.gasUsed) {
Log("info:", info)
break
}
Log('Transaction not yet mined', txApprove)
}
// 再次查询授权数量
allowanceAmount = exchange.IO("api", tokenIn.address, "allowance", walletAddress, contractV3SwapRouterV2Address)
Log("再次查询授权数量,", "allowanceAmount:", allowanceAmount, ", 使用toAmount()函数转换为可读数值:", toAmount(allowanceAmount, tokenIn.decimals))
}
}
// 兑换
var recipientAddress = "0x0000000000000000000000000000000000000002"
var fee = exchange.IO("encodePacked", "uint24", 10000)
var path = tokenIn.address.slice(2).toLowerCase() + fee + tokenOut.address.slice(2).toLowerCase()
var minOut = 1
var amountIn = toInnerAmount(swapAmount, tokenIn.decimals)
var swapToken = exchange.IO("encode", contractV3SwapRouterV2Address, "exactInput", {
path: path,
recipient: recipientAddress,
amountIn: amountIn,
amountOutMinimum: minOut
})
var data = [swapToken]
data.push(exchange.IO("encode", contractV3SwapRouterV2Address, "unwrapWETH9(uint256,address)", 1, walletAddress))
var tx = exchange.IO("api", contractV3SwapRouterV2Address, "multicall(uint256,bytes[])", 0, (new Date().getTime() / 1000) + 3600, data)
Log("tx:", tx)
}
পুলে বিনিময় মূল্য পান
যেমনটি আমরা আগে ব্যাখ্যা করেছি, যখন আমরা টোকেন ঠিকানা (দুটি আছে, টোকেনইন এবং টোকেনআউট) এবং রেট সেটিং ব্যবহার করি, তখন আমরাUniswapএরFactoryচুক্তিভিত্তিকgetPoolএই বিনিময় সংমিশ্রণের বিনিময় পুল (স্মার্ট চুক্তি) ঠিকানা প্রাপ্ত করার পদ্ধতি।
বিনিময় পুলের ঠিকানা পাওয়ার পর, পুল চুক্তির ABI নিবন্ধন করুন। তারপর আপনি পুল চুক্তি কল করতে পারেনslot0বর্তমান বিনিময় মূল্য সম্পর্কিত ডেটা প্রাপ্ত করার পদ্ধতি এবং বিনিময় মূল্য আরও বিশ্লেষণ।
javascript
var abiRoute = '[{"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"}]';
var abiPool = '[{\"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\"}]'
var abiFactory = '[{\"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\"}]'
var contractV3FactoryAddress = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
var contractV3SwapRouterV2Address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
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)
}
function main() {
// 注册Uniswap工厂合约的ABI
exchange.IO("abi", contractV3FactoryAddress, abiFactory)
// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)
// 获取交易对的池地址
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 10000)
// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)
var slot0 = exchange.IO("api", poolAddress, "slot0")
Log("slot0:", slot0)
}
এক্সচেঞ্জ পুলের দামের তথ্য প্রাপ্ত করুন এবং কোডটি প্রিন্ট করুনslot0পরিবর্তনশীল:
javascript
{
"feeProtocol":0,
"unlocked":true,
"sqrtPriceX96":"1128983883551457130720648561",
"tick":"-85025",
"observationIndex":5,
"observationCardinality":6,
"observationCardinalityNext":6
}
প্রধান মূল্য তথ্য তথ্য রেকর্ড করা হয়sqrtPriceX96ক্ষেত্রে, বিনিময় সংমিশ্রণের টোকেন নির্ভুলতা ডেটার উপর ভিত্তি করে এক্সচেঞ্জ পুলের বর্তমান মূল্য গণনা করা প্রয়োজন।Uniswapডকুমেন্টেশনে বর্ণিত হিসাবে আমরা গণনা করার জন্য একটি ফাংশন বাস্তবায়ন করি:
javascript
function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
// sqrtPriceX96 = sqrt(price) * 2^96
[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)
);
}
টোকেন সংমিশ্রণ হিসাবে গণনা করতে এই ফাংশনটি ব্যবহার করুন1INCH/WETH, 10,000 হারের সাথে বিনিময় পুলের বর্তমান মূল্য।
javascript
function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
// sqrtPriceX96 = sqrt(price) * 2^96
[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 main() {
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
// 获取的slot0变量中"sqrtPriceX96":"1128983883551457130720648561",
var price = computePoolPrice(tokenIn.decimals, tokenOut.decimals, "1128983883551457130720648561")
Log("price:", price)
}
প্রিন্ট ভেরিয়েবলpriceদেখান:price: 0.000203(0.000203 WETH এর জন্য 1 ইঞ্চি বিনিময় করা হয়)।
Uniswap V3 ট্রেডিং লাইব্রেরি
পরিমাণগত ট্রেডিং প্ল্যাটফর্মের উদ্ভাবক একটি প্যাকেজ প্রকাশ করেছেনUniswapটেমপ্লেট, রিডেম্পশন, মূল্য অধিগ্রহণ, এবং ওয়ালেট ব্যালেন্স কোয়েরি প্রয়োগ করা হয়েছে উপরের ব্যাখ্যার বিষয়বস্তুর উপর ভিত্তি করে বারবার কোড লেখার প্রয়োজন নেই আপনি আরও গভীরভাবে শিখতে এবং অ্যাপ্লিকেশন বিকাশ করতে পারেন Web3 দিক থেকে।
এই টেমপ্লেট ক্লাস লাইব্রেরিতে অনেক বিস্তারিত ডিজাইন রয়েছে যা শেখার মতো:
-
স্বয়ংক্রিয়ভাবে টোকেন তথ্য প্রাপ্ত
ব্যাখ্যা করার জন্য কোডের একটি অংশ বের করুন, যখন টেমপ্লেটের পরামিতিAutoFetchTokensসত্য হিসাবে সেট করা হলে, টেমপ্লেট প্রোগ্রাম স্বয়ংক্রিয়ভাবে অ্যাক্সেস করবেhttps://tokens.coingecko.com/uniswap/all.jsonলিঙ্ক করুন, প্রাপ্ত করুন এবং স্বয়ংক্রিয়ভাবে সমস্ত টোকেন তথ্য প্রক্রিয়া করুন। এটি কৌশল কোডে ম্যানুয়ালি একটি টোকেন যোগ করার প্রয়োজনীয়তা দূর করে (অন্যথায় আপনাকে ব্যবহার করতে হবেaddToken(name, address)টোকেন যোগ করুন)।javascriptif (AutoFetchTokens) { let res = JSON.parse(HttpQuery("https://tokens.coingecko.com/uniswap/all.json")) Log("fetch", res.tokens.length, "tokens from", res.name) res.tokens.forEach(function(token) { if (token.chainId == chainId && token.symbol != "WETH") { self.tokenInfo[token.symbol] = { name: token.symbol, decimals: token.decimals, address: token.address } } }) } -
চেইন সেটিংস অনুযায়ী বিভিন্ন চুক্তির ঠিকানা মানিয়ে নিন
এই টেমপ্লেট সেট করা হয়ChainTypeএকাধিক চেইন পরিবর্তন সমর্থন করার পরামিতি:desc'https://rpc.ankr.com/eth', 'https://arb1.arbitrum.io/rpc', 'https://mainnet.optimism.io/', 'https://rpc.ankr.com/avalanche', 'https://polygon-rpc.com', 'https://rpc.ankr.com/celo',উদ্ধৃতি কোড:
javascriptif (typeof(ChainType) === 'number') { let chainRpc = [ '', 'https://rpc.ankr.com/eth', 'https://arb1.arbitrum.io/rpc', 'https://mainnet.optimism.io/', 'https://rpc.ankr.com/avalanche', 'https://polygon-rpc.com', 'https://rpc.ankr.com/celo', //'https://mainnet.aurora.dev', //'https://bsc-dataseed.binance.org', //'https://exchainrpc.okex.org' ][ChainType] if (chainRpc && chainRpc.length > 0) { e.IO("base", chainRpc) Log("change base rpc to", chainRpc) } }ইথেরিয়ামের RPC পদ্ধতিতে কল করা
eth_chainIdপ্রশ্ন বর্তমানchainId, এবং তারপর উপর ভিত্তি করেchainIdWETH ঠিকানার সাথে মানিয়ে নিতে,Uniswapচুক্তির ঠিকানাগুলির একটি সিরিজ,USDTচুক্তির ঠিকানা, ইত্যাদি (একটি নির্দিষ্ট স্মার্ট চুক্তির বিভিন্ন চেইনে বিভিন্ন চুক্তির ঠিকানা থাকতে পারে)।উদ্ধৃতি কোড:
javascript// https://docs.uniswap.org/contracts/v3/reference/deployments let WETHAddress = { 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // Ethereum 3: "0xc778417E063141139Fce010982780140Aa0cD5Ab", // Ropsten 4: "0xc778417E063141139Fce010982780140Aa0cD5Ab", // Rinkeby 5: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", // Goerli 42: "0xd0A1E359811322d97991E03f863a0C30C2cF029C", // Kovan 10: "0x4200000000000000000000000000000000000006", // Optimism 69: "0x4200000000000000000000000000000000000006", // Optimistic Kovan 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // Arbitrum One 421611: "0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681", // Arbitrum Rinkeby 137: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", // Polygon 80001: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", // Polygon Mumbai } let chainId = e.IO("api", "ETH", "eth_chainId") if (chainId) { chainId = Number(chainId) Log("chainId: ", chainId) let addr = WETHAddress[chainId] if (addr) { Log("Register WETH address", addr) self.addToken("ETH", addr) } if (chainId == 42220) { // Celo Address ContractV3Factory = '0xAfE208a311B21f13EF87E33A90049fC17A7acDEc' ContractV3SwapRouterV2 = '0x5615CDAb10dc425a742d643d949a7F474C01abc4' self.addToken('CELO', '0x471ece3750da237f93b8e339c536989b8978a438') } else if (chainId == 42161) { self.addToken('USDT', '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9') } } else { panic("get chain Id error") } -
"Uniswap V3 লেনদেন লাইব্রেরি" ব্যবহার করুন
এই টেমপ্লেটে
$.testUniswap()ফাংশনটি এমন একটি ফাংশন যা টেমপ্লেটের ফাংশন পরীক্ষা করে এর কোডটি টেমপ্লেটটি কীভাবে ব্যবহার করতে হয় তার একটি উদাহরণ দেয়:javascript$.testUniswap = function() { let ex = $.NewUniswapV3() Log("walletAddress: ", ex.walletAddress) let tokenAddressMap = { "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7", "1INCH": "0x111111111117dC0aa78b770fA6A738034120C302", "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "DAI": "0x6b175474e89094c44da98b954eedeac495271d0f", } 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 USDT to DAI then DAI to ETH Log(ex.swapToken('USDT', usdtBalance, 'DAI,ETH')) Log("balance of ETH", ex.getETHBalance()) // Log(ex.sendETH('0x11111', 0.02)) // ... }যখন একটি কৌশল "Uniswap V3 ট্রানজ্যাকশন লাইব্রেরি" উল্লেখ করে (টেমপ্লেট লাইব্রেরির রেফারেন্সের জন্য, অনুগ্রহ করে FMZ প্ল্যাটফর্ম ডকুমেন্টেশন দেখুন), আপনি এই টেমপ্লেট লাইব্রেরিতে এনক্যাপসুলেটেড ফাংশনগুলিকে কল করতে পারেন।
নামে একটি ফাইল তৈরি করুন
exভেরিয়েবল, "Uniswap V3 ট্রেডিং লাইব্রেরি" টেমপ্লেট দ্বারা আবদ্ধ ইন্টারফেস ফাংশনকে কল করুন$.NewUniswapV3()একটি অবজেক্ট তৈরি করুন এবং এটিকে বরাদ্দ করুনex。javascriptlet ex = $.NewUniswapV3()ব্যবহার
exবস্তু সদস্য ফাংশনaddToken()টোকেন তথ্য যোগ করুন (নিবন্ধন করুন)।javascriptlet tokenAddressMap = { "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7", "1INCH": "0x111111111117dC0aa78b770fA6A738034120C302", "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "DAI": "0x6b175474e89094c44da98b954eedeac495271d0f", } for (let name in tokenAddressMap) { ex.addToken(name, tokenAddressMap[name]) }আপনি যদি একটি নির্দিষ্ট ট্রেডিং পেয়ারের বিনিময় পুল মূল্য পেতে এবং মুদ্রণ করতে চান, আপনি ব্যবহার করতে পারেন
exবস্তু সদস্য ফাংশনgetPrice(), এভাবে লেখা যেতে পারে:javascriptLog(ex.getPrice('ETH_USDT')) Log(ex.getPrice('1INCH_USDT'))আপনি একটি খালাস অপারেশন সঞ্চালন করতে চান, আপনি ব্যবহার করতে পারেন
exবস্তু সদস্য ফাংশনswapToken(), এক্সচেঞ্জ চালান:javascript// swap 0.01 ETH to USDT Log(ex.swapToken('ETH', 0.01, 'USDT')) let usdtBalance = ex.balanceOf('USDT') Log("balance of USDT", usdtBalance) // swap USDT to DAI then DAI to ETH Log(ex.swapToken('USDT', usdtBalance, 'DAI,ETH'))
ঘটনা পুনরুদ্ধার
এই অধ্যায়ে আমরা ইথেরিয়াম ভার্চুয়াল মেশিনের লগে স্মার্ট চুক্তির দ্বারা প্রকাশিত ইভেন্টগুলি পড়তে উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্ম ব্যবহার করতে শিখব।
eth_getLogs
স্মার্ট চুক্তি দ্বারা প্রকাশিত ইভেন্টগুলি জিজ্ঞাসা করতে, আপনাকে Ethereum-এর RPC পদ্ধতি ব্যবহার করতে হবে৷eth_getLogs, অন-চেইন লগ ডেটা পান। আমরা আমাদের পূর্ববর্তী কোর্সে ইথেরিয়াম RPC নোড কীভাবে কল করতে হয় তা ইতিমধ্যেই ব্যাখ্যা করেছি।
যেমন আমরা পেতেWETHচুক্তি ইভেন্টগুলি FMZ ব্যবহার করে কোড করা যেতে পারেডিবাগিং টুলপরীক্ষা, বিনিময় বস্তু দ্বারা কনফিগার করা RPC নোড হল Ethereum প্রধান নেটওয়ার্ক নোড, এবং কল করার সময়eth_getLogsপদ্ধতিটি ব্যবহার করার সময় আমরা তিনটি পরামিতি নির্দিষ্ট করেছিfromBlock、toBlock、address, আমরা fromBlock এবং toBlock প্যারামিটার ব্যবহার করি একটি ব্লকের মধ্যে থাকা ডেটাতে ক্যোয়ারী সীমাবদ্ধ করতে:
javascript
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)
}
function main() {
// getBlockNumber
var blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log("blockNumber:", blockNumber)
// get logs
var fromBlock = "0x" + (toAmount(blockNumber, 0) - 1).toString(16)
var toBlock = "0x" + toAmount(blockNumber, 0).toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" // WETH合约的地址
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
// 由于数据量比较大,如果使用Log函数打印,数据会被截断。使用return将完整数据返回在页面「函数结果」编辑框中
return logs
}
লগ ডেটা প্রাপ্ত যেহেতু ডেটা বিষয়বস্তু বড়, আমরা এর কিছু অংশ বাদ দিই:
javascript
[{
"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a80", "0x000000000000000000000000bcb095c1f9c3dc02e834976706c87dee5d0f1fb6"],
"transactionHash": "0x27f9bf5abe3148169b4b85a83e1de32bd50eb81ecc52e5af006157d93353e4c4",
"transactionIndex": "0x0",
"removed": false,
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
"blockNumber": "0x109b1cc",
"logIndex": "0x0"
}, {
"data": "0x00000000000000000000000000000000000000000000000008ea20cdea027c00",
"logIndex": "0x5",
"topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", "0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d"],
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
"blockNumber": "0x109b1cc",
"removed": false,
"transactionHash": "0xace3afa02e8af5d1ef6fc1635fbdf7bee37624547937ea5272c23968dd034c09",
"transactionIndex": "0x1"
},
...
{
"blockNumber": "0x109b1cd",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"data": "0x00000000000000000000000000000000000000000000000002c053531ab8a000",
"logIndex": "0xd3",
"removed": false,
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582", "0x000000000000000000000000252ba9b5916171dbdadd2cec7f91875a006955d0"],
"transactionHash": "0x3012b82891f85b077cfe1c12cb9722b93c696ef2c37d67981ccddcc9c3396aca",
"transactionIndex": "0x8d",
"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9"
}, {
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],
"transactionIndex": "0x91",
"logIndex": "0xdb",
"removed": false,
"blockNumber": "0x109b1cd",
"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
"transactionHash": "0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9"
}, {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9",
"blockNumber": "0x109b1cd",
"logIndex": "0xde",
"removed": false,
"topics": ["0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],
"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
"transactionHash": "0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048",
"transactionIndex": "0x91"
}]
আপনি দেখতে পারেন যে লগ ডেটাতে বিভিন্ন ইভেন্ট রয়েছে যদি আমরা কেবল যত্ন করিTransferইভেন্ট এই তথ্য অন্তর্ভুক্ত করা প্রয়োজনTransferইভেন্ট ফিল্টার আউট করা হয়.
লগ পুনরুদ্ধার করুন
Ethereum লগ দুটি ভাগে বিভক্ত, 1. বিষয়topics;2data。
-
থিম
topics
দ্বারাeth_getLogsউদাহরণ হিসাবে অধ্যায় পরীক্ষার কোড চলমান ফলাফল নিন,topicsক্ষেত্রের তথ্য হল:desc"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],এই
topics(বিষয়) ক্ষেত্রের মান হল একটি অ্যারে কাঠামো যা ঘটনাটি বর্ণনা করে। এটি নির্ধারিত যে এর (অ্যারের) দৈর্ঘ্য 4 এর বেশি হতে পারে না, এবং প্রথম উপাদানটি হল ইভেন্টের স্বাক্ষর হ্যাশ মান।
ইনভেনটর কোয়ান্টিটেটিভ ট্রেডিং প্ল্যাটফর্মে, আমরা ব্যবহার করিEncodeফাংশন গণনা করতে নিম্নলিখিত কোড ব্যবহার করে স্বাক্ষর হ্যাশ মান গণনা করতে পারে:javascriptfunction main() { var eventFunction = "Transfer(address,address,uint256)" var eventHash = Encode("keccak256", "string", "hex", eventFunction) Log("eventHash:", "0x" + eventHash) // eventHash: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef }গণনা করা
Transfer(address,address,uint256)এরkeccak256হ্যাশ মান (হেক্স এনকোডেড) হল0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef。topicsক্ষেত্রের মান একটি অ্যারে গঠন, এবং দ্বিতীয় এবং তৃতীয় উপাদান হল:- ঠিকানা প্রদান
from - ঠিকানা গ্রহণ
to
- ঠিকানা প্রদান
-
তথ্য
datadataক্ষেত্রের তথ্য হল:desc"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",ইভেন্টের কিছু প্যারামিটার (স্মার্ট চুক্তির সলিডিটি কোডের পরামিতিগুলিকে সূচীকৃত ঘোষণা করা হয় না) সংরক্ষণ করা হবে
dataঅংশএই ডেটা পার্স করুন
0x0000000000000000000000000000000000000000000000000164f2434262e1ccjavascriptfunction toAmount(s, decimals) { return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString()) } function main() { var value = "0x0000000000000000000000000000000000000000000000000164f2434262e1cc" Log(toAmount(value, 0) / 1e18) // 0.10047146239950075 }এই তথ্য প্রাপ্ত করা হয়: 0.10047146239950075,
dataডেটা স্থানান্তর পরিমাণের সাথে মিলে যায়।
উপরের বিষয়বস্তু ব্যাখ্যা এবং অনুশীলন করার পরে, আপনি প্রস্তুত। আমরা লগগুলি পুনরুদ্ধার শুরু করতে পারি:
javascript
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)
}
function main() {
// getBlockNumber
var blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log("blockNumber:", blockNumber)
// get logs
var fromBlock = "0x" + (toAmount(blockNumber, 0) - 1).toString(16)
var toBlock = "0x" + toAmount(blockNumber, 0).toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
// 遍历logs
var eventFunction = "Transfer(address,address,uint256)"
var eventHash = "0x" + Encode("keccak256", "string", "hex", eventFunction)
Log("eventHash:", eventHash)
var counter = 0
for (var i = logs.length - 1; i >= 0 && counter < 10; i--) {
if (logs[i].topics[0] == eventHash) {
Log("Event Transfer, data:", toAmount(logs[i].data, 0) / 1e18, ", blockNumber:", toAmount(logs[i].blockNumber, 0), ", transactionHash:", logs[i].transactionHash,
", log:", logs[i])
counter++
}
}
}
বিদ্যমানhttps://etherscan.io/প্রশ্ন:
FMZ ডিবাগিং টুলে পরীক্ষার কোড চালানোর ফলাফল:
পুনরুদ্ধারের সময় প্রয়োজন অনুযায়ী, এটি পার্স করা যেতে পারেfrom,toক্ষেত্রের তথ্য, উদাহরণস্বরূপ:
javascript
function main() {
var from = "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c"
var address = "0x" + exchange.IO("encodePacked", "address", from)
Log("address:", address)
}
চলমান ফলাফল:
address: 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c
চুক্তি ঘটনা শুনুন
কারণডিবাগিং টুলকোডটি শুধুমাত্র অল্প সময়ের জন্য পরীক্ষা করা যেতে পারে, এবং কোড এক্সিকিউশন সম্পূর্ণ হওয়ার পরেই কন্টেন্ট আউটপুট হবে, এবং লগটি রিয়েল টাইমে প্রদর্শিত বা আউটপুট করা যাবে না। এই বিভাগে, আমরা পরীক্ষার জন্য একটি বাস্তব অফার তৈরি করতে উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্ম ব্যবহার করি।
এখানে আমরা ইথেরিয়াম মেইননেট ব্যবহার করি, আসুন নিরীক্ষণ করিUSDTএই মুদ্রা চুক্তিTransfer(address,address,uint256)ইভেন্টগুলি, আমরা পূর্ববর্তী পাঠে যা শিখেছি তার উপর ভিত্তি করে, আমরা একটি নির্দিষ্ট স্মার্ট চুক্তি ইভেন্টকে ক্রমাগত পর্যবেক্ষণ করার একটি উদাহরণ ডিজাইন এবং প্রোগ্রাম করেছি:
javascript
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)
}
function addEventListener(contractAddress, event, callBack) {
var self = {}
self.eventHash = "0x" + Encode("keccak256", "string", "hex", event)
self.contractAddress = contractAddress
self.latestBlockNumber = 0
self.fromBlockNumber = 0
self.firstBlockNumber = 0
/* TODO: test
self.isFirst = true
*/
self.getBlockNumber = function() {
var maxTry = 10
for (var i = 0; i < maxTry; i++) {
var ret = exchange.IO("api", "eth", "eth_blockNumber")
if (ret) {
return toAmount(ret, 0)
}
Sleep(5000)
}
throw "getBlockNumber failed"
}
self.run = function() {
var currBlockNumber = self.getBlockNumber()
var fromBlock = "0x" + self.fromBlockNumber.toString(16)
var toBlock = "0x" + currBlockNumber.toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : self.contractAddress,
"topics" : [self.eventHash]
}
// Log("fromBlockNumber:", self.fromBlockNumber, ", currBlockNumber:", currBlockNumber, "#FF0000")
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
if (!logs) {
return
}
for (var i = 0; i < logs.length; i++) {
if (toAmount(logs[i].blockNumber, 0) > self.latestBlockNumber) {
/* TODO: test
if (self.isFirst) {
self.firstBlockNumber = toAmount(logs[i].blockNumber, 0)
Log("firstBlockNumber:", self.firstBlockNumber)
self.isFirst = false
}
*/
callBack(logs[i])
}
}
self.latestBlockNumber = currBlockNumber
self.fromBlockNumber = self.latestBlockNumber - 1
}
self.latestBlockNumber = self.getBlockNumber()
self.fromBlockNumber = self.latestBlockNumber - 1
return self
}
var listener = null
function main() {
var event = "Transfer(address,address,uint256)"
var contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7"
var decimals = exchange.IO("api", contractAddress, "decimals")
Log(exchange.IO("api", contractAddress, "name"), " decimals:", decimals)
listener = addEventListener(contractAddress, event, function(log) {
var fromAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[1])
var toAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[2])
Log("Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0))
/* TODO: test
arrLog.push(log)
*/
})
while (true) {
listener.run()
Sleep(5000)
}
}
/* TODO: test
var arrLog = []
function onexit() {
Log("结束运行,验证记录")
var firstBlockNumber = listener.firstBlockNumber
var endBlockNumber = listener.latestBlockNumber
Log("getLogs, from:", firstBlockNumber, " -> to:", endBlockNumber)
var fromBlock = "0x" + (firstBlockNumber).toString(16)
var toBlock = "0x" + (endBlockNumber).toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"topics" : ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
"address" : "0xdac17f958d2ee523a2206206994597c13d831ec7"
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
Log("arrLog:", arrLog.length)
Log("logs:", logs.length)
if (arrLog.length != logs.length) {
Log("长度不等!")
return
}
for (var i = 0; i < arrLog.length; i++) {
Log("判断blockNumber:", logs[i].blockNumber == arrLog[i].blockNumber, ",判断from:", logs[i].topics[1] == arrLog[i].topics[1],
"判断to:", logs[i].topics[2] == arrLog[i].topics[2])
}
}
*/
বাস্তব অপারেশন:
সম্পাদনের ফলাফলের জন্য, একটি যাচাইকরণ অংশ (TODO: পরীক্ষা) কোডটিতেও লেখা আছে। সহজ যাচাইকরণের পরে, আপনি দেখতে পারেন যে USDT চুক্তি ক্রমাগত নিরীক্ষণ করা হয়।Transferইভেন্ট এবং ডেটা রেকর্ড করুন একবার প্রাপ্ত ইভেন্ট ডেটার সাথে তুলনা করে, আপনি দেখতে পারেন যে ডেটা সামঞ্জস্যপূর্ণ:
ইভেন্ট ফিল্টারিং
পূর্ববর্তী পাঠ "মনিটরিং কন্ট্রাক্ট ইভেন্টস" এর উপর ভিত্তি করে, আসুন এটিকে প্রসারিত করি এবং নির্দিষ্ট ঠিকানার ভিতরে এবং বাইরে স্থানান্তর নিরীক্ষণ করার জন্য মনিটরিং প্রক্রিয়া চলাকালীন ফিল্টার যোগ করি। যখন একটি স্মার্ট চুক্তি একটি লগ তৈরি করে (অর্থাৎ, একটি রিলিজ ইভেন্ট), লগ ডেটাtopics4টি পর্যন্ত বার্তা রয়েছে। তাই আমরা একটি ফিল্টারিং নিয়ম ডিজাইন[[A1, A2, ...An], null, [C1], D]উদাহরণ হিসেবে।
1、[A1, A2, ...An]অনুরূপtopics[0]অবস্থান ডেটা।
2、nullঅনুরূপtopics[1]অবস্থান ডেটা।
3、[C1]অনুরূপtopics[2]অবস্থান ডেটা।
4、Dঅনুরূপtopics[3]অবস্থান ডেটা।
- শর্তাধীন কাঠামোর উপাদানগুলি সেট করা থাকলে
nullইঙ্গিত করে যে এটি ফিল্টার করা হয় না, উদাহরণস্বরূপnullঅনুরূপtopics[1], যেকোনো মান মেলে। - যদি একটি শর্তাধীন কাঠামোর একটি উপাদান একটি একক মান সেট করা হয় তবে এর অর্থ হল অবস্থানটি অবশ্যই মিলবে, যেমন
[C1]অনুরূপtopics[2]অথবাDঅনুরূপtopics[3], অতুলনীয় লগ ফিল্টার করা হয়. - যদি শর্তাধীন কাঠামোর উপাদানটি একটি অ্যারে হয়, তাহলে এর অর্থ হল অ্যারের কমপক্ষে একটি উপাদান অবশ্যই মিলিত হতে হবে, উদাহরণস্বরূপ
[A1, A2, ...An]অনুরূপtopics[0],[A1, A2, ...An]কোন যোগফল আছেtopics[0]মিলে গেলে, লগ ফিল্টার করা হবে না।
এক্সচেঞ্জে USDT স্থানান্তর নিরীক্ষণ করুন
Binance এক্সচেঞ্জ থেকে এবং থেকে স্থানান্তর মনিটরUSDTলেনদেন:
javascript
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)
}
function addEventListener(contractAddress, event, callBack) {
var self = {}
self.eventHash = "0x" + Encode("keccak256", "string", "hex", event)
self.contractAddress = contractAddress
self.latestBlockNumber = 0
self.fromBlockNumber = 0
self.firstBlockNumber = 0
self.filters = []
self.setFilter = function(filterCondition) {
if (filterCondition.length > 4) {
throw "filterCondition error"
}
self.filters.push(filterCondition)
Log("设置过滤条件:", filterCondition)
}
self.getTokenBalanceOfWallet = function(walletAddress, tokenAddress, tokenDecimals) {
var balance = exchange.IO("api", tokenAddress, "balanceOf", walletAddress)
if (balance) {
return toAmount(balance, tokenDecimals)
}
return null
}
self.getBlockNumber = function() {
var maxTry = 10
for (var i = 0; i < maxTry; i++) {
var ret = exchange.IO("api", "eth", "eth_blockNumber")
if (ret) {
return toAmount(ret, 0)
}
Sleep(5000)
}
throw "getBlockNumber failed"
}
self.run = function() {
var currBlockNumber = self.getBlockNumber()
var fromBlock = "0x" + self.fromBlockNumber.toString(16)
var toBlock = "0x" + currBlockNumber.toString(16)
var params = {
"fromBlock" : fromBlock,
"toBlock" : toBlock,
"address" : self.contractAddress,
"topics" : [self.eventHash]
}
var logs = exchange.IO("api", "eth", "eth_getLogs", params)
if (!logs) {
return
}
for (var i = 0; i < logs.length; i++) {
if (toAmount(logs[i].blockNumber, 0) > self.latestBlockNumber) {
// 检查过滤条件,设置了过滤条件则执行判断
if (self.filters.length != 0) {
// 初始过滤标记
var isFilter = true
// 遍历过滤条件设置
for (var j = 0; j < self.filters.length; j++) {
// 取一个过滤设置,例如:[[A1, A2, ...An], null, [C1], D]
var cond = self.filters[j]
// 遍历这个过滤设置
var final = true
for (var topicsIndex = 0; topicsIndex < cond.length; topicsIndex++) {
// 拿到这个过滤设置中的某一个条件,如果是第一个条件:即要和topics[0]对比的数据
var condValue = cond[topicsIndex]
// 日志中的数据
if (topicsIndex > logs[i].topics.length - 1) {
continue
}
var topicsEleValue = logs[i].topics[topicsIndex]
// 如果是Transfer事件,需要处理from和to
if (logs[i].topics[0] == "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") {
if (topicsIndex == 1 || topicsIndex == 2) {
topicsEleValue = "0x" + exchange.IO("encodePacked", "address", topicsEleValue)
}
}
// 如果condValue类型是数组,表示该位置的对比条件有多个,多个条件对比是逻辑或关系
if (Array.isArray(condValue) && condValue.length > 1) {
// 判断 condValue[0] == topicsEleValue || condValue[1] == topicsEleValue
final = final && condValue.some(element => element === topicsEleValue)
}else if (condValue === null) {
final = final && true
} else {
final = final && (condValue === topicsEleValue)
}
}
if (final) {
isFilter = false
}
}
if (isFilter) {
continue
}
}
callBack(logs[i])
}
}
self.latestBlockNumber = currBlockNumber
self.fromBlockNumber = self.latestBlockNumber - 1
}
self.latestBlockNumber = self.getBlockNumber()
self.fromBlockNumber = self.latestBlockNumber - 1
return self
}
var listener = null
function main() {
// 初始清理日志
LogReset(1)
LogProfitReset()
var event = "Transfer(address,address,uint256)" // 监听事件
var contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7" // USDT合约地址
var decimals = exchange.IO("api", contractAddress, "decimals") // 获取USDT token的精度信息
var accountBinanceAddress = "0x28C6c06298d514Db089934071355E5743bf21d60" // Binance 热钱包地址
accountBinanceAddress = accountBinanceAddress.toLowerCase() // 地址处理为小写
Log(exchange.IO("api", contractAddress, "name"), " decimals:", decimals)
// 创建监听对象
listener = addEventListener(contractAddress, event, function(log) {
var fromAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[1])
var toAddress = "0x" + exchange.IO("encodePacked", "address", log.topics[2])
if (fromAddress == accountBinanceAddress) {
Log("币安转出 - ", " Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0), "#CD32CD")
} else if (toAddress == accountBinanceAddress) {
Log("转入币安 - ", " Transfer:", fromAddress, "->", toAddress, ", value:", toAmount(log.data, decimals), ", blockNumber:", toAmount(log.blockNumber, 0), "#FF0000")
}
})
// 设置事件过滤
listener.setFilter([null, accountBinanceAddress, null]) // Binance -> USDT
listener.setFilter([null, null, accountBinanceAddress]) // USDT -> Binance
var preBalance = 0
while (true) {
listener.run()
var balance = listener.getTokenBalanceOfWallet(accountBinanceAddress, contractAddress, decimals)
if (balance) {
var direction = ""
if (preBalance != 0 && preBalance > balance) {
direction = " ↓ " + (preBalance - balance) + "#CD32CD"
} else if (preBalance != 0 && preBalance < balance) {
direction = " ↑ " + (balance - preBalance) + "#FF0000"
}
Log("币安钱包地址:", accountBinanceAddress, " 余额:", balance, direction)
LogProfit(balance, "&") // 只画图,不打印日志
preBalance = balance
}
LogStatus(_D(), "币安钱包地址:", accountBinanceAddress, ", 余额:", balance)
Sleep(5000 * 3)
}
}
উপরের কোডটি বাস্তব ডিস্কে চলে:
এই পাঠে, আমরা কীভাবে ইভেন্ট ফিল্টার ডিজাইন করতে হয় তা উপস্থাপন করেছি। এবং Binance এক্সচেঞ্জ হট ওয়ালেট সম্পর্কিত নিরীক্ষণ এটি ব্যবহার করেUSDTবাণিজ্য আপনি এই নমুনা প্রোগ্রামটি সংশোধন এবং প্রসারিত করতে পারেন আপনার আগ্রহের যে কোনো ইভেন্ট শুনতে। একবার দেখুনsmart moneyকি নতুন চুক্তি করা হয়েছে?NFTবস কোন নতুন প্রকল্পে ছুটে এসেছেন ইত্যাদি।
ইউনিট রূপান্তর
ইথেরিয়াম সম্পর্কিত অনেক গণনায়, মানগুলি অতিক্রম করেJavaScriptভাষার জন্য সর্বোচ্চ নিরাপদ পূর্ণসংখ্যা। তাই, উদ্ভাবক কোয়ান্টিটেটিভ ট্রেডিং প্ল্যাটফর্মে বড় মানগুলি পরিচালনা করার জন্য কিছু পদ্ধতির প্রয়োজন হয়, আমরা এই পদ্ধতিগুলিকে বিস্তারিত ব্যাখ্যা না করেই পূর্ববর্তী কোর্সে ব্যবহার করেছি। তাই এই অধ্যায়ে এই দিকটি বিস্তারিত আলোচনা করা হবে।
প্রিন্টJavaScriptভাষায় সংজ্ঞায়িত বৃহত্তম নিরাপদ পূর্ণসংখ্যা:
javascript
function main() {
Log("Number.MAX_SAFE_INTEGER:", Number.MAX_SAFE_INTEGER)
}
চলমান ফলাফল:
Number.MAX_SAFE_INTEGER: 9007199254740991
BigInt
Ethereum সংজ্ঞায়িত ক্ষুদ্রতম একক হয়1wei, সংজ্ঞা1Gweiসমান1000000000 wei。1Gweiইথেরিয়াম-সম্পর্কিত গণনায়, এটি আসলে একটি খুব বড় সংখ্যা নয় কিছু ডেটা এর থেকে অনেক বড়। তাহলে অত্যন্ত বড় মান সহ এই ডেটাগুলি সহজেই অতিক্রম করতে পারেNumber.MAX_SAFE_INTEGER: 9007199254740991。
উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্মে, আমরা প্ল্যাটফর্ম ব্যবহার করিBigIntএই খুব বড় পূর্ণসংখ্যা ডেটা উপস্থাপন করতে অবজেক্ট। কনস্ট্রাক্টর ব্যবহার করুনBigInt()নির্মাণBigIntবস্তু পরামিতি হিসাবে সংখ্যাসূচক মান বা হেক্সাডেসিমেল মান স্ট্রিং ব্যবহার করে নির্মাণ করা যেতে পারেBigIntবস্তু ব্যবহারBigIntবস্তুtoString()পদ্ধতি একটি স্ট্রিং হিসাবে বস্তু দ্বারা উপস্থাপিত তথ্য আউটপুট.
BigIntবস্তু দ্বারা সমর্থিত অপারেশন:
- সংযোজন অপারেশন:
+ - বিয়োগ ক্রিয়া:
- - গুণন অপারেশন:
* - বিভাগ পরিচালনা:
/ - মডিউল অপারেশন:
% - সূচক অপারেশন:
**
নিম্নলিখিত কোড উদাহরণ পড়ুন:
javascript
function main() {
// 1Gwei的十进制表示
var oneGwei = 1000000000
// 1Gwei的十进制转换为十六进制表示
var oneGweiForHex = "0x" + oneGwei.toString(16)
Log("oneGwei : ", oneGwei)
Log("oneGweiForHex : ", oneGweiForHex)
// 构造BigInt对象
Log("1Gwei / 1Gwei : ", (BigInt(oneGwei) / BigInt(oneGweiForHex)).toString(10))
Log("1Gwei * 1Gwei : ", (BigInt(oneGwei) * BigInt(oneGweiForHex)).toString(10))
Log("1Gwei - 1Gwei : ", (BigInt(oneGwei) - BigInt(oneGweiForHex)).toString(10))
Log("1Gwei + 1Gwei : ", (BigInt(oneGwei) + BigInt(oneGweiForHex)).toString(10))
Log("(1Gwei + 1) % 1Gwei : ", (BigInt(oneGwei + 1) % BigInt(oneGweiForHex)).toString(10))
Log("1Gwei ** 2 : ", (BigInt(oneGwei) ** BigInt(2)).toString(10))
Log("100 的平方根 : ", (BigInt(100) ** BigFloat(0.5)).toString(10))
Log("Number.MAX_SAFE_INTEGER : ", BigInt(Number.MAX_SAFE_INTEGER).toString(10))
Log("Number.MAX_SAFE_INTEGER * 2 : ", (BigInt(Number.MAX_SAFE_INTEGER) * BigInt("2")).toString(10))
}
ডিবাগিং টুল পরীক্ষা:
run
2023-06-08 11:39:50 信息 Number.MAX_SAFE_INTEGER * 2 : 18014398509481982
2023-06-08 11:39:50 信息 Number.MAX_SAFE_INTEGER : 9007199254740991
2023-06-08 11:39:50 信息 100 的平方根 : 10
2023-06-08 11:39:50 信息 1Gwei ** 2 : 1000000000000000000
2023-06-08 11:39:50 信息 (1Gwei + 1) % 1Gwei : 1
2023-06-08 11:39:50 信息 1Gwei + 1Gwei : 2000000000
2023-06-08 11:39:50 信息 1Gwei - 1Gwei : 0
2023-06-08 11:39:50 信息 1Gwei * 1Gwei : 1000000000000000000
2023-06-08 11:39:50 信息 1Gwei / 1Gwei : 1
2023-06-08 11:39:50 信息 oneGweiForHex : 0x3b9aca00
2023-06-08 11:39:50 信息 oneGwei : 1000000000
BigFloat
BigFloatসঙ্গে বস্তুBigIntবস্তু একইভাবে ব্যবহৃত হয়, বৃহত্তর ভাসমান বিন্দু সংখ্যার প্রতিনিধিত্ব করতে ব্যবহৃত হয়, এবং যোগ, বিয়োগ, গুণ এবং ভাগ ক্রিয়াগুলিকে সমর্থন করে।
BigFloatঅবজেক্ট সাপোর্টtoFixed()পদ্ধতি
নিম্নলিখিত কোড উদাহরণ পড়ুন:
javascript
function main() {
var pi = 3.14
var oneGwei = "1000000000"
var oneGweiForHex = "0x3b9aca00"
Log("pi + oneGwei : ", (BigFloat(pi) + BigFloat(oneGwei)).toFixed(2))
Log("pi - oneGweiForHex : ", (BigFloat(pi) - BigFloat(oneGweiForHex)).toFixed(2))
Log("pi * 2.0 : ", (BigFloat(pi) * BigFloat(2.0)).toFixed(2))
Log("pi / 2.0 : ", (BigFloat(pi) / BigFloat(2.0)).toFixed(2))
}
ডিবাগিং টুল পরীক্ষা:
javascript
2023-06-08 13:56:44 信息 pi / 2.0 : 1.57
2023-06-08 13:56:44 信息 pi * 2.0 : 6.28
2023-06-08 13:56:44 信息 pi - oneGweiForHex : -999999996.86
2023-06-08 13:56:44 信息 pi + oneGwei : 1000000003.14
BigDecimal
BigDecimalবস্তুটি পূর্ণসংখ্যার মান এবং ভাসমান বিন্দুর মানগুলির সাথে সামঞ্জস্যপূর্ণ এবং এর ব্যবহার সমর্থন করেBigIntবস্তুBigFloatঅবজেক্ট ইনিশিয়ালাইজেশন যোগ, বিয়োগ, গুণ এবং ভাগ অপারেশনকেও সমর্থন করে।
নিম্নলিখিত কোড উদাহরণ পড়ুন:
javascript
function main() {
var pi = 3.1415
var oneGwei = 1000000000
var oneGweiForHex = "0x3b9aca00"
Log("pi : ", BigDecimal(pi).toFixed(2))
Log("oneGwei : ", BigDecimal(oneGwei).toString())
Log("oneGweiForHex : ", BigDecimal(BigInt(oneGweiForHex)).toString())
Log("BigInt(oneGwei) : ", BigDecimal(BigInt(oneGwei)).toString())
Log("BigFloat(pi) : ", BigDecimal(BigFloat(pi)).toFixed(4))
Log("oneGwei + pi : ", (BigDecimal(oneGwei) + BigDecimal(pi)).toString())
Log("oneGwei - pi : ", (BigDecimal(oneGwei) - BigDecimal(pi)).toString())
Log("2.0 * pi : ", (BigDecimal(2.0) * BigDecimal(pi)).toString())
Log("pi / pi : ", (BigDecimal(pi) / BigDecimal(pi)).toString())
}
ডিবাগিং টুলে চালান:
run
2023-06-08 14:52:53 信息 pi / pi : 1
2023-06-08 14:52:53 信息 2.0 * pi : 6.283
2023-06-08 14:52:53 信息 oneGwei - pi : 999999996.8585
2023-06-08 14:52:53 信息 oneGwei + pi : 1000000003.1415
2023-06-08 14:52:53 信息 BigFloat(pi) : 3.1415
2023-06-08 14:52:53 信息 BigInt(oneGwei) : 1e+9
2023-06-08 14:52:53 信息 oneGweiForHex : 1e+9
2023-06-08 14:52:53 信息 oneGwei : 1e+9
2023-06-08 14:52:53 信息 pi : 3.14
ইউনিট রূপান্তর
নিম্নলিখিত দুটি ফাংশন:toAmount()、toInnerAmount()আমরা পূর্ববর্তী কোর্সে অনেকবার ব্যবহার করেছি।
javascript
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)
}
toAmount()ফাংশন একটি পরিবর্তনশীল পরিবর্তনs, নির্ভুলতা পরামিতি অনুযায়ীdecimalsএকটি (নিচে) রূপান্তর সম্পাদন করুন। ওয়েব 3 এর প্রকৃত বিকাশে, চেইনের কিছু হেক্সাডেসিমেল ডেটা প্রক্রিয়া করার জন্য প্রায়ই প্রয়োজন হয়।
আমরা প্রায়ই আমাদের পূর্ববর্তী কোর্সে এটির সম্মুখীন হই, যেমন স্মার্ট চুক্তিTransfer(address,address,uint256)ইভেন্টেdataক্ষেত্রের তথ্য:
desc
{
"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000",
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a80", "0x000000000000000000000000bcb095c1f9c3dc02e834976706c87dee5d0f1fb6"],
"transactionHash": "0x27f9bf5abe3148169b4b85a83e1de32bd50eb81ecc52e5af006157d93353e4c4",
"transactionIndex": "0x0",
"removed": false,
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
"blockNumber": "0x109b1cc",
"logIndex": "0x0"
}
ডেটা প্রক্রিয়া করুন"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000", এই সময় ব্যবহার করুনtoAmount()ফাংশন এই ধরনের প্রসেসিং ডিজাইন খুব ভালোভাবে পরিচালনা করতে পারেdataফিল্ড ডেটা পঠনযোগ্য মানগুলিতে রূপান্তরিত হয়।
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
var data = "0x00000000000000000000000000000000000000000000000001c1a55000000000"
Log(toAmount(data, 18)) // 打印出 0.12656402755905127
}
1 ETH টোকেন আমরা জানি1e18 wei, আমরা যদি একটি পেতেweiইউনিটে ডেটা126564027559051260কিভাবে ETH টোকেন সংখ্যা রূপান্তর করতে?
ব্যবহারtoAmount(, 18)ফাংশন সহজে রূপান্তর করা যেতে পারে.toInnerAmount()ফাংশনটি হলtoAmount()ফাংশনের বিপরীত অপারেশন (নির্ভুলতা, পরিবর্ধন অনুসারে), এই দুটি ফাংশন ব্যবহার করে, ডেটা রূপান্তর করা খুবই সুবিধাজনক।
এটি লক্ষ করা উচিত যে জাভাস্ক্রিপ্ট ভাষায় পূর্ণসংখ্যার মানগুলির নিরাপদ পরিসরNumber.MAX_SAFE_INTEGER, নিম্নলিখিত উদাহরণটি ডেটা রূপান্তরের ক্ষেত্রে আরও লুকানো সমস্যাটি চিত্রিত করে:
javascript
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)
}
function main() {
var amount = 0.01
var innerAmount = Number(toInnerAmount(amount, 18))
Log("Number.MAX_SAFE_INTEGER:", Number.MAX_SAFE_INTEGER) // 9007199254740991
Log("innerAmount:", innerAmount) // 10000000000000000
Log("typeof(innerAmount):", typeof(innerAmount), ", innerAmount:", innerAmount)
// 十进制数值 10000000000000000 -> 十六进制数值 0x2386f26fc10000
Log("转换", innerAmount, "为十六进制:", innerAmount.toString(16))
Log("转换", BigInt(10000000000000000).toString(10), "为十六进制:", BigInt(10000000000000000).toString(16))
Log("0x" + BigInt(10000000000000000).toString(16), "转换为10进制:", toAmount("0x" + BigInt(10000000000000000).toString(16), 0))
}
ডিবাগিং টুলে চালানো যেতে পারে:
run
2023-06-15 16:21:40 信息 0x2386f26fc10000 转换为10进制: 10000000000000000
2023-06-15 16:21:40 信息 转换 10000000000000000 为十六进制: 2386f26fc10000
2023-06-15 16:21:40 信息 转换 10000000000000000 为十六进制: 10000000000000000
2023-06-15 16:21:40 信息 typeof(innerAmount): number , innerAmount: 10000000000000000
2023-06-15 16:21:40 信息 innerAmount: 10000000000000000
2023-06-15 16:21:40 信息 Number.MAX_SAFE_INTEGER: 9007199254740991
পর্যবেক্ষণের মাধ্যমে আমরা পেয়েছি:
javascript
Log("转换", innerAmount, "为十六进制:", innerAmount.toString(16))
কোডের এই লাইনের সাথে সম্পর্কিত লগ আউটপুট:转换 10000000000000000 为十六进制: 10000000000000000, এটি সঠিকভাবে রূপান্তরিত হয়নি। কারণ স্বাভাবিকভাবেই কারণ 10000000000000000 ছাড়িয়ে গেছেNumber.MAX_SAFE_INTEGER。
কিন্তু যখন দশমিক মান নিরাপদ সীমার মধ্যে থাকে, অর্থাৎ এর চেয়ে কমNumber.MAX_SAFE_INTEGERঘন্টা,toString(16)ফাংশন রূপান্তর আবার স্বাভাবিক, উদাহরণস্বরূপ:
javascript
function main() {
var value = 1000
Log("把value转换为十六进制:", "0x" + value.toString(16)) // 0x3e8
Log("把0x3e8转换为十进制:", Number("0x3e8")) // 1000
}
এমনকি ব্লকচেইন ক্ষেত্রেও0.01ETH রূপান্তরিতweiইউনিটে মান10000000000000000ছাড়িয়ে যাবেNumber.MAX_SAFE_INTEGER, তাই এই ধরনের ক্ষেত্রে একটি নিরাপদ রূপান্তর হল:BigInt(10000000000000000).toString(16)。
মক কল
Ethereum-এ লেনদেন সম্পাদন করুন এবং স্মার্ট চুক্তি কল করুনWriteপদ্ধতিগুলির জন্য একটি নির্দিষ্ট পরিমাণ গ্যাসের প্রয়োজন হয় এবং কখনও কখনও ব্যর্থতার ঝুঁকি থাকে। সেগুলি পাঠানো বা কল করার আগে কোন লেনদেনগুলি ব্যর্থ হওয়ার সম্ভাবনা রয়েছে তা জানা গুরুত্বপূর্ণ৷ পরীক্ষার জন্য ইথেরিয়ামে একটি সিমুলেটেড কল পদ্ধতি রয়েছে।
eth_call
Ethereum এর RPC পদ্ধতিeth_call: এটি একটি লেনদেন অনুকরণ করতে পারে এবং সম্ভাব্য লেনদেনের ফলাফল ফেরত দিতে পারে, কিন্তু এটি আসলে ব্লকচেইনে লেনদেন সম্পাদন করবে না।
eth_callপদ্ধতিটির 2টি পরামিতি রয়েছে, প্রথম প্যারামিটারটি একটি অভিধান কাঠামো,transactionObject:
javascript
// transactionObject
{
"from" : ..., // The address from which the transaction is sent
"to" : ..., // The address to which the transaction is addressed
"gas" : ..., // The integer of gas provided for the transaction execution
"gasPrice" : ..., // The integer of gasPrice used for each paid gas encoded as hexadecimal
"value" : ..., // The integer of value sent with this transaction encoded as hexadecimal
"data" : ..., // The hash of the method signature and encoded parameters. For more information, see the Contract ABI description in the Solidity documentation
}
দ্বিতীয় প্যারামিটার হলblockNumber: ট্যাগ পাস করতে পারেনlatest/pending/earliestঅপেক্ষা করুন:
javascript
/* blockNumber
The block number in hexadecimal format or the string latest, earliest, pending, safe or
finalized (safe and finalized tags are only supported on Ethereum, Gnosis, Arbitrum,
Arbitrum Nova and Avalanche C-chain), see the default block parameter description in
the official Ethereum documentation
*/
পরবর্তীতে আমরা টোকেন ব্যবহার করিDAIস্মার্ট চুক্তি পদ্ধতিapprove、transferকল অনুকরণ করার জন্য একটি উদাহরণ হল নিম্নলিখিত পরীক্ষা পরিবেশ হল Ethereum প্রধান নেটওয়ার্ক।
অনুকরণ কলিং অনুমোদন
ERC20 চুক্তির জন্যapproveআমরা সবাই পদ্ধতির সাথে পরিচিত এবং পূর্ববর্তী কোর্সে এটি অনুশীলন করেছি। যেহেতু ERC20 চুক্তিটি FMZ প্ল্যাটফর্ম ABI-তে তৈরি করা হয়েছে, তাই সিমুলেটেড এবং কল করার জন্য স্মার্ট চুক্তির ABI নিবন্ধন করার প্রয়োজন নেই।
javascript
function main() {
var contractAddressUniswapV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
// encode approve
var data = exchange.IO("encode", contractAddress_DAI, "approve(address,uint256)",
contractAddressUniswapV3SwapRouterV2, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
Log("ERC20 token DAI approve encode, data:", data)
var transactionObject = {
"from" : wallet,
"to" : contractAddress_DAI,
// "gasPrice" : "0x" + parseInt("21270894680").toString(16),
// "gas" : "0x" + parseInt("21000").toString(16),
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
Log("ret:", ret)
}
উদাহরণের কোডটি প্রথমে থাকবেapprove(address,uint256)পদ্ধতি এবং পরামিতি এনকোড করা হয়,approveপদ্ধতির প্যারামিটারের মান0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffঅনুমোদনের সর্বোচ্চ সংখ্যা নির্দেশ করে। স্মার্ট চুক্তি অনুমোদন, ঠিকানা0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45এখনইUniswap V3রাউটিং চুক্তি। অবশেষে Ethereum RPC পদ্ধতিতে কল করুনeth_callসিমুলেশন সঞ্চালন. দেখা যায়transactionObjectপ্যারামিটারেgasPrice、gasক্ষেত্রগুলি বাদ দেওয়া যেতে পারে।
ডিবাগিং টুল রান করে এবং সফলভাবে অনুমোদন করার জন্য অনুমোদন পদ্ধতিকে কল করার অনুকরণ করে (এটি আসলে অনুমোদন করে না):
run
2023-06-09 11:58:39 信息 ret: 0x0000000000000000000000000000000000000000000000000000000000000001
2023-06-09 11:58:39 信息 ERC20 token DAI approve encode, data: 095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
আমরা যখন সামঞ্জস্য করি তখন আমরা কিছু ব্যর্থতার পরিস্থিতিও অনুকরণ করতে পারিgasPriceএবংgasপ্যারামিটার, যদি মানিব্যাগে থাকা ETH গ্যাস ফি প্রদানের জন্য যথেষ্ট না হয়, একটি ত্রুটি রিপোর্ট করা হবে:
insufficient funds
খুব কম গ্যাস ফি সেট করার সময়, একটি ত্রুটি রিপোর্ট করা হবে:
intrinsic gas too low: have 21000, want 21944 (supplied gas 21000)
কলিং স্থানান্তর অনুকরণ
ERC20 এর জন্যtransferপদ্ধতিটি আমাদের কাছে অপরিচিত নয়।
javascript
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
var walletVitalik = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
// 转账给V神
var decimals_DAI = exchange.IO("api", contractAddress_DAI, "decimals")
var transferAmount = toInnerAmount(1000, decimals_DAI)
Log("转账金额:", 1000, "DAI, 使用 toInnerAmount 转换为:", transferAmount)
// encode transfer
var data = exchange.IO("encode", contractAddress_DAI, "transfer(address,uint256)",
walletVitalik, transferAmount)
var transactionObject = {
"from" : wallet,
"to" : contractAddress_DAI,
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
return ret
}
যেহেতু আমার টেস্ট ওয়ালেটে DAI টোকেন নেই, তাই ডিবাগিং টুলে এটি চালানোর ফলাফল একটি প্রত্যাশিত ত্রুটি:
execution reverted: Dai/insufficient-balance
ভি ঈশ্বরের এই মানিব্যাগ ঠিকানা দেখুন:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045দেখা যায় যে এই ওয়ালেটে DAI টোকেন রয়েছে। তাহলে আসুন সিমুলেটেড কলের ট্রান্সফার ডিরেকশন রিভার্স করি এবং ভি গড ট্রান্সফারিং 1000DAI আমাদের কাছে সিমুলেট করি।
কোড পরিবর্তন করুন এবং পরিবর্তিত জায়গায় মন্তব্য করুন:
javascript
function toInnerAmount(n, decimals) {
return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
var walletVitalik = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
var contractAddress_DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"
var wallet = exchange.IO("address")
var decimals_DAI = exchange.IO("api", contractAddress_DAI, "decimals")
var transferAmount = toInnerAmount(1000, decimals_DAI)
Log("转账金额:", 1000, "DAI, 使用 toInnerAmount 转换为:", transferAmount)
// encode transfer
var data = exchange.IO("encode", contractAddress_DAI, "transfer(address,uint256)",
wallet, transferAmount) // 使用wallet变量作为参数,转账接收方地址改为我自己
var transactionObject = {
"from" : walletVitalik, // 使用walletVitalik变量作为from字段的值,模拟这个调用是由V神钱包地址发出
"to" : contractAddress_DAI,
"data" : "0x" + data,
}
var blockNumber = "latest"
var ret = exchange.IO("api", "eth", "eth_call", transactionObject, blockNumber)
Log(ret)
}
ডিবাগিং টুল পরীক্ষা:
javascript
2023-06-09 13:34:31 信息 0x0000000000000000000000000000000000000000000000000000000000000001
2023-06-09 13:34:31 信息 转账金额: 1000 DAI, 使用 toInnerAmount 转换为: 1000000000000000000000
উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্ম ব্যবহার করে, আপনি সহজেই লেনদেনের ফলাফল অনুকরণ করতে পারেন এবং ব্যর্থ হতে পারে এমন লেনদেন প্রেরণের কারণে অপ্রয়োজনীয় গ্যাস খরচের ক্ষতি এড়াতে পারেন। আমরা এই অধ্যায়ে উদাহরণ কোডটি ব্যবহার করেছি বুটেরিনের ওয়ালেটে অর্থ স্থানান্তর করতে এবং বুটেরিনের ওয়ালেট থেকে আমাদের কাছে অর্থ স্থানান্তর করতে কলগুলিকে অনুকরণ করতে। অবশ্যই, এইeth_callপদ্ধতির জন্য আরো অনেক ব্যবহার আছে। আপনার কল্পনা ব্যবহার করুন এবং আপনি হবেeth_callপদ্ধতিটি কোথায় ব্যবহৃত হয়?
ERC721 চুক্তি চিহ্নিত করুন
আমরা জানি যে ETH এবং BTC-এর মতো টোকেন হল সমজাতীয় টোকেন আপনার হাতে থাকা টোকেন আমার হাতে থাকা টোকেন থেকে আলাদা নয়৷ কিন্তু পৃথিবীতে এমন অনেক জিনিস রয়েছে যা সমজাতীয় নয়, যেমন রিয়েল এস্টেট, এন্টিকস, ভার্চুয়াল আর্ট ইত্যাদি, যা সমজাতীয় টোকেন দ্বারা বিমূর্তভাবে উপস্থাপন করা যায় না। অতএব, অ-ছত্রাকযোগ্য বস্তুগুলিকে বিমূর্ত করার জন্য ERC721 মান আছে এবং NFT এবং সম্পর্কিত ধারণা রয়েছে।
সুতরাং ইথেরিয়ামে স্থাপন করা অনেক স্মার্ট চুক্তির মধ্যে, আমরা কীভাবে সনাক্ত করব কোন স্মার্ট চুক্তিগুলি ERC721 স্ট্যান্ডার্ড স্মার্ট চুক্তি?
ERC721 সনাক্ত করতে, আপনাকে প্রথমে ERC165 মান বুঝতে হবে।
ERC165
ERC165 স্ট্যান্ডার্ডের মাধ্যমে, একটি স্মার্ট চুক্তি অন্য চুক্তিগুলি পরীক্ষা করার জন্য সমর্থন করে এমন ইন্টারফেসগুলি ঘোষণা করতে পারে। ERC165 ইন্টারফেস চুক্তির শুধুমাত্র একটি ফাংশন আছে:supportsInterface(bytes4 interfaceId),পরামিটারinterfaceIdঅর্থাৎ ইন্টারফেস আইডি থেকে প্রশ্ন করতে হবে। যদি চুক্তিটি ইন্টারফেস আইডি প্রয়োগ করে একটি বুলিয়ান সত্য মান প্রদান করে, অন্যথায় এটি একটি মিথ্যা মান প্রদান করে।
পরবর্তী আমরা এই সম্পর্কে কথা বলতে যাচ্ছিinterfaceIdবিশেষভাবে কিভাবে গণনা এবং কোড.
ERC165 স্ট্যান্ডার্ডএকটি উদাহরণ দেওয়া হল:
solidity
pragma solidity ^0.4.20;
interface Solidity101 {
function hello() external pure;
function world(int) external pure;
}
contract Selector {
function calculateSelector() public pure returns (bytes4) {
Solidity101 i;
return i.hello.selector ^ i.world.selector;
}
}
ইন্টারফেসের ফাংশন স্বাক্ষরে একটি XOR অপারেশন সম্পাদন করুন (ফাংশনের নাম এবং পরামিতি টাইপ তালিকা নিয়ে গঠিত) ERC165 ইন্টারফেস চুক্তির জন্য যেখানে চুক্তির শুধুমাত্র একটি ফাংশন রয়েছে:
solidity
pragma solidity ^0.4.20;
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
The interface identifier for this interface is 0x01ffc9a7. You can calculate this by running bytes4(keccak256('supportsInterface(bytes4)')); or using the Selector contract above.
সরাসরি ফাংশন স্বাক্ষর গণনা করুন এবং ফলাফল পেতে প্রথম 4 বাইট নিন:interfaceId。
javascript
function main() {
var ret = Encode("keccak256", "string", "hex", "supportsInterface(bytes4)")
Log("supportsInterface(bytes4) interfaceId:", "0x" + ret.slice(0, 8))
}
পরীক্ষাগুলি ডিবাগিং সরঞ্জামগুলিতে চালানো যেতে পারে:
run
2023-06-13 14:53:35 信息 supportsInterface(bytes4) interfaceId: 0x01ffc9a7
আপনি গণনা করা ফলাফল দেখতে পারেন এবংERC165 স্ট্যান্ডার্ডনথিতে বর্ণনা সামঞ্জস্যপূর্ণ।
ERC721
এর পরে, আসুন ERC721 চুক্তির স্ট্যান্ডার্ডের ইন্টারফেস সংজ্ঞাটি দেখি:
solidity
interface ERC721 /* is ERC165 */ {
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
যদি আমরা একটি স্মার্ট চুক্তি একটি ERC721 চুক্তি কিনা তা নির্ধারণ করতে চাই, আমাদের প্রথমে ERC721 চুক্তিটি জানতে হবেinterfaceId, এবং তারপর ব্যবহার করার চেষ্টা করুনsupportsInterface(bytes4 interfaceId)পদ্ধতি থেকে বিচার করে, আমরা ইতিমধ্যেই পূর্ববর্তী কোর্সে ERC165 স্ট্যান্ডার্ডের কিছু ধারণা এবং গণনার সাথে পরিচিত।interfaceIdঅ্যালগরিদম, আমরা গণনা করতে সরাসরি কোড লিখি:
javascript
function calcSelector(arrSelector) {
var ret = null
if (Array.isArray(arrSelector)) {
if (arrSelector.length == 1) {
ret = Encode("keccak256", "string", "hex", arrSelector[0])
} else if (arrSelector.length == 0) {
throw "错误:数组中元素个数为0"
} else {
var viewEncodeData = null
for (var i = 0; i < arrSelector.length; i++) {
if (i == 0) {
ret = new Uint8Array(Encode("keccak256", "string", "raw", arrSelector[i]))
} else {
viewData = new Uint8Array(Encode("keccak256", "string", "raw", arrSelector[i]))
if (viewData.length != ret.length) {
throw "错误:TypeArray view长度不同"
}
for (var index = 0; index < ret.length; index++) {
ret[index] ^= viewData[index]
}
}
}
ret = Encode("raw", "raw", "hex", ret.buffer)
}
} else {
throw "错误:参数需要数组类型。"
}
return "0x" + ret.slice(0, 8)
}
function main() {
// supportsInterface(bytes4): 0x01ffc9a7
// var ret = calcSelector(["supportsInterface(bytes4)"])
// ERC721Metadata: 0x5b5e139f
/*
var arrSelector = [
"name()",
"symbol()",
"tokenURI(uint256)"
]
var ret = calcSelector(arrSelector)
*/
// ERC721: 0x80ac58cd
// /*
var arrSelector = [
"balanceOf(address)",
"ownerOf(uint256)",
"safeTransferFrom(address,address,uint256,bytes)",
"safeTransferFrom(address,address,uint256)",
"transferFrom(address,address,uint256)",
"approve(address,uint256)",
"setApprovalForAll(address,bool)",
"getApproved(uint256)",
"isApprovedForAll(address,address)",
]
var ret = calcSelector(arrSelector)
// */
Log(ret)
}
কোডটি ব্যবহার করেEncode()ফাংশন ফাংশন স্বাক্ষর গণনা সম্পাদন করে (keccak256অ্যালগরিদম), উপরের কোড উদাহরণে গণনার জন্য, নির্দিষ্ট করুনEncode()ফাংশনের আউটপুট প্যারামিটারগুলি হল"raw", ফাংশন রিটার্ন করেJavaScriptভাষাগতArrayBufferটাইপ
আপনি যদি দুটি তুলনা করতে চানArrayBufferবস্তু^(XOR) অপারেশন, উপর ভিত্তি করে করা প্রয়োজনArrayBufferবস্তু সৃষ্টিTypedArrayদেখুন, এবং তারপর এটিতে থাকা ডেটার মাধ্যমে পুনরাবৃত্তি করুন এবং একের পর এক XOR ক্রিয়াকলাপ সম্পাদন করুন।
ডিবাগিং টুলে চালান:
run
2023-06-13 15:04:09 信息 0x80ac58cd
আপনি গণনা করা ফলাফল দেখতে পারেন এবংeip-721-এ বর্ণিত একই রকম।
solidity
pragma solidity ^0.4.20;
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface ERC721 /* is ERC165 */ {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
...
ERC721 ইন্টারফেস আইডির সাহায্যে আমরা নির্ধারণ করতে পারি যে কোনও চুক্তি ERC721 স্ট্যান্ডার্ড চুক্তি কিনা। আমরা ব্যবহার করিBAYCপরীক্ষার জন্য, এটি একটি চুক্তি যা ERC721 অনুসরণ করে প্রথমে আমাদের ABI নিবন্ধন করতে হবে, যেহেতু আমরা শুধুমাত্র নিম্নলিখিত তিনটি পদ্ধতিতে নিবন্ধন করতে পারি:
- supportsInterface(interfaceId)
- symbol()
- name()
নির্দিষ্ট কোড নিম্নরূপ:
javascript
function main() {
// ERC721的合约地址,这里用的BAYC
var testContractAddress = "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
var testABI = `[{
"inputs": [{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}],
"name": "supportsInterface",
"outputs": [{
"internalType": "bool",
"name": "",
"type": "bool"
}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [],
"name": "symbol",
"outputs": [{
"internalType": "string",
"name": "",
"type": "string"
}],
"stateMutability": "view",
"type": "function"
}, {
"inputs": [],
"name": "name",
"outputs": [{
"internalType": "string",
"name": "",
"type": "string"
}],
"stateMutability": "view",
"type": "function"
}]`
// ERC721接口Id,在之前的课程中计算得出
var interfaceId = "0x80ac58cd"
// 注册ABI
exchange.IO("abi", testContractAddress, testABI)
// 调用supportsInterface方法
var isErc721 = exchange.IO("api", testContractAddress, "supportsInterface", interfaceId)
// 输出信息
Log("合约地址:", testContractAddress)
Log("合约名称:", exchange.IO("api", testContractAddress, "name"))
Log("合约代号:", exchange.IO("api", testContractAddress, "symbol"))
Log("合约是否为ERC721标准:", isErc721)
}
পরীক্ষাগুলি ডিবাগিং সরঞ্জামগুলিতে চালানো যেতে পারে:
run
2023-06-13 16:32:57 信息 合约是否为ERC721标准: true
2023-06-13 16:32:57 信息 合约代号: BAYC
2023-06-13 16:32:57 信息 合约名称: BoredApeYachtClub
2023-06-13 16:32:57 信息 合约地址: 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d
ঠিকানা নির্ধারণ করুন0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13dচুক্তিটি ERC721 স্ট্যান্ডার্ড।
এই বক্তৃতায়, আমরা ERC721 চুক্তিগুলিকে কীভাবে চিহ্নিত করতে পারি যেগুলি ERC165 মানকে সমর্থন করে না, তাদের সনাক্ত করার জন্য অন্যান্য পদ্ধতিগুলি ব্যবহার করা আবশ্যক৷ আপনি কি জানেন কিভাবে একটি চুক্তি ERC20 স্ট্যান্ডার্ড কিনা তা পরীক্ষা করতে হয়?
কলডেটা এনকোডিং
কিcalldata? লেখকের বোধগম্যতা অনুসারে, এখানে সহজ এবং জনপ্রিয় বর্ণনাটি হল:
"Calldata" হল একটি নির্দিষ্ট ফাংশন কলের এনকোডিং এবং Ethereum-এ "Calldata" চুক্তির স্পেসিফিকেশন (Application Binary Interface) অনুযায়ী এনকোড করা হয়
উদাহরণস্বরূপ, আমরা পূর্ববর্তী কোর্সে অধ্যয়ন করা ERC20 চুক্তিটি নিতে পারিbalanceOf、transferমেথড কল, কল করার সময় পরামিতি সহ, a এ এনকোড করা হয়calldata. কিছু অ্যাপ্লিকেশন পরিস্থিতিতে, উদাহরণস্বরূপ:চুক্তির মধ্যে মিথস্ক্রিয়া, এই দৃশ্যে ব্যবহার করা হবেcalldata, অবশ্যই এখানে তালিকাভুক্ত নয় এমন আরও অনেক অ্যাপ্লিকেশন পরিস্থিতি রয়েছে।
পেতে একটি স্মার্ট চুক্তি ফাংশন কল কোড কিভাবেcalldata?
উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্মে ব্যবহার করা যেতে পারেexchange.IO("encode", ...)এনকোডিং স্মার্ট কন্ট্রাক্ট ফাংশন কল ব্যবহার করা খুব সহজ।exchange.IO("encode", ...)ফাংশনের প্রথম প্যারামিটারটি একটি নির্দিষ্ট স্ট্রিং"encode"; দ্বিতীয় প্যারামিটারটি হল স্মার্ট চুক্তির ঠিকানা; তৃতীয় প্যারামিটারটি হল এনকোড করা স্মার্ট চুক্তি পদ্ধতির নাম; বাকি প্যারামিটারগুলি এনকোড করা স্মার্ট চুক্তি পদ্ধতির নির্দিষ্ট প্যারামিটার মানগুলিতে পাস করে।
eth_sendRawTransaction
যখন আমরা একটি স্মার্ট কন্ট্রাক্ট মেথড কোড করি তখন কল করি এবং সংশ্লিষ্ট জেনারেট করিcalldataডেটা, যদি এই স্মার্ট চুক্তি পদ্ধতিটি একটি লেখার পদ্ধতি হয় (যেমন: রাইটিং অপারেশন), আমাদের তৈরি করতে হবেcalldataলেনদেনের ডেটা ফিল্ড হিসেবে ডেটা ব্যবহার করা হয়, এবং তারপর ইথেরিয়ামের RPC পদ্ধতি ব্যবহার করা হয়।eth_sendRawTransactionEthereum নেটওয়ার্কে লেনদেনের কাঁচা ডেটা সম্বলিত একটি অনুরোধ পাঠান।
eth_sendRawTransactionপদ্ধতির শুধুমাত্র একটি প্যারামিটার আছেdata:
data: The signed transaction (typically signed with a library, using your private key)
এইdataপরামিতি হল স্বাক্ষর গণনার পরে একটি লেনদেন ডেটা Ethereum এর লেনদেন ডেটা কাঠামোতে প্রধানত নিম্নলিখিত ক্ষেত্রগুলি রয়েছে:
javascript
{
"nonce": "0x1", // 交易发送方的账户交易次数
"gasPrice": "0x12a05f200", // 交易的Gas价格
"gasLimit": "0x5208", // 交易的Gas限制
"to": "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2", // 目标合约地址或接收方地址
"value": "0x4563918244F40000", // 转账的以太币数量
"data": "0x0123456789ABCDEF", // 要发送给合约的数据
}
কিভাবে একটি Ethereum লেনদেন সাইন ইন করবেন?
উদ্ভাবক পরিমাণগত ট্রেডিং প্ল্যাটফর্মে আমরা ব্যবহার করিEncode()সিগনেচার ক্যালকুলেশন করার ফাংশন আমরা পরবর্তী কোর্সে নির্দিষ্ট উদাহরণ লিখব "Executing Write method calldata"।
রিড মেথড কলডেটা এক্সিকিউট করুন
রিড পদ্ধতির জন্যcalldataকার্যকর করার জন্য, আমরা RPC পদ্ধতি ব্যবহার করি যা আমরা আগে শিখেছি:eth_callচালানোর জন্য, আমরা আগে ব্যাখ্যাeth_callএই Ethereum RPC পদ্ধতি শুধুমাত্র স্মার্ট চুক্তি করেWriteএই অধ্যায়ে ব্যবহৃত পদ্ধতির প্রদর্শনcalldataস্মার্ট কন্ট্রাক্টের রিড মেথডে কলের কার্য সম্পাদন প্রদর্শন করুন। আসুন WETH চুক্তিটি ব্যবহার করিbalanceOfবর্তমান ওয়ালেটের WETH টোকেন ব্যালেন্স পড়ার পদ্ধতি।
আমরা Ethereum মেইননেট পরীক্ষা করার জন্য ডিবাগিং টুল ব্যবহার করি:
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
// WETH合约的ABI
var abiWETH = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]`
// WETH合约地址
var wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
// 注册WETH合约的ABI
exchange.IO("abi", wethAddress, abiWETH)
// 当前配置的交易所对象的钱包地址
var walletAddress = exchange.IO("address")
// 编码WETH合约的deposit方法调用
var calldataForDeposit = exchange.IO("encode", wethAddress, "balanceOf(address)", walletAddress)
Log("calldataForDeposit:", "0x" + calldataForDeposit)
// 构造transaction,作为eth_call的第一个参数
var transaction = {
"from" : walletAddress,
"to" : wethAddress,
"data" : "0x" + calldataForDeposit,
}
// eth_call的第二个参数
var blockNumber = "latest"
// 使用eth_call调用
var ret = exchange.IO("api", "eth", "eth_call", transaction, blockNumber)
var wethBalance = exchange.IO("decode", "uint256", ret) // 可以使用exchange.IO("decode", ...) 函数解码
Log("wethBalance:", toAmount(wethBalance, 18)) // 从以wei为单位,换算成WETH个数为单位
}
ডিবাগিং টুলে চালান:
run
2023-06-15 11:51:31 信息 wethBalance: 0.015
2023-06-15 11:51:31 信息 calldataForDeposit: 0x70a082310000000000000000000000006b3f11d807809b0b1e5e3243df04a280d9f94bf4
যদি স্মার্ট চুক্তি পদ্ধতিতে একটি রিটার্ন মান থাকে, আপনি ব্যবহার করতে পারেনexchange.IO("decode", ...)ফাংশন ডিকোডিং। এটি পাস করে দেখা যায়calldataপদ্ধতি এবং সরাসরি স্মার্ট চুক্তি কলbalanceOfপদ্ধতিটি একই, এবং আমার টেস্ট ওয়ালেটের WETH ব্যালেন্স 0.015 WETH।
কলডাটা লিখুন পদ্ধতি চালান
রাইট পদ্ধতির কলডেটা সম্পাদনের জন্য, আপনাকে RPC পদ্ধতি ব্যবহার করতে হবে:eth_sendRawTransaction.
আমরা Ethereum মেইননেট পরীক্ষা করার জন্য ডিবাগিং টুল ব্যবহার করি:
javascript
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
// WETH合约的ABI
var abiWETH = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]`
// WETH合约地址
var wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
// 注册WETH合约的ABI
exchange.IO("abi", wethAddress, abiWETH)
// 当前配置的交易所对象的钱包地址
var walletAddress = exchange.IO("address")
// 编码WETH合约的deposit方法调用
var calldataForDeposit = exchange.IO("encode", wethAddress, "deposit")
Log("calldataForDeposit:", "0x" + calldataForDeposit)
// 获取nonce
var nonce = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
// 获取gasPrice
var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
// 调用deposit方法把ETH换为WETH,需要转账ETH,这里把0.01ETH转换为以wei为单位的十六进制数值
var innerAmount = BigInt(Number(toInnerAmount(0.005, 18))).toString(16)
// The transaction call object:
var obj = {
"from" : walletAddress,
"to" : wethAddress,
"gasPrice" : gasPrice,
"value" : "0x" + innerAmount,
"data" : "0x" + calldataForDeposit,
}
// 计算gasLimit
var gasLimit = exchange.IO("api", "eth", "eth_estimateGas", obj)
// 构造交易
var transaction = {
"to": wethAddress,
"value": toAmount("0x" + innerAmount, 0), // 转换为10进制
"data": "0x" + calldataForDeposit,
"gasLimit": toAmount(gasLimit, 0), // 转换为10进制
"gasPrice": toAmount(gasPrice, 0), // 转换为10进制
"nonce": toAmount(nonce, 0), // 转换为10进制
"chainId": 1, // 以太坊主网Id
}
Log("transaction:", transaction)
// 签名,your key 替换为你的私钥
var signedTx = Encode("signTx", "string", "hex", JSON.stringify(transaction), "hex", "0x" + "your key")
Log("signedTx:", "0x" + signedTx)
// 调用eth_sendRawTransaction发送交易
var ret = exchange.IO("api", "eth", "eth_sendRawTransaction", "0x" + signedTx)
return ret
}
ডিবাগিং টুলে চালান:
run
2023-06-15 09:58:50 信息 signedTx: 0xf86f4f8504202067888...
2023-06-15 09:58:50 信息 transaction: {"to":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","value":5000000000000000,"data":"0xd0e30db0","gasLimit":27938,"gasPrice":17718863752,"nonce":79,"chainId":1}
2023-06-15 09:58:50 信息 calldataForDeposit: 0xd0e30db0
বাস্তবায়নvar ret = exchange.IO("api", "eth", "eth_sendRawTransaction", "0x" + signedTx)ফাংশন, ফেরত লেনদেন হ্যাশ হল:0x2ff585504b0fe59b0122f696e8808abfe2f3ce263448066533f3bb8a4f55e8e6. এইeth_sendRawTransactionকলডেটা কার্যকর করা হয় এবং WETH চুক্তি বলা হয়।depositপাঠানো 0.005 ETH-কে WETH-এ বিনিময় করার পদ্ধতি।
মেমপুলের কথা শুনুন
ইথেরিয়ামে ব্যবহারকারীর লেনদেন খনি শ্রমিকদের দ্বারা ইথেরিয়াম ব্লকচেইনে প্যাকেজ করার আগে, সমস্ত লেনদেন এখানে একত্রিত হবেMempool(লেনদেন মেমরি পুল), "মানিরা" খনির সুবিধাগুলি সর্বাধিক করার জন্য প্রথমে প্যাকেজ করা উচ্চ-মূল্যের লেনদেনগুলি সন্ধান করতে এখানে রয়েছে৷ অতএব, সাধারণত একটি লেনদেনের গ্যাসপ্রাইস সেটিং যত বেশি হবে, প্যাকেজ করা তত সহজ হবে।
কিছু ট্রেডিং স্ক্রিপ্ট এছাড়াও হবেMempoolকিছু লাভজনক ডিল খুঁজে পাওয়ার আশায় শুঁকে যান। উদাহরণস্বরূপ, যদি একটি লেনদেনের একটি বিনিময় স্লিপেজ থাকে যা খুব বেশি হয়, তাহলে এই লেনদেন স্ক্রিপ্টগুলি দ্বারা লেনদেন "স্যান্ডউইচ আক্রমণ" হতে পারে। তাহলে এই স্ক্রিপ্টগুলো কিভাবে মনিটর করবেনMempoolমধ্যেpending(মুলতুবি, প্যাকেজ করা হবে) লেনদেন সম্পর্কে কি?
REST প্রোটোকল ব্যবহার করে শোনা
আমরা আগে শিখেছি RPC পদ্ধতি ব্যবহার করুন:eth_getBlockByNumber, কিন্তু আমরা এই সময় নির্দিষ্ট তথ্য প্রেরণ করছি না.blockNumber, আমরা ব্যবহার করি"pending"লেবেল।
javascript
function main() {
var data = exchange.IO("api", "eth", "eth_getBlockByNumber", "pending", true)
if (Array.isArray(data.transactions)) {
for (var i = 0; i < data.transactions.length; i++) {
Log(data.transactions[i])
}
}
}
ডিবাগিং টুলে চালান:
run
2023-06-18 19:23:05 信息 {"blockNumber":"0x10b2027","type":"0x2","accessList":[],"blockHash":"0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89","from":"0xd50521974d62f1fa34b8e81cb742ccf6147d05ff","gasPrice":"0x32ea2db37","hash":"0xf8f10f8f473c340b021298feb48d0affe529e8737a309c4cc1902e8989ef0914","input":"0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001","v":"0x0","value":"0x0","maxFeePerGas":"0x48a413364","maxPriorityFeePerGas":"0x5f5e100","nonce":"0x8","r":"0x8c1cc36f43b02c9e9e454153588cc9d38757f1da69ec49d3cfdda74ab69e06a8","s":"0x2f3dd3e5ddf9e5d42c128a8e900026aca7568fa83c68cf332e1328066ee8d03a","transactionIndex":"0x3a","chainId":"0x1","gas":"0x1142d","to":"0x8c3c0274c33f263f0a55d129cfc8eaa3667a9e8b"}
2023-06-18 19:23:05 信息 {"input":"0x646174613a2c7b2270223a226572632d3230222c226f70223a226d696e74222c227469636b223a2265746873222c226964223a223139323732222c22616d74223a2231303030227d","nonce":"0x1d","blockHash":"0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89","from":"0xe7fa86855af674837cea1b58f88b5352543ca27b","gas":"0x81cc","gasPrice":"0x32ea2db37","to":"0xe7fa86855af674837cea1b58f88b5352543ca27b","chainId":"0x1","transactionIndex":"0x39","type":"0x2","value":"0x0","accessList":[],"blockNumber":"0x10b2027","hash":"0x55702f5d14736fc9d0c58fdac2d2052a602db171c46b5e1fa9ff6af5c277f9a2","maxFeePerGas":"0x48a413364","maxPriorityFeePerGas":"0x5f5e100","r":"0x5a703d389d23b51adf8ef0f55db8876e7392636797b68a4be6afe73e76d7e1f2","s":"0x4b4bb11257c4434a0acc2672357f8793476e4bfdf98bc30d2389ce335e7de64e","v":"0x1"}
2023-06-18 19:23:05 信息 {"gas":"0x186a0","nonce":"0x46533","r":"0xfeea052a4ac2283ca058a657a806ba0916d8e7d52d2a577f150c40eb1dfbec65","s":"0x5bf0089a3c060ba787b67a205b44e1065a0d11d132b41737ab9adf0f55066811","transactionIndex":"0x38","value":"0x78f0975742c400","blockHash":"0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89","chainId":"0x1","hash":"0x56bdf1b38e23db66e8d1c4014d1e9f690a9217d8a0232489210325fc69e25cf9","v":"0x25","input":"0x","type":"0x0","blockNumber":"0x10b2027","gasPrice":"0x4a817c800","from":"0x97b9d2102a9a65a26e1ee82d59e42d1b73b68689","to":"0xcb513e99c020e9d15a6eafef873fef5d9f078221"}
...
এক টুকরো ডেটা বের করুন:
javascript
{
"blockNumber": "0x10b2027",
"type": "0x2",
"accessList": [],
"blockHash": "0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89",
"from": "0xd50521974d62f1fa34b8e81cb742ccf6147d05ff",
"gasPrice": "0x32ea2db37",
"hash": "0xf8f10f8f473c340b021298feb48d0affe529e8737a309c4cc1902e8989ef0914",
"input": "0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001",
"v": "0x0",
"value": "0x0",
"maxFeePerGas": "0x48a413364",
"maxPriorityFeePerGas": "0x5f5e100",
"nonce": "0x8",
"r": "0x8c1cc36f43b02c9e9e454153588cc9d38757f1da69ec49d3cfdda74ab69e06a8",
"s": "0x2f3dd3e5ddf9e5d42c128a8e900026aca7568fa83c68cf332e1328066ee8d03a",
"transactionIndex": "0x3a",
"chainId": "0x1",
"gas": "0x1142d",
"to": "0x8c3c0274c33f263f0a55d129cfc8eaa3667a9e8b"
}
ওয়েবসকেট প্রোটোকল ব্যবহার করে শোনা
ইনভেনটর কোয়ান্টিটেটিভ ট্রেডিং প্ল্যাটফর্মে, আমরা ব্যবহার করিDialতৈরি করার ফাংশনWebSocketসংযুক্ত এবং দেখতে পারেনFMZ APIনথি বোঝারDialফাংশন
এই অধ্যায়ের পরীক্ষার কোডটি Ethereum প্রধান নেটওয়ার্ক পরিবেশে চলে যেহেতু এটি যোগাযোগের জন্য WebSocket প্রোটোকল ব্যবহার করে, এটি উদ্ভাবকের পরিমাণগত রিয়েল-টাইম পরীক্ষা ব্যবহার করা আরও সুবিধাজনক। ওয়েবসকেট প্রোটোকল সাবস্ক্রিপশন বার্তা হল:
javascript
{"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}
ছাড়াওnewPendingTransactions, আপনি সাবস্ক্রাইব করতে পারেনnewHeads、logs。
গ্রহণWebSocketসংযোগ দ্বারা ধাক্কা ডেটা:
javascript
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x2c5c087b4aa188e008f4747828ef4e61",
"result": "0x69c4251cecb814e17cfe7a5ee41742a616f9a4d1bbf245c49b186b1006fd14d3"
}
}
তারপর এটি অনুযায়ী:"result": "0x69c4251cecb814e17cfe7a5ee41742a616f9a4d1bbf245c49b186b1006fd14d3", আরও তদন্তtransaction. একটি নির্দিষ্ট জন্যtransactionআমরা Ethereum RPC পদ্ধতি ব্যবহার করিeth_getTransactionByHashজিজ্ঞাসা করা
javascript
var ws = null
function main () {
// {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["xxxxx"]} , "xxxxx" 是订阅的具体消息
var payload = {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}
// wss://mainnet.infura.io/ws/v3/xxxxx , "xxxxx" 是你的infura key
var infuraKey = "your key"
ws = Dial("wss://mainnet.infura.io/ws/v3/" + infuraKey + "|reconnect=true&payload=" + JSON.stringify(payload))
if (!ws) {
throw "websocket链接infura失败!"
}
// eth_getTransactionByHash 调用计数
var getTransactionCounter = 0
var beginTS = new Date().getTime()
// 循环获取消息
while (true) {
// 接收推送的消息
var data = ws.read()
if (data) {
var ts = new Date().getTime()
if (ts - beginTS >= 1000) {
getTransactionCounter = 0
beginTS = ts
}
// 根据txHash查询交易详情
if (ts - beginTS < 1000 && getTransactionCounter >= 100) {
Sleep(1000)
getTransactionCounter = 0
beginTS = ts
}
var obj = JSON.parse(data)
if (obj["params"] && obj["params"]["result"]) {
var transcationInfo = exchange.IO("api", "eth", "eth_getTransactionByHash", obj["params"]["result"])
Log(obj["params"]["result"], "transcationInfo:", transcationInfo)
}
getTransactionCounter++
}
LogStatus(_D())
}
}
function onexit() {
Log("断开WS连接")
ws.close()
}
একটি আসল ডিস্ক তৈরি করুন এবং উপরের কোডটি চালান। আপনি ওয়েবসকেট সংযোগ দ্বারা পুশ করা ডেটা পেতে পারেন। ডেটা ক্রমাগত পুশ করা হয়। আসুন তাদের মধ্যে একটি বের করি।transaction:
javascript
{
"maxPriorityFeePerGas": "0x5f5e100",
"nonce": "0x1a9",
"accessList": [],
"blockNumber": "0x10b1c9f",
"from": "0x5888700be02f52c8adf85890886ef84a6b8a7829",
"blockHash": "0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9",
"chainId": "0x1",
"gasPrice": "0x34fdbf43d",
"s": "0x7d86ae29a786a61b9e74a7a9e2cc4b39b7913aa3d4c3816ccb07528fed82048a",
"to": "0xfc2068c3d47b575a60f6a4a7bf60dea0ac368e01",
"type": "0x2",
"v": "0x1",
"value": "0x0",
"gas": "0x1aad3",
"hash": "0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22",
"input": "0x42842e0e0000000000000000000000005888700be02f52c8adf85890886ef84a6b8a7829000000000000000000000000d2d07e4d1bb0f40ac3e4aa7cc3ad05d348bfd2c3000000000000000000000000000000000000000000000000000000000000180b",
"maxFeePerGas": "0x4712d1273",
"r": "0x8ec58f95f6d9729a6eee075e6976658b6c5346cbc90eb68ac361a40af073b10e",
"transactionIndex": "0xc1"
}
উদ্ধৃত (এর অংশ বাদ দেওয়া) লগ ডেটা:
run
2023-06-18 16:20:07 信息 断开WS连接
2023-06-18 16:20:07 信息 0xba07ca903f9eafbfa7d494bb26197713034b9ca2dd3c19bc0898af3f35b59343 transcationInfo: {"accessList":[],"from":"0xe2977d60182da068dfd78693f96362ee7a2e9644","nonce":"0xf","value":"0x0","blockHash":"0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9","blockNumber":"0x10b1c9f","chainId":"0x1","hash":"0xba07ca903f9eafbfa7d494bb26197713034b9ca2dd3c19bc0898af3f35b59343","maxFeePerGas":"0x530c30b70","r":"0xf28bfdf372a5401a2e00675c6ebe8d5e73f2c955db44b1aa56240b9197d6cbc7","type":"0x2","v":"0x0","gas":"0x21079","gasPrice":"0x367b3783d","input":"0x657bb1130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001e0300000000000000000000000033c6eec1723b12c46732f7ab41398de45641fa42000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041976bd7d021a5b94cbba72b291093b50a0ecf21d1c6cd8193fbfcd685c4723ce068feb249bdcace58c28eb3b6cc647e8c839b0826c84f8dfe4c31d57d1ac1f0111b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000648ebef50000000000000000000000000000000000000000000000000000000000000000","maxPriorityFeePerGas":"0x1dcd6500","s":"0x71d51246bb60e792f963a3c75c46fd8f557921ce6face7224c944e1768a76ca","to":"0x0b51eb9d0e54c562fedc07ceba453f05b70c4b79","transactionIndex":"0x40"}
2023-06-18 16:20:07 信息 0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22 transcationInfo: {"maxPriorityFeePerGas":"0x5f5e100","nonce":"0x1a9","accessList":[],"blockNumber":"0x10b1c9f","from":"0x5888700be02f52c8adf85890886ef84a6b8a7829","blockHash":"0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9","chainId":"0x1","gasPrice":"0x34fdbf43d","s":"0x7d86ae29a786a61b9e74a7a9e2cc4b39b7913aa3d4c3816ccb07528fed82048a","to":"0xfc2068c3d47b575a60f6a4a7bf60dea0ac368e01","type":"0x2","v":"0x1","value":"0x0","gas":"0x1aad3","hash":"0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22","input":"0x42842e0e0000000000000000000000005888700be02f52c8adf85890886ef84a6b8a7829000000000000000000000000d2d07e4d1bb0f40ac3e4aa7cc3ad05d348bfd2c3000000000000000000000000000000000000000000000000000000000000180b","maxFeePerGas":"0x4712d1273","r":"0x8ec58f95f6d9729a6eee075e6976658b6c5346cbc90eb68ac361a40af073b10e","transactionIndex":"0xc1"}
2023-06-18 16:20:07 信息 0xbc42d5db10e5cb2e888c76005c522cb2474a0c0a7325feb867b618f69ff26f2a transcationInfo: {"accessList":[],"blockNumber":"0x10b1c9f","gas":"0x1cc12b","hash":"0xbc42d5db10e5cb2e888c76005c522cb2474a0c0a7325feb867b618f69ff26f2a","maxFeePerGas":"0x6ab262e5c","value":"0x0","v":"0x1","chainId":"0x1","from":"0xc1b634853cb333d3ad8663715b08f41a3aec47cc","input":"0x8f111f3c000000000000000000000000000000000000000000000000000000000003b83700000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000e0fa2000000000000000000000000e64a54e2533fd126c2e452c5fab544d80e2e4eb50000000000000000000000000000000000000000000000000000000004c6ff1c0000000000000000000000000000000000000000000000000000000004c70029000000000000000000000000000000000000000000000000000000000001822d005b1979341221e80ed20b20d832de88a8a4b535fe9990a90c165f3c95ad085ab9445c0a998c70edff76f1c2de3f4263d7e4fe3c3fb73fe7dcfbdede92371842fb883267f5408c8aaf08ba2f6c22463f19da98183d2302735615460d7380d6f9ff5e764e75bcaca9a93946cf644cd4d4448f314c4cf60cd0353f085aa0562d70e16a510b8bc4c2a09b5e7fafcd43f07dc1b5dd1782962af8f6fff7a6965bfc127e11501a72c64913d58e624333f9ec51687c7cb1bb4a9850541f1e03b2790ed4ee508052910dfe22542d900548d5243ca238811427491d49e98cf269ccab5b1724f0f9698120e406c00910c4090c0e84e0400e2706822d2a001a3964a0ca8101700a547342c2c1fff8934a988416f020a0c98f0909c7f529875f8443914e10b58145c79d38914d1fafbc9ee57ebcb377e4ac1cd252bdebe3c59e8e917fea7dbc7bf66dfc1846482a858645b95555b3ecc9ab4f9e2b0e3e78d68379b009e606a1cefe675670a5eabd5f5a2efa5d77a1084288480c98d01c70a3d8c6b854496e2a966dc9051b13b872b7c6c2c5d82676fd8e82c680514333db21db2006d23f42074021de7e61c54d88b01824d40f03d1505eb6ec6d0cb7ccd38deb821517a5e63d0e89f6bf0385f109c81ea36dd00e7a903a100290f5b47a940ed146ae9338ff8bc17a2b5bc457614d0831e743e485c0de84636b034400bf6bd192ff723045cc170e109aabf273dc9de19c9987038515b6613249f471f9ddeb31331cc1643902212d20241c417532ad7e4a9ac742b4b5f68e1019795cf9386dcf36037502c13ff51f50a2202b2c1cac1c0b38a21ec798deff778c9a6b679d16d0521d2df89c439f4f8f9425ed378f4194d03d00
2023-06-18 16:20:06 信息 0xff0945c3d682a37e18ee433d56c8bedbb93d9ac368af968ed8d53b655575e8e5 transcationInfo: {"gas":"0x5208","s":"0x63572e1fa060841b939cea0849154e55781fe0efcbdfe5ce6979b44ce0980e4a","transactionIndex":"0xa7","value":"0x113e9d515e400","blockHash":"0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9","hash":"0xff0945c3d682a37e18ee433d56c8bedbb93d9ac368af968ed8d53b655575e8e5","nonce":"0x2","r":"0x698fe26331ad39ba89c4d30985b707792ea4ab09b25205727f8fac2a6120b54a","gasPrice":"0x35458af00","from":"0x228d93af92d03184c07aa9e39b3d2d61b666686d","input":"0x","to":"0x0246177b98a5e42835cdcfaac1c274d3e6c39486","v":"0x26","blockNumber":"0x10b1c9f","type":"0x0","chainId":"0x1"}
...
লেনদেনের বিবরণ ডিকোড করুন
শেষ বক্তৃতায়, আমরা Ethereum-এ মুলতুবি লেনদেনগুলি নিরীক্ষণ করার জন্য একটি মনিটরিং প্রোগ্রাম লিখেছিলাম, WebSocket প্রোটোকলের মাধ্যমে পুশ করা লেনদেন হ্যাশ পেতে এবং তারপর লেনদেন হ্যাশের উপর ভিত্তি করে নির্দিষ্ট লেনদেনের বিশদ অনুসন্ধান করতে।
এরপরে আমাদের লেনদেনের বিবরণের ডেটা পরীক্ষা করতে হবেinputফিল্ড ডেটা আরও পার্স করা হয়।inputফিল্ড ডেটা অগোছালো হেক্সাডেসিমাল ডেটা বলে মনে হয়, কিন্তু আসলে লেনদেনের বিষয়বস্তুকে এনকোড করে: কল ফাংশন, প্রবেশ করা প্যারামিটার ইত্যাদি সহ।
বারবার এবং বিস্তৃত পরীক্ষার পরে, এটি পাওয়া গেছে যে ওয়েবসকেট সংযোগ দ্বারা পুশ করা ডেটার সময়সূচী এবং পরিমাণ বর্তমানে ব্যবহৃত RPC নোডের সাথে ঘনিষ্ঠভাবে সম্পর্কিত দুটি ভিন্ন RPC নোড পরিষেবা (যেমন infura, ALCHEMY) একই সময়ে WebSocket সংযোগ তৈরি করে। , এবং পুশ ডেটা প্রাপ্ত এটি ঠিক একই নয় যেহেতু এই বর্তমান দৃশ্যটি প্রচুর সংখ্যক অনুরোধ তৈরি করবে, এটি এখনও একটি আরও স্থিতিশীল এবং দ্রুততর RPC পরিষেবা ব্যবহার করা প্রয়োজন৷ WebSocket সংযোগটি ব্যবহার করার সময় অনেক লেনদেন হ্যাশকে পুশ করবেeth_getTransactionByHashপ্রশ্ন করার সময়, আমি প্রায়ই একটি নাল মান পাই (FMZ, node.js পরীক্ষায় পরীক্ষা করা হয়েছে)।
এই সময় আমরা ব্যবহার করিalchemyRPC নোড:wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN. এই নোডটি WebSocket প্রোটোকল এবং REST প্রোটোকল উভয়কেই সমর্থন করে।
আমরা Uniswap বিকেন্দ্রীভূত বিনিময়ের রাউটিং স্মার্ট চুক্তি নিরীক্ষণ করিmulticall(uint256,bytes[])পদ্ধতি, তাই প্রথমে আমাদের এই পদ্ধতির ফাংশন স্বাক্ষর হ্যাশ গণনা করতে হবে।
// 取完整哈希值的前8个字符
// multicall: 0x5ae401dc
var sigHash = "0x" + Encode("keccak256", "string", "hex", "multicall(uint256,bytes[])").slice(0, 8)
পূর্ববর্তী পাঠের উদাহরণের উপর ভিত্তি করে, আমরা কিছু পরিবর্তন করেছি। একটি WebSocket সংযোগ দ্বারা ধাক্কা বার্তা গ্রহণ করার সময়, ব্যবহার করুনvar data = ws.read(-2)সর্বশেষ তথ্য পাওয়ার পদ্ধতি,read()ফাংশন প্যারামিটার -2 সেট করার অর্থ অবিলম্বে সর্বশেষ ডেটা ফেরত দেওয়া। আমরা শুধুমাত্র ধারণ সম্পর্কে যত্নশীলmulticallডাকাTransaction , ব্যবহার করুনif (tx && tx.input.indexOf(sigHash) !== -1)বিচার ফিল্টারিং.
দুটি কাস্টম ফাংশন ডিজাইন করা প্রয়োজন:
calcAllFuncSigHash(): ABI ভিত্তিক সমস্ত পদ্ধতির জন্য স্বাক্ষর হ্যাশ গণনা করে।decodeCall(): ডিকোডিং ফাংশন।
এরপর, সনাক্ত করুনmulticallকল করার সময়, আপনি প্রথমবার ডিকোডিং অপারেশন শুরু করতে পারেন৷multicallপদ্ধতি পরামিতি:deadlineএবংdata。deadlineএটি কেবল একটি টাইমস্ট্যাম্প যা বোঝা সহজ।dataএটি আরেকটি এনকোড করা কলডেটা, তাই এটি ব্যবহার করা চালিয়ে যেতে হবে।decodeCall()ফাংশন ডিকোডিং।
সম্পূর্ণ বাস্তবায়ন উদাহরণ:
javascript
var ws = null
var arrLog = []
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"}]'
function calcAllFuncSigHash(jsonABI) {
var mapSigHash = {}
for (var i in jsonABI) {
var ele = jsonABI[i]
if (typeof(ele["name"]) != "undefined") {
if (ele["inputs"]) {
var funcName = ele["name"]
if (ele["inputs"].length == 0) {
var methodId = "0x" + Encode("keccak256", "string", "hex", funcName + "()").slice(0, 8)
mapSigHash[methodId] = {"argsTypeList": [], "argsNameList": [], "funcName": funcName}
} else {
var arr = []
var arrName = []
var argPrototype = []
for (var j in ele["inputs"]) {
var inputType = ele["inputs"][j]["type"]
if (inputType == "tuple") {
var components = ele["inputs"][j]["components"]
var tupleType = []
var protoType = []
for (var componentsIdx = 0; componentsIdx < components.length; componentsIdx++) {
tupleType.push(components[componentsIdx]["type"])
protoType.push(components[componentsIdx]["name"] + " " + components[componentsIdx]["type"])
}
arr.push("(" + tupleType.join() + ")")
arrName.push(ele["inputs"][j]["name"])
// 原型
argPrototype.push("tuple" + "(" + protoType.join() + ")")
} else {
arr.push(inputType)
arrName.push(ele["inputs"][j]["name"])
// 原型
argPrototype.push(inputType)
}
}
var functionSignature = funcName + "(" + arr.join() + ")"
var methodId = "0x" + Encode("keccak256", "string", "hex", functionSignature).slice(0, 8)
mapSigHash[methodId] = {"argsTypeList": arr, "argsNameList": arrName, "funcName": funcName, "argPrototype": argPrototype}
}
}
}
}
return mapSigHash
}
function decodeCall(input, abi) {
var mapSigHash = calcAllFuncSigHash(JSON.parse(abi))
var methodId = input.slice(0, 10)
var data = input.slice(10)
var decodedArgs = {}
var infoMethod = mapSigHash[methodId]
if (typeof(infoMethod) == "undefined") {
return [methodId, mapSigHash]
}
var arr = []
for (var i = 0; i < infoMethod["argsTypeList"].length; i++) {
if (infoMethod["argsTypeList"][i].startsWith("(")) {
arr.push(infoMethod["argPrototype"][i])
} else {
arr.push(infoMethod["argsTypeList"][i])
}
}
if (arr.length == 0) {
return {"funcName": infoMethod["funcName"], "args": decodedArgs}
}
var args = exchange.IO("decode", arr.join(), data)
if (!Array.isArray(args)) {
args = [args]
}
if (args.length != infoMethod["argsNameList"].length) {
Log("args:", args)
Log("infoMethod:", infoMethod)
throw "解码后的args与argsNameList不等"
}
for (var i = 0; i < infoMethod["argsNameList"].length; i++) {
var key = infoMethod["argsNameList"][i]
var value = args[i]
decodedArgs[key] = value
}
return {"funcName": infoMethod["funcName"], "args": decodedArgs}
}
function main () {
// {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["xxxxx"]} , "xxxxx" 是订阅的具体消息
var payload = {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}
// 使用alchemy服务
ws = Dial("wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN" + "|reconnect=true&payload=" + JSON.stringify(payload))
if (!ws) {
throw "websocket链接alchemy失败!"
}
// eth_getTransactionByHash 调用计数
var getTransactionCounter = 0
// 起始时间戳
var beginTS = new Date().getTime()
// 计算函数签名哈希
var sigHash = "0x" + Encode("keccak256", "string", "hex", "multicall(uint256,bytes[])").slice(0, 8)
Log("sigHash:", sigHash)
// 循环获取消息
while (true) {
var msg = ""
var recv = null
// 接收推送的消息,使用read参数-2,立即返回最新数据
var data = ws.read(-2)
if (data && data != "") {
var ts = new Date().getTime()
if (ts - beginTS >= 1000) {
getTransactionCounter = 0
beginTS = ts
}
// 根据txHash查询交易详情
if (ts - beginTS < 1000 && getTransactionCounter >= 100) {
Sleep(1000)
getTransactionCounter = 0
beginTS = ts
}
var obj = JSON.parse(data)
if (obj["params"] && obj["params"]["result"]) {
var txHash = obj["params"]["result"]
var tx = exchange.IO("api", "eth", "eth_getTransactionByHash", txHash)
if (tx && tx.input.indexOf(sigHash) !== -1) {
// 解码交易详情
arrLog = []
var decodedInput = decodeCall(tx.input, ABI_Route)
// Log("----------------", txHash, "/", decodedInput["funcName"], "----------------", "#FF0000")
arrLog.push("----------------" + txHash + "/" + decodedInput["funcName"] + "----------------" + "#FF0000")
arrLog.push(tx.from + " -> " + tx.to)
for (var i = 0; i < decodedInput["args"]["data"].length; i++) {
var calldata = "0x" + decodedInput["args"]["data"][i]
var decodedCalldata = decodeCall(calldata, ABI_Route)
// Log("----------------", decodedCalldata["funcName"], "----------------", "#FF0000")
arrLog.push("----------------" + decodedCalldata["funcName"] + "----------------" + "#FF0000")
for (var key in decodedCalldata["args"]) {
// Log(key, decodedCalldata["args"][key])
arrLog.push(key + ": " + JSON.stringify(decodedCalldata["args"][key]))
}
}
// 输出日志
for (var logIdx = arrLog.length - 1; logIdx >= 0; logIdx--) {
Log(arrLog[logIdx])
}
}
getTransactionCounter++
}
recv = obj
} else if (data == null) {
msg = "缓冲区队列空了,时间:" + _D()
}
LogStatus(_D(), ", msg:", msg, ", recv:", recv)
}
}
function onexit() {
Log("断开WS连接")
ws.close()
}
function onerror() {
Log("断开WS连接")
ws.close()
for (var logIdx = arrLog.length - 1; logIdx >= 0; logIdx--) {
Log(arrLog[logIdx])
}
}
একটি বাস্তব ডিস্ক তৈরি করুন এবং পরীক্ষা চালান:
run
2023-06-20 17:01:00 信息 ----------------0x5288a7bd6e0f57162ca763df722de73793e542734d7d2b7af5755664e2e67910/multicall----------------
2023-06-20 17:01:00 信息 0x851b594033d57c98af753bcb3a7d0237a615de32 -> 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45
2023-06-20 17:01:00 信息 ----------------exactInputSingle----------------
2023-06-20 17:01:00 信息 params: {"tokenOut":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","fee":"10000","recipient":"0x0000000000000000000000000000000000000002","amountIn":"8952087000296027130940868","amountOutMinimum":"41638694112306829","sqrtPriceLimitX96":"0","tokenIn":"0xe1283567345349942acdfad3692924a1b16cf3cc"}
2023-06-20 17:01:00 信息 ----------------unwrapWETH9----------------
2023-06-20 17:01:00 信息 amountMinimum: "41638694112306829"
2023-06-20 17:01:00 信息 recipient: "0x851b594033d57c98af753bcb3a7d0237a615de32"
2023-06-20 16:59:03 信息 ----------------0x55e0c4a38a17d3aa6e8f558a66c77e9defa9f8f6e347536363ac1b921de9aaf3/multicall----------------
2023-06-20 16:59:03 信息 0x27457ada2dd725c7d0f28e1737bdd0bf583c0f0b -> 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45
2023-06-20 16:59:03 信息 ----------------swapExactTokensForTokens----------------
2023-06-20 16:59:03 信息 amountIn: "816769666850161"
2023-06-20 16:59:03 信息 amountOutMin: "40404501509302321"
2023-06-20 16:59:03 信息 path: ["0x7863e06bca47ded821fcb53ab788eeb371243eda","0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]
2023-06-20 16:59:03 信息 to: "0x27457ada2dd725c7d0f28e1737bdd0bf583c0f0b"
2023-06-20 16:58:25 信息 sigHash: 0x5ae401dc
স্ক্রিনশট:
আপনি লেনদেন হ্যাশ দেখতে পারেন0x5288a7bd6e0f57162ca763df722de73793e542734d7d2b7af5755664e2e67910এই লেনদেনের, কলে থাকা ইনপুট ডেটা হল amulticallপদ্ধতি কল। এই লেনদেনের পাঠানোর দিক হল: 0x851b594033d57c98af753bcb3a7d0237a615de32 -> 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45।0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45অর্থাৎ, Uniswap-এর রাউটিং চুক্তির ঠিকানা।
পার্স আউটmulticallচুক্তি প্যাকেজ এবং বলা হয়exactInputSingleএবংunwrapWETH9পদ্ধতি, এবং এই পদ্ধতির নির্দিষ্ট পরামিতি।
----------------exactInputSingle----------------
params: {
"tokenOut":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"fee":"10000",
"recipient":"0x0000000000000000000000000000000000000002",
"amountIn":"8952087000296027130940868",
"amountOutMinimum":"41638694112306829",
"sqrtPriceLimitX96":"0",
"tokenIn":"0xe1283567345349942acdfad3692924a1b16cf3cc"
}
----------------unwrapWETH9----------------
amountMinimum: "41638694112306829"
recipient: "0x851b594033d57c98af753bcb3a7d0237a615de32"
আগ্রহী শিক্ষার্থীরা আরও লেনদেন নিরীক্ষণ করতে এবং এই অন-চেইন ক্রিয়াকলাপগুলি বিশ্লেষণ করতে এই উদাহরণটি সংশোধন এবং প্রসারিত করতে পারে।
- 1



































