├── Procfile ├── .prettierrc ├── src ├── meta.json ├── index.ts ├── util.ts ├── opensea.ts ├── twitter.ts └── discord.ts ├── .gitignore ├── example-discord.png ├── tsconfig.json ├── package.json ├── README.md └── yarn.lock /Procfile: -------------------------------------------------------------------------------- 1 | worker: yarn start -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | semi: false 2 | singleQuote: true -------------------------------------------------------------------------------- /src/meta.json: -------------------------------------------------------------------------------- 1 | { "lastEventId": 3945993497 } 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn-error.log 3 | dist 4 | env.txt -------------------------------------------------------------------------------- /example-discord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HappyMicky0317/opensea-activity-bot/HEAD/example-discord.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/*.ts"], 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es2020", 6 | "outDir": "dist", 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { fetchEvents } from './opensea' 2 | import { messageEvents } from './discord' 3 | import { tweetEvents } from './twitter' 4 | import { botInterval, logStart } from './util' 5 | 6 | const { DEBUG } = process.env 7 | 8 | async function main() { 9 | const run = async () => { 10 | const events = await fetchEvents() 11 | if (!events || events.length === 0) return 12 | 13 | if (DEBUG) { 14 | console.log(`${logStart}Opensea - DEBUG - Events:`) 15 | console.log(JSON.stringify(events)) 16 | } 17 | 18 | void messageEvents(events) 19 | void tweetEvents(events) 20 | } 21 | 22 | run() 23 | 24 | const interval = setInterval(run.bind(this), botInterval * 1000) 25 | 26 | process.on('SIGINT', () => { 27 | console.log('Caught interrupt signal. Stopping...') 28 | clearInterval(interval) 29 | process.exit() 30 | }) 31 | } 32 | 33 | main() 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opensea-activity-bot", 3 | "version": "1.0.10", 4 | "description": "A bot that shares new OpenSea events for a collection to Discord and Twitter.", 5 | "author": "Ryan Ghods ", 6 | "license": "MIT", 7 | "engines": { 8 | "node": "^16.13.1" 9 | }, 10 | "scripts": { 11 | "postinstall": "yarn build && yarn createMetaJsonFile", 12 | "build": "npx tsc", 13 | "createMetaJsonFile": "[ -f dist/meta.json ] || echo '{\"lastEventId\":0}' > dist/meta.json", 14 | "start": "node dist/index.js" 15 | }, 16 | "dependencies": { 17 | "discord.js": "^13.3.1", 18 | "ethers": "^5.5.2", 19 | "file-api": "^0.10.4", 20 | "node-fetch": "^2.6.6", 21 | "timeago.js": "^4.0.2", 22 | "twitter-lite": "^1.1.0" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^16.11.19", 26 | "prettier": "^2.5.1", 27 | "ts-node": "^10.4.0", 28 | "typescript": "^4.5.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opensea-activity-bot 2 | 3 | ![Example Discord messages](./example-discord.png) 4 | 5 | A bot that shares new OpenSea events for a collection to Discord and Twitter. 6 | 7 | Designed to handle multiple output configurations, like a Discord activity feed and a Twitter sales feed. 8 | 9 | Originally developed for [@dutchtide](https://twitter.com/dutchtide)'s [𝕄𝕚𝕕𝕟𝕚𝕘𝕙𝕥 夏季 𝔹𝕣𝕖𝕖𝕫𝕖](https://opensea.io/collection/midnightbreeze) collection, on Twitter at [@mbsalesbot](https://twitter.com/mbsalesbot). 10 | 11 | An OpenSea API key is needed - [request one here](https://docs.opensea.io/reference/request-an-api-key). 12 | 13 | To run multiple instances of this bot at once check out [bot-runner](https://github.com/ryanio/bot-runner). Also check out [discord-nft-bot](https://github.com/ryanio/discord-nft-bot). 14 | 15 | ## Setup 16 | 17 | ### Env 18 | 19 | Please define the env variables outlined in this section for the repository to work as intended. 20 | 21 | **Valid event types** 22 | 23 | Valid string values for event types to react on are: 24 | 25 | - `created` for new listings and auctions 26 | - `successful` for sales 27 | - `cancelled` 28 | - `offer_entered` 29 | - `bid_entered` 30 | - `bid_withdrawn` 31 | - `transfer` 32 | 33 | #### Project-specific 34 | 35 | - `TOKEN_ADDRESS` 36 | 37 | #### APIs 38 | 39 | - `OPENSEA_API_TOKEN` 40 | - `INFURA_PROJECT_ID` (for ENS support) 41 | 42 | #### To share on Discord 43 | 44 | - `DISCORD_EVENTS` 45 | - The Discord channel ID with a comma separated list of event types for the bot to send through discord 46 | - e.g. `662377002338091020=successful` 47 | - For multiple channels separate with an ampersand (&) 48 | - e.g. `662377002338091020=successful,created,cancelled&924064011820077076=bid_entered,bid_withdrawn` 49 | - `DISCORD_TOKEN` 50 | - To get your `DISCORD_TOKEN`, [create a Discord app](https://discord.com/developers/applications). Create a bot with the permissions: `Send Messages` and `Embed Links`. Then [add your bot to your server](https://discordjs.guide/preparations/adding-your-bot-to-servers.html#bot-invite-links). 51 | - The `DISCORD_TOKEN` looks like this: `OTE5MzY5ODIyNzEyNzc5NzUz.YBuz2g.x1rGh4zx_XlSNj43oreukvlwsfw` 52 | 53 | #### To tweet 54 | 55 | - `TWITTER_EVENTS` 56 | - Comma separated list of event types for the bot to tweet 57 | - e.g. `successful,bid_entered` 58 | 59 | Create an application in the [Twitter Developer Platform](https://developer.twitter.com/) and provide: 60 | 61 | - `TWITTER_CONSUMER_KEY` 62 | - `TWITTER_CONSUMER_SECRET` 63 | - `TWITTER_ACCESS_TOKEN` 64 | - `TWITTER_ACCESS_TOKEN_SECRET` 65 | 66 | #### Optional 67 | 68 | - `OPENSEA_BOT_INTERVAL` 69 | - Number of seconds interval for the bot to run (default: 60) 70 | - `MIN_OFFER_USD` 71 | - Offers or bids less than this amount will be ignored (default: 100) 72 | 73 | ### Run 74 | 75 | `yarn start` 76 | 77 | #### Heroku 78 | 79 | A `Procfile` is included for easy use on platforms like Heroku. 80 | 81 | Clone this repo, push it to heroku, set up the environment variables above, and spin up a worker with `heroku ps:scale web=0 worker=1` 82 | 83 | Then watch the logs with `heroku logs --tail` 84 | 85 | If your discord bot is not able to post messages ensure it is added to the channels you've specified and it has the permissions to `Send Messages` and `Embed Links`. 86 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import { FixedNumber, providers, utils } from 'ethers' 2 | 3 | const { commify, formatUnits } = utils 4 | 5 | export function timeout(ms: number) { 6 | return new Promise((resolve) => setTimeout(resolve, ms)) 7 | } 8 | 9 | export const unixTimestamp = (date: Date) => Math.floor(date.getTime() / 1000) 10 | 11 | /** 12 | * ENS 13 | */ 14 | const infuraProvider = new providers.InfuraProvider( 15 | 'mainnet', 16 | process.env.INFURA_PROJECT_ID ? process.env.INFURA_PROJECT_ID : undefined 17 | ) 18 | 19 | export const ensName = async (addr: string): Promise => { 20 | try { 21 | const ens = await infuraProvider.lookupAddress(addr) 22 | return ens 23 | } catch (error) { 24 | console.error(`Error from ensName: ${error}`) 25 | } 26 | } 27 | 28 | /** 29 | * Returns a shortened version of a full ethereum address 30 | * (e.g. 0x38a16...c7eb3) 31 | */ 32 | export const shortAddr = (addr: string) => 33 | addr.slice(0, 7) + '...' + addr.slice(37, 42) 34 | 35 | /** 36 | * OpenSea utils and helpers 37 | */ 38 | 39 | /** 40 | * Processes an OpenSea user object and returns, in order: 41 | * 1. An OpenSea username 42 | * 2. An ENS address 43 | * 3. A short formatted address 44 | * 4. 'Unknown' 45 | * */ 46 | export const username = async (user) => { 47 | if (user.user?.username) return user.user.username 48 | const ens = await ensName(user.address) 49 | if (ens) return ens 50 | if (user.address) return shortAddr(user.address) 51 | return 'Unknown' 52 | } 53 | 54 | /** 55 | * Formats amount, decimals, and symbols to final string output. 56 | */ 57 | export const formatAmount = ( 58 | amount: number, 59 | decimals: number, 60 | symbol: string 61 | ) => { 62 | let value = formatUnits(amount, decimals) 63 | const split = value.split('.') 64 | if (split[1].length > 4) { 65 | // Trim to 4 decimals max 66 | value = `${split[0]}.${split[1].slice(0, 5)}` 67 | } else if (split[1] === '0') { 68 | // If whole number remove '.0' 69 | value = split[0] 70 | } 71 | return `${value} ${symbol}` 72 | } 73 | 74 | /** 75 | * Formats price and usdPrice to final string output. 76 | */ 77 | export const formatUSD = (price: string, usdPrice: string) => { 78 | let value = commify( 79 | FixedNumber.from(price.split(' ')[0]) 80 | .mulUnsafe(FixedNumber.from(usdPrice)) 81 | .toUnsafeFloat() 82 | .toFixed(2) 83 | ) 84 | // Format to 2 decimal places e.g. $1.3 -> $1.30 85 | if (value.split('.')[1].length === 1) { 86 | value = `${value}0` 87 | } 88 | return value 89 | } 90 | 91 | export const assetUSDValue = (event: any) => { 92 | const { bid_amount, total_price, payment_token } = event 93 | const { decimals, usd_price } = payment_token 94 | const price = formatUnits(bid_amount ?? total_price, decimals) 95 | return Number( 96 | FixedNumber.from(price) 97 | .mulUnsafe(FixedNumber.from(usd_price)) 98 | .toUnsafeFloat() 99 | .toFixed(2) 100 | ) 101 | } 102 | 103 | export const imageForAsset = (asset: any) => { 104 | // Format ipfs:// urls to https://ipfs.io/ipfs/ 105 | if (asset.image_original_url.slice(0, 7) === 'ipfs://') { 106 | const hash = asset.image_original_url.slice(7) 107 | return `https://ipfs.io/ipfs/${hash}` 108 | } 109 | return asset.image_original_url 110 | } 111 | 112 | /** 113 | * Env helpers 114 | */ 115 | export const botInterval = Number(process.env.OPENSEA_BOT_INTERVAL ?? 60) 116 | export const minOfferUSD = Number(process.env.MIN_OFFER_USD ?? 100) 117 | export const shortTokenAddr = shortAddr(process.env.TOKEN_ADDRESS) 118 | export const logStart = `${shortTokenAddr} - ` 119 | -------------------------------------------------------------------------------- /src/opensea.ts: -------------------------------------------------------------------------------- 1 | import { writeFileSync } from 'fs' 2 | import { resolve } from 'path' 3 | import { URLSearchParams } from 'url' 4 | import fetch from 'node-fetch' 5 | import { channelsWithEvents } from './discord' 6 | import { assetUSDValue, logStart, minOfferUSD } from './util' 7 | import meta from './meta.json' 8 | 9 | const { 10 | OPENSEA_API_TOKEN, 11 | TOKEN_ADDRESS, 12 | TWITTER_EVENTS, 13 | DEBUG, 14 | LAST_EVENT_ID, 15 | } = process.env 16 | 17 | if (LAST_EVENT_ID && Number(LAST_EVENT_ID) > meta.lastEventId) { 18 | console.log(`${logStart}Using LAST_EVENT_ID: ${LAST_EVENT_ID}`) 19 | meta.lastEventId = Number(LAST_EVENT_ID) 20 | } 21 | 22 | const updateMeta = (lastEventId: number) => { 23 | meta.lastEventId = lastEventId 24 | writeFileSync(resolve(__dirname, './meta.json'), JSON.stringify(meta)) 25 | } 26 | 27 | export const opensea = { 28 | events: 'https://api.opensea.io/api/v1/events', 29 | bundlePermalink: (slug) => `https://opensea.io/bundles/${slug}`, 30 | GET_OPTS: { 31 | method: 'GET', 32 | headers: { Accept: 'application/json', 'X-API-KEY': OPENSEA_API_TOKEN }, 33 | } as any, 34 | } 35 | 36 | export enum EventType { 37 | created = 'created', 38 | successful = 'successful', 39 | cancelled = 'cancelled', 40 | offer_entered = 'offer_entered', 41 | bid_entered = 'bid_entered', 42 | bid_withdrawn = 'bid_withdrawn', 43 | transfer = 'transfer', 44 | } 45 | 46 | const enabledEventTypes = () => { 47 | const eventTypes = new Set() 48 | for (const [_channelId, discordEventTypes] of channelsWithEvents()) { 49 | for (const eventType of discordEventTypes) { 50 | eventTypes.add(eventType) 51 | } 52 | } 53 | const twitterEventTypes = TWITTER_EVENTS?.split(',') 54 | if (twitterEventTypes?.length > 0) { 55 | for (const eventType of twitterEventTypes) { 56 | eventTypes.add(eventType) 57 | } 58 | } 59 | if (eventTypes.size === 0) { 60 | throw new Error( 61 | 'No events enabled. Please specify DISCORD_EVENTS or TWITTER_EVENTS' 62 | ) 63 | } 64 | return [...eventTypes] 65 | } 66 | 67 | export const fetchEvents = async (): Promise => { 68 | console.log(`${logStart}OpenSea - Fetching events`) 69 | const eventTypes = enabledEventTypes() 70 | const params: any = { 71 | asset_contract_address: TOKEN_ADDRESS, 72 | limit: 100, 73 | } 74 | // OpenSea only allows filtering for one event at a time so 75 | // we'll only filter by an event if there's only one type specified 76 | if (eventTypes.length === 1) { 77 | params.event_type = eventTypes[0] 78 | } 79 | 80 | const url = `${opensea.events}?${new URLSearchParams(params)}` 81 | let events: any[] 82 | 83 | try { 84 | const response = await fetch(url, opensea.GET_OPTS) 85 | if (!response.ok) { 86 | console.error( 87 | `${logStart}OpenSea - Fetch Error - ${response.status}: ${response.statusText}`, 88 | DEBUG ? `DEBUG: ${JSON.stringify(await response.text())}` : '' 89 | ) 90 | return 91 | } 92 | const result = await response.json() 93 | if (!result || !result.asset_events) { 94 | console.error( 95 | `${logStart}OpenSea - Fetch Error (missing asset_events) - Result: ${JSON.stringify( 96 | result 97 | )}` 98 | ) 99 | return 100 | } 101 | events = result.asset_events 102 | } catch (error) { 103 | console.error( 104 | `${logStart}OpenSea - Fetch Error: ${error?.message ?? error}` 105 | ) 106 | return 107 | } 108 | 109 | // Filter since lastEventId 110 | events = events.filter((event) => event.id > meta.lastEventId) 111 | if (events.length > 0) { 112 | updateMeta(Math.max(...events.map((event) => event.id))) 113 | } 114 | 115 | // Filter out private listings 116 | events = events.filter( 117 | (event) => 118 | event.event_type !== EventType.created || 119 | (event.event_type === EventType.created && !event.is_private) 120 | ) 121 | 122 | const eventsPreFilter = events.length 123 | console.log(`${logStart}OpenSea - Fetched events: ${eventsPreFilter}`) 124 | 125 | // Filter out low value bids or offers 126 | events = events.filter((event) => 127 | [ 128 | EventType.offer_entered, 129 | EventType.bid_entered, 130 | EventType.bid_withdrawn, 131 | ].includes(event.event_type) 132 | ? assetUSDValue(event) >= minOfferUSD 133 | : true 134 | ) 135 | 136 | const eventsPostFilter = events.length 137 | const eventsFiltered = eventsPreFilter - eventsPostFilter 138 | if (eventsFiltered > 0) { 139 | console.log( 140 | `${logStart}Opensea - Offers under $${minOfferUSD} USD filtered out: ${eventsFiltered}` 141 | ) 142 | } 143 | 144 | return events.reverse() 145 | } 146 | -------------------------------------------------------------------------------- /src/twitter.ts: -------------------------------------------------------------------------------- 1 | import { File, FileReader } from 'file-api' 2 | import { format } from 'timeago.js' 3 | import fetch from 'node-fetch' 4 | import Twitter from 'twitter-lite' 5 | import { opensea, EventType } from './opensea' 6 | import { 7 | formatAmount, 8 | formatUSD, 9 | imageForAsset, 10 | logStart, 11 | timeout, 12 | username, 13 | } from './util' 14 | 15 | const { 16 | TWITTER_EVENTS, 17 | TWITTER_CONSUMER_KEY, 18 | TWITTER_CONSUMER_SECRET, 19 | TWITTER_ACCESS_TOKEN, 20 | TWITTER_ACCESS_TOKEN_SECRET, 21 | } = process.env 22 | 23 | const secrets = { 24 | consumer_key: TWITTER_CONSUMER_KEY, 25 | consumer_secret: TWITTER_CONSUMER_SECRET, 26 | access_token_key: TWITTER_ACCESS_TOKEN, 27 | access_token_secret: TWITTER_ACCESS_TOKEN_SECRET, 28 | } 29 | 30 | const textForTweet = async (event: any) => { 31 | const permalink = event.asset.permalink 32 | 33 | const { 34 | asset, 35 | payment_token, 36 | event_type, 37 | auction_type, 38 | starting_price, 39 | ending_price, 40 | total_price, 41 | bid_amount, 42 | created_date, 43 | duration, 44 | from_account, 45 | to_account, 46 | winner_account, 47 | seller, 48 | asset_bundle, 49 | } = event 50 | 51 | let text = `#${asset.token_id} ` 52 | 53 | if (asset_bundle) { 54 | text = `${asset_bundle.name} ` 55 | } 56 | 57 | if (event_type === EventType.created) { 58 | const { symbol, decimals, usd_price } = payment_token 59 | const name = await username(from_account ?? seller) 60 | if (auction_type === 'english') { 61 | const price = formatAmount(starting_price, decimals, symbol) 62 | const priceUSD = formatUSD(price, usd_price) 63 | const inTime = format( 64 | new Date(new Date(created_date).getTime() + Number(duration)) 65 | ) 66 | text += `English auction started for ${price} ($${priceUSD} USD), ends ${inTime}, by ${name}` 67 | // Opening Price, Ends in 68 | } else if (auction_type === 'dutch') { 69 | const price = formatAmount(starting_price, decimals, symbol) 70 | const priceUSD = formatUSD(price, usd_price) 71 | const endPrice = formatAmount(ending_price, decimals, symbol) 72 | const endPriceUSD = formatUSD(endPrice, usd_price) 73 | const inTime = format( 74 | new Date(new Date(created_date).getTime() + Number(duration) * 1000) 75 | ) 76 | text += `Reverse Dutch auction started for ${price} ($${priceUSD} USD), ends ${inTime} at ${endPrice} ($${endPriceUSD} USD), by ${name}` 77 | // Start Price, End Price (in x time) 78 | } else if (auction_type === null) { 79 | const price = formatAmount(starting_price, decimals, symbol) 80 | const priceUSD = formatUSD(price, usd_price) 81 | const inTime = format( 82 | new Date(new Date(created_date).getTime() + Number(duration) * 1000) 83 | ) 84 | text += `listed on sale for ${price} ($${priceUSD} USD) for ${inTime} by ${name}` 85 | // Price 86 | } 87 | } else if (event_type === EventType.successful) { 88 | const { symbol, decimals, usd_price } = payment_token 89 | const amount = formatAmount(total_price, decimals, symbol) 90 | const amountUSD = formatUSD(amount, usd_price) 91 | const name = await username(winner_account) 92 | text += `purchased for ${amount} ($${amountUSD} USD) by ${name}` 93 | } else if (event_type === EventType.cancelled) { 94 | const { symbol, decimals, usd_price } = payment_token 95 | const price = formatAmount(total_price, decimals, symbol) 96 | const priceUSD = formatUSD(price, usd_price) 97 | const name = await username(seller) 98 | text += `listing cancelled for ${price} ($${priceUSD} USD) by ${name}` 99 | } else if (event_type === EventType.offer_entered) { 100 | const { symbol, decimals, usd_price } = payment_token 101 | const amount = formatAmount(bid_amount, decimals, symbol) 102 | const amountUSD = formatUSD(amount, usd_price) 103 | const name = await username(from_account) 104 | text += `offer entered for ${amount} ($${amountUSD} USD) by ${name}` 105 | } else if (event_type === EventType.bid_entered) { 106 | const { symbol, decimals, usd_price } = payment_token 107 | const amount = formatAmount(bid_amount, decimals, symbol) 108 | const amountUSD = formatUSD(amount, usd_price) 109 | const name = await username(from_account) 110 | text += `bid entered for ${amount} ($${amountUSD} USD) by ${name}` 111 | } else if (event_type === EventType.bid_withdrawn) { 112 | const { symbol, decimals, usd_price } = payment_token 113 | const amount = formatAmount(total_price, decimals, symbol) 114 | const amountUSD = formatUSD(amount, usd_price) 115 | const name = await username(from_account) 116 | text += `bid withdrawn for ${amount} ($${amountUSD} USD) by ${name}` 117 | } else if (event_type === EventType.transfer) { 118 | const fromName = await username(from_account) 119 | const toName = await username(to_account) 120 | text += `transferred from ${fromName} to ${toName}` 121 | } 122 | 123 | if (asset_bundle) { 124 | text += ` (${asset_bundle.assets.length} items)` 125 | text += ` ${opensea.bundlePermalink(asset_bundle.slug)}` 126 | } else { 127 | text += ` ${permalink}` 128 | } 129 | 130 | return text 131 | } 132 | 133 | export const base64Image = async (imageURL, tokenId) => { 134 | return await new Promise(async (resolve) => { 135 | const response = await fetch(imageURL) 136 | const blob = await response.blob() 137 | const reader = new FileReader() 138 | reader.onload = function (ev: any) { 139 | const base64Image = ev.target.result 140 | // Format to satisfy Twitter API 141 | const formattedBase64Image = base64Image.replace( 142 | /^data:image\/png;base64,/, 143 | '' 144 | ) 145 | resolve(formattedBase64Image) 146 | } 147 | reader.readAsDataURL( 148 | new File({ 149 | name: `${tokenId}.png`, 150 | type: 'image/png', 151 | buffer: Buffer.from(await (blob as any).arrayBuffer()), 152 | }) 153 | ) 154 | }) 155 | } 156 | 157 | const tweetEvent = async (client: any, uploadClient: any, event: any) => { 158 | try { 159 | // Fetch and upload image 160 | const media_data = await base64Image( 161 | imageForAsset(event.asset), 162 | event.asset.token_id 163 | ) 164 | const mediaUploadResponse = await uploadClient.post('media/upload', { 165 | media_data, 166 | }) 167 | 168 | // Create tweet 169 | const status = await textForTweet(event) 170 | await client.post('statuses/update', { 171 | status, 172 | media_ids: mediaUploadResponse.media_id_string, 173 | }) 174 | console.log( 175 | `${logStart}Twitter - Tweeted (event id: ${event.id}): ${status}` 176 | ) 177 | } catch (error) { 178 | console.error(`${logStart}Twitter - Error:`) 179 | console.error(error) 180 | } 181 | } 182 | 183 | export const tweetEvents = async (events: any[]) => { 184 | if (!TWITTER_EVENTS) return 185 | 186 | const client = new Twitter(secrets) 187 | const uploadClient = new Twitter({ 188 | subdomain: 'upload', 189 | ...secrets, 190 | }) 191 | 192 | // only handle event types specified by TWITTER_EVENTS 193 | const filteredEvents = events.filter((event) => 194 | TWITTER_EVENTS.split(',').includes(event.event_type) 195 | ) 196 | 197 | console.log(`${logStart}Twitter - Relevant events: ${filteredEvents.length}`) 198 | 199 | if (filteredEvents.length === 0) return 200 | 201 | for (const [index, event] of filteredEvents.entries()) { 202 | await tweetEvent(client, uploadClient, event) 203 | // Wait 5s between tweets 204 | if (filteredEvents[index + 1]) { 205 | await timeout(3000) 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/discord.ts: -------------------------------------------------------------------------------- 1 | import { Client, MessageEmbed } from 'discord.js' 2 | import { format } from 'timeago.js' 3 | import { opensea, EventType } from './opensea' 4 | import { 5 | formatAmount, 6 | formatUSD, 7 | imageForAsset, 8 | logStart, 9 | timeout, 10 | username, 11 | } from './util' 12 | 13 | const { DISCORD_EVENTS, DISCORD_TOKEN } = process.env 14 | 15 | type ChannelEvents = Array<[channelId: string, eventTypes: EventType[]]> 16 | export const channelsWithEvents = (): ChannelEvents => { 17 | if (!DISCORD_EVENTS) return [] 18 | 19 | const list = [] 20 | for (const channel of DISCORD_EVENTS.split('&')) { 21 | const channelWithEvents = channel.split('=') 22 | const channelId = channelWithEvents[0] 23 | const eventTypes = channelWithEvents[1].split(',') 24 | list.push([channelId, eventTypes]) 25 | } 26 | 27 | return list 28 | } 29 | 30 | const channelsForEventType = ( 31 | eventType: EventType, 32 | channelEvents: ChannelEvents, 33 | discordChannels: any[] 34 | ) => { 35 | const channels = [] 36 | for (const [channelId, eventTypes] of channelEvents) { 37 | if (eventTypes.includes(eventType)) { 38 | const channel = discordChannels[channelId] 39 | channels.push(channel) 40 | } 41 | } 42 | return channels 43 | } 44 | 45 | const colorFor = (eventType: EventType) => { 46 | switch (eventType) { 47 | case EventType.created: 48 | return '#66dcf0' 49 | case EventType.successful: 50 | return '#62b778' 51 | case EventType.cancelled: 52 | return '#9537b0' 53 | case EventType.offer_entered: 54 | return '#d63864' 55 | case EventType.bid_entered: 56 | return '#d63864' 57 | case EventType.bid_withdrawn: 58 | return '#9537b0' 59 | case EventType.transfer: 60 | return '#5296d5' 61 | default: 62 | return '#5296d5' 63 | } 64 | } 65 | 66 | const embed = async (event: any) => { 67 | const { 68 | asset, 69 | event_type, 70 | payment_token, 71 | auction_type, 72 | starting_price, 73 | ending_price, 74 | total_price, 75 | bid_amount, 76 | created_date, 77 | duration, 78 | from_account, 79 | to_account, 80 | winner_account, 81 | seller, 82 | asset_bundle, 83 | } = event 84 | const fields: any[] = [] 85 | 86 | let title = '' 87 | 88 | if (event_type === EventType.created) { 89 | const { symbol, decimals, usd_price } = payment_token 90 | if (auction_type === 'english') { 91 | title += 'English auction:' 92 | const price = formatAmount(starting_price, decimals, symbol) 93 | const priceUSD = formatUSD(price, usd_price) 94 | const inTime = format( 95 | new Date(new Date(created_date).getTime() + Number(duration) * 1000) 96 | ) 97 | fields.push({ 98 | name: 'Starting Price', 99 | value: `${price} ($${priceUSD} USD)`, 100 | }) 101 | fields.push({ 102 | name: 'Ends', 103 | value: inTime, 104 | }) 105 | } else if (auction_type === 'dutch' && starting_price !== ending_price) { 106 | title += 'Reverse Dutch auction:' 107 | const price = formatAmount(starting_price, decimals, symbol) 108 | const priceUSD = formatUSD(price, usd_price) 109 | const endPrice = formatAmount(ending_price, decimals, symbol) 110 | const endPriceUSD = formatUSD(endPrice, usd_price) 111 | const inTime = format( 112 | new Date(new Date(created_date).getTime() + Number(duration) * 1000) 113 | ) 114 | fields.push({ 115 | name: 'Start Price', 116 | value: `${price} ($${priceUSD} USD)`, 117 | }) 118 | fields.push({ 119 | name: 'End Price', 120 | value: `${endPrice} ($${endPriceUSD} USD) ${inTime}`, 121 | }) 122 | } else { 123 | title += 'Listed for sale:' 124 | const price = formatAmount(starting_price, decimals, symbol) 125 | const priceUSD = formatUSD(price, usd_price) 126 | fields.push({ 127 | name: 'Price', 128 | value: `${price} ($${priceUSD} USD)`, 129 | }) 130 | if (duration) { 131 | const inTime = format( 132 | new Date(new Date(created_date).getTime() + Number(duration) * 1000) 133 | ) 134 | fields.push({ 135 | name: 'Expires', 136 | value: inTime, 137 | }) 138 | } 139 | } 140 | fields.push({ 141 | name: 'By', 142 | value: await username(from_account ?? seller), 143 | }) 144 | } else if (event_type === EventType.successful) { 145 | const { symbol, decimals, usd_price } = payment_token 146 | title += 'Purchased:' 147 | const price = formatAmount(total_price, decimals, symbol) 148 | const priceUSD = formatUSD(price, usd_price) 149 | fields.push({ 150 | name: 'Price', 151 | value: `${price} ($${priceUSD} USD)`, 152 | }) 153 | fields.push({ 154 | name: 'By', 155 | value: await username(winner_account), 156 | }) 157 | } else if (event_type === EventType.cancelled) { 158 | const { symbol, decimals, usd_price } = payment_token 159 | title += 'Listing cancelled:' 160 | const price = formatAmount(total_price, decimals, symbol) 161 | const priceUSD = formatUSD(price, usd_price) 162 | fields.push({ 163 | name: 'Price', 164 | value: `${price} ($${priceUSD} USD)`, 165 | }) 166 | fields.push({ 167 | name: 'By', 168 | value: await username(seller), 169 | }) 170 | } else if (event_type === EventType.offer_entered) { 171 | const { symbol, decimals, usd_price } = payment_token 172 | title += 'Offer entered: ' 173 | const amount = formatAmount(bid_amount, decimals, symbol) 174 | const amountUSD = formatUSD(amount, usd_price) 175 | fields.push({ 176 | name: 'Amount', 177 | value: `${amount} ($${amountUSD} USD)`, 178 | }) 179 | fields.push({ 180 | name: 'By', 181 | value: await username(from_account), 182 | }) 183 | } else if (event_type === EventType.bid_entered) { 184 | const { symbol, decimals, usd_price } = payment_token 185 | title += 'Bid entered: ' 186 | const amount = formatAmount(bid_amount, decimals, symbol) 187 | const amountUSD = formatUSD(amount, usd_price) 188 | fields.push({ 189 | name: 'Amount', 190 | value: `${amount} ($${amountUSD} USD)`, 191 | }) 192 | fields.push({ 193 | name: 'By', 194 | value: await username(from_account), 195 | }) 196 | } else if (event_type === EventType.bid_withdrawn) { 197 | const { symbol, decimals, usd_price } = payment_token 198 | title += 'Bid withdrawn: ' 199 | const amount = formatAmount(total_price, decimals, symbol) 200 | const amountUSD = formatUSD(amount, usd_price) 201 | fields.push({ 202 | name: 'Amount', 203 | value: `${amount} ($${amountUSD} USD)`, 204 | }) 205 | fields.push({ 206 | name: 'By', 207 | value: await username(from_account), 208 | }) 209 | } else if (event_type === EventType.transfer) { 210 | title += 'Transferred:' 211 | fields.push({ 212 | name: 'From', 213 | value: await username(from_account), 214 | }) 215 | fields.push({ 216 | name: 'To', 217 | value: await username(to_account), 218 | }) 219 | } 220 | 221 | let url = asset.permalink 222 | 223 | if (asset_bundle) { 224 | title += ` (bundle)` 225 | fields.push({ 226 | name: 'Number of items', 227 | value: asset_bundle.assets.length, 228 | }) 229 | title += ` ${asset_bundle.name}` 230 | url = opensea.bundlePermalink(asset_bundle.slug) 231 | } else { 232 | let assetName = asset.name 233 | if (!assetName) { 234 | if (asset.asset_contract.name) { 235 | assetName = `${asset.asset_contract.name} ` 236 | } 237 | assetName += `#${asset.token_id}` 238 | } 239 | title += ` ${assetName}` 240 | } 241 | 242 | return new MessageEmbed() 243 | .setColor(colorFor(event_type)) 244 | .setTitle(title) 245 | .setURL(url) 246 | .setFields( 247 | fields.map((f) => { 248 | f.inline = true 249 | return f 250 | }) 251 | ) 252 | .setImage(imageForAsset(asset)) 253 | } 254 | 255 | const messagesForEvents = async (events: any[]) => { 256 | const messages = [] 257 | for (const event of events) { 258 | const embeds = [await embed(event)] 259 | const message = { embeds } 260 | messages.push(message) 261 | } 262 | return messages 263 | } 264 | 265 | const login = async (client: Client): Promise => { 266 | return new Promise((resolve) => { 267 | client.on('ready', async () => { 268 | console.log(`${logStart}Discord - Logged in as: ${client?.user?.tag}`) 269 | resolve() 270 | }) 271 | client.login(DISCORD_TOKEN) 272 | }) 273 | } 274 | 275 | const getChannels = async ( 276 | client: Client, 277 | channelEvents: ChannelEvents 278 | ): Promise => { 279 | const channels = {} 280 | console.log(`${logStart}Discord - Selected channels:`) 281 | for (const [channelId, events] of channelEvents) { 282 | const channel = await client.channels.fetch(channelId) 283 | channels[channelId] = channel 284 | console.log( 285 | `${logStart}Discord - * #${ 286 | (channel as any).name ?? (channel as any).channelId 287 | }: ${events.join(', ')}` 288 | ) 289 | } 290 | return channels 291 | } 292 | 293 | export async function messageEvents(events: any[]) { 294 | if (!DISCORD_EVENTS) return 295 | 296 | const client = new Client({ intents: [] }) 297 | const channelEvents = channelsWithEvents() 298 | 299 | // only handle event types specified by DISCORD_EVENTS 300 | const filteredEvents = events.filter((event) => 301 | [...channelEvents.map((c) => c[1])].flat().includes(event.event_type) 302 | ) 303 | 304 | console.log(`${logStart}Discord - Relevant events: ${filteredEvents.length}`) 305 | 306 | if (filteredEvents.length === 0) return 307 | 308 | try { 309 | await login(client) 310 | const discordChannels = await getChannels(client, channelEvents) 311 | const messages = await messagesForEvents(filteredEvents) 312 | 313 | for (const [index, message] of messages.entries()) { 314 | const { event_type, id } = filteredEvents[index] 315 | const channels = channelsForEventType( 316 | event_type, 317 | channelEvents, 318 | discordChannels 319 | ) 320 | console.log( 321 | `${logStart}Discord - Sending message (event id: ${id}) in ${channels 322 | .map((c) => '#' + c.name ?? c.channelId) 323 | .join(', ')}: ${message.embeds[0].title} ` 324 | ) 325 | for (const channel of channels) { 326 | await channel.send(message) 327 | 328 | // Wait 3s between messages 329 | if (messages[index + 1]) { 330 | await timeout(3000) 331 | } 332 | } 333 | } 334 | } catch (error) { 335 | console.error(error) 336 | } 337 | 338 | client.destroy() 339 | } 340 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@cspotcode/source-map-consumer@0.8.0": 6 | version "0.8.0" 7 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" 8 | integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== 9 | 10 | "@cspotcode/source-map-support@0.7.0": 11 | version "0.7.0" 12 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" 13 | integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== 14 | dependencies: 15 | "@cspotcode/source-map-consumer" "0.8.0" 16 | 17 | "@discordjs/builders@^0.8.1": 18 | version "0.8.2" 19 | resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.8.2.tgz#c3ef99caa9ebe70a4196b987011d90136c71054a" 20 | integrity sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ== 21 | dependencies: 22 | "@sindresorhus/is" "^4.2.0" 23 | discord-api-types "^0.24.0" 24 | ow "^0.27.0" 25 | ts-mixer "^6.0.0" 26 | tslib "^2.3.1" 27 | 28 | "@discordjs/collection@^0.3.2": 29 | version "0.3.2" 30 | resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.3.2.tgz#3c271dd8a93dad89b186d330e24dbceaab58424a" 31 | integrity sha512-dMjLl60b2DMqObbH1MQZKePgWhsNe49XkKBZ0W5Acl5uVV43SN414i2QfZwRI7dXAqIn8pEWD2+XXQFn9KWxqg== 32 | 33 | "@discordjs/form-data@^3.0.1": 34 | version "3.0.1" 35 | resolved "https://registry.yarnpkg.com/@discordjs/form-data/-/form-data-3.0.1.tgz#5c9e6be992e2e57d0dfa0e39979a850225fb4697" 36 | integrity sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg== 37 | dependencies: 38 | asynckit "^0.4.0" 39 | combined-stream "^1.0.8" 40 | mime-types "^2.1.12" 41 | 42 | "@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.5.0": 43 | version "5.5.0" 44 | resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" 45 | integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== 46 | dependencies: 47 | "@ethersproject/address" "^5.5.0" 48 | "@ethersproject/bignumber" "^5.5.0" 49 | "@ethersproject/bytes" "^5.5.0" 50 | "@ethersproject/constants" "^5.5.0" 51 | "@ethersproject/hash" "^5.5.0" 52 | "@ethersproject/keccak256" "^5.5.0" 53 | "@ethersproject/logger" "^5.5.0" 54 | "@ethersproject/properties" "^5.5.0" 55 | "@ethersproject/strings" "^5.5.0" 56 | 57 | "@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.5.0": 58 | version "5.5.1" 59 | resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" 60 | integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== 61 | dependencies: 62 | "@ethersproject/bignumber" "^5.5.0" 63 | "@ethersproject/bytes" "^5.5.0" 64 | "@ethersproject/logger" "^5.5.0" 65 | "@ethersproject/networks" "^5.5.0" 66 | "@ethersproject/properties" "^5.5.0" 67 | "@ethersproject/transactions" "^5.5.0" 68 | "@ethersproject/web" "^5.5.0" 69 | 70 | "@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.5.0": 71 | version "5.5.0" 72 | resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" 73 | integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== 74 | dependencies: 75 | "@ethersproject/abstract-provider" "^5.5.0" 76 | "@ethersproject/bignumber" "^5.5.0" 77 | "@ethersproject/bytes" "^5.5.0" 78 | "@ethersproject/logger" "^5.5.0" 79 | "@ethersproject/properties" "^5.5.0" 80 | 81 | "@ethersproject/address@5.5.0", "@ethersproject/address@^5.5.0": 82 | version "5.5.0" 83 | resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" 84 | integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== 85 | dependencies: 86 | "@ethersproject/bignumber" "^5.5.0" 87 | "@ethersproject/bytes" "^5.5.0" 88 | "@ethersproject/keccak256" "^5.5.0" 89 | "@ethersproject/logger" "^5.5.0" 90 | "@ethersproject/rlp" "^5.5.0" 91 | 92 | "@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": 93 | version "5.5.0" 94 | resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" 95 | integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== 96 | dependencies: 97 | "@ethersproject/bytes" "^5.5.0" 98 | 99 | "@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": 100 | version "5.5.0" 101 | resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" 102 | integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== 103 | dependencies: 104 | "@ethersproject/bytes" "^5.5.0" 105 | "@ethersproject/properties" "^5.5.0" 106 | 107 | "@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@^5.5.0": 108 | version "5.5.0" 109 | resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" 110 | integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== 111 | dependencies: 112 | "@ethersproject/bytes" "^5.5.0" 113 | "@ethersproject/logger" "^5.5.0" 114 | bn.js "^4.11.9" 115 | 116 | "@ethersproject/bytes@5.5.0", "@ethersproject/bytes@^5.5.0": 117 | version "5.5.0" 118 | resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" 119 | integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== 120 | dependencies: 121 | "@ethersproject/logger" "^5.5.0" 122 | 123 | "@ethersproject/constants@5.5.0", "@ethersproject/constants@^5.5.0": 124 | version "5.5.0" 125 | resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" 126 | integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== 127 | dependencies: 128 | "@ethersproject/bignumber" "^5.5.0" 129 | 130 | "@ethersproject/contracts@5.5.0": 131 | version "5.5.0" 132 | resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" 133 | integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== 134 | dependencies: 135 | "@ethersproject/abi" "^5.5.0" 136 | "@ethersproject/abstract-provider" "^5.5.0" 137 | "@ethersproject/abstract-signer" "^5.5.0" 138 | "@ethersproject/address" "^5.5.0" 139 | "@ethersproject/bignumber" "^5.5.0" 140 | "@ethersproject/bytes" "^5.5.0" 141 | "@ethersproject/constants" "^5.5.0" 142 | "@ethersproject/logger" "^5.5.0" 143 | "@ethersproject/properties" "^5.5.0" 144 | "@ethersproject/transactions" "^5.5.0" 145 | 146 | "@ethersproject/hash@5.5.0", "@ethersproject/hash@^5.5.0": 147 | version "5.5.0" 148 | resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" 149 | integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== 150 | dependencies: 151 | "@ethersproject/abstract-signer" "^5.5.0" 152 | "@ethersproject/address" "^5.5.0" 153 | "@ethersproject/bignumber" "^5.5.0" 154 | "@ethersproject/bytes" "^5.5.0" 155 | "@ethersproject/keccak256" "^5.5.0" 156 | "@ethersproject/logger" "^5.5.0" 157 | "@ethersproject/properties" "^5.5.0" 158 | "@ethersproject/strings" "^5.5.0" 159 | 160 | "@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": 161 | version "5.5.0" 162 | resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" 163 | integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== 164 | dependencies: 165 | "@ethersproject/abstract-signer" "^5.5.0" 166 | "@ethersproject/basex" "^5.5.0" 167 | "@ethersproject/bignumber" "^5.5.0" 168 | "@ethersproject/bytes" "^5.5.0" 169 | "@ethersproject/logger" "^5.5.0" 170 | "@ethersproject/pbkdf2" "^5.5.0" 171 | "@ethersproject/properties" "^5.5.0" 172 | "@ethersproject/sha2" "^5.5.0" 173 | "@ethersproject/signing-key" "^5.5.0" 174 | "@ethersproject/strings" "^5.5.0" 175 | "@ethersproject/transactions" "^5.5.0" 176 | "@ethersproject/wordlists" "^5.5.0" 177 | 178 | "@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": 179 | version "5.5.0" 180 | resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" 181 | integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== 182 | dependencies: 183 | "@ethersproject/abstract-signer" "^5.5.0" 184 | "@ethersproject/address" "^5.5.0" 185 | "@ethersproject/bytes" "^5.5.0" 186 | "@ethersproject/hdnode" "^5.5.0" 187 | "@ethersproject/keccak256" "^5.5.0" 188 | "@ethersproject/logger" "^5.5.0" 189 | "@ethersproject/pbkdf2" "^5.5.0" 190 | "@ethersproject/properties" "^5.5.0" 191 | "@ethersproject/random" "^5.5.0" 192 | "@ethersproject/strings" "^5.5.0" 193 | "@ethersproject/transactions" "^5.5.0" 194 | aes-js "3.0.0" 195 | scrypt-js "3.0.1" 196 | 197 | "@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@^5.5.0": 198 | version "5.5.0" 199 | resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" 200 | integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== 201 | dependencies: 202 | "@ethersproject/bytes" "^5.5.0" 203 | js-sha3 "0.8.0" 204 | 205 | "@ethersproject/logger@5.5.0", "@ethersproject/logger@^5.5.0": 206 | version "5.5.0" 207 | resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" 208 | integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== 209 | 210 | "@ethersproject/networks@5.5.1", "@ethersproject/networks@^5.5.0": 211 | version "5.5.1" 212 | resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.1.tgz#b7f7b9fb88dec1ea48f739b7fb9621311aa8ce6c" 213 | integrity sha512-tYRDM4zZtSUcKnD4UMuAlj7SeXH/k5WC4SP2u1Pn57++JdXHkRu2zwNkgNogZoxHzhm9Q6qqurDBVptHOsW49Q== 214 | dependencies: 215 | "@ethersproject/logger" "^5.5.0" 216 | 217 | "@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": 218 | version "5.5.0" 219 | resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" 220 | integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== 221 | dependencies: 222 | "@ethersproject/bytes" "^5.5.0" 223 | "@ethersproject/sha2" "^5.5.0" 224 | 225 | "@ethersproject/properties@5.5.0", "@ethersproject/properties@^5.5.0": 226 | version "5.5.0" 227 | resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" 228 | integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== 229 | dependencies: 230 | "@ethersproject/logger" "^5.5.0" 231 | 232 | "@ethersproject/providers@5.5.1": 233 | version "5.5.1" 234 | resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.1.tgz#ba87e3c93219bbd2e2edf8b369873aee774abf04" 235 | integrity sha512-2zdD5sltACDWhjUE12Kucg2PcgM6V2q9JMyVvObtVGnzJu+QSmibbP+BHQyLWZUBfLApx2942+7DC5D+n4wBQQ== 236 | dependencies: 237 | "@ethersproject/abstract-provider" "^5.5.0" 238 | "@ethersproject/abstract-signer" "^5.5.0" 239 | "@ethersproject/address" "^5.5.0" 240 | "@ethersproject/basex" "^5.5.0" 241 | "@ethersproject/bignumber" "^5.5.0" 242 | "@ethersproject/bytes" "^5.5.0" 243 | "@ethersproject/constants" "^5.5.0" 244 | "@ethersproject/hash" "^5.5.0" 245 | "@ethersproject/logger" "^5.5.0" 246 | "@ethersproject/networks" "^5.5.0" 247 | "@ethersproject/properties" "^5.5.0" 248 | "@ethersproject/random" "^5.5.0" 249 | "@ethersproject/rlp" "^5.5.0" 250 | "@ethersproject/sha2" "^5.5.0" 251 | "@ethersproject/strings" "^5.5.0" 252 | "@ethersproject/transactions" "^5.5.0" 253 | "@ethersproject/web" "^5.5.0" 254 | bech32 "1.1.4" 255 | ws "7.4.6" 256 | 257 | "@ethersproject/random@5.5.0", "@ethersproject/random@^5.5.0": 258 | version "5.5.0" 259 | resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.0.tgz#305ed9e033ca537735365ac12eed88580b0f81f9" 260 | integrity sha512-egGYZwZ/YIFKMHcoBUo8t3a8Hb/TKYX8BCBoLjudVCZh892welR3jOxgOmb48xznc9bTcMm7Tpwc1gHC1PFNFQ== 261 | dependencies: 262 | "@ethersproject/bytes" "^5.5.0" 263 | "@ethersproject/logger" "^5.5.0" 264 | 265 | "@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": 266 | version "5.5.0" 267 | resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" 268 | integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== 269 | dependencies: 270 | "@ethersproject/bytes" "^5.5.0" 271 | "@ethersproject/logger" "^5.5.0" 272 | 273 | "@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": 274 | version "5.5.0" 275 | resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" 276 | integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== 277 | dependencies: 278 | "@ethersproject/bytes" "^5.5.0" 279 | "@ethersproject/logger" "^5.5.0" 280 | hash.js "1.1.7" 281 | 282 | "@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": 283 | version "5.5.0" 284 | resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" 285 | integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== 286 | dependencies: 287 | "@ethersproject/bytes" "^5.5.0" 288 | "@ethersproject/logger" "^5.5.0" 289 | "@ethersproject/properties" "^5.5.0" 290 | bn.js "^4.11.9" 291 | elliptic "6.5.4" 292 | hash.js "1.1.7" 293 | 294 | "@ethersproject/solidity@5.5.0": 295 | version "5.5.0" 296 | resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" 297 | integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== 298 | dependencies: 299 | "@ethersproject/bignumber" "^5.5.0" 300 | "@ethersproject/bytes" "^5.5.0" 301 | "@ethersproject/keccak256" "^5.5.0" 302 | "@ethersproject/logger" "^5.5.0" 303 | "@ethersproject/sha2" "^5.5.0" 304 | "@ethersproject/strings" "^5.5.0" 305 | 306 | "@ethersproject/strings@5.5.0", "@ethersproject/strings@^5.5.0": 307 | version "5.5.0" 308 | resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" 309 | integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== 310 | dependencies: 311 | "@ethersproject/bytes" "^5.5.0" 312 | "@ethersproject/constants" "^5.5.0" 313 | "@ethersproject/logger" "^5.5.0" 314 | 315 | "@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.5.0": 316 | version "5.5.0" 317 | resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" 318 | integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== 319 | dependencies: 320 | "@ethersproject/address" "^5.5.0" 321 | "@ethersproject/bignumber" "^5.5.0" 322 | "@ethersproject/bytes" "^5.5.0" 323 | "@ethersproject/constants" "^5.5.0" 324 | "@ethersproject/keccak256" "^5.5.0" 325 | "@ethersproject/logger" "^5.5.0" 326 | "@ethersproject/properties" "^5.5.0" 327 | "@ethersproject/rlp" "^5.5.0" 328 | "@ethersproject/signing-key" "^5.5.0" 329 | 330 | "@ethersproject/units@5.5.0": 331 | version "5.5.0" 332 | resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" 333 | integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== 334 | dependencies: 335 | "@ethersproject/bignumber" "^5.5.0" 336 | "@ethersproject/constants" "^5.5.0" 337 | "@ethersproject/logger" "^5.5.0" 338 | 339 | "@ethersproject/wallet@5.5.0": 340 | version "5.5.0" 341 | resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" 342 | integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== 343 | dependencies: 344 | "@ethersproject/abstract-provider" "^5.5.0" 345 | "@ethersproject/abstract-signer" "^5.5.0" 346 | "@ethersproject/address" "^5.5.0" 347 | "@ethersproject/bignumber" "^5.5.0" 348 | "@ethersproject/bytes" "^5.5.0" 349 | "@ethersproject/hash" "^5.5.0" 350 | "@ethersproject/hdnode" "^5.5.0" 351 | "@ethersproject/json-wallets" "^5.5.0" 352 | "@ethersproject/keccak256" "^5.5.0" 353 | "@ethersproject/logger" "^5.5.0" 354 | "@ethersproject/properties" "^5.5.0" 355 | "@ethersproject/random" "^5.5.0" 356 | "@ethersproject/signing-key" "^5.5.0" 357 | "@ethersproject/transactions" "^5.5.0" 358 | "@ethersproject/wordlists" "^5.5.0" 359 | 360 | "@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": 361 | version "5.5.1" 362 | resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" 363 | integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== 364 | dependencies: 365 | "@ethersproject/base64" "^5.5.0" 366 | "@ethersproject/bytes" "^5.5.0" 367 | "@ethersproject/logger" "^5.5.0" 368 | "@ethersproject/properties" "^5.5.0" 369 | "@ethersproject/strings" "^5.5.0" 370 | 371 | "@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": 372 | version "5.5.0" 373 | resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" 374 | integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== 375 | dependencies: 376 | "@ethersproject/bytes" "^5.5.0" 377 | "@ethersproject/hash" "^5.5.0" 378 | "@ethersproject/logger" "^5.5.0" 379 | "@ethersproject/properties" "^5.5.0" 380 | "@ethersproject/strings" "^5.5.0" 381 | 382 | "@sapphire/async-queue@^1.1.8": 383 | version "1.1.9" 384 | resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.1.9.tgz#ce69611c8753c4affd905a7ef43061c7eb95c01b" 385 | integrity sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ== 386 | 387 | "@sindresorhus/is@^4.0.1", "@sindresorhus/is@^4.2.0": 388 | version "4.2.0" 389 | resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.2.0.tgz#667bfc6186ae7c9e0b45a08960c551437176e1ca" 390 | integrity sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw== 391 | 392 | "@tsconfig/node10@^1.0.7": 393 | version "1.0.8" 394 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" 395 | integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== 396 | 397 | "@tsconfig/node12@^1.0.7": 398 | version "1.0.9" 399 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" 400 | integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== 401 | 402 | "@tsconfig/node14@^1.0.0": 403 | version "1.0.1" 404 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" 405 | integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== 406 | 407 | "@tsconfig/node16@^1.0.2": 408 | version "1.0.2" 409 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" 410 | integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== 411 | 412 | "@types/node-fetch@^2.5.12": 413 | version "2.5.12" 414 | resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" 415 | integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== 416 | dependencies: 417 | "@types/node" "*" 418 | form-data "^3.0.0" 419 | 420 | "@types/node@*": 421 | version "17.0.0" 422 | resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.0.tgz#62797cee3b8b497f6547503b2312254d4fe3c2bb" 423 | integrity sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw== 424 | 425 | "@types/node@^16.11.19": 426 | version "16.11.19" 427 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.19.tgz#1afa165146997b8286b6eabcb1c2d50729055169" 428 | integrity sha512-BPAcfDPoHlRQNKktbsbnpACGdypPFBuX4xQlsWDE7B8XXcfII+SpOLay3/qZmCLb39kV5S1RTYwXdkx2lwLYng== 429 | 430 | "@types/ws@^8.2.0": 431 | version "8.2.2" 432 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" 433 | integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== 434 | dependencies: 435 | "@types/node" "*" 436 | 437 | "File@>= 0.10.0", File@^0.10.2: 438 | version "0.10.2" 439 | resolved "https://registry.yarnpkg.com/File/-/File-0.10.2.tgz#e899f776d273e2243ba86105bb3b056d0fb95604" 440 | integrity sha1-6Jn3dtJz4iQ7qGEFuzsFbQ+5VgQ= 441 | dependencies: 442 | mime ">= 0.0.0" 443 | 444 | "FileList@>= 0.10.0", FileList@^0.10.2: 445 | version "0.10.2" 446 | resolved "https://registry.yarnpkg.com/FileList/-/FileList-0.10.2.tgz#6003b1a9715934164b67c434ad6a8741a1cd147a" 447 | integrity sha1-YAOxqXFZNBZLZ8Q0rWqHQaHNFHo= 448 | 449 | acorn-walk@^8.1.1: 450 | version "8.2.0" 451 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" 452 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== 453 | 454 | acorn@^8.4.1: 455 | version "8.6.0" 456 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" 457 | integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== 458 | 459 | aes-js@3.0.0: 460 | version "3.0.0" 461 | resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" 462 | integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= 463 | 464 | arg@^4.1.0: 465 | version "4.1.3" 466 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 467 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 468 | 469 | asynckit@^0.4.0: 470 | version "0.4.0" 471 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 472 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 473 | 474 | bech32@1.1.4: 475 | version "1.1.4" 476 | resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" 477 | integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== 478 | 479 | bn.js@^4.11.9: 480 | version "4.12.0" 481 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 482 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 483 | 484 | brorand@^1.1.0: 485 | version "1.1.0" 486 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 487 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= 488 | 489 | "bufferjs@> 0.2.0": 490 | version "3.0.1" 491 | resolved "https://registry.yarnpkg.com/bufferjs/-/bufferjs-3.0.1.tgz#0692e829cb10a10550e647390b035eb06c38e8ef" 492 | integrity sha1-BpLoKcsQoQVQ5kc5CwNesGw46O8= 493 | 494 | bufferjs@^2.0.0: 495 | version "2.0.0" 496 | resolved "https://registry.yarnpkg.com/bufferjs/-/bufferjs-2.0.0.tgz#685e71ed5c0600e3d703ff9bd012bb3270a39e28" 497 | integrity sha1-aF5x7VwGAOPXA/+b0BK7MnCjnig= 498 | 499 | callsites@^3.1.0: 500 | version "3.1.0" 501 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 502 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 503 | 504 | combined-stream@^1.0.8: 505 | version "1.0.8" 506 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 507 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 508 | dependencies: 509 | delayed-stream "~1.0.0" 510 | 511 | create-require@^1.1.0: 512 | version "1.1.1" 513 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 514 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 515 | 516 | cross-fetch@^3.0.0: 517 | version "3.1.4" 518 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" 519 | integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== 520 | dependencies: 521 | node-fetch "2.6.1" 522 | 523 | delayed-stream@~1.0.0: 524 | version "1.0.0" 525 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 526 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 527 | 528 | diff@^4.0.1: 529 | version "4.0.2" 530 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 531 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 532 | 533 | discord-api-types@^0.24.0: 534 | version "0.24.0" 535 | resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.24.0.tgz#9e429b8a1ddb4147134dfb3109093422de7ec549" 536 | integrity sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A== 537 | 538 | discord.js@^13.3.1: 539 | version "13.3.1" 540 | resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.3.1.tgz#94fe05bc3ec0a3e4761e4f312a2a418c29721ab6" 541 | integrity sha512-zn4G8tL5+tMV00+0aSsVYNYcIfMSdT2g0nudKny+Ikd+XKv7m6bqI7n3Vji0GIRqXDr5ArPaw+iYFM2I1Iw3vg== 542 | dependencies: 543 | "@discordjs/builders" "^0.8.1" 544 | "@discordjs/collection" "^0.3.2" 545 | "@discordjs/form-data" "^3.0.1" 546 | "@sapphire/async-queue" "^1.1.8" 547 | "@types/node-fetch" "^2.5.12" 548 | "@types/ws" "^8.2.0" 549 | discord-api-types "^0.24.0" 550 | node-fetch "^2.6.1" 551 | ws "^8.2.3" 552 | 553 | dot-prop@^6.0.1: 554 | version "6.0.1" 555 | resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" 556 | integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== 557 | dependencies: 558 | is-obj "^2.0.0" 559 | 560 | elliptic@6.5.4: 561 | version "6.5.4" 562 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" 563 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 564 | dependencies: 565 | bn.js "^4.11.9" 566 | brorand "^1.1.0" 567 | hash.js "^1.0.0" 568 | hmac-drbg "^1.0.1" 569 | inherits "^2.0.4" 570 | minimalistic-assert "^1.0.1" 571 | minimalistic-crypto-utils "^1.0.1" 572 | 573 | ethers@^5.5.2: 574 | version "5.5.2" 575 | resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.2.tgz#cd2e508c7342c44fa70392f722e8de8f2416489f" 576 | integrity sha512-EF5W+6Wwcu6BqVwpgmyR5U2+L4c1FQzlM/02dkZOugN3KF0cG9bzHZP+TDJglmPm2/IzCEJDT7KBxzayk7SAHw== 577 | dependencies: 578 | "@ethersproject/abi" "5.5.0" 579 | "@ethersproject/abstract-provider" "5.5.1" 580 | "@ethersproject/abstract-signer" "5.5.0" 581 | "@ethersproject/address" "5.5.0" 582 | "@ethersproject/base64" "5.5.0" 583 | "@ethersproject/basex" "5.5.0" 584 | "@ethersproject/bignumber" "5.5.0" 585 | "@ethersproject/bytes" "5.5.0" 586 | "@ethersproject/constants" "5.5.0" 587 | "@ethersproject/contracts" "5.5.0" 588 | "@ethersproject/hash" "5.5.0" 589 | "@ethersproject/hdnode" "5.5.0" 590 | "@ethersproject/json-wallets" "5.5.0" 591 | "@ethersproject/keccak256" "5.5.0" 592 | "@ethersproject/logger" "5.5.0" 593 | "@ethersproject/networks" "5.5.1" 594 | "@ethersproject/pbkdf2" "5.5.0" 595 | "@ethersproject/properties" "5.5.0" 596 | "@ethersproject/providers" "5.5.1" 597 | "@ethersproject/random" "5.5.0" 598 | "@ethersproject/rlp" "5.5.0" 599 | "@ethersproject/sha2" "5.5.0" 600 | "@ethersproject/signing-key" "5.5.0" 601 | "@ethersproject/solidity" "5.5.0" 602 | "@ethersproject/strings" "5.5.0" 603 | "@ethersproject/transactions" "5.5.0" 604 | "@ethersproject/units" "5.5.0" 605 | "@ethersproject/wallet" "5.5.0" 606 | "@ethersproject/web" "5.5.1" 607 | "@ethersproject/wordlists" "5.5.0" 608 | 609 | file-api@^0.10.4: 610 | version "0.10.4" 611 | resolved "https://registry.yarnpkg.com/file-api/-/file-api-0.10.4.tgz#2f101226db727cc0172a0dd688f2f6883d52883d" 612 | integrity sha1-LxASJttyfMAXKg3WiPL2iD1SiD0= 613 | dependencies: 614 | File ">= 0.10.0" 615 | FileList ">= 0.10.0" 616 | bufferjs "> 0.2.0" 617 | file-error ">= 0.10.0" 618 | filereader ">= 0.10.3" 619 | formdata ">= 0.10.0" 620 | mime ">= 1.2.11" 621 | remedial ">= 1.0.7" 622 | 623 | "file-error@>= 0.10.0": 624 | version "0.10.2" 625 | resolved "https://registry.yarnpkg.com/file-error/-/file-error-0.10.2.tgz#963b48b9273b3d4b84b400ee571bc78b1739724a" 626 | integrity sha1-ljtIuSc7PUuEtADuVxvHixc5cko= 627 | 628 | "filereader@>= 0.10.3", filereader@^0.10.3: 629 | version "0.10.3" 630 | resolved "https://registry.yarnpkg.com/filereader/-/filereader-0.10.3.tgz#c747d4a2cd8f61e5418a7c07fe1257a43f0acdb1" 631 | integrity sha1-x0fUos2PYeVBinwH/hJXpD8KzbE= 632 | 633 | foreachasync@^3.0.0: 634 | version "3.0.0" 635 | resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" 636 | integrity sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY= 637 | 638 | form-data@^3.0.0: 639 | version "3.0.1" 640 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" 641 | integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== 642 | dependencies: 643 | asynckit "^0.4.0" 644 | combined-stream "^1.0.8" 645 | mime-types "^2.1.12" 646 | 647 | "formdata@>= 0.10.0": 648 | version "0.10.4" 649 | resolved "https://registry.yarnpkg.com/formdata/-/formdata-0.10.4.tgz#9621fdc0cc361f4a0111de5d25b35f6a78dc55a0" 650 | integrity sha1-liH9wMw2H0oBEd5dJbNfanjcVaA= 651 | dependencies: 652 | File "^0.10.2" 653 | FileList "^0.10.2" 654 | bufferjs "^2.0.0" 655 | filereader "^0.10.3" 656 | foreachasync "^3.0.0" 657 | remedial "^1.0.7" 658 | 659 | hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: 660 | version "1.1.7" 661 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 662 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 663 | dependencies: 664 | inherits "^2.0.3" 665 | minimalistic-assert "^1.0.1" 666 | 667 | hmac-drbg@^1.0.1: 668 | version "1.0.1" 669 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 670 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= 671 | dependencies: 672 | hash.js "^1.0.3" 673 | minimalistic-assert "^1.0.0" 674 | minimalistic-crypto-utils "^1.0.1" 675 | 676 | inherits@^2.0.3, inherits@^2.0.4: 677 | version "2.0.4" 678 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 679 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 680 | 681 | is-obj@^2.0.0: 682 | version "2.0.0" 683 | resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" 684 | integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== 685 | 686 | js-sha3@0.8.0: 687 | version "0.8.0" 688 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" 689 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== 690 | 691 | lodash.isequal@^4.5.0: 692 | version "4.5.0" 693 | resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" 694 | integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= 695 | 696 | make-error@^1.1.1: 697 | version "1.3.6" 698 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 699 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 700 | 701 | mime-db@1.51.0: 702 | version "1.51.0" 703 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" 704 | integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== 705 | 706 | mime-types@^2.1.12: 707 | version "2.1.34" 708 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" 709 | integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== 710 | dependencies: 711 | mime-db "1.51.0" 712 | 713 | "mime@>= 0.0.0", "mime@>= 1.2.11": 714 | version "3.0.0" 715 | resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" 716 | integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== 717 | 718 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 719 | version "1.0.1" 720 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 721 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 722 | 723 | minimalistic-crypto-utils@^1.0.1: 724 | version "1.0.1" 725 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 726 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= 727 | 728 | node-fetch@2.6.1: 729 | version "2.6.1" 730 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" 731 | integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== 732 | 733 | node-fetch@^2.6.1, node-fetch@^2.6.6: 734 | version "2.6.6" 735 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" 736 | integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== 737 | dependencies: 738 | whatwg-url "^5.0.0" 739 | 740 | oauth-1.0a@^2.2.4: 741 | version "2.2.6" 742 | resolved "https://registry.yarnpkg.com/oauth-1.0a/-/oauth-1.0a-2.2.6.tgz#eadbccdb3bceea412d24586e6f39b2b412f0e491" 743 | integrity sha512-6bkxv3N4Gu5lty4viIcIAnq5GbxECviMBeKR3WX/q87SPQ8E8aursPZUtsXDnxCs787af09WPRBLqYrf/lwoYQ== 744 | 745 | ow@^0.27.0: 746 | version "0.27.0" 747 | resolved "https://registry.yarnpkg.com/ow/-/ow-0.27.0.tgz#d44da088e8184fa11de64b5813206f9f86ab68d0" 748 | integrity sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ== 749 | dependencies: 750 | "@sindresorhus/is" "^4.0.1" 751 | callsites "^3.1.0" 752 | dot-prop "^6.0.1" 753 | lodash.isequal "^4.5.0" 754 | type-fest "^1.2.1" 755 | vali-date "^1.0.0" 756 | 757 | prettier@^2.5.1: 758 | version "2.5.1" 759 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" 760 | integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== 761 | 762 | "remedial@>= 1.0.7", remedial@^1.0.7: 763 | version "1.0.8" 764 | resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" 765 | integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg== 766 | 767 | scrypt-js@3.0.1: 768 | version "3.0.1" 769 | resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" 770 | integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== 771 | 772 | timeago.js@^4.0.2: 773 | version "4.0.2" 774 | resolved "https://registry.yarnpkg.com/timeago.js/-/timeago.js-4.0.2.tgz#724e8c8833e3490676c7bb0a75f5daf20e558028" 775 | integrity sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w== 776 | 777 | tr46@~0.0.3: 778 | version "0.0.3" 779 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 780 | integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= 781 | 782 | ts-mixer@^6.0.0: 783 | version "6.0.0" 784 | resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.0.tgz#4e631d3a36e3fa9521b973b132e8353bc7267f9f" 785 | integrity sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ== 786 | 787 | ts-node@^10.4.0: 788 | version "10.4.0" 789 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" 790 | integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== 791 | dependencies: 792 | "@cspotcode/source-map-support" "0.7.0" 793 | "@tsconfig/node10" "^1.0.7" 794 | "@tsconfig/node12" "^1.0.7" 795 | "@tsconfig/node14" "^1.0.0" 796 | "@tsconfig/node16" "^1.0.2" 797 | acorn "^8.4.1" 798 | acorn-walk "^8.1.1" 799 | arg "^4.1.0" 800 | create-require "^1.1.0" 801 | diff "^4.0.1" 802 | make-error "^1.1.1" 803 | yn "3.1.1" 804 | 805 | tslib@^2.3.1: 806 | version "2.3.1" 807 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" 808 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== 809 | 810 | twitter-lite@^1.1.0: 811 | version "1.1.0" 812 | resolved "https://registry.yarnpkg.com/twitter-lite/-/twitter-lite-1.1.0.tgz#77f250cc73f14ecc5a493ddb81ff0a3e9ae72680" 813 | integrity sha512-v37I0zyYXjn3/zdm/ii+1RiBFZ2SCB3wLl1N5nfW8TUqoNDYBR66oXBFbQavKEvjg5WqcTUzNhAhe6FkgylPsw== 814 | dependencies: 815 | cross-fetch "^3.0.0" 816 | oauth-1.0a "^2.2.4" 817 | 818 | type-fest@^1.2.1: 819 | version "1.4.0" 820 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" 821 | integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== 822 | 823 | typescript@^4.5.4: 824 | version "4.5.4" 825 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" 826 | integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== 827 | 828 | vali-date@^1.0.0: 829 | version "1.0.0" 830 | resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" 831 | integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= 832 | 833 | webidl-conversions@^3.0.0: 834 | version "3.0.1" 835 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 836 | integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= 837 | 838 | whatwg-url@^5.0.0: 839 | version "5.0.0" 840 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 841 | integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= 842 | dependencies: 843 | tr46 "~0.0.3" 844 | webidl-conversions "^3.0.0" 845 | 846 | ws@7.4.6: 847 | version "7.4.6" 848 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" 849 | integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== 850 | 851 | ws@^8.2.3: 852 | version "8.3.0" 853 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d" 854 | integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw== 855 | 856 | yn@3.1.1: 857 | version "3.1.1" 858 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 859 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 860 | --------------------------------------------------------------------------------