मुख्य सामग्री पर जाएं
इस tutorial में, हम एक Web3 Action बनाएंगे जो हर बार तब चलता है जब UniswapV2Factory एक नया UniswapV2Pair contract deploy करता है। Web3 Action नए deploy किए गए contract के bytecode की तुलना किसी अन्य UniswapV2Pair contract के bytecode से करेगा। इस मामले में, हम USDC Pair contract का उपयोग करेंगे। bytecodes प्राप्त करने के लिए, हम अपने node provider के रूप में Node RPC का उपयोग करेंगे। यदि bytecodes match करते हैं, तो Web3 Action Web3 Action के Storage में pair के address और contract के bytecode को store करेगा। यदि आप tutorial को skip करना चाहते हैं, तो यहाँ पूरा समाधान है:
example.tsx



type UniswapPair = {
  token0: string;
  token1: string;
  pair: string;
};

const USDC_PAIR_CONTRACT_ADDRESS = '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc';

export const onPairCreatedEventEmitted: ActionFn = async (context: Context, event: Event) => {
  try {
    const txEvent = event as TransactionEvent;
    const newPair = await getPairCreatedEvent(txEvent);

    const gatewayURL = context.gateways.getGateway(Network.MAINNET);
    const provider = new ethers.providers.JsonRpcProvider(gatewayURL);

    const usdcPairContract = await provider.getCode(USDC_PAIR_CONTRACT_ADDRESS);
    const newPairContract = await provider.getCode(newPair.pair);

    if (usdcPairContract === newPairContract) {
      const pairContracts = await context.storage.getJson('PairContracts');
      pairContracts[newPair.pair] = newPairContract;
      await context.storage.putJson('PairContracts', pairContracts);
    }
  } catch (error) {
    console.error(error);
  }
};

const getPairCreatedEvent = async (txEvent: TransactionEvent): Promise<UniswapPair> => {
  const i = new ethers.utils.Interface(UniswapV2FactoryAbi);
  const pairCreatedTopic = i.getEventTopic('PairCreated');

  const pairCreatedEventLog = txEvent.logs.find(log => {
    return log.topics.find(topic => topic == pairCreatedTopic) !== undefined;
  });

  if (pairCreatedEventLog == undefined) {
    throw Error('PairCreatedEvent missing');
  }

  return i.decodeEventLog(
    'PairCreated',
    pairCreatedEventLog.data,
    pairCreatedEventLog.topics,
  ) as unknown as UniswapPair;
};

पूर्वापेक्षाएँ

Web3 Actions के लिए triggering mechanism केवल तभी काम करता है जब trigger definition में उपयोग किया गया contract Tenderly पर verified है। यहाँ Tenderly पर contracts कैसे verify करें सीखें।
इस उदाहरण में, हम UniswapV2Factory और UniswapV2Pair contracts का उपयोग करेंगे। चूंकि दोनों contracts Tenderly पर publicly verified हैं, उन्हें manually verify करने की आवश्यकता नहीं है। UniswapV2Factory पर navigate करें और अपने project में contract जोड़ने के लिए Add to Project बटन पर क्लिक करें। UniswapV2Pair के लिए भी वही चरण दोहराएँ।

चरण 1: trigger परिभाषित करें

जब भी UniswapV2Factory contract का createPair function कॉल होता है, तो निम्न होता है:
  • token pair के लिए एक नया UniswapV2Pair contract बनाया जाता है (यदि पहले से मौजूद नहीं है)
  • एक PairCreated event emit होता है
हम trigger को इस तरह परिभाषित कर सकते हैं कि हर बार जब contract को hit करने वाला transaction किसी function को कॉल करता है जो एक विशिष्ट event emit करता है तो Web3 Action चले। हमारे मामले में, हम trigger लिखेंगे जो हर बार UniswapV2Factory contract के PairCreated event को emit करने पर fire होगा। दूसरे शब्दों में, जब भी एक नया UniswapV2Pair contract deploy होता है। trigger के लिए configuration इस तरह दिखता है, और इसे tenderly.yaml file में save किया जाना चाहिए:
example.yaml
account_id: ''
actions:
  YOUR_USERNAME/YOUR_PROJECT_SLUG:
    runtime: v2
    sources: actions
    specs:
      uniswapNewPair:
        description: Runs when a new pair is created on uniswap
        function: uniswapActions:onPairCreatedEventEmitted
        execution_type: parallel
        trigger:
          type: transaction
          transaction:
            status:
              - mined
            filters:
              - network: 1
                eventEmitted:
                  contract:
                    address: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
                  name: PairCreated
project_slug: ''

चरण 2: Web3 Action logic परिभाषित करें

जब हमारी Web3 Action चलती है, तो यह दो inputs प्राप्त करती है:
  • एक context object जो Node RPC और Storage तक पहुँच प्रदान करता है
  • एक transactionEvent payload जिसमें Web3 Action को trigger करने वाले transaction से संबंधित data होता है
हम gateways तक पहुँचने के लिए context object का उपयोग करेंगे, जो Ethers के लिए हमारा node provider होगा और matched bytecode को store करने के लिए Storage।
URLs या secret keys के प्रबंधन की परेशानी के बिना Mainnet सहित किसी भी समर्थित network तक पहुँचने के लिए Web3 Actions में Node RPC का उपयोग कैसे करें जानें।
transactionEvent payload के बारे में, हम PairCreated topic के अनुरूप event log खोजने के लिए इसकी logs property का उपयोग करेंगे।

चरण 2.1: PairCreated event को decode करें

trigger होने पर, Web3 Action को payload के logs में PairCreated event खोजने की आवश्यकता होती है। हम इस code को getPairCreatedEvent function में डालेंगे। PairCreated topic के लिए hash प्राप्त करने के लिए, हमें UniswapV2Factory contract के ABI का उपयोग करना होगा। ऐसा करने के लिए, UniswapV2Factory Tenderly में contract पर जाएँ, View ABI पर क्लिक करें और इसे actions directory में एक local file में copy/paste करें। अब हम निम्न code के साथ उस topic का reference प्राप्त कर सकते हैं:
example.tsx
const i = new ethers.utils.Interface(UniswapV2FactoryAbi);
const pairCreatedTopic = i.getEventTopic('PairCreated');
इसके बाद, हमें transaction logs के माध्यम से जाना होगा और उस topic का reference देने वाली entry इस तरह खोजनी होगी।
example.tsx
const pairCreatedEventLog = txEvent.logs.find(log => {
  return log.topics.find(topic => topic == pairCreatedTopic) !== undefined;
});
अंत में, हम Ethers का उपयोग करके log entry को UniswapPair type में decode करेंगे। getPairCreatedEvent function का परिणाम तब एक object है जिसमें निम्नलिखित शामिल है:
  • pair बनाने वाले tokens के addresses - token0 और token1 properties
  • deployed UniswapV2Pair contract का address - pair property

चरण 3: bytecodes की तुलना करें

अब जब हमारे पास नए deploy किए गए contract का address है (जो UniswapPair type की pair property में समाहित है), हम इसका उपयोग contract का bytecode प्राप्त करने के लिए कर सकते हैं। हम यह निर्धारित करने के लिए USDC UniswapV2Pair contract के bytecode का उपयोग करेंगे कि क्या नए बनाए गए contract का bytecode एक मान्य UniswapV2Pair contract है। उनके bytecodes को बिल्कुल match करना चाहिए। उन contracts के bytecodes प्राप्त करने के लिए, हमें Ethers getCode function का उपयोग करने की आवश्यकता है। इन चरणों को पूरा करने के लिए, हमें पहले एक node provider, Node RPC: gateways सेट अप करना होगा। context object की gateways property तक पहुँचकर, हम आसानी से अपने वांछित network (हमारे मामले में MAINNET) के लिए JSON-RPC URL प्राप्त कर सकते हैं getGateway() function को invoke करके और इसे Ethers के लिए provider के रूप में उपयोग करके।
example.tsx
const gatewayURL = context.gateways.getGateway(Network.MAINNET);
const provider = new ethers.providers.JsonRpcProvider(gatewayURL);
यह हमें नए pair और USDC pair दोनों का bytecode प्राप्त करने की अनुमति देगा।
example.tsx
const usdcPairContract = await provider.getCode(USDC_PAIR_CONTRACT_ADDRESS);
const newPairContract = await provider.getCode(newPair.pair);
यदि कोई match होता है, तो हम नए pair के bytecode को pair_address: bytecode format में PairContracts नामक JSON property के तहत अपने project के Storage में store करना चाहते हैं:
example.tsx
if (usdcPairContract === newPairContract) {
  const pairContracts = await context.storage.getJson('PairContracts');
  pairContracts[newPair.pair] = newPairContract;
  await context.storage.putJson('PairContracts', pairContracts);
}
Web3 Action को कुछ समय तक चलने देने के बाद, हम project के Storage की जाँच कर सकते हैं और बनाए गए pairs देख सकते हैं: keys नए deploy किए गए UniswapV2Pair contracts के addresses हैं, जबकि values सभी समान हैं और UniswapV2Pair contract के bytecode का प्रतिनिधित्व करते हैं।