मुख्य सामग्री पर जाएं
यह tutorial आपको दिखाता है कि Web3 Action का उपयोग करके Discord channel को message कैसे भेजें जब Uniswap V3 पर एक नया pool बनाया जाता है। आप इस Web3 Action का उपयोग अपने community को chain पर कुछ होने पर सूचित करने के लिए कर सकते हैं।
पूरा code इस Github repo में उपलब्ध है। ध्यान दें कि यह इस समय एक अलग branch में है।

Project अवलोकन

इस project का लक्ष्य आपको सिखाना है कि जब भी Uniswap Pool बनाया जाता है तो Discord message भेजने के लिए Web3 Actions का उपयोग कैसे करें। हम आपको दो दृष्टिकोण दिखाएंगे - अधिक सुविधाजनक हमारे Web3 Action के लिए trigger के रूप में PoolCreated event का उपयोग करना है (देखें functions, events, और triggers और Uniswap docs)।

योजना

  • अपने Tenderly project में contracts जोड़ें - UniswapV3ContractFactory। यह पहले से ही verified है और Tenderly में मौजूद है, इसलिए आपको बस उन्हें अपने project में जोड़ने की आवश्यकता है।
  • Discord Webhook URL को अपने Web3 Action Secrets में store करें।
  • एक Web3 Action बनाएँ जो [PoolCreated](<https://developers.uniswap.org/protocol/reference/core/interfaces/IUniswapV3Factory#poolcreated>) event पर प्रतिक्रिया देगा।

1: अपने Tenderly Project में Uniswap Contracts जोड़ें

Web3 Actions को यह आवश्यक है कि triggers निर्दिष्ट करने के लिए उपयोग किए जाने वाले smart contracts Tenderly में verified हों। Web3 Actions को यह आवश्यक है कि triggers निर्दिष्ट करने के लिए उपयोग किए जाने वाले smart contracts Tenderly में verified हों। चूंकि हम मौजूदा contracts का उपयोग कर रहे हैं, आप contract name या address type करके search bar का उपयोग करके उन्हें ढूंढ सकते हैं। वैकल्पिक रूप से, UniswapV2ContractFactory पर जाएँ और “Add to Project” पर क्लिक करें। UniswapV2Pair के लिए भी ऐसा ही करें।

2: PoolCreated Event के लिए Web3 Action बनाएँ

नीचे आपको हमारी Web3 Action के लिए code के साथ-साथ यह भी मिलेगा कि यह कैसे काम करता है इसकी व्याख्या:
example.ts


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

    const eventLog = await getPoolCreatedEvent(txEvent);

    const tokensData = await getTokensData(eventLog.token0, eventLog.token1);
    console.log('Received Tokens Data: ', tokensData);

    await notifyDiscord(`${tokensData.token0.name} ↔️ ${tokensData.token1.name}`, context);
  } catch (error) {
    console.error(error);
  }
};

const getPoolCreatedEvent = async (txEvent: TransactionEvent) => {
  const ifc = new ethers.utils.Interface(UniswapV3FactoryAbi);
  const poolCreatedTopic = ifc.getEventTopic('PoolCreated');

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

  if (poolCreatedEventLog == undefined) {
    throw Error('PoolCreatedEvent missing');
  }
  return ifc.decodeEventLog(
    'PoolCreated',
    poolCreatedEventLog.data,
    poolCreatedEventLog.topics,
  ) as unknown as UniswapPool;
};

const getTokensData = async (token0: string, token1: string) => {
  const tokenFields = `id, name, symbol, totalValueLocked, totalSupply, derivedETH`;
  const theGraphQuery = `
{
	token0: token(id:"${token0.toLowerCase()}"){${tokenFields}},
	token1: token(id:"${token1.toLowerCase()}"){${tokenFields}}
}`;

  const UNISWAP_THE_GRAPH = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3';
  const resp = await axios.post(UNISWAP_THE_GRAPH, {
    query: theGraphQuery,
  });

  return resp.data.data as unknown as {
    token0: UniwswapToken;
    token1: UniwswapToken;
  };
};

const notifyDiscord = async (text: string, context: Context) => {
  console.log('Sending to Discord:', `🐥 ${text}`);
  const webhookLink = await context.secrets.get('discord.uniswapChannelWebhook');
  await axios.post(
    webhookLink,
    {
      content: `🐥 ${text}`,
    },
    {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    },
  );
};

type UniswapPool = {
  token0: string;
  token1: string;
  fee: number;
  tickSpacing: number;
  pool: number;
};

type UniwswapToken = {
  id: string;
  name: string;
  symbol: string;
  tokenValueLocked: number;
  totalSupply: number;
  derivedEth: number;
};
नए बनाए गए Pool में Tokens प्राप्त करें। नए pool में दो tokens के बारे में जानकारी प्राप्त करने के लिए, हमें getEventLog function में transaction logs के माध्यम से search करने की आवश्यकता है। हम Ethers और contract के ABI का उपयोग कर रहे हैं: UniswapV3FactoryAbiUniswapV3Factory Tenderly में contract पर जाएँ, “View ABI” पर क्लिक करें और इसे actions directory में एक local file में copy/paste करें। अनिवार्य रूप से, हम topic PoolCreate में log entry की तलाश कर रहे हैं। पहले, हम उस topic का reference ले रहे हैं (poolCreatedTopic = ifc.getEventTopic("PoolCreated")) और फिर हम वास्तविक logs (tx.logs) को filter कर रहे हैं जब तक कि हमें उस topic का reference देने वाली entry नहीं मिल जाती। अंत में, हम Ethers का उपयोग करके पाए गए log (poolCreatedEventLog) को decode कर रहे हैं। यह वह event है जिसकी हम तलाश कर रहे हैं, और इसमें tokens के addresses हैं: token0 और token1 TheGraph पर Uniswap के Graph API का उपयोग करके Token Data प्राप्त करें। Uniswap TheGraph के माध्यम से अपने data तक पहुँच का खुलासा करता है। हम TheGraph को query करने और पहले चरण के PoolCreated event में मौजूद token0 और token1 IDs के लिए कई fields प्राप्त करने के लिए getTokensData function का उपयोग कर रहे हैं। Discord Community को सूचित करें। सभी प्रासंगिक जानकारी एकत्र करने के बाद, हम अपने Discord channel को message भेजने के लिए तैयार हैं। notifyDiscord function के साथ, हमें secrets से Webhook URL प्राप्त करने की आवश्यकता है। हम Webhook चलाने और content पास करने के लिए HTTP post request बनाने हेतु Axios का उपयोग कर रहे हैं।

3: अपनी Web3 Action कॉन्फ़िगर करें

tenderly.yaml file में, हमें यह निर्दिष्ट करना होगा कि हम uniswapActions:onPoolCreatedEventEmitted को तब चलाना चाहते हैं जब Mainnet (network 1) पर mine किए गए transaction के भीतर UniswapV3Factory contract (0xd849b2af570ffa3033973ea11be6e01b7ba661d9 address पर) से एक event fire होता है।
example.yaml
account_id: ''
actions:
  YOUR_USERNAME/YOUR_PROJECT_SLUG:
    runtime: v1
    sources: actions
    specs:
      uniswapNewPool:
        description: Runs when a new swap is made on Uniswap
        function: uniswapActions:onPoolCreatedEventEmitted
        trigger:
          type: transaction
          transaction:
            status:
              - mined
            filters:
              - network: 1
                eventEmitted:
                  contract:
                    address: 0xd849b2af570ffa3033973ea11be6e01b7ba661d9
                  name: PoolCreated
project_slug: ''

4: Discord Webhook URL को Secrets में Store करें

Tenderly में हमारी Web3 Action चलाने से पहले, हमें Discord Webhook के लिए value सेट करना होगा। Tenderly Dashboard में, अपने project के Actions पेज पर जाएँ और Secrets पर क्लिक करें। discord.uniswapChannelWebhook नामक एक नया secret जोड़ें और अपने Discord channel का Webhook paste करें।

5: अपनी Web3 Action Deploy और Try Out करें

इस command को चलाकर अपनी Web3 Action deploy करें:
example.yaml
tenderly actions deploy
यह देखने के लिए कि आपकी Web3 Action काम कर रही है या नहीं, अपने Tenderly Dashboard में Actions पेज पर जाएँ। अपनी Action का चयन करें और Manual Trigger पर क्लिक करें। बस इतना ही! उम्मीद है, आपने अपने Discord channel पर एक message प्राप्त कर लिया है 🎉