├── .prettierrc ├── nest-cli.json ├── tsconfig.build.json ├── example.env ├── src ├── main.ts ├── app.module.ts ├── fiat-symobols.json ├── config.ts ├── app.service.ts └── abi │ └── looksRareABI.json ├── tsconfig.json ├── .gitignore ├── .eslintrc.js ├── LICENSE ├── README.md └── package.json /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | TW_CONSUMER_KEY="" 2 | TW_CONSUMER_SECRET="" 3 | TW_ACCESS_TOKEN_KEY="" 4 | TW_ACCESS_TOKEN_SECRET="" 5 | 6 | ALCHEMY_API_KEY="" -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | await NestFactory.create(AppModule); 6 | } 7 | 8 | bootstrap(); 9 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { HttpModule } from '@nestjs/axios'; 3 | 4 | import { AppService } from './app.service'; 5 | 6 | @Module({ 7 | imports: [HttpModule], 8 | controllers: [], 9 | providers: [AppService], 10 | }) 11 | 12 | export class AppModule {} 13 | -------------------------------------------------------------------------------- /src/fiat-symobols.json: -------------------------------------------------------------------------------- 1 | { 2 | "eth": { 3 | "symbol": "Ξ" 4 | }, 5 | "usd": { 6 | "symbol": "$" 7 | }, 8 | "cad": { 9 | "symbol": "$" 10 | }, 11 | "eur": { 12 | "symbol": "€" 13 | }, 14 | "gbp": { 15 | "symbol": "£" 16 | }, 17 | "aud": { 18 | "symbol": "$" 19 | }, 20 | "cny": { 21 | "symbol": "¥" 22 | }, 23 | "jpy": { 24 | "symbol": "¥" 25 | } 26 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "resolveJsonModule": true, 16 | "esModuleInterop": true, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | .env 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | pnpm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | 15 | # OS 16 | .DS_Store 17 | 18 | # Tests 19 | /coverage 20 | /.nyc_output 21 | 22 | # IDEs and editors 23 | /.idea 24 | .project 25 | .classpath 26 | .c9/ 27 | *.launch 28 | .settings/ 29 | *.sublime-workspace 30 | 31 | # IDE - VSCode 32 | .vscode/* 33 | !.vscode/settings.json 34 | !.vscode/tasks.json 35 | !.vscode/launch.json 36 | !.vscode/extensions.json -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | sourceType: 'module', 6 | }, 7 | plugins: ['@typescript-eslint/eslint-plugin'], 8 | extends: [], 9 | root: true, 10 | env: { 11 | node: true, 12 | jest: true, 13 | }, 14 | ignorePatterns: ['.eslintrc.js'], 15 | rules: { 16 | '@typescript-eslint/interface-name-prefix': 'off', 17 | '@typescript-eslint/explicit-function-return-type': 'off', 18 | '@typescript-eslint/explicit-module-boundary-types': 'off', 19 | '@typescript-eslint/no-explicit-any': 'off', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ‼️ This repo is no longer maintained & has been deprecated in favor of https://github.com/Crypto-Phunks/nft-sales-twitter-bot 2 | 3 |

Twitter NFT sales bot

4 | 5 | ## Description 6 | 7 | Tweets real-time NFT sales for ERC721 Smart contracts 8 | 9 | In order to use this you’ll need to apply for Elevated access via the Twitter Developer Portal. You can learn more [here](https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api#v2-access-leve). 10 | 11 | ## Installation 12 | 13 | ```bash 14 | $ npm install 15 | ``` 16 | 17 | 1. Create `.env` file & add contents from `example.env` -- Add your API credentials. 18 | 2. Edit the `src/config.ts` file to add your smart contract & customize the tweet parameters. 19 | 3. Edit `src/app.service.ts` to customize for your use (Experienced users only & not a requirement). 20 | 4. Build & Deploy `npm run build` 21 | 5. Feel free to reach out on twitter 22 | 23 | ## Running the app 24 | 25 | ```bash 26 | # development 27 | $ npm run start 28 | 29 | # watch mode 30 | $ npm run start:dev 31 | 32 | # production mode 33 | $ npm run start:prod 34 | ``` 35 | 36 | ## Created by 37 | 38 | - Author - [Chopper](https://twitter.com/chopper__dad) 39 | 40 | ## License 41 | 42 | Created using [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 43 | Nest is [MIT licensed](LICENSE). 44 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const config = { 2 | // Contract Address ======================================== // 3 | contract_address: '0x23581767a106ae21c074b2276D25e5C3e136a68b', 4 | // Fiat Conversion Currency ================================ // 5 | // Available Options: ====================================== // 6 | // usd, aud, gbp, eur, cad, jpy, cny ======================= // 7 | currency: 'usd', 8 | // Message ================================================= // 9 | // Available Parameters: =================================== // 10 | // ==================== Token ID of transfered NFT // 11 | // ================= Value of transactions in eth // 12 | // =============== Value of transactions in fiat // 13 | // =========================== The transaction hash // 14 | // ===================================== From address // 15 | // ========================================= To address // 16 | message: '🚨 MOONBIRD # was sold for 💰 ()\n\nfrom: \nto: \n\nhttps://etherscan.io/tx/\nhttps://opensea.io/assets/0x23581767a106ae21c074b2276d25e5c3e136a68b/\nhttps://looksrare.org/collections/0x23581767a106ae21c074b2276d25e5c3e136a68b/\n\n#MOONBIRDS #NFT', 17 | // Prefer ENS over 0x address (Uses more Alchemy requests) = // 18 | // Available Options: ====================================== // 19 | // true, false ============================================= // 20 | ens: true, 21 | // Include free mints in tweets ============================ // 22 | // Available Options: ====================================== // 23 | // true, false ============================================= // 24 | includeFreeMint: false, 25 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nft-sales-twitter-bot", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "chopper", 6 | "license": "UNLICENSED", 7 | "scripts": { 8 | "prebuild": "rimraf dist", 9 | "build": "nest build", 10 | "start": "nest start", 11 | "start:dev": "nest start --watch", 12 | "start:debug": "nest start --debug --watch", 13 | "start:prod": "node dist/main" 14 | }, 15 | "dependencies": { 16 | "@nestjs/axios": "0.0.7", 17 | "@nestjs/common": "^8.0.0", 18 | "@nestjs/core": "^8.0.0", 19 | "@nestjs/platform-express": "^8.0.0", 20 | "axios": "^0.26.1", 21 | "currency.js": "^2.0.4", 22 | "dotenv": "^16.0.0", 23 | "ethers": "^5.6.1", 24 | "lodash": "^4.17.21", 25 | "moment": "^2.29.1", 26 | "reflect-metadata": "^0.1.13", 27 | "rimraf": "^3.0.2", 28 | "rxjs": "^7.2.0", 29 | "twit": "^2.2.11", 30 | "web3-utils": "^1.7.1" 31 | }, 32 | "devDependencies": { 33 | "@nestjs/cli": "^8.0.0", 34 | "@nestjs/schematics": "^8.0.0", 35 | "@nestjs/testing": "^8.0.0", 36 | "@types/express": "^4.17.13", 37 | "@types/jest": "27.4.1", 38 | "@types/node": "^16.0.0", 39 | "@types/supertest": "^2.0.11", 40 | "@typescript-eslint/eslint-plugin": "^5.0.0", 41 | "@typescript-eslint/parser": "^5.0.0", 42 | "eslint": "^8.0.1", 43 | "eslint-config-prettier": "^8.3.0", 44 | "eslint-plugin-prettier": "^4.0.0", 45 | "jest": "^27.2.5", 46 | "prettier": "^2.3.2", 47 | "source-map-support": "^0.5.20", 48 | "supertest": "^6.1.3", 49 | "ts-jest": "^27.0.3", 50 | "ts-loader": "^9.2.3", 51 | "ts-node": "^10.0.0", 52 | "tsconfig-paths": "^3.10.1", 53 | "typescript": "^4.3.5" 54 | }, 55 | "jest": { 56 | "moduleFileExtensions": [ 57 | "js", 58 | "json", 59 | "ts" 60 | ], 61 | "rootDir": "src", 62 | "testRegex": ".*\\.spec\\.ts$", 63 | "transform": { 64 | "^.+\\.(t|j)s$": "ts-jest" 65 | }, 66 | "collectCoverageFrom": [ 67 | "**/*.(t|j)s" 68 | ], 69 | "coverageDirectory": "../coverage", 70 | "testEnvironment": "node" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { HttpService } from '@nestjs/axios'; 3 | 4 | import twit from 'twit'; 5 | 6 | import { BigNumber, ethers } from 'ethers'; 7 | import { hexToNumberString, hexToString, stripHexPrefix } from 'web3-utils'; 8 | 9 | import { catchError, firstValueFrom, map, Observable, of, switchMap, timer } from 'rxjs'; 10 | 11 | import currency from 'currency.js'; 12 | 13 | import dotenv from 'dotenv'; 14 | dotenv.config(); 15 | 16 | import looksRareABI from './abi/looksRareABI.json'; 17 | 18 | import { config } from './config'; 19 | import fiatSymbols from './fiat-symobols.json'; 20 | 21 | const alchemyAPIUrl = 'https://eth-mainnet.alchemyapi.io/v2/'; 22 | const alchemyAPIKey = process.env.ALCHEMY_API_KEY; 23 | 24 | const tokenContractAddress = config.contract_address; 25 | const looksRareContractAddress = '0x59728544b08ab483533076417fbbb2fd0b17ce3a'; // Don't change unless deprecated 26 | 27 | const provider = new ethers.providers.JsonRpcProvider(alchemyAPIUrl + alchemyAPIKey); 28 | const looksInterface = new ethers.utils.Interface(looksRareABI); 29 | 30 | // This can be an array if you want to filter by multiple topics 31 | // 'Transfer' topic 32 | const topics = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; 33 | 34 | const twitterConfig = { 35 | consumer_key: process.env.TW_CONSUMER_KEY, 36 | consumer_secret: process.env.TW_CONSUMER_SECRET, 37 | access_token: process.env.TW_ACCESS_TOKEN_KEY, 38 | access_token_secret: process.env.TW_ACCESS_TOKEN_SECRET, 39 | }; 40 | 41 | const twitterClient = new twit(twitterConfig); 42 | 43 | interface Response { 44 | from: any; 45 | to: any; 46 | tokenId: string; 47 | ether: number; 48 | transactionHash: string; 49 | looksRareValue: number; 50 | imageUrl?: string; 51 | } 52 | 53 | @Injectable() 54 | export class AppService { 55 | 56 | fiatValues: any; 57 | 58 | constructor( 59 | private readonly http: HttpService 60 | ) { 61 | 62 | this.getEthToFiat().subscribe((fiat) => this.fiatValues = fiat.ethereum); 63 | 64 | // Listen for Transfer event 65 | provider.on({ address: tokenContractAddress, topics: [topics] }, (tx) => { 66 | this.getTransactionDetails(tx).then((res) => { 67 | 68 | // Only tweet transfers with value (Ignore w2w transfers) 69 | if (res?.ether || res?.looksRareValue) this.tweet(res); 70 | // If free mint is enabled we can tweet 0 value 71 | else if (config.includeFreeMint) this.tweet(res); 72 | 73 | // console.log(res); 74 | }); 75 | }); 76 | } 77 | 78 | async getTransactionDetails(tx: any): Promise { 79 | 80 | let tokenId: string; 81 | 82 | try { 83 | 84 | // Get addresses of seller / buyer from topics 85 | let from = ethers.utils.defaultAbiCoder.decode(['address'], tx?.topics[1])[0]; 86 | let to = ethers.utils.defaultAbiCoder.decode(['address'], tx?.topics[2])[0]; 87 | 88 | // Get tokenId from topics 89 | tokenId = hexToNumberString(tx?.topics[3]); 90 | 91 | // Get transaction hash 92 | const { transactionHash } = tx; 93 | const isMint = BigNumber.from(from).isZero(); 94 | 95 | // Get transaction 96 | const transaction = await provider.getTransaction(transactionHash); 97 | const { value } = transaction; 98 | const ether = ethers.utils.formatEther(value.toString()); 99 | 100 | // Get transaction receipt 101 | const receipt: any = await provider.getTransactionReceipt(transactionHash); 102 | 103 | // Get token image 104 | const imageUrl = await this.getTokenMetadata(tokenId); 105 | 106 | // Check if LooksRare & parse the event & get the value 107 | let looksRareValue = 0; 108 | const LR = receipt.logs.map((log: any) => { 109 | if (log.address.toLowerCase() === looksRareContractAddress.toLowerCase()) { 110 | return looksInterface.parseLog(log); 111 | } 112 | }).filter((log: any) => log?.name === 'TakerAsk'); 113 | 114 | if (LR.length) { 115 | const weiValue = (LR[0]?.args?.price)?.toString(); 116 | const value = ethers.utils.formatEther(weiValue); 117 | looksRareValue = parseFloat(value); 118 | } 119 | 120 | // If ens is configured, get ens addresses 121 | let ensTo: string; 122 | let ensFrom: string; 123 | if (config.ens) { 124 | ensTo = await provider.lookupAddress(`${to}`); 125 | ensFrom = await provider.lookupAddress(`${from}`); 126 | } 127 | 128 | // Set the values for address to & from -- Shorten non ens 129 | to = config.ens ? (ensTo ? ensTo : this.shortenAddress(to)) : this.shortenAddress(to); 130 | from = (isMint && config.includeFreeMint) ? 'Mint' : config.ens ? (ensFrom ? ensFrom : this.shortenAddress(from)) : this.shortenAddress(from); 131 | 132 | // Create response object 133 | const response: Response = { 134 | from, 135 | to, 136 | tokenId, 137 | ether: parseFloat(ether), 138 | transactionHash, 139 | looksRareValue 140 | }; 141 | 142 | // If the image was successfully obtained 143 | if (imageUrl) response.imageUrl = imageUrl; 144 | 145 | return response; 146 | 147 | } catch (err) { 148 | console.log(`${tokenId} failed to send`); 149 | return null; 150 | } 151 | } 152 | 153 | shortenAddress(address: string): string { 154 | const shortAddress = `${address.slice(0, 5)}...${address.slice(address.length - 5, address.length)}`; 155 | if (address.startsWith('0x')) return shortAddress; 156 | return address; 157 | } 158 | 159 | async getTokenMetadata(tokenId: string): Promise { 160 | const url = alchemyAPIUrl + alchemyAPIKey + '/getNFTMetadata'; 161 | return await firstValueFrom( 162 | this.http.get(url, { 163 | params: { 164 | contractAddress: tokenContractAddress, 165 | tokenId, 166 | tokenType: 'erc721' 167 | } 168 | }).pipe( 169 | map((res: any) => { 170 | return res?.data?.metadata?.image_url || res?.data?.metadata?.image || res?.data?.tokenUri?.gateway; 171 | }), 172 | catchError(() => { 173 | return of(null); 174 | }) 175 | ) 176 | ); 177 | } 178 | 179 | async tweet(data: any) { 180 | 181 | let tweetText: string; 182 | 183 | // Cash value 184 | const fiatValue = this.fiatValues[config.currency] * (data.ether ? data.ether : data.looksRareValue); 185 | const fiat = currency(fiatValue, { symbol: fiatSymbols[config.currency].symbol, precision: 0 }); 186 | 187 | const ethValue = data.ether ? data.ether : data.looksRareValue; 188 | const eth = currency(ethValue, { symbol: 'Ξ', precision: 3 }); 189 | 190 | // Replace tokens from config file 191 | tweetText = config.message.replace(new RegExp('', 'g'), data.tokenId); 192 | tweetText = tweetText.replace(new RegExp('', 'g'), eth.format()); 193 | tweetText = tweetText.replace(new RegExp('', 'g'), data.transactionHash); 194 | tweetText = tweetText.replace(new RegExp('', 'g'), data.from); 195 | tweetText = tweetText.replace(new RegExp('', 'g'), data.to); 196 | tweetText = tweetText.replace(new RegExp('', 'g'), fiat.format()); 197 | 198 | // Format our image to base64 199 | const image = this.transformImage(data.imageUrl); 200 | 201 | let processedImage: string; 202 | if (image) processedImage = await this.getBase64(image); 203 | 204 | let media_ids: Array; 205 | if (processedImage) { 206 | // Upload the item's image to Twitter & retrieve a reference to it 207 | media_ids = await new Promise((resolve) => { 208 | twitterClient.post('media/upload', { media_data: processedImage }, (error, media: any) => { 209 | resolve(error ? null : [media.media_id_string]); 210 | }); 211 | }); 212 | } 213 | 214 | let tweet: any = { status: tweetText }; 215 | if (media_ids) tweet.media_ids = media_ids; 216 | 217 | // Post the tweet 👇 218 | // If you need access to this endpoint, you’ll need to apply for Elevated access via the Developer Portal. You can learn more here: https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api#v2-access-leve 219 | twitterClient.post('statuses/update', tweet, (error) => { 220 | if (!error) console.log(`Successfully tweeted: ${tweetText}`); 221 | else console.error(error); 222 | }); 223 | } 224 | 225 | async getBase64(url: string) { 226 | return await firstValueFrom( 227 | this.http.get(url, { responseType: 'arraybuffer' }).pipe( 228 | map((res) => Buffer.from(res.data, 'binary').toString('base64')), 229 | catchError(() => of(null)) 230 | ) 231 | ); 232 | } 233 | 234 | getEthToFiat(): Observable { 235 | const endpoint = `https://api.coingecko.com/api/v3/simple/price`; 236 | const params = { 237 | ids: 'ethereum', 238 | vs_currencies: 'usd,aud,gbp,eur,cad,jpy,cny' 239 | }; 240 | return timer(0, 300000).pipe( 241 | switchMap(() => this.http.get(endpoint, {params})), 242 | map((res: any) => res.data), 243 | // tap((res) => console.log(res)), 244 | catchError((err: any) => { 245 | console.log(err); 246 | return of({}); 247 | }) 248 | ); 249 | } 250 | 251 | transformImage(value: string): string { 252 | let val: any = value; 253 | if (value?.includes('gateway.pinata.cloud')) { 254 | val = value.replace('gateway.pinata.cloud', 'cloudflare-ipfs.com'); 255 | // } else if (value?.startsWith('data:image')) { 256 | // val = `${value}`; 257 | } else if (value?.startsWith('ipfs://')) { 258 | val = value.replace('ipfs://', 'https://cloudflare-ipfs.com/ipfs/'); 259 | } 260 | return val ? val : null; 261 | } 262 | 263 | } 264 | -------------------------------------------------------------------------------- /src/abi/looksRareABI.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_currencyManager", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_executionManager", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "address", 16 | "name": "_royaltyFeeManager", 17 | "type": "address" 18 | }, 19 | { "internalType": "address", "name": "_WETH", "type": "address" }, 20 | { 21 | "internalType": "address", 22 | "name": "_protocolFeeRecipient", 23 | "type": "address" 24 | } 25 | ], 26 | "stateMutability": "nonpayable", 27 | "type": "constructor" 28 | }, 29 | { 30 | "anonymous": false, 31 | "inputs": [ 32 | { 33 | "indexed": true, 34 | "internalType": "address", 35 | "name": "user", 36 | "type": "address" 37 | }, 38 | { 39 | "indexed": false, 40 | "internalType": "uint256", 41 | "name": "newMinNonce", 42 | "type": "uint256" 43 | } 44 | ], 45 | "name": "CancelAllOrders", 46 | "type": "event" 47 | }, 48 | { 49 | "anonymous": false, 50 | "inputs": [ 51 | { 52 | "indexed": true, 53 | "internalType": "address", 54 | "name": "user", 55 | "type": "address" 56 | }, 57 | { 58 | "indexed": false, 59 | "internalType": "uint256[]", 60 | "name": "orderNonces", 61 | "type": "uint256[]" 62 | } 63 | ], 64 | "name": "CancelMultipleOrders", 65 | "type": "event" 66 | }, 67 | { 68 | "anonymous": false, 69 | "inputs": [ 70 | { 71 | "indexed": true, 72 | "internalType": "address", 73 | "name": "currencyManager", 74 | "type": "address" 75 | } 76 | ], 77 | "name": "NewCurrencyManager", 78 | "type": "event" 79 | }, 80 | { 81 | "anonymous": false, 82 | "inputs": [ 83 | { 84 | "indexed": true, 85 | "internalType": "address", 86 | "name": "executionManager", 87 | "type": "address" 88 | } 89 | ], 90 | "name": "NewExecutionManager", 91 | "type": "event" 92 | }, 93 | { 94 | "anonymous": false, 95 | "inputs": [ 96 | { 97 | "indexed": true, 98 | "internalType": "address", 99 | "name": "protocolFeeRecipient", 100 | "type": "address" 101 | } 102 | ], 103 | "name": "NewProtocolFeeRecipient", 104 | "type": "event" 105 | }, 106 | { 107 | "anonymous": false, 108 | "inputs": [ 109 | { 110 | "indexed": true, 111 | "internalType": "address", 112 | "name": "royaltyFeeManager", 113 | "type": "address" 114 | } 115 | ], 116 | "name": "NewRoyaltyFeeManager", 117 | "type": "event" 118 | }, 119 | { 120 | "anonymous": false, 121 | "inputs": [ 122 | { 123 | "indexed": true, 124 | "internalType": "address", 125 | "name": "transferSelectorNFT", 126 | "type": "address" 127 | } 128 | ], 129 | "name": "NewTransferSelectorNFT", 130 | "type": "event" 131 | }, 132 | { 133 | "anonymous": false, 134 | "inputs": [ 135 | { 136 | "indexed": true, 137 | "internalType": "address", 138 | "name": "previousOwner", 139 | "type": "address" 140 | }, 141 | { 142 | "indexed": true, 143 | "internalType": "address", 144 | "name": "newOwner", 145 | "type": "address" 146 | } 147 | ], 148 | "name": "OwnershipTransferred", 149 | "type": "event" 150 | }, 151 | { 152 | "anonymous": false, 153 | "inputs": [ 154 | { 155 | "indexed": true, 156 | "internalType": "address", 157 | "name": "collection", 158 | "type": "address" 159 | }, 160 | { 161 | "indexed": true, 162 | "internalType": "uint256", 163 | "name": "tokenId", 164 | "type": "uint256" 165 | }, 166 | { 167 | "indexed": true, 168 | "internalType": "address", 169 | "name": "royaltyRecipient", 170 | "type": "address" 171 | }, 172 | { 173 | "indexed": false, 174 | "internalType": "address", 175 | "name": "currency", 176 | "type": "address" 177 | }, 178 | { 179 | "indexed": false, 180 | "internalType": "uint256", 181 | "name": "amount", 182 | "type": "uint256" 183 | } 184 | ], 185 | "name": "RoyaltyPayment", 186 | "type": "event" 187 | }, 188 | { 189 | "anonymous": false, 190 | "inputs": [ 191 | { 192 | "indexed": false, 193 | "internalType": "bytes32", 194 | "name": "orderHash", 195 | "type": "bytes32" 196 | }, 197 | { 198 | "indexed": false, 199 | "internalType": "uint256", 200 | "name": "orderNonce", 201 | "type": "uint256" 202 | }, 203 | { 204 | "indexed": true, 205 | "internalType": "address", 206 | "name": "taker", 207 | "type": "address" 208 | }, 209 | { 210 | "indexed": true, 211 | "internalType": "address", 212 | "name": "maker", 213 | "type": "address" 214 | }, 215 | { 216 | "indexed": true, 217 | "internalType": "address", 218 | "name": "strategy", 219 | "type": "address" 220 | }, 221 | { 222 | "indexed": false, 223 | "internalType": "address", 224 | "name": "currency", 225 | "type": "address" 226 | }, 227 | { 228 | "indexed": false, 229 | "internalType": "address", 230 | "name": "collection", 231 | "type": "address" 232 | }, 233 | { 234 | "indexed": false, 235 | "internalType": "uint256", 236 | "name": "tokenId", 237 | "type": "uint256" 238 | }, 239 | { 240 | "indexed": false, 241 | "internalType": "uint256", 242 | "name": "amount", 243 | "type": "uint256" 244 | }, 245 | { 246 | "indexed": false, 247 | "internalType": "uint256", 248 | "name": "price", 249 | "type": "uint256" 250 | } 251 | ], 252 | "name": "TakerAsk", 253 | "type": "event" 254 | }, 255 | { 256 | "anonymous": false, 257 | "inputs": [ 258 | { 259 | "indexed": false, 260 | "internalType": "bytes32", 261 | "name": "orderHash", 262 | "type": "bytes32" 263 | }, 264 | { 265 | "indexed": false, 266 | "internalType": "uint256", 267 | "name": "orderNonce", 268 | "type": "uint256" 269 | }, 270 | { 271 | "indexed": true, 272 | "internalType": "address", 273 | "name": "taker", 274 | "type": "address" 275 | }, 276 | { 277 | "indexed": true, 278 | "internalType": "address", 279 | "name": "maker", 280 | "type": "address" 281 | }, 282 | { 283 | "indexed": true, 284 | "internalType": "address", 285 | "name": "strategy", 286 | "type": "address" 287 | }, 288 | { 289 | "indexed": false, 290 | "internalType": "address", 291 | "name": "currency", 292 | "type": "address" 293 | }, 294 | { 295 | "indexed": false, 296 | "internalType": "address", 297 | "name": "collection", 298 | "type": "address" 299 | }, 300 | { 301 | "indexed": false, 302 | "internalType": "uint256", 303 | "name": "tokenId", 304 | "type": "uint256" 305 | }, 306 | { 307 | "indexed": false, 308 | "internalType": "uint256", 309 | "name": "amount", 310 | "type": "uint256" 311 | }, 312 | { 313 | "indexed": false, 314 | "internalType": "uint256", 315 | "name": "price", 316 | "type": "uint256" 317 | } 318 | ], 319 | "name": "TakerBid", 320 | "type": "event" 321 | }, 322 | { 323 | "inputs": [], 324 | "name": "DOMAIN_SEPARATOR", 325 | "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], 326 | "stateMutability": "view", 327 | "type": "function" 328 | }, 329 | { 330 | "inputs": [], 331 | "name": "WETH", 332 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 333 | "stateMutability": "view", 334 | "type": "function" 335 | }, 336 | { 337 | "inputs": [ 338 | { "internalType": "uint256", "name": "minNonce", "type": "uint256" } 339 | ], 340 | "name": "cancelAllOrdersForSender", 341 | "outputs": [], 342 | "stateMutability": "nonpayable", 343 | "type": "function" 344 | }, 345 | { 346 | "inputs": [ 347 | { 348 | "internalType": "uint256[]", 349 | "name": "orderNonces", 350 | "type": "uint256[]" 351 | } 352 | ], 353 | "name": "cancelMultipleMakerOrders", 354 | "outputs": [], 355 | "stateMutability": "nonpayable", 356 | "type": "function" 357 | }, 358 | { 359 | "inputs": [], 360 | "name": "currencyManager", 361 | "outputs": [ 362 | { 363 | "internalType": "contract ICurrencyManager", 364 | "name": "", 365 | "type": "address" 366 | } 367 | ], 368 | "stateMutability": "view", 369 | "type": "function" 370 | }, 371 | { 372 | "inputs": [], 373 | "name": "executionManager", 374 | "outputs": [ 375 | { 376 | "internalType": "contract IExecutionManager", 377 | "name": "", 378 | "type": "address" 379 | } 380 | ], 381 | "stateMutability": "view", 382 | "type": "function" 383 | }, 384 | { 385 | "inputs": [ 386 | { "internalType": "address", "name": "user", "type": "address" }, 387 | { "internalType": "uint256", "name": "orderNonce", "type": "uint256" } 388 | ], 389 | "name": "isUserOrderNonceExecutedOrCancelled", 390 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], 391 | "stateMutability": "view", 392 | "type": "function" 393 | }, 394 | { 395 | "inputs": [ 396 | { 397 | "components": [ 398 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 399 | { "internalType": "address", "name": "taker", "type": "address" }, 400 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 401 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 402 | { 403 | "internalType": "uint256", 404 | "name": "minPercentageToAsk", 405 | "type": "uint256" 406 | }, 407 | { "internalType": "bytes", "name": "params", "type": "bytes" } 408 | ], 409 | "internalType": "struct OrderTypes.TakerOrder", 410 | "name": "takerBid", 411 | "type": "tuple" 412 | }, 413 | { 414 | "components": [ 415 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 416 | { "internalType": "address", "name": "signer", "type": "address" }, 417 | { 418 | "internalType": "address", 419 | "name": "collection", 420 | "type": "address" 421 | }, 422 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 423 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 424 | { "internalType": "uint256", "name": "amount", "type": "uint256" }, 425 | { "internalType": "address", "name": "strategy", "type": "address" }, 426 | { "internalType": "address", "name": "currency", "type": "address" }, 427 | { "internalType": "uint256", "name": "nonce", "type": "uint256" }, 428 | { "internalType": "uint256", "name": "startTime", "type": "uint256" }, 429 | { "internalType": "uint256", "name": "endTime", "type": "uint256" }, 430 | { 431 | "internalType": "uint256", 432 | "name": "minPercentageToAsk", 433 | "type": "uint256" 434 | }, 435 | { "internalType": "bytes", "name": "params", "type": "bytes" }, 436 | { "internalType": "uint8", "name": "v", "type": "uint8" }, 437 | { "internalType": "bytes32", "name": "r", "type": "bytes32" }, 438 | { "internalType": "bytes32", "name": "s", "type": "bytes32" } 439 | ], 440 | "internalType": "struct OrderTypes.MakerOrder", 441 | "name": "makerAsk", 442 | "type": "tuple" 443 | } 444 | ], 445 | "name": "matchAskWithTakerBid", 446 | "outputs": [], 447 | "stateMutability": "nonpayable", 448 | "type": "function" 449 | }, 450 | { 451 | "inputs": [ 452 | { 453 | "components": [ 454 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 455 | { "internalType": "address", "name": "taker", "type": "address" }, 456 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 457 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 458 | { 459 | "internalType": "uint256", 460 | "name": "minPercentageToAsk", 461 | "type": "uint256" 462 | }, 463 | { "internalType": "bytes", "name": "params", "type": "bytes" } 464 | ], 465 | "internalType": "struct OrderTypes.TakerOrder", 466 | "name": "takerBid", 467 | "type": "tuple" 468 | }, 469 | { 470 | "components": [ 471 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 472 | { "internalType": "address", "name": "signer", "type": "address" }, 473 | { 474 | "internalType": "address", 475 | "name": "collection", 476 | "type": "address" 477 | }, 478 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 479 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 480 | { "internalType": "uint256", "name": "amount", "type": "uint256" }, 481 | { "internalType": "address", "name": "strategy", "type": "address" }, 482 | { "internalType": "address", "name": "currency", "type": "address" }, 483 | { "internalType": "uint256", "name": "nonce", "type": "uint256" }, 484 | { "internalType": "uint256", "name": "startTime", "type": "uint256" }, 485 | { "internalType": "uint256", "name": "endTime", "type": "uint256" }, 486 | { 487 | "internalType": "uint256", 488 | "name": "minPercentageToAsk", 489 | "type": "uint256" 490 | }, 491 | { "internalType": "bytes", "name": "params", "type": "bytes" }, 492 | { "internalType": "uint8", "name": "v", "type": "uint8" }, 493 | { "internalType": "bytes32", "name": "r", "type": "bytes32" }, 494 | { "internalType": "bytes32", "name": "s", "type": "bytes32" } 495 | ], 496 | "internalType": "struct OrderTypes.MakerOrder", 497 | "name": "makerAsk", 498 | "type": "tuple" 499 | } 500 | ], 501 | "name": "matchAskWithTakerBidUsingETHAndWETH", 502 | "outputs": [], 503 | "stateMutability": "payable", 504 | "type": "function" 505 | }, 506 | { 507 | "inputs": [ 508 | { 509 | "components": [ 510 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 511 | { "internalType": "address", "name": "taker", "type": "address" }, 512 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 513 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 514 | { 515 | "internalType": "uint256", 516 | "name": "minPercentageToAsk", 517 | "type": "uint256" 518 | }, 519 | { "internalType": "bytes", "name": "params", "type": "bytes" } 520 | ], 521 | "internalType": "struct OrderTypes.TakerOrder", 522 | "name": "takerAsk", 523 | "type": "tuple" 524 | }, 525 | { 526 | "components": [ 527 | { "internalType": "bool", "name": "isOrderAsk", "type": "bool" }, 528 | { "internalType": "address", "name": "signer", "type": "address" }, 529 | { 530 | "internalType": "address", 531 | "name": "collection", 532 | "type": "address" 533 | }, 534 | { "internalType": "uint256", "name": "price", "type": "uint256" }, 535 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, 536 | { "internalType": "uint256", "name": "amount", "type": "uint256" }, 537 | { "internalType": "address", "name": "strategy", "type": "address" }, 538 | { "internalType": "address", "name": "currency", "type": "address" }, 539 | { "internalType": "uint256", "name": "nonce", "type": "uint256" }, 540 | { "internalType": "uint256", "name": "startTime", "type": "uint256" }, 541 | { "internalType": "uint256", "name": "endTime", "type": "uint256" }, 542 | { 543 | "internalType": "uint256", 544 | "name": "minPercentageToAsk", 545 | "type": "uint256" 546 | }, 547 | { "internalType": "bytes", "name": "params", "type": "bytes" }, 548 | { "internalType": "uint8", "name": "v", "type": "uint8" }, 549 | { "internalType": "bytes32", "name": "r", "type": "bytes32" }, 550 | { "internalType": "bytes32", "name": "s", "type": "bytes32" } 551 | ], 552 | "internalType": "struct OrderTypes.MakerOrder", 553 | "name": "makerBid", 554 | "type": "tuple" 555 | } 556 | ], 557 | "name": "matchBidWithTakerAsk", 558 | "outputs": [], 559 | "stateMutability": "nonpayable", 560 | "type": "function" 561 | }, 562 | { 563 | "inputs": [], 564 | "name": "owner", 565 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 566 | "stateMutability": "view", 567 | "type": "function" 568 | }, 569 | { 570 | "inputs": [], 571 | "name": "protocolFeeRecipient", 572 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 573 | "stateMutability": "view", 574 | "type": "function" 575 | }, 576 | { 577 | "inputs": [], 578 | "name": "renounceOwnership", 579 | "outputs": [], 580 | "stateMutability": "nonpayable", 581 | "type": "function" 582 | }, 583 | { 584 | "inputs": [], 585 | "name": "royaltyFeeManager", 586 | "outputs": [ 587 | { 588 | "internalType": "contract IRoyaltyFeeManager", 589 | "name": "", 590 | "type": "address" 591 | } 592 | ], 593 | "stateMutability": "view", 594 | "type": "function" 595 | }, 596 | { 597 | "inputs": [ 598 | { "internalType": "address", "name": "newOwner", "type": "address" } 599 | ], 600 | "name": "transferOwnership", 601 | "outputs": [], 602 | "stateMutability": "nonpayable", 603 | "type": "function" 604 | }, 605 | { 606 | "inputs": [], 607 | "name": "transferSelectorNFT", 608 | "outputs": [ 609 | { 610 | "internalType": "contract ITransferSelectorNFT", 611 | "name": "", 612 | "type": "address" 613 | } 614 | ], 615 | "stateMutability": "view", 616 | "type": "function" 617 | }, 618 | { 619 | "inputs": [ 620 | { 621 | "internalType": "address", 622 | "name": "_currencyManager", 623 | "type": "address" 624 | } 625 | ], 626 | "name": "updateCurrencyManager", 627 | "outputs": [], 628 | "stateMutability": "nonpayable", 629 | "type": "function" 630 | }, 631 | { 632 | "inputs": [ 633 | { 634 | "internalType": "address", 635 | "name": "_executionManager", 636 | "type": "address" 637 | } 638 | ], 639 | "name": "updateExecutionManager", 640 | "outputs": [], 641 | "stateMutability": "nonpayable", 642 | "type": "function" 643 | }, 644 | { 645 | "inputs": [ 646 | { 647 | "internalType": "address", 648 | "name": "_protocolFeeRecipient", 649 | "type": "address" 650 | } 651 | ], 652 | "name": "updateProtocolFeeRecipient", 653 | "outputs": [], 654 | "stateMutability": "nonpayable", 655 | "type": "function" 656 | }, 657 | { 658 | "inputs": [ 659 | { 660 | "internalType": "address", 661 | "name": "_royaltyFeeManager", 662 | "type": "address" 663 | } 664 | ], 665 | "name": "updateRoyaltyFeeManager", 666 | "outputs": [], 667 | "stateMutability": "nonpayable", 668 | "type": "function" 669 | }, 670 | { 671 | "inputs": [ 672 | { 673 | "internalType": "address", 674 | "name": "_transferSelectorNFT", 675 | "type": "address" 676 | } 677 | ], 678 | "name": "updateTransferSelectorNFT", 679 | "outputs": [], 680 | "stateMutability": "nonpayable", 681 | "type": "function" 682 | }, 683 | { 684 | "inputs": [{ "internalType": "address", "name": "", "type": "address" }], 685 | "name": "userMinOrderNonce", 686 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 687 | "stateMutability": "view", 688 | "type": "function" 689 | } 690 | ] 691 | --------------------------------------------------------------------------------