diff --git a/README.md b/README.md index d3c6189..2f81b97 100644 --- a/README.md +++ b/README.md @@ -17,22 +17,28 @@ ## 🤖 | Features: - **Auto registration** -- **Auto bind referral** -- **Auto bind twitter** -- **Auto collect all possible rewards (boxes, energy)** -- **Auto spin turntable** -- **Auto inject** -- **Auto bridge from SEPOLIA to MINT (testnet)** -- **Auto completing tasks** - - -## 📝 | Description: -```Auto bridge from SEPOLIA to MINT (testnet)``` -```- The script will bridge a random amount of ETH from SEPOLIA to MINT (testnet).``` - -```Auto completing tasks``` -```- The script will complete all twitter tasks and testnet``` - +- **Bind referral** +- **Bind twitter** +- **Collect all possible rewards (boxes, energy)** +- **Spin turntable** +- **Inject** +- **Completing tasks** +- **Bridge from ARB to MINT via CometBridge** +- **Fix sign** +- **Export Trees IDs** +- **Mint the following NFTs:** + + - Green ID + - Commemorative NFT + - Make NFT Great Again + - Flag NFT + - Shop NFT + - Air3 NFT + - SuperMint NFT + - Owlto SummerFest NFT + - Omnihub SummerFest NFT + - Vip3 NFT + - Summer NFT @@ -50,18 +56,22 @@ ## ⚙️ Config (config > settings.yaml) -| Name | Description | -|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------| -| referral_code | Your referral code | -| eth_rpc_url | ETH RPC URL (if not have, leave the default value) | -| sepolia_rpc_url | SEPOLIA RPC URL (if not have, leave the default value) | -| threads | Number of accounts that will work simultaneously | -| min_delay_before_start | min delay before start accounts actions (in seconds) | -| max_delay_before_start | max delay before start accounts actions (in seconds) | -| min_amount_to_bridge | min amount of ETH to bridge from SEPOLIA to MINT | -| max_amount_to_bridge | max amount of ETH to bridge from SEPOLIA to MINT | +| Name | Description | +|----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| referral_code | Your referral code | +| mint_rpc_url | MINT RPC URL (if not have, leave the default value) | +| arb_rpc_url | ARB RPC URL (if not have, leave the default value) | +| threads | Number of accounts that will work simultaneously | +| min_delay_before_start | min delay before start accounts actions (in seconds) | +| max_delay_before_start | max delay before start accounts actions (in seconds) | | spin_turntable_by_percentage_of_energy | percentage of balance that will be spent on spins (for example, if you have 500 energy daily and you bet 60%, the script will make 1 spin on your account) | -| shuffle_accounts | shuffle accounts before start | +| shuffle_accounts | shuffle accounts before start | +| mint_random_all_nfts | mint random NFTs in list | +delay_between_mint_min | min delay between mint NFTs (in seconds) | +| delay_between_mint_max | max delay between mint NFTs (in seconds) | +| comet_bridge_wallet | main wallet (pr or mnemonic) for bridge from ARB to MINT multi wallets | +| comet_bridge_amount_min | min amount for bridge from ARB to MINT | +| comet_bridge_amount_max | max amount for bridge from ARB to MINT | ## ⚙️ Accounts format (config > accounts.txt) diff --git a/abi/cometa.json b/abi/cometa.json new file mode 100644 index 0000000..fe3cfb9 --- /dev/null +++ b/abi/cometa.json @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AmountMustEqualValue","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"Initialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidArgs","type":"error"},{"inputs":[],"name":"InvalidProvider","type":"error"},{"inputs":[],"name":"InvalidRecipientAddress","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"OnlyEnabled","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ParamsError","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"Bridged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"EnableChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"Released","type":"event"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address payable","name":"provider","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable[]","name":"recipients","type":"address[]"},{"internalType":"bytes[]","name":"metadatas","type":"bytes[]"}],"name":"multiRelease","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"release","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"setIsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/abi/commemorative_nft.json b/abi/commemorative_nft.json new file mode 100644 index 0000000..f6049f2 --- /dev/null +++ b/abi/commemorative_nft.json @@ -0,0 +1,1141 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_nftName", + "type": "string" + }, + { + "internalType": "string", + "name": "_nftToken", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPerWallet", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "ref", + "type": "address" + } + ], + "name": "FundsDistributed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "ref", + "type": "address" + } + ], + "name": "MintWithRef", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "OWNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_addressData", + "outputs": [ + { + "internalType": "uint256", + "name": "WalletMinted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "WithdrawStatus", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEndless", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkMaxPerWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkOnlyCorePayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkTotalPayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkUnlimitedSupply", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "coreTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "name": "devMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPerWallet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "mintEndDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPause", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintStartDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutRefPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxperwallet", + "type": "uint256" + } + ], + "name": "setMaxPerWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + } + ], + "name": "setMintPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + } + ], + "name": "setNewEndDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + } + ], + "name": "setNewStartDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_pauseStatus", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_address", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_percent", + "type": "uint256[]" + } + ], + "name": "setPayoutCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ownerAddress", + "type": "address" + } + ], + "name": "setPayoutOwnerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutOwnerPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutRefPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/abi/green_id.json b/abi/green_id.json new file mode 100644 index 0000000..44a6e8d --- /dev/null +++ b/abi/green_id.json @@ -0,0 +1,775 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "TokenClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "claimedTokens", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "internalType": "struct GreenID.MintParam[]", + "name": "params", + "type": "tuple[]" + } + ], + "name": "mintBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "setDefaultURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "setDynamicURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/make_nft_great_again.json b/abi/make_nft_great_again.json new file mode 100644 index 0000000..ce0454d --- /dev/null +++ b/abi/make_nft_great_again.json @@ -0,0 +1,752 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_totalsupply", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "string", + "name": "__base_uri", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "ExceedingTotalSupply", + "type": "error" + }, + { + "inputs": [], + "name": "HasClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMerkleRoot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "IsStop", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroRoot", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256" + } + ], + "name": "BatchMetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "MetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "_baseUri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proofs", + "type": "bytes32[]" + } + ], + "name": "awardItem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAvailableCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isStop", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "merkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "baseUri", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_isStop", + "type": "bool" + } + ], + "name": "setStop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_tree", + "type": "bytes32" + } + ], + "name": "updateTree", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/mint_air3.json b/abi/mint_air3.json new file mode 100644 index 0000000..5861071 --- /dev/null +++ b/abi/mint_air3.json @@ -0,0 +1,1079 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_nftName", + "type": "string" + }, + { + "internalType": "string", + "name": "_nftToken", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPerWallet", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "OWNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_addressData", + "outputs": [ + { + "internalType": "uint256", + "name": "WalletMinted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "WithdrawStatus", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEndless", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkMaxPerWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkOnlyCorePayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkTotalPayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkUnlimitedSupply", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "coreTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "name": "devMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPerWallet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "mintEndDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPause", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintStartDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutRefPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxperwallet", + "type": "uint256" + } + ], + "name": "setMaxPerWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + } + ], + "name": "setMintPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + } + ], + "name": "setNewEndDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + } + ], + "name": "setNewStartDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_pauseStatus", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_address", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_percent", + "type": "uint256[]" + } + ], + "name": "setPayoutCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ownerAddress", + "type": "address" + } + ], + "name": "setPayoutOwnerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutOwnerPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutRefPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_cost", + "type": "uint256" + } + ], + "name": "transferETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/mint_flag.json b/abi/mint_flag.json new file mode 100644 index 0000000..f6049f2 --- /dev/null +++ b/abi/mint_flag.json @@ -0,0 +1,1141 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_nftName", + "type": "string" + }, + { + "internalType": "string", + "name": "_nftToken", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPerWallet", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "ref", + "type": "address" + } + ], + "name": "FundsDistributed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "ref", + "type": "address" + } + ], + "name": "MintWithRef", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "OWNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_addressData", + "outputs": [ + { + "internalType": "uint256", + "name": "WalletMinted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "WithdrawStatus", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEndless", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkMaxPerWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkOnlyCorePayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkTotalPayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkUnlimitedSupply", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "coreTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "name": "devMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPerWallet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "mintEndDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPause", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintStartDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutRefPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxperwallet", + "type": "uint256" + } + ], + "name": "setMaxPerWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + } + ], + "name": "setMintPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + } + ], + "name": "setNewEndDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + } + ], + "name": "setNewStartDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_pauseStatus", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_address", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_percent", + "type": "uint256[]" + } + ], + "name": "setPayoutCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ownerAddress", + "type": "address" + } + ], + "name": "setPayoutOwnerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutOwnerPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutRefPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/abi/mint_shop.json b/abi/mint_shop.json new file mode 100644 index 0000000..5861071 --- /dev/null +++ b/abi/mint_shop.json @@ -0,0 +1,1079 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_nftName", + "type": "string" + }, + { + "internalType": "string", + "name": "_nftToken", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPerWallet", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "OWNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_addressData", + "outputs": [ + { + "internalType": "uint256", + "name": "WalletMinted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "WithdrawStatus", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEndless", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkMaxPerWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkOnlyCorePayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkTotalPayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkUnlimitedSupply", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "coreTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "name": "devMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPerWallet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "mintEndDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPause", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintStartDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutRefPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxperwallet", + "type": "uint256" + } + ], + "name": "setMaxPerWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + } + ], + "name": "setMintPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + } + ], + "name": "setNewEndDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + } + ], + "name": "setNewStartDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_pauseStatus", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_address", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_percent", + "type": "uint256[]" + } + ], + "name": "setPayoutCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ownerAddress", + "type": "address" + } + ], + "name": "setPayoutOwnerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutOwnerPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutRefPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_cost", + "type": "uint256" + } + ], + "name": "transferETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/mint_supermint.json b/abi/mint_supermint.json new file mode 100644 index 0000000..5861071 --- /dev/null +++ b/abi/mint_supermint.json @@ -0,0 +1,1079 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "_nftName", + "type": "string" + }, + { + "internalType": "string", + "name": "_nftToken", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPerWallet", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "OWNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_addressData", + "outputs": [ + { + "internalType": "uint256", + "name": "WalletMinted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "WithdrawStatus", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_payoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEndless", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkMaxPerWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkOnlyCorePayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkTotalPayoutPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkUnlimitedSupply", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "coreTeam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "name": "devMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPerWallet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "mintEndDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPause", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintStartDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutCoreTeamPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "payoutFinalPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutOwnerPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "payoutRefPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxperwallet", + "type": "uint256" + } + ], + "name": "setMaxPerWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupply", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintPrice", + "type": "uint256" + } + ], + "name": "setMintPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintEndDate", + "type": "uint256" + } + ], + "name": "setNewEndDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintStartDate", + "type": "uint256" + } + ], + "name": "setNewStartDate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_pauseStatus", + "type": "bool" + } + ], + "name": "setPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_address", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_percent", + "type": "uint256[]" + } + ], + "name": "setPayoutCoreTeam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ownerAddress", + "type": "address" + } + ], + "name": "setPayoutOwnerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutOwnerPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_percent", + "type": "uint256" + } + ], + "name": "setPayoutRefPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + }, + { + "internalType": "address", + "name": "_ref", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_cost", + "type": "uint256" + } + ], + "name": "transferETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/omnihub.json b/abi/omnihub.json new file mode 100644 index 0000000..0537010 --- /dev/null +++ b/abi/omnihub.json @@ -0,0 +1,250 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_deployProtocolFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintProtocolFee", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_contractBaseURI", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "deployedContractAddress", + "type": "address" + } + ], + "name": "ContractDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "contractBaseURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_price", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_supply", + "type": "uint256" + } + ], + "name": "deploy", + "outputs": [ + { + "internalType": "contract ERC721OmniHubContract", + "name": "", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "deployProtocolFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintProtocolFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_contractBaseURI", + "type": "string" + } + ], + "name": "setContractBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_deployProtocolFee", + "type": "uint256" + } + ], + "name": "setDeployProtocolFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_mintProtocolFee", + "type": "uint256" + } + ], + "name": "setMintProtocolFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/abi/summer_nft.json b/abi/summer_nft.json new file mode 100644 index 0000000..e54c346 --- /dev/null +++ b/abi/summer_nft.json @@ -0,0 +1,54 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "recipient", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "currency", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "components": [ + { + "name": "proof", + "type": "bytes32[]" + }, + { + "name": "maxAmount", + "type": "uint256" + }, + { + "name": "minValue", + "type": "uint256" + }, + { + "name": "currency", + "type": "address" + } + ], + "name": "details", + "type": "tuple" + }, + { + "name": "extraData", + "type": "bytes" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/abi/vip3_nft.json b/abi/vip3_nft.json new file mode 100644 index 0000000..8c199c1 --- /dev/null +++ b/abi/vip3_nft.json @@ -0,0 +1,862 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "level", + "type": "uint256" + } + ], + "name": "Attest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Revoke", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "BURN_METHOD", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GoldLevel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINT_METHOD", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROVENANCE", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROLE_ADMIN", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROLE_SUPER_ADMIN", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_tokenIdCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_tokenLevelMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_level", + "type": "uint256" + } + ], + "name": "attest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseTokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addrs", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "level", + "type": "uint256" + } + ], + "name": "batchAttest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addrs", + "type": "address[]" + } + ], + "name": "batchRevoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getLevel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "string", + "name": "_baseTokenURI", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "level", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "setBaseTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "setSymbol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "tokenIdOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "level", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "updateLevel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "level", + "type": "uint256" + } + ], + "name": "updateLevelByAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/config/__init__.py b/config/__init__.py deleted file mode 100644 index 8476494..0000000 --- a/config/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .load_config import load_config diff --git a/config/accounts.txt b/config/accounts.txt index bf871f9..4fd849a 100644 --- a/config/accounts.txt +++ b/config/accounts.txt @@ -1,4 +1 @@ -auth_token|mnemonic/pk|proxy -auth_token|mnemonic/pk|proxy -auth_token|mnemonic/pk|proxy -auth_token|mnemonic/pk|proxy \ No newline at end of file +auth_token|pk_or_mnemonic|ip:port:user:pass \ No newline at end of file diff --git a/config/settings.yaml b/config/settings.yaml index 450fd18..d1d2d18 100644 --- a/config/settings.yaml +++ b/config/settings.yaml @@ -1,15 +1,32 @@ +# MAIN SETTINGS # referral_code: C4ACD869 # Referral code (If you don't have one, pls, use mine) - -eth_rpc_url: https://eth.llamarpc.com # RPC URL (Ethereum) -sepolia_rpc_url: https://ethereum-sepolia-rpc.publicnode.com # RPC URL (Sepolia) - threads: 3 -min_delay_before_start: 30 # seconds -max_delay_before_start: 60 # seconds +mint_rpc_url: https://rpc.mintchain.io +arb_rpc_url: https://arbitrum.llamarpc.com -min_amount_to_bridge: 0.00001 # ETH -max_amount_to_bridge: 0.0003 # ETH +min_delay_before_start: 60 # seconds +max_delay_before_start: 120 # seconds -spin_turntable_by_percentage_of_energy: 60 # 0-100 +spin_turntable_by_percentage_of_energy: 0 # 0-100 shuffle_accounts: True # True/False +# MAIN SETTINGS # +# +# +# +## MINT NFTs ## +# available: mint_comm_nft, mint_make_nft_great_again, mint_flag, mint_shop, mint_air3, mint_supermint, mint_owlto_summer_nft, mint_omnihub_summer_nft, mint_summer_nft, mint_vip3_nft, mint_green_id +mint_random_all_nfts: ["mint_make_nft_great_again", "mint_flag", "mint_shop", "mint_air3", "mint_supermint", "mint_owlto_summer_nft", "mint_omnihub_summer_nft", "mint_summer_nft", "mint_vip3_nft", "mint_green_id", "mint_comm_nft"] +delay_between_mint_min: 10 # seconds +delay_between_mint_max: 20 # seconds +## MINT NFTs ## +# +# +# +# +## COMET BRIDGE ## +comet_bridge_wallet: "" # pk or mnemonic from which script will send ETH to bridge to your multiwallet +comet_bridge_amount_min: 0.00115 # ETH +comet_bridge_amount_max: 0.0012 # ETH +## COMET BRIDGE ## + diff --git a/console/images/console.png b/console/images/console.png index f391945..9edc6db 100644 Binary files a/console/images/console.png and b/console/images/console.png differ diff --git a/console/main.py b/console/main.py index e28c170..8ca5a57 100644 --- a/console/main.py +++ b/console/main.py @@ -13,18 +13,52 @@ class Console: - MODULES = ("Test the Mint Testnet Bridge", "Complete Tasks", "Claim Daily Rewards and Inject", "Exit") + MODULES = ( + "Complete Tasks", + "Mint Random All NFTs", + "Claim Daily Rewards and Inject", + "Bridge ETH to MINT (via Comet)", + "Only Claim Daily Rewards", + "Export Trees IDs", + "Fix sign", + "Mint Green ID", + "Mint Commemorative NFT", + "Mint OmniHub Collection", + "Mint Make NFT Great Again", + "Mint Flag NFT", + "Mint Shop NFT", + "Mint Air3 NFT", + "Mint SuperMint NFT", + "Mint Owlto SummerFest NFT", + "Mint Omnihub SummerFest NFT", + "Mint Vip3 NFT", + "Exit", + ) MODULES_DATA = { - "Test the Mint Testnet Bridge": "bridge", "Complete Tasks": "tasks", "Claim Daily Rewards and Inject": "rewards", + "Mint Random All NFTs": "mint_random_all_nfts", + "Bridge ETH to MINT (via Comet)": "comet_bridge", + "Export Trees IDs": "export_trees_ids", + "Only Claim Daily Rewards": "only_rewards", + "Fix sign": "fix_sign", + "Mint Commemorative NFT": "mint_comm_nft", + "Mint Make NFT Great Again": "mint_make_nft_great_again", + "Mint Flag NFT": "mint_flag", + "Mint Shop NFT": "mint_shop", + "Mint Air3 NFT": "mint_air3", + "Mint SuperMint NFT": "mint_supermint", + "Mint Owlto SummerFest NFT": "mint_owlto_summer_nft", + "Mint Omnihub SummerFest NFT": "mint_omnihub_summer_nft", + "Mint Vip3 NFT": "mint_vip3_nft", + "Mint Green ID": "mint_green_id", } @staticmethod def show_dev_info(): os.system("cls") tprint("JamBit") - print("\033[36m" + "VERSION: " + "\033[34m" + "2.0" + "\033[34m") + print("\033[36m" + "VERSION: " + "\033[34m" + "3.0" + "\033[34m") print( "\033[36m" + "Channel: " + "\033[34m" + "https://t.me/JamBitPY" + "\033[34m" ) @@ -64,7 +98,9 @@ def get_module(self): def build(self) -> None: os.system("cls") self.show_dev_info() - info_log(f"\n- accounts: {len(config.accounts)}\n- referral_code: {config.referral_code}\n- threads: {config.threads}\n") + info_log( + f"\n- accounts: {len(config.accounts)}\n- referral_code: {config.referral_code}\n- threads: {config.threads}\n" + ) module = self.get_module() if module == "Exit": diff --git a/core/api.py b/core/api.py new file mode 100644 index 0000000..08c4fad --- /dev/null +++ b/core/api.py @@ -0,0 +1,574 @@ +import asyncio +import random + +import httpx +import pyuseragents +import names + +from typing import Literal, List +from noble_tls import Session, Client +from Jam_Twitter_API.account_async import TwitterAccountAsync + +from models import * +from loader import config as configuration + +from .wallet import Wallet +from .modules import * +from .exceptions.base import APIError + + +class MintChainAPI(Wallet): + API_URL = "https://www.mintchain.io/api" + + def __init__(self, account_data: Account): + super().__init__( + mnemonic=account_data.pk_or_mnemonic, rpc_url=configuration.mint_rpc_url + ) + self.account = account_data + self.session = self.setup_session() + self.twitter_account: TwitterAccountAsync = None # type: ignore + + @property + def jwt_token(self) -> str: + return self.session.headers["authorization"].replace("Bearer ", "") + + @property + async def energy_balance(self) -> int: + return (await self.user_info()).energy + + @property + async def tree_size(self) -> int: + return (await self.user_info()).tree + + @property + async def rank(self) -> int: + return (await self.rank_info()).rank + + def setup_session(self) -> Session: + session = Session(client=Client.CHROME_120) + session.random_tls_extension_order = True + + session.timeout_seconds = 15 + session.headers = { + "accept": "application/json, text/plain, */*", + "accept-language": "en-US,en;q=0.9,ru;q=0.8", + "referer": "https://www.mintchain.io", + "user-agent": pyuseragents.random(), + } + session.proxies = { + "http": self.account.proxy, + "https": self.account.proxy, + } + return session + + async def send_request( + self, + request_type: Literal["POST", "GET"] = "POST", + method: str = None, + json_data: dict = None, + params: dict = None, + url: str = None, + headers: dict = None, + verify: bool = True, + ): + def _verify_response(_response: dict) -> dict: + if "code" in _response: + if _response["code"] not in (10000, 200): + raise APIError( + f"{_response.get('msg')} | Method: {method} | URL: {url}" + ) + + return _response + + if request_type == "POST": + if not url: + response = await self.session.post( + f"{self.API_URL}{method}", + json=json_data, + params=params, + headers=headers, + ) + + else: + response = await self.session.post( + url, json=json_data, params=params, headers=headers + ) + + else: + if not url: + response = await self.session.get( + f"{self.API_URL}{method}", params=params, headers=headers + ) + + else: + response = await self.session.get(url, params=params, headers=headers) + + response.raise_for_status() + if verify: + return _verify_response(response.json()) + else: + return response.json() + + async def is_daily_reward_claimed(self) -> bool: + response = await self.send_request( + request_type="GET", method="/tree/energy-list" + ) + return response["result"][-1]["freeze"] + + async def green_id(self) -> dict: + response = await self.send_request(request_type="GET", method="/tree/green-id") + return response + + async def get_energy_list(self, user_id: str = None) -> EnergyListData: + if not user_id: + response = await self.send_request( + request_type="GET", method="/tree/energy-list" + ) + else: + response = await self.send_request( + request_type="GET", + method="/tree/steal/energy-list", + params={"id": user_id}, + ) + + if ( + response + and response.get("msg", "") + == "You are too late, the energy has already been collected by its owner." + ): + return EnergyListData(result=[]) + + return EnergyListData(**response) + + async def get_task_list(self) -> TaskListData: + response = await self.send_request( + request_type="GET", method=f"/tree/task-list?address={self.keypair.address}" + ) + return TaskListData(**response) + + async def complete_tasks(self): + task_list = await self.get_task_list() + for task in task_list.result: + if task.spec not in ("discord-follow", "stake"): + if task.claimed: + logger.debug( + f"Account: {self.account.auth_token} | Task already completed: {task.name}" + ) + continue + + try: + if task.spec in ("twitter-post", "twitter-follow"): + if not self.twitter_account: + self.load_twitter_account() + + if task.spec == "twitter-follow": + user_id = self.twitter_account.get_user_id( + "Mint_Blockchain" + ) + self.twitter_account.follow(user_id) + await self.submit_task_id(task.id) + + else: + tweet_text = "I'm collecting @Mint_Blockchain's ME $MINT in the #MintForest🌳!\n\nMint is the L2 for NFT industry, powered by @nftscan_com and @Optimism.\n\nJoin Mint Forest here: https://mintchain.io/mint-forest\n\n#MintBlockchain #L2forNFT" + + data = self.twitter_account.tweet(tweet_text) + tweet_url = f'https://x.com/JammerCrypto/status/{data["data"]["create_tweet"]["tweet_results"]["result"]["rest_id"]}' + await self.submit_task_id(task.id, twitter_post=tweet_url) + + else: + await self.submit_task_id(task.id) + + logger.debug( + f"Account: {self.account.auth_token} | Task completed: {task.name} | Reward: {task.amount} energy" + ) + await asyncio.sleep(3) + + except APIError as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to complete task: {task.name} | {error}" + ) + await asyncio.sleep(3) + + async def claim_daily_rewards(self) -> None: + energy_list = await self.get_energy_list() + for energy in energy_list.result: + json_data = { + "uid": energy.uid, + "amount": energy.amount, + "includes": energy.includes, + "type": energy.type, + "id": energy.id, + } + + if energy.type == "daily": + if energy.freeze: + logger.debug( + f"Account: {self.account.auth_token} | Daily reward already claimed" + ) + continue + else: + json_data["freeze"] = energy.freeze + + await self.send_request(method="/tree/claim", json_data=json_data) + logger.debug( + f"Account: {self.account.auth_token} | Claimed {energy.amount} energy | Type: {energy.type}" + ) + await asyncio.sleep(1) + + await self.claim_boxes() + + async def bind_invite_code(self) -> ResponseData: + jwt_token = self.jwt_token + + session = Session(client=Client.CHROME_120) + session.headers = { + "accept": "application/json, text/plain, */*", + "accept-language": "sk-SK,sk;q=0.9,en-US;q=0.8,en;q=0.7", + "authorization": "Bearer", + "referer": "https://www.mintchain.io/mint-forest", + "user-agent": self.session.headers["user-agent"], + } + + json_data = { + "code": str(configuration.referral_code), + "jwtToken": jwt_token, + } + + response = await session.get( + "https://www.mintchain.io/api/tree/invitation", params=json_data + ) + return ResponseData(**response.json()) + + async def load_twitter_account(self) -> None: + self.twitter_account = await TwitterAccountAsync.run( + auth_token=self.account.auth_token, + setup_session=True, + proxy=self.account.proxy, + ) + + async def connect_twitter(self) -> dict: + params = { + "code_challenge": "mintchain", + "code_challenge_method": "plain", + "client_id": "enpfUjhndkdrdHhld29aTW96eGM6MTpjaQ", + "redirect_uri": "https://www.mintchain.io/mint-forest", + "response_type": "code", + "scope": "tweet.read users.read follows.read offline.access", + "state": "mintchain", + } + + if not self.twitter_account: + await self.load_twitter_account() + + approved_code = await self.twitter_account.bind_account_v2(params) + + params = { + "code": approved_code, + "jwtToken": self.jwt_token, + "address": self.keypair.address, + } + response = await self.send_request( + url="https://www.mintchain.io/api/twitter/verify", params=params + ) + return response + + async def rank_info(self) -> RankData: + response = await self.send_request(request_type="GET", method="/tree/me-rank") + return RankData(**response["result"]) + + async def user_info(self, tree_id: str = None) -> UserInfo: + if not tree_id: + response = await self.send_request( + request_type="GET", method="/tree/user-info" + ) + else: + response = await self.send_request( + request_type="GET", method="/tree/user-info", params={"treeid": tree_id} + ) + + return UserInfo(**response["result"]) + + async def assets(self) -> List[AssetData]: + response = await self.send_request(request_type="GET", method="/tree/asset") + return [AssetData(**data) for data in response["result"]] + + async def open_box(self, box_id: int) -> OpenBoxData: + json_data = { + "boxId": box_id, + } + + response = await self.send_request(method="/tree/open-box", json_data=json_data) + return OpenBoxData(**response["result"]) + + async def claim_boxes(self): + assets = await self.assets() + for asset in assets: + if not asset.createdAt: + try: + opened_box_data = await self.open_box(asset.id) + logger.debug( + f"Account: {self.account.auth_token} | Box opened | Reward: {opened_box_data.energy} energy" + ) + except APIError as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to open box: {asset.type} | {error}" + ) + + await asyncio.sleep(1) + + async def spin_turntable(self) -> TurntableData: + response = await self.send_request( + request_type="GET", method="/tree/turntable/open" + ) + return TurntableData(**response["result"]) + + async def steal_claim(self, user_id: str) -> None: + json_data = { + "id": user_id, + } + + await self.send_request( + request_type="GET", method="/tree/steal/claim", params=json_data + ) + + async def inject(self, amount: int = None) -> InjectData: + if not amount: + amount = await self.energy_balance + + if amount <= 0: + return InjectData(code=0, result=False, msg="Energy balance is 0") + + json_data = { + "address": self.keypair.address, + "energy": amount, + } + + response = await self.send_request(method="/tree/inject", json_data=json_data) + return InjectData(**response) + + async def fix_sign(self) -> None: + await self.send_request(request_type="GET", method="/tree/fix-sign") + + async def submit_task_id(self, task_id: int, twitter_post: str = None) -> None: + json_data = { + "id": task_id, + } + + if twitter_post: + json_data["twitterurl"] = twitter_post + + await self.send_request(method="/tree/task-submit", json_data=json_data) + + async def get_make_nft_great_again_proofs(self) -> list[str]: + params = { + "user": self.keypair.address, + } + + headers = { + "accept": "application/json, text/plain, */*", + "accept-language": "en-US,en;q=0.9,ru;q=0.8", + "priority": "u=1, i", + "referer": "https://mn-ga.com/?allow=true", + "user-agent": self.session.headers["user-agent"], + } + + async with httpx.AsyncClient(headers=headers) as client: + response = await client.get( + "https://mn-ga.com/api/reward/nft-proof", params=params + ) + response = response.json() + return response["msg"]["proof"] + + async def mint_commemorative_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_commemorative_nft_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint commemorative NFT: {error}") + + async def mint_flag_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_mint_flag_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Flag NFT: {error}") + + async def mint_shop_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_mint_shop_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Shop NFT: {error}") + + async def mint_air3_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_mint_air3_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Air3 NFT: {error}") + + async def mint_green_id_nft(self, tree_id: int) -> tuple[bool | Any, str]: + try: + transaction = await self.build_green_id_nft_transaction(tree_id) + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Green ID NFT: {error}") + + async def mint_vip3_nft(self) -> tuple[bool | Any, str]: + try: + client = Vip3API(self.account) + await client.login() + mint_data = await client.get_mint_data() + transaction = await self.build_vip3_nft_transaction(mint_data) + + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint VIP3 NFT: {error}") + + async def mint_supermint_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_mint_supermint_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint SuperMint NFT: {error}") + + async def mint_summer_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_summer_nft_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Summer NFT: {error}") + + async def mint_make_nft_great_again(self) -> tuple[bool | Any, str]: + try: + proofs = await self.get_make_nft_great_again_proofs() + transaction = await self.build_make_nft_great_again_transaction( + proofs=proofs + ) + + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Make NFT Great Again: {error}") + + async def mint_createx_collection(self) -> tuple[bool | Any, str]: + try: + name = f"{names.get_first_name()} {names.get_last_name()}" + symbol = random.choice( + [f"{name[:3].upper()}", f"{name[:4].upper()}", f"{name[:5].upper()}"] + ) + description = f"Collection of {name} NFTs" + price = random.uniform(0.00001, 0.05) + royalty_fee = random.randint(1, 50) + + client = CreateXAPI( + mnemonic=self.account.pk_or_mnemonic, rpc_url=configuration.mint_rpc_url + ) + await client.login() + collection_id = await client.create_collection( + name=name, + symbol=symbol, + description=description, + price=str(price), + royalty_fee=str(royalty_fee), + ) + await client.create_query_collection(collection_id=collection_id) + trx_data = await client.deploy(collection_id=collection_id) + + transaction = await self.build_createx_collection_transaction(trx_data) + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint OmniHub collection: {error}") + + async def mint_owlto_summer_fest_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_owlto_summer_fest_nft_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint Owlto Summer Fest NFT: {error}") + + async def mint_omnihub_summer_fest_nft(self) -> tuple[bool | Any, str]: + try: + transaction = await self.build_omnihub_summer_fest_nft_transaction() + status, tx_hash = await self.send_and_verify_transaction(transaction) + return status, tx_hash + + except Exception as error: + raise Exception(f"Failed to mint OmniHub Summer Fest NFT: {error}") + + async def verify_wallet(self) -> ResponseData: + json_data = { + "jwtToken": self.jwt_token, + } + + response = await self.send_request(method="/wallet/verify", json_data=json_data) + return ResponseData(**response) + + async def join_airdrop(self) -> dict: + messages = self.sign_mint_message("airdrop") + + params = { + "wallet_address": self.keypair.address, + "signature": messages.signed_message, + "message": messages.message, + "invite_code": "", + } + + return await self.send_request( + request_type="GET", + url="https://mpapi.mintchain.io/api/user/sign", + params=params, + ) + + async def login(self): + messages = self.sign_mint_message("forest") + + json_data = { + "address": self.keypair.address, + "signature": messages.signed_message, + "message": messages.message, + } + + response = await self.send_request(method="/tree/login", json_data=json_data) + data = LoginWalletData(**response["result"]) + self.session.headers["authorization"] = f"Bearer {data.access_token}" + + if data.user.status == "pending": + await self.verify_wallet() + + if not data.user.twitter: + await self.connect_twitter() + logger.debug( + f"Account: {self.account.auth_token} | Twitter account connected" + ) + + if not data.user.inviteId: + await self.bind_invite_code() + logger.debug(f"Account: {self.account.auth_token} | Referral code bound") + + await self.green_id() + await self.assets() + await self.rank_info() + await self.user_info() + await self.get_energy_list() diff --git a/core/bot.py b/core/bot.py new file mode 100644 index 0000000..0c4c9d3 --- /dev/null +++ b/core/bot.py @@ -0,0 +1,549 @@ +import asyncio +import random +from typing import Any + +from models import Account +from loguru import logger +from loader import config + +from .api import MintChainAPI +from .exceptions.base import APIError +from .modules import CometBridge + + +class Bot(MintChainAPI): + def __init__(self, account: Account): + super().__init__(account_data=account) + + async def safe_operation( + self, + operation: callable, + success_message: str, + error_message: str, + retries: int = 0, + delay: int = 3, + argument: Any = None, + ) -> bool: + for _ in range(retries): + try: + await operation() if argument is None else await operation(argument) + logger.success( + f"Account: {self.account.auth_token} | {success_message}" + ) + return True + + except APIError as error: + logger.error( + f"Account: {self.account.auth_token} | {error_message}: {error}" + ) + return False + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | {error_message}: {error} | {'Retrying..' if retries > 0 else ''}" + ) + await asyncio.sleep(delay) + continue + + return False + + async def process_login(self) -> bool: + logger.info(f"Account: {self.account.auth_token} | Logging in..") + return await self.safe_operation( + operation=self.login, + success_message="Logged in", + error_message="Failed to login", + retries=3, + ) + + async def process_fix_sign(self) -> bool: + return await self.safe_operation( + operation=self.fix_sign, + success_message="Fixed sign", + error_message="Failed to fix sign", + retries=2, + ) + + async def process_claim_daily_reward(self) -> bool: + return await self.safe_operation( + operation=self.claim_daily_rewards, + success_message="Finished claiming daily rewards", + error_message="Failed to claim daily rewards", + delay=10, + retries=3, + ) + + async def process_inject(self) -> bool: + return await self.safe_operation( + operation=self.inject, + success_message="Finished injecting energy", + error_message="Failed to inject energy", + retries=3, + ) + + async def process_spin_turntable(self) -> bool: + if config.spin_turntable_by_percentage_of_energy > 0: + try: + balance = await self.energy_balance + if balance < 300: + logger.warning( + f"Account: {self.account.auth_token} | Not enough energy to spin turntable" + ) + return True + + amount = int( + balance * (config.spin_turntable_by_percentage_of_energy / 100) + ) + number_of_spins = int(amount // 300) + if number_of_spins > 5: + number_of_spins = 5 + + for _ in range(number_of_spins): + reward = await self.spin_turntable() + logger.success( + f"Account: {self.account.auth_token} | Opened turntable | Reward: {reward.energy} energy" + ) + await asyncio.sleep(3) + + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to spin turntable: {error}" + ) + + return True + + async def process_show_user_info(self) -> None: + try: + info = await self.tree_size + logger.success( + f"Account: {self.account.auth_token} | Total injected energy: {info} | Daily actions done.." + ) + + except Exception as error: + logger.warning( + f"Account: {self.account.auth_token} | Failed to get user info: {error} | Daily actions done.." + ) + + async def process_mint_comm_nft(self) -> None: + try: + await self.check_balance() + + try: + await self.join_airdrop() + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to join airdrop: {error}" + ) + + logger.info( + f"Account: {self.account.auth_token} | Minting commemorative NFT.." + ) + status, transaction_hash = await self.mint_commemorative_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted commemorative NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint commemorative NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_make_nft_great_again(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting MNGA NFT..") + status, transaction_hash = await self.mint_make_nft_great_again() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted MNGA NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint MNGA NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_flag_nft(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting Flag NFT..") + status, transaction_hash = await self.mint_flag_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Flag NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Flag NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_supermint_nft(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting SuperMint NFT..") + status, transaction_hash = await self.mint_supermint_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted SuperMint NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint SuperMint NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_air3_nft(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting Air3 NFT..") + status, transaction_hash = await self.mint_air3_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Air3 NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Air3 NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_shop_nft(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting Shop NFT..") + status, transaction_hash = await self.mint_shop_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Shop NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Shop NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_join_airdrop(self) -> None: + try: + await self.join_airdrop() + + except APIError as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to join airdrop: {error}" + ) + return + + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to join airdrop: {error}" + ) + + async def process_mint_vip3_nft(self) -> None: + try: + await self.check_balance() + + try: + await self.join_airdrop() + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to join airdrop: {error}" + ) + + logger.info(f"Account: {self.account.auth_token} | Minting VIP3 NFT..") + status, transaction_hash = await self.mint_vip3_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted VIP3 NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint VIP3 NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_green_id(self) -> None: + try: + await self.check_balance() + logger.info(f"Account: {self.account.auth_token} | Minting Green ID..") + + tree_id = await self.process_get_tree_id() + if not tree_id: + return + + status, transaction_hash = await self.mint_green_id_nft(int(tree_id)) + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Green ID | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Green ID | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + # async def process_mint_omnihub_collection(self) -> None: + # try: + # if await self.human_balance() < 0.0001: + # raise Exception("Insufficient balance to mint OmniHub collection | Required: 0.0001 ETH") + # + # logger.info(f"Account: {self.account.auth_token} | Minting OmniHub collection") + # status, transaction_hash = await self.mint_omnihub_collection() + # + # if status: + # logger.success( + # f"Account: {self.account.auth_token} | Minted OmniHub collection | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + # ) + # else: + # logger.error( + # f"Account: {self.account.auth_token} | Failed to mint OmniHub collection | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + # ) + # + # except Exception as error: + # logger.error( + # f"Account: {self.account.auth_token} | {error}" + # ) + + async def process_mint_summer_nft(self) -> None: + try: + if await self.human_balance() < 0.0001: + raise Exception( + "Insufficient balance to mint Summer NFT | Required: 0.0001 ETH" + ) + + logger.info(f"Account: {self.account.auth_token} | Minting Summer NFT..") + status, transaction_hash = await self.mint_summer_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Summer NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Summer NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_owlto_summer_fest_nft(self) -> None: + try: + if await self.human_balance() < 0.0001: + raise Exception( + "Insufficient balance to mint Owlto Summer Fest NFT | Required: 0.0001 ETH" + ) + + logger.info( + f"Account: {self.account.auth_token} | Minting Owlto Summer Fest NFT.." + ) + status, transaction_hash = await self.mint_owlto_summer_fest_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted Owlto Summer Fest NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint Owlto Summer Fest NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_mint_omnihub_summer_nft(self) -> None: + try: + if await self.human_balance() < 0.0001: + raise Exception( + "Insufficient balance to mint OmniHub Summer NFT | Required: 0.0001 ETH" + ) + + logger.info( + f"Account: {self.account.auth_token} | Minting OmniHub Summer NFT.." + ) + status, transaction_hash = await self.mint_omnihub_summer_fest_nft() + + if status: + logger.success( + f"Account: {self.account.auth_token} | Minted OmniHub Summer NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to mint OmniHub Summer NFT | Transaction: https://explorer.mintchain.io/tx/{transaction_hash}" + ) + + except Exception as error: + logger.error(f"Account: {self.account.auth_token} | {error}") + + async def process_comet_bridge(self) -> None: + try: + amount_to_bridge = random.uniform( + config.comet_bridge_amount_min, config.comet_bridge_amount_max + ) + client = CometBridge( + amount_to_bridge=amount_to_bridge, + to_address=self.keypair.address, + mnemonic=config.comet_bridge_wallet, + rpc_url=config.arb_rpc_url, + ) + + logger.info( + f"Account: {self.account.auth_token} | Bridging {amount_to_bridge} ETH to MINT (via Comet)" + ) + transaction = await client.build_bridge_transaction() + status, tx_hash = await client.send_and_verify_transaction(transaction) + + if status: + logger.success( + f"Account: {self.account.auth_token} | Bridged {amount_to_bridge} ETH to MINT | Transaction: https://arbiscan.io/tx/{tx_hash}" + ) + + else: + logger.error( + f"Account: {self.account.auth_token} | Failed to bridge {amount_to_bridge} ETH to MINT | Transaction: https://arbiscan.io/tx/{tx_hash}" + ) + + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Error while bridging: {error}" + ) + + async def process_complete_tasks(self): + return await self.safe_operation( + operation=self.complete_tasks, + success_message="Finished completing tasks", + error_message="Failed to complete tasks", + delay=10, + retries=3, + ) + + async def process_get_tree_id(self) -> bool | str: + for _ in range(2): + try: + if not await self.process_login(): + return False + + user_info = await self.user_info() + return str(user_info.treeId) + + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to get tree id: {error} | Retrying.." + ) + await asyncio.sleep(1) + + logger.error( + f"Account: {self.account.auth_token} | Failed to get tree id after 2 retries | Skipping.." + ) + return False + + async def process_mint_random_all_nfts(self) -> None: + operations_dict = { + "mint_comm_nft": self.process_mint_comm_nft, + "mint_make_nft_great_again": self.process_mint_make_nft_great_again, + "mint_flag": self.process_mint_flag_nft, + "mint_shop": self.process_mint_shop_nft, + "mint_air3": self.process_mint_air3_nft, + "mint_supermint": self.process_mint_supermint_nft, + "mint_summer_nft": self.process_mint_summer_nft, + "mint_owlto_summer_nft": self.process_mint_owlto_summer_fest_nft, + "mint_omnihub_summer_nft": self.process_mint_omnihub_summer_nft, + "mint_vip3_nft": self.process_mint_vip3_nft, + "mint_green_id": self.process_mint_green_id, + } + + mint_modules = config.mint_random_all_nfts + random.shuffle(mint_modules) + + for module in mint_modules: + operation = operations_dict.get(module) + if operation: + try: + await operation() + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Failed to process {module}: {error}" + ) + finally: + delay = random.randint( + config.delay_between_mint_min, config.delay_between_mint_max + ) + logger.debug( + f"Account: {self.account.auth_token} | Sleeping for {delay} seconds.." + ) + await asyncio.sleep(delay) + + async def start(self): + random_delay = random.randint( + config.min_delay_before_start, config.max_delay_before_start + ) + logger.info( + f"Account: {self.account.auth_token} | Work will start in {random_delay} seconds.." + ) + await asyncio.sleep(random_delay) + + operations_dict = { + "rewards": [ + self.process_login, + self.process_claim_daily_reward, + self.process_spin_turntable, + self.process_inject, + self.process_show_user_info, + ], + "only_rewards": [ + self.process_login, + self.process_claim_daily_reward, + self.process_show_user_info, + ], + "fix_sign": [self.process_login, self.process_show_user_info], + "mint_comm_nft": [self.process_mint_comm_nft], + "mint_make_nft_great_again": [self.process_mint_make_nft_great_again], + "mint_summer_nft": [self.process_mint_summer_nft], + "mint_flag": [self.process_mint_flag_nft], + "mint_shop": [self.process_mint_shop_nft], + "mint_air3": [self.process_mint_air3_nft], + "mint_supermint": [self.process_mint_supermint_nft], + "comet_bridge": [self.process_comet_bridge], + "mint_random_all_nfts": [self.process_mint_random_all_nfts], + "mint_owlto_summer_nft": [self.process_mint_owlto_summer_fest_nft], + "mint_omnihub_summer_nft": [self.process_mint_omnihub_summer_nft], + "mint_vip3_nft": [self.process_mint_vip3_nft], + "tasks": [self.process_login, self.process_complete_tasks], + "default": [self.process_login, self.process_complete_tasks], + } + + operations = operations_dict.get(config.module, operations_dict["default"]) + + try: + for operation in operations: + if not await operation(): + break + + except Exception as error: + logger.error( + f"Account: {self.account.auth_token} | Unhandled error: {error}" + ) + finally: + logger.success(f"Account: {self.account.auth_token} | Finished") diff --git a/core/exceptions/base.py b/core/exceptions/base.py new file mode 100644 index 0000000..62304da --- /dev/null +++ b/core/exceptions/base.py @@ -0,0 +1,10 @@ +class APIError(Exception): + """Base class for API exceptions""" + + pass + + +class StealEnergyError(APIError): + """Raised when failed to steal energy""" + + pass diff --git a/core/modules/__init__.py b/core/modules/__init__.py new file mode 100644 index 0000000..a41a251 --- /dev/null +++ b/core/modules/__init__.py @@ -0,0 +1,3 @@ +from .comet_bridge import CometBridge +from .createx_api import CreateXAPI +from .vip3_api import Vip3API diff --git a/core/modules/comet_bridge.py b/core/modules/comet_bridge.py new file mode 100644 index 0000000..3ecf1be --- /dev/null +++ b/core/modules/comet_bridge.py @@ -0,0 +1,75 @@ +import json + +from pydantic import HttpUrl +from web3 import AsyncWeb3 + +from core.wallet import Wallet + + +class CometBridge(Wallet): + def __init__( + self, + amount_to_bridge: float, + to_address: str, + mnemonic: str, + rpc_url: HttpUrl | str, + ): + super().__init__(mnemonic, rpc_url) + self.amount_to_bridge = amount_to_bridge + self.to_address = to_address + + @staticmethod + def pad_to_32(x) -> str: + return x.rjust(64, "0") + + async def build_bridge_transaction(self): + function_signature = "0x78499054" + destination_gas_cost = AsyncWeb3.to_wei(0.0003, "ether") + amount = AsyncWeb3.to_wei(self.amount_to_bridge, "ether") + destination_gas_cost + token_address = "0x0000000000000000000000000000000000000000".lower() + provider_address = "0xb50ac92d6d8748ac42721c25a3e2c84637385a6b".lower() + + metadata = {"targetChain": "185", "targetAddress": self.to_address} + + encoded_metadata = ( + f"data:,{json.dumps(metadata, separators=(',', ':'))}".encode("utf-8").hex() + ) + transaction_data = ( + function_signature + + self.pad_to_32(hex(amount)[2:]) + + self.pad_to_32(token_address[2:]) + + self.pad_to_32(provider_address[2:].lower()) + + self.pad_to_32( + hex(32 * 4)[2:] + ) # Смещение для данных (4 параметра по 32 байта) + + self.pad_to_32( + hex(len(encoded_metadata) // 2)[2:] + ) # Длина metadata в байтах + + encoded_metadata + ) + final_data = f"{transaction_data}0000000000000000" + + gas_limit = await self.eth.estimate_gas( + { + "chainId": 42161, + "from": self.keypair.address, + "to": AsyncWeb3.to_checksum_address( + "0x0fbCf4a62036E96C4F6770B38a9B536Aa14d1846" + ), + "value": amount, + "data": final_data, + } + ) + + return { + "chainId": 42161, + "from": self.keypair.address, + "to": AsyncWeb3.to_checksum_address( + "0x0fbCf4a62036E96C4F6770B38a9B536Aa14d1846" + ), + "value": amount, + "gas": gas_limit, + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "data": final_data, + } diff --git a/core/modules/createx_api.py b/core/modules/createx_api.py new file mode 100644 index 0000000..e5207a0 --- /dev/null +++ b/core/modules/createx_api.py @@ -0,0 +1,239 @@ +import asyncio +import json +import time +from datetime import datetime, timezone +from typing import Literal + +import pyuseragents +from eth_account.messages import encode_typed_data +from noble_tls import Client, Session + +from loader import config +from models import Account +from core.exceptions.base import APIError +from core.wallet import Wallet + + +class CreateXAPI(Wallet): + API_URL = "https://createx.art/api" + + def __init__(self, account_data: Account): + super().__init__(account_data.pk_or_mnemonic, config.mint_rpc_url) + self.account = account_data + self.session = self.setup_session() + + def setup_session(self) -> Session: + session = Session(client=Client.CHROME_120) + session.random_tls_extension_order = True + + session.timeout_seconds = 15 + session.headers = { + "accept": "application/json, text/plain, */*", + "accept-language": "en-US,en;q=0.9,ru;q=0.8", + "priority": "u=1, i", + "referer": "https://createx.art/", + "user-agent": pyuseragents.random(), + } + session.proxies = { + "http": self.account.proxy, + "https": self.account.proxy, + } + return session + + async def send_request( + self, + request_type: Literal["POST", "GET"] = "POST", + method: str = None, + json_data: dict = None, + params: dict = None, + url: str = None, + headers: dict = None, + verify: bool = True, + ): + def _verify_response(_response: dict) -> dict: + if "status" in _response: + if _response["status"] != 0: + raise APIError(f"{_response.get('msg')} | Method: {method}") + + return _response + + raise APIError(f"{_response} | Method: {method}") + + if request_type == "POST": + if not url: + response = await self.session.post( + f"{self.API_URL}{method}", + json=json_data, + params=params, + headers=headers, + ) + + else: + response = await self.session.post( + url, json=json_data, params=params, headers=headers + ) + + else: + if not url: + response = await self.session.get( + f"{self.API_URL}{method}", params=params, headers=headers + ) + + else: + response = await self.session.get(url, params=params, headers=headers) + + response.raise_for_status() + if verify: + return _verify_response(response.json()) + else: + return response.json() + + async def get_timestamp(self) -> tuple[int, str]: + response = await self.send_request( + request_type="GET", + method="/v1/creator/public/timestamp", + ) + + timestamp = response["data"]["timestamp_ms"] + timestamp_seconds = timestamp / 1000 + dt = datetime.fromtimestamp(timestamp_seconds, tz=timezone.utc) + formatted_date = dt.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" + + return timestamp, formatted_date + + async def get_login_data(self) -> tuple[str, str]: + timestamp, formatted_date = await self.get_timestamp() + + message = { + "types": { + "Message": [ + {"name": "Message", "type": "string"}, + {"name": "URI", "type": "string"}, + {"name": "Version", "type": "string"}, + {"name": "ChainId", "type": "uint256"}, + {"name": "Nonce", "type": "uint256"}, + {"name": "issuedAt", "type": "string"}, + ], + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + ], + }, + "primaryType": "Message", + "domain": {"name": "", "version": "1", "chainId": "185"}, + "message": { + "Message": "Sign in to the CreateX", + "URI": "https://createx.art", + "Version": "1", + "ChainId": "185", + "Nonce": timestamp, + "issuedAt": formatted_date, + }, + } + signed_json = { + "domain": {"name": "", "version": "1", "chainId": 185}, + "message": { + "Message": "Sign in to the CreateX", + "URI": "https://createx.art", + "Version": "1", + "ChainId": 185, + "Nonce": timestamp, + "issuedAt": formatted_date, + }, + "primaryType": "Message", + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + ], + "Message": [ + {"name": "Message", "type": "string"}, + {"name": "URI", "type": "string"}, + {"name": "Version", "type": "string"}, + {"name": "ChainId", "type": "uint256"}, + {"name": "Nonce", "type": "uint256"}, + {"name": "issuedAt", "type": "string"}, + ], + }, + } + + encoded_message = encode_typed_data(full_message=message) + signed_message = self.keypair.sign_message(encoded_message) + return signed_message.signature.hex(), json.dumps(signed_json) + + async def create_collection( + self, name: str, symbol: str, description: str, price: str, royalty_fee: str + ) -> str: + json_data = { + "chain": "MINTCHAIN", + "chain_name": "", + "is_single_create": True, + "nftUpload": True, + "collection_name": name, + "symbol": symbol, + "description": description, + "is_limit_count": False, + "mint_price": price, + "mint_start_time": int(time.time() * 1000), + "mint_end_time": 0, + "mint_qty_per_user": "1", + "royalty_fee": royalty_fee, + "royalty_fee_recipient": self.keypair.address, + "collection_id": False, + "is_image_update": False, + "media_file_count": 1, + "currency": "eth", + } + + response = await self.send_request( + request_type="POST", + method="/v1/createx/create/collection", + json_data=json_data, + ) + return response["data"]["collection_id"] + + async def deploy(self, collection_id: str) -> str: + json_data = { + "chain": "MINTCHAIN", + "chain_name": "MINTCHAIN", + "collection_id": collection_id, + "is_sbt": 0, + } + + response = await self.send_request( + request_type="POST", + method="/v1/createx/create/direct_deploy", + json_data=json_data, + ) + + return f"0x{response['data']['bin']}" + + async def create_query_collection(self, collection_id: str) -> dict: + json_data = { + "chain": "MINTCHAIN", + "chain_name": "MINTCHAIN", + "collection_id": collection_id, + } + + response = await self.send_request( + request_type="POST", + method="/v1/createx/create/query_collection", + json_data=json_data, + ) + return response["data"] + + async def login(self) -> dict: + signature, signed_json = await self.get_login_data() + + response = await self.send_request( + method="/v1/creator/auth/login_with_type_data", + json_data={ + "msg_signature": signature, + "msg_signer": self.keypair.address, + "signed_json": signed_json, + }, + ) + + return response diff --git a/core/modules/vip3_api.py b/core/modules/vip3_api.py new file mode 100644 index 0000000..1251a23 --- /dev/null +++ b/core/modules/vip3_api.py @@ -0,0 +1,128 @@ +import asyncio +import json +import time +from datetime import datetime, timezone +from typing import Literal, Tuple, Any + +import pyuseragents +from eth_account.messages import encode_typed_data, encode_defunct +from noble_tls import Client, Session +from pydantic import HttpUrl + +from loader import config +from models import Account +from core.exceptions.base import APIError +from core.wallet import Wallet + + +class Vip3API(Wallet): + API_URL = "https://dappapi.vip3.io/api" + + def __init__(self, account_data: Account): + super().__init__(account_data.pk_or_mnemonic, config.mint_rpc_url) + self.account = account_data + self.session = self.setup_session() + + def setup_session(self) -> Session: + session = Session(client=Client.CHROME_120) + session.random_tls_extension_order = True + + session.timeout_seconds = 15 + session.headers = { + "accept": "application/json, text/plain, */*", + "accept-language": "en-US,en;q=0.9,ru;q=0.8", + "content-type": "application/json", + "origin": "https://dapp.vip3.io", + "referer": "https://dapp.vip3.io/", + "user-agent": pyuseragents.random(), + } + session.proxies = { + "http": self.account.proxy, + "https": self.account.proxy, + } + return session + + async def send_request( + self, + request_type: Literal["POST", "GET"] = "POST", + method: str = None, + json_data: dict = None, + params: dict = None, + url: str = None, + headers: dict = None, + verify: bool = True, + ): + def _verify_response(_response: dict) -> dict: + if "code" in _response: + if _response["code"] != 0: + raise APIError(f"{_response.get('msg')} | Method: {method}") + + return _response + + raise APIError(f"{_response} | Method: {method}") + + if request_type == "POST": + if not url: + response = await self.session.post( + f"{self.API_URL}{method}", + json=json_data, + params=params, + headers=headers, + ) + + else: + response = await self.session.post( + url, json=json_data, params=params, headers=headers + ) + + else: + if not url: + response = await self.session.get( + f"{self.API_URL}{method}", params=params, headers=headers + ) + + else: + response = await self.session.get(url, params=params, headers=headers) + + response.raise_for_status() + if verify: + return _verify_response(response.json()) + else: + return response.json() + + async def get_login_signature(self) -> tuple[str, Any]: + message = f'Welcome to VIP3!\n\nClick "Sign" to sign in and accept the VIP3 Terms of Use(https://vip3.gitbook.io/term-of-use/).\n\nThis request will not trigger a blockchain transaction or cost any gas fees.\n\nWallet address:\n{self.keypair.address}\n\nNonce: {int(time.time() * 1000)}' + + encoded_message = encode_defunct(text=message) + signed_message = self.keypair.sign_message(encoded_message) + return message, signed_message.signature.hex() + + async def get_mint_data(self) -> dict: + json_data = { + "lang": "en", + "chainId": 185, + } + + response = await self.send_request( + method="/v1/sbt/mint", + json_data=json_data, + ) + return response["data"] + + async def login(self) -> None: + message, signature = await self.get_login_signature() + + json_data = { + "address": self.keypair.address, + "sign": signature, + "raw": message, + } + + response = await self.send_request( + method="/v1/auth", + json_data=json_data, + ) + + self.session.headers.update( + {"Authorization": f"Bearer {response['data']['token']}"} + ) diff --git a/core/wallet.py b/core/wallet.py new file mode 100644 index 0000000..e756809 --- /dev/null +++ b/core/wallet.py @@ -0,0 +1,349 @@ +import random +from typing import Any, Literal + +from eth_account import Account +from eth_account.messages import encode_defunct +from pydantic import HttpUrl +from web3 import AsyncWeb3 +from web3.contract import AsyncContract +from web3.eth import AsyncEth +from web3.types import Nonce + +from models import ( + LoginData, + CommemorativeNFTData, + OmnihubData, + MakeNFTGreatAgainData, + SummerNFTData, + MintFlagData, + MintShopData, + MintAir3Data, + MintSupermintData, + CometBridgeData, + Vip3MintData, + GreenIDData, +) + +Account.enable_unaudited_hdwallet_features() + + +class Wallet(AsyncWeb3, Account): + def __init__(self, mnemonic: str, rpc_url: HttpUrl | str): + super().__init__( + AsyncWeb3.AsyncHTTPProvider(str(rpc_url)), + modules={"eth": (AsyncEth,)}, + middlewares=[], + ) + self.keypair = ( + self.from_mnemonic(mnemonic) + if len(mnemonic.split()) in (12, 24) + else self.from_key(mnemonic) + ) + + @property + def get_commemorative_nft_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(CommemorativeNFTData.address), + abi=CommemorativeNFTData.abi, + ) + + @property + def get_omnihub_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(OmnihubData.address), + abi=OmnihubData.abi, + ) + + @property + def get_make_nft_great_again_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(MakeNFTGreatAgainData.address), + abi=MakeNFTGreatAgainData.abi, + ) + + @property + def get_summer_nft_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(SummerNFTData.address), + abi=SummerNFTData.abi, + ) + + @property + def get_mint_flag_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(MintFlagData.address), + abi=MintFlagData.abi, + ) + + @property + def get_min_shop_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(MintShopData.address), + abi=MintShopData.abi, + ) + + @property + def get_mint_air3_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(MintAir3Data.address), + abi=MintAir3Data.abi, + ) + + @property + def get_mint_supermint_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(MintSupermintData.address), + abi=MintSupermintData.abi, + ) + + @property + def get_comet_bridge_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(CometBridgeData.address), + abi=CometBridgeData.abi, + ) + + @property + def get_vip3_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(Vip3MintData.address), + abi=Vip3MintData.abi, + ) + + @property + def get_green_contract(self) -> AsyncContract: + return self.eth.contract( + address=AsyncWeb3.to_checksum_address(GreenIDData.address), + abi=GreenIDData.abi, + ) + + async def transactions_count(self) -> Nonce: + return await self.eth.get_transaction_count(self.keypair.address) + + async def check_balance(self) -> None: + balance = await self.eth.get_balance(self.keypair.address) + + if balance <= 0: + raise Exception(f"ETH balance is empty") + + async def human_balance(self) -> float | int: + balance = await self.eth.get_balance(self.keypair.address) + return AsyncWeb3.from_wei(balance, "ether") + + async def build_make_nft_great_again_transaction(self, proofs: list[str]): + contract = self.get_make_nft_great_again_contract + transaction = contract.functions.awardItem(proofs) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_green_id_nft_transaction(self, mint_id: int): + contract = self.get_green_contract + transaction = contract.functions.claim(mint_id) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_mint_air3_transaction(self): + contract = self.get_mint_air3_contract + transaction = contract.functions.mint(1) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_mint_supermint_transaction(self): + contract = self.get_mint_supermint_contract + transaction = contract.functions.mint(1) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_mint_shop_transaction(self): + contract = self.get_min_shop_contract + transaction = contract.functions.mint(1) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_mint_flag_transaction(self): + contract = self.get_mint_flag_contract + transaction = contract.functions.mint(1) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_summer_nft_transaction(self): + contract = self.get_summer_nft_contract + transaction = contract.functions.claim( + self.keypair.address, + 1, + AsyncWeb3.to_checksum_address("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), + 0, + ( + ["0x0000000000000000000000000000000000000000000000000000000000000000"], + 115792089237316195423570985008687907853269984665640564039457584007913129639935, + 0, + AsyncWeb3.to_checksum_address( + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + ), + ), + b"", + ) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_vip3_nft_transaction(self, mint_data: dict): + contract = self.get_vip3_contract + transaction = contract.functions.mint( + self.keypair.address, + mint_data["data"]["deadline"], + mint_data["data"]["level"], + 0, + mint_data["data"]["signature"], + ) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_commemorative_nft_transaction(self): + contract = self.get_commemorative_nft_contract + transaction = contract.functions.mint(1) + + return await transaction.build_transaction( + { + "gasPrice": await self.eth.gas_price, + "nonce": await self.transactions_count(), + "gas": int( + await transaction.estimate_gas({"from": self.keypair.address}) * 1.2 + ), + } + ) + + async def build_createx_collection_transaction(self, data: str): + transaction = { + "from": self.keypair.address, + "data": data, + "nonce": await self.transactions_count(), + } + + estimated_gas = await self.eth.estimate_gas(transaction) + transaction["gas"] = int(estimated_gas * 1.2) + transaction["gasPrice"] = await self.eth.gas_price + + return transaction + + async def build_owlto_summer_fest_nft_transaction(self): + transaction = { + "from": self.keypair.address, + "to": AsyncWeb3.to_checksum_address( + "0x0000C019d60b628F9Ba553092CdA375191319c5e" + ), + "value": AsyncWeb3.to_wei(0.0001, "ether"), + "data": "0x5e752eb40000000000000000000000000c1308dd0b5886b48cb14da2d6cf766cfc8be6ea0000000000000000000000000000000000000000000000000000000000000001", + "nonce": await self.transactions_count(), + } + + estimated_gas = await self.eth.estimate_gas(transaction) + transaction["gas"] = int(estimated_gas * 1.2) + transaction["gasPrice"] = await self.eth.gas_price + + return transaction + + async def build_omnihub_summer_fest_nft_transaction(self): + transaction = { + "from": self.keypair.address, + "to": AsyncWeb3.to_checksum_address( + "0x0000C019d60b628F9Ba553092CdA375191319c5e" + ), + "value": AsyncWeb3.to_wei(0.0001, "ether"), + "data": "0x5e752eb400000000000000000000000050b42f700a5feba13ee6437c43fac4df33062f2b0000000000000000000000000000000000000000000000000000000000000001", + "nonce": await self.transactions_count(), + } + + estimated_gas = await self.eth.estimate_gas(transaction) + transaction["gas"] = int(estimated_gas * 1.2) + transaction["gasPrice"] = await self.eth.gas_price + + return transaction + + @property + def get_forest_message(self) -> str: + message = f"You are participating in the Mint Forest event: \n {self.keypair.address}\n\nNonce: {str(random.randint(1000000, 9000000))}" + return message + + @property + def get_airdrop_message(self) -> str: + message = f"You are participating in the Mint Airdrop event: \n {self.keypair.address}\n\nNonce: {str(random.randint(1000000, 9000000))}" + return message + + def sign_mint_message(self, type_: Literal["airdrop", "forest"]) -> LoginData: + if type_ == "forest": + message = self.get_forest_message + else: + message = self.get_airdrop_message + encoded_message = encode_defunct(text=message) + signed_message = self.keypair.sign_message(encoded_message) + return LoginData(message=message, signed_message=signed_message.signature.hex()) + + async def send_and_verify_transaction(self, trx: Any) -> tuple[bool | Any, str]: + signed = self.keypair.sign_transaction(trx) + tx_hash = await self.eth.send_raw_transaction(signed.rawTransaction) + receipt = await self.eth.wait_for_transaction_receipt(tx_hash) + return receipt["status"] == 1, tx_hash.hex() diff --git a/loader.py b/loader.py index d528938..d116961 100644 --- a/loader.py +++ b/loader.py @@ -1,7 +1,7 @@ import asyncio from models import Config -from config import load_config +from utils import load_config config: Config = load_config() semaphore = asyncio.Semaphore(config.threads) diff --git a/models/account.py b/models/account.py index 5d81b7d..a9b5ff1 100644 --- a/models/account.py +++ b/models/account.py @@ -7,7 +7,6 @@ class Account(BaseModel): pk_or_mnemonic: str proxy: str = None - @field_validator("proxy", mode="before") def check_proxy(cls, value) -> str | None: if not value: diff --git a/models/api.py b/models/api.py index 96a9d97..fb93a64 100644 --- a/models/api.py +++ b/models/api.py @@ -13,11 +13,11 @@ class RankData(BaseModel): class AssetData(BaseModel): - id: int - uid: int - reward: Any + id: int | None = None + uid: int | None = None + reward: Any | None = None type: str = "energy" - openAt: Any + openAt: Any | None = None createdAt: str | None = None @@ -42,18 +42,19 @@ class UserInfo(BaseModel): id: int treeId: int address: str - ens: Any + ens: Any | None = None energy: int tree: int - inviteId: int + inviteId: int | None = None type: str = "normal" - stake_id: int - nft_id: int - nft_pass: int + stake_id: int | None = None + nft_id: int | None = None + nft_pass: int | None = None signin: int - code: Any + code: Any | None = None createdAt: str - invitePercent: int + invitePercent: int | None = None + stealCount: int | None = None class ResponseData(BaseModel): @@ -75,7 +76,6 @@ class User(BaseModel): user: User - class EnergyListData(BaseModel): class Energy(BaseModel): uid: list[str] @@ -84,6 +84,7 @@ class Energy(BaseModel): type: str id: str = None freeze: bool = None + stealable: bool = None @model_validator(mode="before") @classmethod diff --git a/models/config.py b/models/config.py index 4def9ab..374dd2c 100644 --- a/models/config.py +++ b/models/config.py @@ -7,16 +7,21 @@ class Config(BaseModel): accounts: list[Account] referral_code: str | int - eth_rpc_url: HttpUrl - sepolia_rpc_url: HttpUrl + mint_rpc_url: HttpUrl + arb_rpc_url: HttpUrl threads: PositiveInt min_delay_before_start: PositiveInt max_delay_before_start: PositiveInt - min_amount_to_bridge: PositiveFloat - max_amount_to_bridge: PositiveFloat + comet_bridge_wallet: str + comet_bridge_amount_min: PositiveFloat + comet_bridge_amount_max: PositiveFloat + + mint_random_all_nfts: list[str] + delay_between_mint_min: PositiveInt + delay_between_mint_max: PositiveInt spin_turntable_by_percentage_of_energy: int module: str = "" diff --git a/models/onchain.py b/models/onchain.py index 681960b..0fc7b60 100644 --- a/models/onchain.py +++ b/models/onchain.py @@ -1,8 +1,73 @@ from dataclasses import dataclass - @dataclass class BridgeData: address: str = "0x57Fc396328b665f0f8bD235F0840fCeD43128c6b" abi: list = open("./abi/bridge.json", "r").read() + + +@dataclass +class GreenIDData: + address: str = "0x776Fcec07e65dC03E35a9585f9194b8a9082CDdb" + abi: list = open("./abi/green_id.json", "r").read() + + +@dataclass +class CommemorativeNFTData: + address: str = "0xbc4b1cbbfF3Fe2C61Ad2Fd94b91126d5F7593D40" + abi: list = open("./abi/commemorative_nft.json", "r").read() + + +@dataclass +class OmnihubData: + address: str = "0xD473b08745288eF9b412a339ACCfaCce5Cebdd90" + abi: list = open("./abi/omnihub.json", "r").read() + + +@dataclass +class MakeNFTGreatAgainData: + address: str = "0x1a7464938aa694c5dB38Da52114C4fEdBc4EBF6A" + abi: list = open("./abi/make_nft_great_again.json", "r").read() + + +@dataclass +class SummerNFTData: + address: str = "0x98b322D37d54fac46f4980F4171bE2D0Ba8c54C2" + abi: list = open("./abi/summer_nft.json", "r").read() + + +@dataclass +class MintFlagData: + address: str = "0xa6660ba7F9a45e2707efC8dc574aF1DB4319Ee55" + abi: list = open("./abi/mint_flag.json", "r").read() + + +@dataclass +class MintShopData: + address: str = "0xBEEbbAEe8F085F506ce0eA3591f8FBb9C24Af356" + abi: list = open("./abi/mint_shop.json", "r").read() + + +@dataclass +class MintAir3Data: + address: str = "0x38f56A88a9eCD523086804f43Bdf881B8403107a" + abi: list = open("./abi/mint_air3.json", "r").read() + + +@dataclass +class MintSupermintData: + address: str = "0xDD351CDd289d9Bdf88D20EA3c9E316b99dF31412" + abi: list = open("./abi/mint_supermint.json", "r").read() + + +@dataclass +class CometBridgeData: + address: str = "0x0fbCf4a62036E96C4F6770B38a9B536Aa14d1846" + abi: list = open("./abi/cometa.json", "r").read() + + +@dataclass +class Vip3MintData: + address: str = "0xabe292b291A18699b09608de86888D77aD6BAf23" + abi: list = open("./abi/vip3_nft.json", "r").read() diff --git a/requirements.txt b/requirements.txt index 134e481..c90c1de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,14 @@ +httpx~=0.27.0 pyuseragents~=1.0.5 -retrying~=1.3.4 +names~=0.3.0 +noble_tls~=0.0.102 +Jam_Twitter_API~=0.6 loguru~=0.7.2 -web3~=6.15.1 -PyYAML~=6.0.1 pydantic~=2.6.4 +web3~=6.15.1 art~=6.1 -orjson~=3.9.15 -httpx~=0.27.0 -tqdm~=4.66.2 -noble_tls~=0.0.102 -eth_account -curl_cffi~=0.6.2 +PyYAML~=6.0.1 urllib3~=2.2.1 inquirer~=3.2.4 -colorama~=0.4.6 \ No newline at end of file +colorama~=0.4.6 +better_proxy diff --git a/run.py b/run.py index c16cce3..29bca5b 100644 --- a/run.py +++ b/run.py @@ -1,13 +1,16 @@ import asyncio import sys +from typing import Any + import urllib3 -from loguru import logger +from loguru import logger from loader import config, semaphore -from src.bot import Bot +from core.bot import Bot from models import Account from console import Console +from utils import export_trees_ids def setup(): @@ -27,15 +30,55 @@ async def run_safe(account: Account): await Bot(account).start() +async def run_get_tree_info_module(account: Account) -> tuple[Any, bool | str]: + async with semaphore: + client = Bot(account) + tree_id = await client.process_get_tree_id() + if tree_id: + logger.info(f"Account: {account.auth_token} | Tree ID: {tree_id}") + return client.keypair.address, tree_id + + async def run(): while True: Console().build() - tasks = [ - asyncio.create_task(run_safe(account)) for account in config.accounts - ] - await asyncio.gather(*tasks) - input("\nPress Enter to continue...") + if config.module in ( + "bridge", + "rewards", + "tasks", + "fix_sign", + "mint_comm_nft", + "only_rewards", + "mint_omnihub", + "mint_make_nft_great_again", + "mint_summer_nft", + "mint_flag", + "mint_shop", + "mint_air3", + "mint_supermint", + "comet_bridge", + "mint_all_nfts", + "mint_owlto_summer_nft", + "mint_omnihub_summer_nft", + "mint_random_all_nfts", + "mint_vip3_nft", + "mint_green_id", + ): + tasks = [ + asyncio.create_task(run_safe(account)) for account in config.accounts + ] + await asyncio.gather(*tasks) + + elif config.module == "export_trees_ids": + tasks = [ + asyncio.create_task(run_get_tree_info_module(account)) + for account in config.accounts + ] + results = await asyncio.gather(*tasks) + export_trees_ids(results) + + input("\n\nPress Enter to continue...") if __name__ == "__main__": diff --git a/src/api.py b/src/api.py deleted file mode 100644 index 354c987..0000000 --- a/src/api.py +++ /dev/null @@ -1,334 +0,0 @@ -import asyncio -import random -import pyuseragents - -from typing import Literal, List -from noble_tls import Session, Client - -from models import EnergyListData -from twitter_api import Account as TwitterAccount -from twitter_api.models import BindAccountParamsV2 - -from models import * -from loader import config as configuration - -from .wallet import Wallet -from .exceptions.base import APIError -from .bridge import Bridge - - -class MintChainAPI(Wallet): - API_URL = "https://www.mintchain.io/api" - - def __init__(self, account_data: Account): - super().__init__(mnemonic=account_data.pk_or_mnemonic, rpc_url=configuration.eth_rpc_url) - self.account = account_data - self.session = self.setup_session() - self.twitter_account: TwitterAccount = None # type: ignore - - @property - def jwt_token(self) -> str: - return self.session.headers["authorization"].replace("Bearer ", "") - - @property - async def energy_balance(self) -> int: - return (await self.user_info()).energy - - @property - async def tree_size(self) -> int: - return (await self.user_info()).tree - - @property - async def rank(self) -> int: - return (await self.rank_info()).rank - - def setup_session(self) -> Session: - session = Session(client=Client.CHROME_120) - session.random_tls_extension_order = True - - session.timeout_seconds = 15 - session.headers = { - "authority": "www.mintchain.io", - "accept": "application/json, text/plain, */*", - "accept-language": "en-US,en;q=0.9,ru;q=0.8", - "authorization": "Bearer", - "content-type": "application/json", - "origin": "https://www.mintchain.io", - "referer": "https://www.mintchain.io", - "user-agent": pyuseragents.random(), - } - session.proxies = { - "http": self.account.proxy, - "https": self.account.proxy, - } - return session - - async def send_request( - self, - request_type: Literal["POST", "GET"] = "POST", - method: str = None, - json_data: dict = None, - params: dict = None, - url: str = None, - ): - def _verify_response(_response: dict) -> dict: - if "code" in _response: - if _response["code"] != 10000: - raise APIError(f"{_response.get('msg')} | Method: {method}") - - return _response - - raise APIError(f"{_response} | Method: {method}") - - if request_type == "POST": - if not url: - response = await self.session.post( - f"{self.API_URL}{method}", json=json_data, params=params - ) - - else: - response = await self.session.post(url, json=json_data, params=params) - - else: - if not url: - response = await self.session.get( - f"{self.API_URL}{method}", params=params - ) - - else: - response = await self.session.get(url, params=params) - - response.raise_for_status() - return _verify_response(response.json()) - - async def is_daily_reward_claimed(self) -> bool: - response = await self.send_request( - request_type="GET", method="/tree/energy-list" - ) - return response["result"][-1]["freeze"] - - - async def get_energy_list(self) -> EnergyListData: - response = await self.send_request(request_type="GET", method="/tree/energy-list") - return EnergyListData(**response) - - async def get_task_list(self) -> TaskListData: - response = await self.send_request(request_type="GET", method=f"/tree/task-list?address={self.keypair.address}") - return TaskListData(**response) - - async def complete_tasks(self): - task_list = await self.get_task_list() - for task in task_list.result: - if task.spec not in ("discord-follow", "stake"): - if task.claimed: - logger.debug(f"Account: {self.account.auth_token} | Task already completed: {task.name}") - continue - - try: - if task.spec in ("twitter-post", "twitter-follow"): - if not self.twitter_account: - self.load_twitter_account() - - if task.spec == "twitter-follow": - user_id = self.twitter_account.get_user_id("Mint_Blockchain") - self.twitter_account.follow(user_id) - await self.submit_task_id(task.id) - - else: - tweet_text = "I'm collecting @Mint_Blockchain's ME $MINT in the #MintForest🌳!\n\nMint is the L2 for NFT industry, powered by @nftscan_com and @Optimism.\n\nJoin Mint Forest here: https://mintchain.io/mint-forest\n\n#MintBlockchain #L2forNFT" - - data = self.twitter_account.tweet(tweet_text) - tweet_url = f'https://x.com/JammerCrypto/status/{data["data"]["create_tweet"]["tweet_results"]["result"]["rest_id"]}' - await self.submit_task_id(task.id, twitter_post=tweet_url) - - else: - await self.submit_task_id(task.id) - - logger.debug(f"Account: {self.account.auth_token} | Task completed: {task.name} | Reward: {task.amount} energy") - await asyncio.sleep(3) - - except APIError as error: - logger.error(f"Account: {self.account.auth_token} | Failed to complete task: {task.name} | {error}") - await asyncio.sleep(3) - - async def claim_daily_rewards(self) -> None: - energy_list = await self.get_energy_list() - for energy in energy_list.result: - json_data = { - "uid": energy.uid, - "amount": energy.amount, - "includes": energy.includes, - "type": energy.type, - "id": energy.id, - } - - if energy.type == "daily": - if energy.freeze: - logger.debug(f"Account: {self.account.auth_token} | Daily reward already claimed") - continue - else: - json_data["freeze"] = energy.freeze - - await self.send_request(method="/tree/claim", json_data=json_data) - logger.debug(f"Account: {self.account.auth_token} | Claimed {energy.amount} energy | Type: {energy.type}") - await asyncio.sleep(1) - - await self.claim_boxes() - - async def bind_invite_code(self) -> ResponseData: - jwt_token = self.jwt_token - - session = Session(client=Client.CHROME_120) - session.headers = { - "accept": "application/json, text/plain, */*", - "accept-language": "sk-SK,sk;q=0.9,en-US;q=0.8,en;q=0.7", - "authorization": "Bearer", - "referer": "https://www.mintchain.io/mint-forest", - "user-agent": self.session.headers["user-agent"], - } - - json_data = { - "code": str(configuration.referral_code), - "jwtToken": jwt_token, - } - - response = await session.get( - "https://www.mintchain.io/api/tree/invitation", params=json_data - ) - return ResponseData(**response.json()) - - def load_twitter_account(self) -> None: - self.twitter_account = TwitterAccount.run( - auth_token=self.account.auth_token, - setup_session=True, - proxy=self.account.proxy, - ) - - - async def connect_twitter(self) -> dict: - params = { - "code_challenge": "mintchain", - "code_challenge_method": "plain", - "client_id": "enpfUjhndkdrdHhld29aTW96eGM6MTpjaQ", - "redirect_uri": "https://www.mintchain.io/mint-forest", - "response_type": "code", - "scope": "tweet.read users.read follows.read offline.access", - "state": "mintchain", - } - - if not self.twitter_account: - self.load_twitter_account() - - bind_data = self.twitter_account.bind_account_v2( - bind_params=BindAccountParamsV2(**params) - ) - - params = { - "code": bind_data.code, - "jwtToken": self.jwt_token, - "address": self.keypair.address, - } - response = await self.send_request( - url="https://www.mintchain.io/api/twitter/verify", params=params - ) - return response - - async def rank_info(self) -> RankData: - response = await self.send_request(request_type="GET", method="/tree/me-rank") - return RankData(**response["result"]) - - async def user_info(self) -> UserInfo: - response = await self.send_request(request_type="GET", method="/tree/user-info") - return UserInfo(**response["result"]) - - async def assets(self) -> List[AssetData]: - response = await self.send_request(request_type="GET", method="/tree/asset") - return [AssetData(**data) for data in response["result"]] - - async def open_box(self, box_id: int) -> OpenBoxData: - json_data = { - "boxId": box_id, - } - - response = await self.send_request(method="/tree/open-box", json_data=json_data) - return OpenBoxData(**response["result"]) - - async def claim_boxes(self): - assets = await self.assets() - for asset in assets: - if not asset.createdAt: - try: - opened_box_data = await self.open_box(asset.id) - logger.debug(f"Account: {self.account.auth_token} | Box opened | Reward: {opened_box_data.energy} energy") - except APIError as error: - logger.error(f"Account: {self.account.auth_token} | Failed to open box: {asset.type} | {error}") - - await asyncio.sleep(1) - - async def spin_turntable(self) -> TurntableData: - response = await self.send_request(request_type="GET", method="/tree/turntable/open") - return TurntableData(**response["result"]) - - async def inject(self, amount: int = None) -> InjectData: - if not amount: - amount = await self.energy_balance - - if amount <= 0: - return InjectData(code=0, result=False, msg="Energy balance is 0") - - json_data = { - "address": self.keypair.address, - "energy": amount, - } - - response = await self.send_request(method="/tree/inject", json_data=json_data) - return InjectData(**response) - - - async def submit_task_id(self, task_id: int, twitter_post: str = None) -> None: - json_data = { - 'id': task_id, - } - - if twitter_post: - json_data["twitterurl"] = twitter_post - - await self.send_request(method="/tree/task-submit", json_data=json_data) - - async def testnet_bridge(self) -> None: - amount_to_bridge = random.uniform(configuration.min_amount_to_bridge, configuration.max_amount_to_bridge) - bridge = Bridge(amount=amount_to_bridge, mnemonic_or_pk=self.account.pk_or_mnemonic) - bridge.send_transaction() - - async def verify_wallet(self) -> ResponseData: - json_data = { - "jwtToken": self.jwt_token, - } - - response = await self.send_request(method="/wallet/verify", json_data=json_data) - return ResponseData(**response) - - async def login(self): - messages = self.sign_login_message() - json_data = { - "address": self.keypair.address, - "signature": messages.signed_message, - "message": messages.message, - } - - response = await self.send_request(method="/tree/login", json_data=json_data) - data = LoginWalletData(**response["result"]) - self.session.headers["authorization"] = f"Bearer {data.access_token}" - - if data.user.status == "pending": - await self.verify_wallet() - - if not data.user.twitter: - await self.connect_twitter() - logger.debug( - f"Account: {self.account.auth_token} | Twitter account connected" - ) - - if not data.user.inviteId: - await self.bind_invite_code() - logger.debug(f"Account: {self.account.auth_token} | Referral code bound") diff --git a/src/bot.py b/src/bot.py deleted file mode 100644 index 251a73d..0000000 --- a/src/bot.py +++ /dev/null @@ -1,166 +0,0 @@ -import asyncio -import random -from typing import Any - -from models import Account -from loguru import logger -from loader import config - -from .api import MintChainAPI - - -class Bot(MintChainAPI): - def __init__(self, account: Account): - super().__init__(account_data=account) - - async def safe_operation( - self, - operation: callable, - success_message: str, - error_message: str, - retries: int = 0, - delay: int = 3, - argument: Any = None, - ) -> bool: - for _ in range(retries): - try: - await operation() if argument is None else await operation(argument) - logger.success( - f"Account: {self.account.auth_token} | {success_message}" - ) - return True - - except Exception as error: - logger.error( - f"Account: {self.account.auth_token} | {error_message}: {error} | {'Retrying..' if retries > 0 else ''}" - ) - await asyncio.sleep(delay) - continue - - return False - - async def process_login(self) -> bool: - return await self.safe_operation( - operation=self.login, - success_message="Logged in", - error_message="Failed to login", - retries=3, - ) - - async def process_claim_daily_reward(self) -> bool: - return await self.safe_operation( - operation=self.claim_daily_rewards, - success_message="Finished claiming daily rewards", - error_message="Failed to claim daily rewards", - delay=10, - retries=3, - ) - - async def process_inject(self) -> bool: - return await self.safe_operation( - operation=self.inject, - success_message="Finished injecting energy", - error_message="Failed to inject energy", - retries=3, - ) - - async def process_spin_turntable(self) -> bool: - if config.spin_turntable_by_percentage_of_energy > 0: - try: - balance = await self.energy_balance - if balance < 300: - logger.warning( - f"Account: {self.account.auth_token} | Not enough energy to spin turntable" - ) - return True - - amount = int(balance * (config.spin_turntable_by_percentage_of_energy / 100)) - number_of_spins = int(amount // 300) - if number_of_spins > 5: - number_of_spins = 5 - - for _ in range(number_of_spins): - reward = await self.spin_turntable() - logger.success(f"Account: {self.account.auth_token} | Opened turntable | Reward: {reward.energy} energy") - await asyncio.sleep(3) - - except Exception as error: - logger.error( - f"Account: {self.account.auth_token} | Failed to spin turntable: {error}" - ) - - return True - - - async def process_show_user_info(self) -> None: - try: - info = await self.tree_size - logger.success( - f"Account: {self.account.auth_token} | Total injected energy: {info} | Daily actions done.." - ) - - except Exception as error: - logger.warning( - f"Account: {self.account.auth_token} | Failed to get user info: {error} | Daily actions done.." - ) - - async def process_testnet_bridge(self) -> bool: - return await self.safe_operation( - operation=self.testnet_bridge, - success_message="Testnet bridge completed", - error_message="Failed to complete testnet bridge", - delay=30, - retries=3, - ) - - async def process_complete_tasks(self): - return await self.safe_operation( - operation=self.complete_tasks, - success_message="Finished completing tasks", - error_message="Failed to complete tasks", - delay=10, - retries=3, - ) - - async def start(self): - random_delay = random.randint(config.min_delay_before_start, config.max_delay_before_start) - logger.info( - f"Account: {self.account.auth_token} | Work will start in {random_delay} seconds.." - ) - await asyncio.sleep(random_delay) - - try: - if config.module == "rewards": - operations = [ - self.process_login, - self.process_claim_daily_reward, - self.process_spin_turntable, - self.process_inject, - self.process_show_user_info, - ] - - elif config.module == "bridge": - operations = [ - self.process_login, - self.process_testnet_bridge, - ] - - else: - operations = [ - self.process_login, - self.process_complete_tasks, - ] - - for operation in operations: - if not await operation(): - break - - except Exception as error: - logger.error( - f"Account: {self.account.auth_token} | Unhandled error: {error}" - ) - - finally: - logger.success( - f"Account: {self.account.auth_token} | Finished" - ) diff --git a/src/bridge.py b/src/bridge.py deleted file mode 100644 index 7646e9f..0000000 --- a/src/bridge.py +++ /dev/null @@ -1,72 +0,0 @@ -import re - -from web3 import Web3, Account -from web3.exceptions import TransactionIndexingInProgress, TransactionNotFound, TimeExhausted - -from models import BridgeData -from loguru import logger -from loader import config as cfg - - -class Bridge(Web3, Account): - def __init__(self, amount: float, mnemonic_or_pk: str): - super().__init__(Web3.HTTPProvider(cfg.sepolia_rpc_url)) - - self.amount = amount - self.nonce = None - self.keypair = self.from_mnemonic(mnemonic_or_pk) if len(mnemonic_or_pk.split()) in (12, 24) else self.from_key(mnemonic_or_pk) - self.contract = self.eth.contract(address=Web3.to_checksum_address(BridgeData.address), abi=BridgeData.abi) - - @property - def address(self): - return self.keypair.address - - def build_transaction(self): - transaction = self.contract.functions.bridgeETHTo( - self.address, - 200000, - b"0x7375706572627269646765" - ) - - return transaction.build_transaction({ - "value": Web3.to_wei(self.amount, "ether"), - "gasPrice": self.eth.gas_price, - "nonce": self.eth.get_transaction_count(self.address) if not self.nonce else self.nonce, - "gas": int( - transaction.estimate_gas({"from": self.address}) * 1.2 - ), - }) - - def check_balance(self) -> None: - balance = self.eth.get_balance(self.address) - human_balance = self.from_wei(balance, "ether") - - if human_balance < self.amount: - raise Exception(f"Insufficient balance: {human_balance} | Required: {self.amount} ETH") - - - def send_transaction(self) -> bool: - try: - self.check_balance() - - signed_transaction = self.keypair.sign_transaction(self.build_transaction()) - transaction_hash = self.eth.send_raw_transaction(signed_transaction.rawTransaction) - logger.debug(f"Account: {self.address} | Bridging {self.amount} ETH | Transaction hash: {transaction_hash.hex()}") - status = self.eth.wait_for_transaction_receipt(transaction_hash, timeout=60) - - if status.status != 1: - raise Exception(f"Failed to bridge {self.amount} ETH to MINT, transaction failed") - - logger.success(f"Account: {self.address} | Bridged {self.amount} ETH to MINT") - - except (TimeExhausted, TransactionNotFound, TransactionIndexingInProgress) as error: - logger.error(f"Account: {self.address} | Transaction not found or time exhausted | {error} | Retrying...") - return self.send_transaction() - - except Exception as error: - if "nonce too low" in str(error): - self.nonce = int(re.search(r"next nonce (\d+)", str(error)).group(1)) - logger.warning(f"Account: {self.address} | Nonce too low | Next nonce: {self.nonce} | Retrying...") - return self.send_transaction() - - raise Exception(f"Failed to bridge {self.amount} ETH | {error}") diff --git a/src/exceptions/base.py b/src/exceptions/base.py deleted file mode 100644 index a2dcb07..0000000 --- a/src/exceptions/base.py +++ /dev/null @@ -1,4 +0,0 @@ -class APIError(Exception): - """Base class for API exceptions""" - - pass diff --git a/src/wallet.py b/src/wallet.py deleted file mode 100644 index 294a8fa..0000000 --- a/src/wallet.py +++ /dev/null @@ -1,31 +0,0 @@ -from eth_account import Account -from eth_account.messages import encode_defunct -from web3 import Web3 -from web3.types import Nonce - -from models import LoginData - - -Account.enable_unaudited_hdwallet_features() - - -class Wallet(Web3, Account): - def __init__(self, mnemonic: str, rpc_url: str): - super().__init__(Web3.HTTPProvider(rpc_url)) - self.keypair = self.from_mnemonic(mnemonic) if len(mnemonic.split()) in (12, 24) else self.from_key(mnemonic) - - @property - def transactions_count(self) -> Nonce: - return self.eth.get_transaction_count(self.keypair.address) - - @property - def get_message(self) -> str: - message = f"You are participating in the Mint Forest event: \n {self.keypair.address}\n\nNonce: {self.transactions_count}" - return message - - def sign_login_message(self) -> LoginData: - encoded_message = encode_defunct(text=self.get_message) - signed_message = self.keypair.sign_message(encoded_message) - return LoginData( - message=self.get_message, signed_message=signed_message.signature.hex() - ) diff --git a/twitter_api/__init__.py b/twitter_api/__init__.py deleted file mode 100644 index b4831a4..0000000 --- a/twitter_api/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .account import Account -from .errors import * diff --git a/twitter_api/account.py b/twitter_api/account.py deleted file mode 100644 index c806bb9..0000000 --- a/twitter_api/account.py +++ /dev/null @@ -1,1664 +0,0 @@ -import asyncio -import hashlib -import math -import mimetypes -import platform -import secrets -import httpx - -from copy import deepcopy -from datetime import datetime -from string import ascii_letters -from typing import Coroutine -from uuid import uuid1, getnode - -from curl_cffi import requests -from curl_cffi.requests.session import Response -from httpx import Cookies, Headers -from tqdm import tqdm - -from .models import * -from .constants import * -from .errors import TwitterAccountSuspended, RateLimitError -from .models import BindAccountDataV1 -from .util import * - -# logging.getLogger("httpx").setLevel(logging.WARNING) - -if platform.system() != "Windows": - try: - import uvloop - - uvloop.install() - except ImportError as e: - ... - - -class Account: - def __init__(self): - self._session: requests.Session = requests.Session() - self._proxy: str = "" - self._reformatted_proxy: str = "" - - self.gql_api = "https://twitter.com/i/api/graphql" - self.v1_api = "https://api.twitter.com/1.1" - self.v2_api = "https://twitter.com/i/api/2" - - @classmethod - def run( - cls, - auth_token: str = None, - cookies: dict[str] = None, - proxy: str = None, - setup_session: bool = True, - ) -> "Account": - account = cls() - account._proxy = proxy - if proxy: - if proxy.startswith("http://"): - account._session = requests.Session( - proxies={"http://": account.proxy}, timeout=30, verify=False - ) - account._reformatted_proxy = account.proxy - - else: - account._reformatted_proxy = account.get_reformatted_proxy - account._session = requests.Session( - proxies=( - {"http://": account._reformatted_proxy} - if account._reformatted_proxy - else None - ), - timeout=30, - verify=False, - ) - - if not (auth_token, cookies): - raise TwitterError( - { - "error_message": "Failed to authenticate account. You need to set cookies or auth_token." - } - ) - - if setup_session: - if auth_token: - account.session.cookies.update({"auth_token": auth_token}) - account.setup_session() - else: - account.session.cookies.update(cookies) - - else: - if not account.session.cookies.get( - "auth_token" - ) and not account.session.cookies.get("ct0"): - account.session.cookies.update({"auth_token": auth_token}) - account.setup_session() - else: - account.session.cookies.update(cookies) - - return account - - @property - def get_auth_data(self) -> dict: - return { - "auth_token": self.auth_token, - "cookies": dict(self.cookies), - "proxy": self.proxy, - } - - def gql( - self, - method: str, - operation: tuple, - variables: dict, - features: dict = Operation.default_features, - ) -> dict: - qid, op = operation - params = { - "queryId": qid, - "features": features, - "variables": Operation.default_variables | variables, - } - if method == "POST": - data = {"json": params} - else: - data = {"params": {k: orjson.dumps(v).decode() for k, v in params.items()}} - - r = self.session.request( - method=method, - url=f"{self.gql_api}/{qid}/{op}", - headers=self.session.headers, - allow_redirects=True, - **data, - ) - - return self._verify_response(r) - - def v1(self, path: str, params: dict) -> dict: - headers = get_headers(self.session) - headers["content-type"] = "application/x-www-form-urlencoded" - r = self.session.post( - f"{self.v1_api}/{path}", headers=headers, data=params, allow_redirects=True - ) - return self._verify_response(r) - - @staticmethod - def _verify_response(r: Response) -> dict: - try: - rate_limit_remaining = r.headers.get("x-rate-limit-remaining") - if rate_limit_remaining and int(rate_limit_remaining) in (0, 1): - reset_ts = int(r.headers.get("x-rate-limit-reset")) - raise RateLimitError( - f"Rate limit reached. Reset in {reset_ts - int(time.time())} seconds. " - ) - # logger.info( - # f"Rate limit reached | Reset in {reset_ts - int(time.time())} seconds | Sleeping..." - # ) - # current_ts = int(time.time()) - # difference = reset_ts - current_ts - # asyncio.sleep(difference) - - data = r.json() - except ValueError: - raise TwitterError( - { - "error_message": f"Failed to parse response: {r.text}. " - "If you are using proxy, make sure it is not blocked by Twitter." - } - ) - - if "errors" in data: - error_message = ( - data["errors"][0].get("message") if data["errors"] else data["errors"] - ) - - error_code = data["errors"][0].get("code") if data["errors"] else None - - if isinstance(error_message, str) and error_message.lower().startswith( - "to protect our users from spam and other" - ): - raise TwitterAccountSuspended(error_message) - - raise TwitterError( - { - "error_code": error_code, - "error_message": error_message, - } - ) - - try: - r.raise_for_status() - except httpx.HTTPError as http_error: - raise TwitterError( - { - "error_message": str(http_error), - } - ) - - return data - - @property - def proxy(self): - return self._proxy - - @property - def get_reformatted_proxy(self): - try: - if self.proxy is None: - return None - - ip, port, username, password = self.proxy.split(":") - return f"http://{username}:{password}@{ip}:{port}" - - except (ValueError, AttributeError): - raise TwitterError( - { - "error_message": "Failed to parse proxy. " - "Make sure you are using correct proxy format: " - "ip:port:username:password" - } - ) - - @property - def session(self): - return self._session - - @property - def cookies(self) -> Cookies: - return self._session.cookies - - @property - def headers(self) -> Headers: - return self._session.headers - - @property - def auth_token(self) -> str: - return self._session.cookies.get("auth_token", "") - - @property - def ct0(self) -> str: - return self._session.cookies.get("ct0", "") - - def request_ct0(self) -> str: - url = "https://twitter.com/i/api/2/oauth2/authorize" - r = self.session.get(url, allow_redirects=True) - - if "ct0" in r.cookies: - return r.cookies.get("ct0") - else: - raise TwitterError( - { - "error_message": "Failed to get ct0 token. " - "Make sure you are using correct cookies." - } - ) - - def request_guest_token( - self, session: requests.Session, csrf_token: str = None - ) -> str: - if not (csrf_token, self.session.cookies.get("ct0", "")): - raise TwitterError( - { - "error_message": "Failed to get guest token. " - "Make sure you are using correct cookies." - } - ) - - headers = { - "content-type": "application/x-www-form-urlencoded", - "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs=1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", - "x-csrf-token": ( - csrf_token if csrf_token else self.session.cookies.get("ct0") - ), - } - r = session.post( - f"{self.v1_api}/guest/activate.json", - headers=headers, - allow_redirects=True, - ) - - data = self._verify_response(r) - return data["guest_token"] - - def setup_session(self): - session = requests.Session( - # follow_redirects=True, - proxies={"http://": self._reformatted_proxy} if self.proxy else None, - timeout=30, - verify=False, - ) - - generated_csrf_token = secrets.token_hex(16) - guest_token = self.request_guest_token(session, generated_csrf_token) - - cookies = {"ct0": generated_csrf_token, "gt": guest_token} - headers = {"x-guest-token": guest_token, "x-csrf-token": generated_csrf_token} - - self.session.headers.update(headers) - self.session.cookies.update(cookies) - csrf_token = self.request_ct0() - - self.session.headers["x-csrf-token"] = csrf_token - self.session.cookies.delete("ct0") - self.session.cookies.update({"ct0": csrf_token}) - self.session.headers = get_headers(self.session) - - self.verify_credentials() - self.session.headers.update( - {"x-csrf-token": self.session.cookies.get("ct0", domain=".twitter.com")} - ) - - def bind_account_v1(self, bind_params: BindAccountParamsV1) -> BindAccountDataV1: - - def get_oauth_token() -> str: - _response = requests.get(str(bind_params.url), allow_redirects=True) - raise_for_status(_response) - - token = re.search( - r' 1: - return token[1] - - raise TwitterError( - { - "error_message": "Failed to get oauth token. " - "Make sure you are using correct cookies or url." - } - ) - - def get_authenticity_token(_oauth_token: str) -> BindAccountDataV1 | str: - params = { - "oauth_token": _oauth_token, - } - _response = self.session.get( - "https://api.twitter.com/oauth/authenticate", params=params - ) - raise_for_status(_response) - - token = re.search( - r' str: - data = { - "authenticity_token": _authenticity_token, - "redirect_after_login": f"https://api.twitter.com/oauth/authorize?oauth_token={_oauth_token}", - "oauth_token": _oauth_token, - } - - response = self.session.post( - "https://api.twitter.com/oauth/authorize", - data=data, - allow_redirects=True, - ) - raise_for_status(response) - - _confirm_url = re.search( - r' BindAccountDataV1: - response = self.session.get(_url, allow_redirects=True) - raise_for_status(response) - - if "status=error" in response.url: - raise TwitterError( - { - "error_message": "Failed to bind account. " - "Make sure you are using correct cookies or url." - } - ) - - _oauth_token, _oauth_verifier = response.url.split("oauth_token=")[1].split( - "&oauth_verifier=" - ) - return BindAccountDataV1( - url=response.url, - oauth_token=_oauth_token, - oauth_verifier=_oauth_verifier, - ) - - oauth_token = get_oauth_token() - authenticity_token = get_authenticity_token(oauth_token) - - if isinstance(authenticity_token, BindAccountDataV1): - return authenticity_token - - confirm_url = get_confirm_url(oauth_token, authenticity_token) - return process_confirm_url(confirm_url) - - def bind_account_v2(self, bind_params: BindAccountParamsV2) -> BindAccountDataV2: - - def get_auth_code() -> str: - response = self.session.get( - "https://twitter.com/i/api/2/oauth2/authorize", - params=bind_params.model_dump(), - ) - raise_for_status(response) - self.session.headers.update( - {"x-csrf-token": self.session.cookies.get("ct0", domain=".twitter.com")} - ) - return response.json()["auth_code"] - - def approve_auth_code(_auth_code: str) -> str: - _params = { - "approval": "true", - "code": _auth_code, - } - - response = self.session.post( - "https://twitter.com/i/api/2/oauth2/authorize", - params=_params, - allow_redirects=True, - ) - raise_for_status(response) - - code = response.json()["redirect_uri"].split("code=")[1] - return code - - auth_code = get_auth_code() - approved_code = approve_auth_code(auth_code) - return BindAccountDataV2(code=approved_code) - - def create_poll(self, text: str, choices: list[str], poll_duration: int) -> dict: - options = { - "twitter:card": "poll4choice_text_only", - "twitter:api:api:endpoint": "1", - "twitter:long:duration_minutes": poll_duration, # max: 10080 - } - for i, c in enumerate(choices): - options[f"twitter:string:choice{i + 1}_label"] = c - - headers = get_headers(self.session) - headers["content-type"] = "application/x-www-form-urlencoded" - url = "https://caps.twitter.com/v2/cards/create.json" - - r = self.session.post( - url, - headers=headers, - params={"card_data": orjson.dumps(options).decode()}, - allow_redirects=True, - ) - card_uri = (self._verify_response(r))["card_uri"] - - data = self.tweet(text, poll_params={"card_uri": card_uri}) - return data - - def verify_credentials(self) -> dict: - r = self.session.get( - f"{self.v1_api}/account/verify_credentials.json", allow_redirects=True - ) - return self._verify_response(r) - - def email_phone_info(self) -> dict: - r = self.session.get( - f"{self.v1_api}/users/email_phone_info.json", allow_redirects=True - ) - return self._verify_response(r) - - def settings_info(self) -> dict: - r = self.session.get( - f"{self.v1_api}/account/settings.json", allow_redirects=True - ) - return self._verify_response(r) - - def screen_name(self) -> str: - data = self.verify_credentials() - return data["screen_name"] - - def user_id(self) -> int: - data = self.verify_credentials() - return data["id"] - - def name(self) -> str: - data = self.verify_credentials() - return data["name"] - - def location(self) -> str: - data = self.verify_credentials() - return data["location"] - - def description(self) -> str: - data = self.verify_credentials() - return data["description"] - - def followers_count(self) -> int: - data = self.verify_credentials() - return data["followers_count"] - - def friends_count(self) -> int: - data = self.verify_credentials() - return data["friends_count"] - - def registration_date(self) -> str: - data = self.verify_credentials() - return data["created_at"] - - def suspended(self) -> bool: - data = self.verify_credentials() - return data["suspended"] - - def dm(self, text: str, receivers: list[int], media: str = "") -> dict: - variables = { - "message": {}, - "requestId": str(uuid1(getnode())), - "target": {"participant_ids": receivers}, - } - if media: - media_id = self.upload_media(media, is_dm=True) - variables["message"]["media"] = {"id": media_id, "text": text} - else: - variables["message"]["text"] = {"text": text} - - res = self.gql("POST", Operation.useSendMessageMutation, variables) - if find_key(res, "dm_validation_failure_type"): - raise TwitterError( - { - "error_message": "Failed to send message. Sender does not have privilege to dm receiver(s)", - "error_code": 349, - } - ) - return res - - def custom_dm(self, text: str, receiver: int) -> dict: - json_data = { - "event": { - "type": "message_create", - "message_create": { - "target": {"recipient_id": f"{receiver}"}, - "message_data": {"text": f"{text}"}, - }, - } - } - - r = self.session.post( - f"{self.v1_api}/direct_messages/events/new.json", - json=json_data, - ) - return self._verify_response(r) - - def delete_tweet(self, tweet_id: int | str) -> dict: - variables = {"tweet_id": tweet_id, "dark_request": False} - return self.gql("POST", Operation.DeleteTweet, variables) - - def tweet( - self, text: str, *, media: List[MediaEntity] = None, **kwargs - ) -> dict: - variables = { - "tweet_text": text, - "dark_request": False, - "media": { - "media_entities": [], - "possibly_sensitive": False, - }, - "semantic_annotation_ids": [], - } - - if reply_params := kwargs.get("reply_params", {}): - variables |= reply_params - if quote_params := kwargs.get("quote_params", {}): - variables |= quote_params - if poll_params := kwargs.get("poll_params", {}): - variables |= poll_params - - draft = kwargs.get("draft") - schedule = kwargs.get("schedule") - - if draft or schedule: - variables = { - "post_tweet_request": { - "auto_populate_reply_metadata": False, - "status": text, - "exclude_reply_user_ids": [], - "media_ids": [], - }, - } - if media: - for m in media: - media_id = self.upload_media(m["media"]) - variables["post_tweet_request"]["media_ids"].append(media_id) - if alt := m.get("alt"): - self._add_alt_text(media_id, alt) - - if schedule: - variables["execute_at"] = ( - datetime.strptime(schedule, "%Y-%m-%d %H:%M").timestamp() - if isinstance(schedule, str) - else schedule - ) - return self.gql("POST", Operation.CreateScheduledTweet, variables) - - return self.gql("POST", Operation.CreateDraftTweet, variables) - - # regular tweet - if media: - for m in media: - - tagged_users_id = [] - for tagged_user in m.tagged_users: - user_id = self.get_user_id(tagged_user) - tagged_users_id.append(user_id) - - variables["media"]["media_entities"].append( - {"media_id": m.media_id, "tagged_users": tagged_users_id} - ) - - return self.gql("POST", Operation.CreateTweet, variables) - - def schedule_tweet( - self, text: str, date: int | str, *, media: List[MediaEntity] = None - ) -> dict: - variables = { - "post_tweet_request": { - "auto_populate_reply_metadata": False, - "status": text, - "exclude_reply_user_ids": [], - "media_ids": [], - }, - "execute_at": ( - datetime.strptime(date, "%Y-%m-%d %H:%M").timestamp() - if isinstance(date, str) - else date - ), - } - if media: - for m in media: - - tagged_users_id = [] - for tagged_user in m.tagged_users: - user_id = self.get_user_id(tagged_user) - tagged_users_id.append(user_id) - - variables["media"]["media_entities"].append( - {"media_id": m.media_id, "tagged_users": tagged_users_id} - ) - - return self.gql("POST", Operation.CreateScheduledTweet, variables) - - def schedule_reply( - self, text: str, date: int | str, tweet_id: int, *, media: list = None - ) -> dict: - variables = { - "post_tweet_request": { - "auto_populate_reply_metadata": True, - "in_reply_to_status_id": tweet_id, - "status": text, - "exclude_reply_user_ids": [], - "media_ids": [], - }, - "execute_at": ( - datetime.strptime(date, "%Y-%m-%d %H:%M").timestamp() - if isinstance(date, str) - else date - ), - } - if media: - for m in media: - media_id = self.upload_media(m["media"]) - variables["post_tweet_request"]["media_ids"].append(media_id) - if alt := m.get("alt"): - self._add_alt_text(media_id, alt) - - return self.gql("POST", Operation.CreateScheduledTweet, variables) - - def unschedule_tweet(self, tweet_id: int | str) -> dict: - variables = {"scheduled_tweet_id": tweet_id} - return self.gql("POST", Operation.DeleteScheduledTweet, variables) - - def untweet(self, tweet_id: int | str) -> dict: - variables = {"tweet_id": tweet_id, "dark_request": False} - return self.gql("POST", Operation.DeleteTweet, variables) - - def reply( - self, text: str, tweet_id: int | str, media: List[MediaEntity] = None - ) -> dict: - variables = { - "tweet_text": text, - "reply": { - "in_reply_to_tweet_id": tweet_id, - "exclude_reply_user_ids": [], - }, - "batch_compose": "BatchSubsequent", - "dark_request": False, - "media": { - "media_entities": [], - "possibly_sensitive": False, - }, - "semantic_annotation_ids": [], - } - - if media: - for m in media: - tagged_users_id = [] - - for tagged_user in m.tagged_users: - user_id = self.get_user_id(tagged_user) - tagged_users_id.append(user_id) - - variables["media"]["media_entities"].append( - {"media_id": m.media_id, "tagged_users": tagged_users_id} - ) - - return self.gql("POST", Operation.CreateTweet, variables) - - def quote(self, text: str, tweet_id: int) -> dict: - variables = { - "tweet_text": text, - # can use `i` as it resolves to screen_name - "attachment_url": f"https://twitter.com/i/status/{tweet_id}", - "dark_request": False, - "media": { - "media_entities": [], - "possibly_sensitive": False, - }, - "semantic_annotation_ids": [], - } - return self.gql("POST", Operation.CreateTweet, variables) - - def retweet(self, tweet_id: int) -> dict: - variables = {"tweet_id": tweet_id, "dark_request": False} - return self.gql("POST", Operation.CreateRetweet, variables) - - def unretweet(self, tweet_id: int) -> dict: - variables = {"source_tweet_id": tweet_id, "dark_request": False} - return self.gql("POST", Operation.DeleteRetweet, variables) - - @staticmethod - def __get_cursor_value(data: dict, target_cursor_type: str, target_entry_type: str): - if target_entry_type != "threaded_conversation_with_injections_v2": - for instruction in ( - data.get("data", {}) - .get(target_entry_type, {}) - .get("timeline", {}) - .get("instructions", []) - ): - for entry in instruction.get("entries", []): - content = entry.get("content", {}) - cursor_type = content.get("cursorType") - if ( - content.get("entryType") == "TimelineTimelineCursor" - and cursor_type == target_cursor_type - ): - return content.get("value") - - else: - for instruction in ( - data.get("data", {}).get(target_entry_type, {}).get("instructions", []) - ): - for entry in instruction.get("entries", []): - content = entry.get("content", {}) - cursor_type = content.get("cursorType") - if ( - content.get("entryType") == "TimelineTimelineCursor" - and cursor_type == target_cursor_type - ): - return content.get("value") - - return None - - def tweet_likes( - self, celery_task, tweet_id: int, limit: int = 0 - ) -> dict[str, list[dict]]: - variables = {"tweetId": tweet_id, "count": 100} - users_data = [] - - while True: - data = self.gql("GET", Operation.Favoriters, variables) - - for instruction in ( - data.get("data", {}) - .get("favoriters_timeline", {}) - .get("timeline", {}) - .get("instructions", []) - ): - try: - for entry in instruction["entries"]: - try: - result = entry["content"]["itemContent"]["user_results"][ - "result" - ] - screen_name = result["legacy"]["screen_name"] - if screen_name not in ( - user["screen_name"] for user in users_data - ): - users_data.append( - self.get_user_data_from_user_results(result) - ) - - except (KeyError, TypeError, IndexError): - continue - - except KeyError: - return {"users": users_data[:limit] if limit > 0 else users_data} - - cursor_value = self.__get_cursor_value( - data, "Bottom", "favoriters_timeline" - ) - if not cursor_value or (0 < limit <= len(users_data)): - return {"users": users_data[:limit] if limit > 0 else users_data} - - variables["cursor"] = cursor_value - - def tweet_retweeters( - self, celery_task, tweet_id: int, limit: int = 0 - ) -> dict[str, list[Any]]: - variables = {"tweetId": tweet_id, "count": 100} - tweets_data = [] - - while True: - data = self.gql("GET", Operation.Retweeters, variables) - - for instruction in data["data"]["retweeters_timeline"]["timeline"][ - "instructions" - ]: - try: - for entry in instruction["entries"]: - try: - result = entry["content"]["itemContent"]["user_results"][ - "result" - ] - screen_name = result["legacy"]["screen_name"] - if screen_name not in ( - user["screen_name"] for user in tweets_data - ): - tweets_data.append( - self.get_user_data_from_user_results(result) - ) - except (KeyError, TypeError, IndexError): - continue - - except KeyError: - return {"users": tweets_data[:limit] if limit > 0 else tweets_data} - - cursor_value = self.__get_cursor_value( - data, "Bottom", "retweeters_timeline" - ) - - if not cursor_value or (0 < limit <= len(tweets_data)): - return {"users": tweets_data[:limit] if limit > 0 else tweets_data} - - variables["cursor"] = cursor_value - - @staticmethod - def get_user_data_from_user_results(data: dict) -> dict: - legacy = data.get("legacy", {}) - - return { - "id": data.get("rest_id"), - "name": legacy.get("name"), - "screen_name": legacy.get("screen_name"), - "profile_image_url": legacy.get("profile_image_url_https"), - "favourites_count": legacy.get("favourites_count"), - "followers_count": legacy.get("followers_count"), - "friends_count": legacy.get("friends_count"), - "location": legacy.get("location"), - "description": legacy.get("description"), - "created_at": legacy.get("created_at"), - } - - def tweet_replies( - self, celery_task, tweet_id: int, limit: int = 0 - ) -> dict[str, list[dict[str, dict | Any]]]: - variables = {"focalTweetId": tweet_id} - replies_data = [] - - while True: - data = self.gql("GET", Operation.TweetDetail, variables) - - for entry in data["data"]["threaded_conversation_with_injections_v2"][ - "instructions" - ][0]["entries"]: - try: - result = entry["content"]["items"][0]["item"]["itemContent"][ - "tweet_results" - ]["result"] - reply_text = result["legacy"]["full_text"] - user_results = result["core"]["user_results"]["result"] - - if reply_text not in ( - reply["reply_text"] for reply in replies_data - ): - replies_data.append( - { - "reply_text": reply_text, - "user_data": self.get_user_data_from_user_results( - user_results - ), - } - ) - except (KeyError, TypeError, IndexError): - continue - - entries = data["data"]["threaded_conversation_with_injections_v2"][ - "instructions" - ][0]["entries"] - if not entries[-1]["entryId"].startswith("cursor-bottom") or ( - 0 < limit <= len(replies_data) - ): - return {"replies": replies_data[:limit] if limit > 0 else replies_data} - - for entry in entries: - if entry["entryId"].startswith("cursor-bottom"): - cursor_value = entry["content"]["itemContent"]["value"] - variables["cursor"] = cursor_value - break - - def user_followers(self, celery_task, username: str, limit: int = 0) -> list[str]: - variables = {"screen_name": username, "count": 200} - users = [] - - while True: - r = self.session.get(f"{self.v1_api}/followers/list.json", params=variables) - if r.status_code == 503: - asyncio.sleep(3) - continue - - else: - data = self._verify_response(r) - new_users = [user["screen_name"] for user in data["users"]] - users.extend(new_users) - - next_cursor = int(data.get("next_cursor")) - if next_cursor == 0 or (0 < limit <= len(users)): - return users[:limit] if limit > 0 else users - - variables["cursor"] = data["next_cursor_str"] - - def user_followings(self, username: str) -> list[str]: - variables = {"screen_name": username, "count": 200} - users = [] - - while True: - r = self.session.get(f"{self.v1_api}/friends/list.json", params=variables) - if r.status_code == 503: - asyncio.sleep(5) - continue - - else: - data = self._verify_response(r) - new_users = [user["screen_name"] for user in data["users"]] - users.extend(new_users) - - if int(data.get("next_cursor")) == 0: - return users - - variables["cursor"] = data["next_cursor_str"] - - def user_last_tweets( - self, user_id: int, username: str - ) -> list[dict[str, str, str | None, str | None, str | None]]: - data = self.gql("GET", Operation.UserTweets, {"userId": user_id}) - - try: - tweets_data = [] - timeline = data["data"]["user"]["result"]["timeline_v2"]["timeline"] - for tweet in timeline["instructions"]: - entries = tweet.get("entries", []) - for entry in entries: - if entry["entryId"].startswith("tweet"): - tweet_link = f"https://twitter.com/{username}/status/{entry['entryId'].split('-')[-1]}" - else: - continue - - tweet_results = ( - entry.get("content", {}) - .get("itemContent", {}) - .get("tweet_results", {}) - .get("result", {}) - .get("legacy") - ) - if tweet_results and tweet_results.get("full_text"): - full_text = tweet_results["full_text"] - created_at = tweet_results.get("created_at", "") - is_quote_status = tweet_results.get("is_quote_status", "") - lang = tweet_results.get("lang", "") - - tweets_data.append( - { - "tweet_link": tweet_link, - "full_text": full_text, - "created_at": created_at, - "is_quote_status": is_quote_status, - "lang": lang, - } - ) - - return tweets_data - - except Exception as error: - raise TwitterError({"error_message": f"Failed to get user tweets: {error}"}) - - def like(self, tweet_id: int) -> dict: - variables = {"tweet_id": tweet_id} - return self.gql("POST", Operation.FavoriteTweet, variables) - - def unlike(self, tweet_id: int) -> dict: - variables = {"tweet_id": tweet_id} - return self.gql("POST", Operation.UnfavoriteTweet, variables) - - def bookmark(self, tweet_id: int) -> dict: - variables = {"tweet_id": tweet_id} - return self.gql("POST", Operation.CreateBookmark, variables) - - def unbookmark(self, tweet_id: int) -> dict: - variables = {"tweet_id": tweet_id} - return self.gql("POST", Operation.DeleteBookmark, variables) - - def create_list(self, name: str, description: str, private: bool) -> dict: - variables = { - "isPrivate": private, - "name": name, - "description": description, - } - return self.gql("POST", Operation.CreateList, variables) - - def update_list( - self, list_id: int, name: str, description: str, private: bool - ) -> dict: - variables = { - "listId": list_id, - "isPrivate": private, - "name": name, - "description": description, - } - return self.gql("POST", Operation.UpdateList, variables) - - def update_pinned_lists(self, list_ids: list[int]) -> dict: - """ - Update pinned lists. - Reset all pinned lists and pin all specified lists in the order they are provided. - - @param list_ids: list of list ids to pin - @return: response - """ - return self.gql("POST", Operation.ListsPinMany, {"listIds": list_ids}) - - def pin_list(self, list_id: int) -> dict: - return self.gql("POST", Operation.ListPinOne, {"listId": list_id}) - - def unpin_list(self, list_id: int) -> dict: - return self.gql("POST", Operation.ListUnpinOne, {"listId": list_id}) - - def add_list_member(self, list_id: int, user_id: int) -> dict: - return self.gql( - "POST", Operation.ListAddMember, {"listId": list_id, "userId": user_id} - ) - - def remove_list_member(self, list_id: int, user_id: int) -> dict: - return self.gql( - "POST", Operation.ListRemoveMember, {"listId": list_id, "userId": user_id} - ) - - def delete_list(self, list_id: int) -> dict: - return self.gql("POST", Operation.DeleteList, {"listId": list_id}) - - def update_list_banner(self, list_id: int, media: str) -> dict: - media_id = self.upload_media(media) - variables = {"listId": list_id, "mediaId": media_id} - return self.gql("POST", Operation.EditListBanner, variables) - - def delete_list_banner(self, list_id: int) -> dict: - return self.gql("POST", Operation.DeleteListBanner, {"listId": list_id}) - - def follow_topic(self, topic_id: int) -> dict: - return self.gql("POST", Operation.TopicFollow, {"topicId": str(topic_id)}) - - def unfollow_topic(self, topic_id: int) -> dict: - return self.gql("POST", Operation.TopicUnfollow, {"topicId": str(topic_id)}) - - def pin(self, tweet_id: int) -> dict: - return self.v1( - "account/pin_tweet.json", {"tweet_mode": "extended", "id": tweet_id} - ) - - def unpin(self, tweet_id: int) -> dict: - return self.v1( - "account/unpin_tweet.json", {"tweet_mode": "extended", "id": tweet_id} - ) - - def get_user_id(self, username: str) -> int: - headers = get_headers(self.session) - headers["content-type"] = "application/x-www-form-urlencoded" - r = self.session.get( - f"{self.v1_api}/users/show.json", - headers=headers, - params={"screen_name": username}, - ) - data = self._verify_response(r) - return data["id"] - - def get_user_info(self, username: str) -> dict: - headers = get_headers(self.session) - headers["content-type"] = "application/x-www-form-urlencoded" - r = self.session.get( - f"{self.v1_api}/users/show.json", - headers=headers, - params={"screen_name": username}, - ) - return self._verify_response(r) - - def follow(self, user_id: int | str) -> dict: - settings = deepcopy(follow_settings) - settings |= {"user_id": user_id} - return self.v1("friendships/create.json", settings) - - def unfollow(self, user_id: int | str) -> dict: - settings = deepcopy(follow_settings) - settings |= {"user_id": user_id} - return self.v1("friendships/destroy.json", settings) - - def mute(self, user_id: int) -> dict: - return self.v1("mutes/users/create.json", {"user_id": user_id}) - - def unmute(self, user_id: int) -> dict: - return self.v1("mutes/users/destroy.json", {"user_id": user_id}) - - def enable_follower_notifications(self, user_id: int) -> dict: - settings = deepcopy(follower_notification_settings) - settings |= {"id": user_id, "device": "true"} - return self.v1("friendships/update.json", settings) - - def disable_follower_notifications(self, user_id: int) -> dict: - settings = deepcopy(follower_notification_settings) - settings |= {"id": user_id, "device": "false"} - return self.v1("friendships/update.json", settings) - - def block(self, user_id: int) -> dict: - return self.v1("blocks/create.json", {"user_id": user_id}) - - def unblock(self, user_id: int) -> dict: - return self.v1("blocks/destroy.json", {"user_id": user_id}) - - def update_profile_image(self, media: str) -> dict: - media_id = self.upload_media(media) - params = {"media_id": media_id} - - r = self.session.post( - f"{self.v1_api}/account/update_profile_image.json", - headers=get_headers(self.session), - params=params, - ) - return self._verify_response(r) - - def update_profile_banner(self, media: str) -> dict: - media_id = self.upload_media(media) - params = {"media_id": media_id} - - r = self.session.post( - f"{self.v1_api}/account/update_profile_banner.json", - headers=get_headers(self.session), - params=params, - ) - return self._verify_response(r) - - def update_profile_info(self, params: dict) -> dict: - headers = get_headers(self.session) - r = self.session.post( - f"{self.v1_api}/account/update_profile.json", headers=headers, params=params - ) - - return self._verify_response(r) - - def update_search_settings(self, settings: dict) -> dict: - twid = int(self.session.cookies.get("twid").split("=")[-1].strip('"')) - headers = get_headers(self.session) - - r = self.session.post( - url=f"{self.v1_api}/strato/column/User/{twid}/search/searchSafety", - headers=headers, - json=settings, - ) - return self._verify_response(r) - - def update_settings(self, settings: dict) -> dict: - return self.v1("account/settings.json", settings) - - def update_username(self, username: str): - return self.update_settings({"screen_name": username}) - - def change_password(self, old: str, new: str) -> dict: - params = { - "current_password": old, - "password": new, - "password_confirmation": new, - } - headers = get_headers(self.session) - headers["content-type"] = "application/x-www-form-urlencoded" - - r = self.session.post( - f"{self.v1_api}/account/change_password.json", - headers=headers, - data=params, - allow_redirects=True, - ) - return self._verify_response(r) - - def remove_interests(self, *args) -> dict: - """ - Pass 'all' to remove all interests - """ - r = self.session.get( - f"{self.v1_api}/account/personalization/twitter_interests.json", - headers=get_headers(self.session), - ) - current_interests = r.json()["interested_in"] - if args == "all": - disabled_interests = [x["id"] for x in current_interests] - else: - disabled_interests = [ - x["id"] for x in current_interests if x["display_name"] in args - ] - payload = { - "preferences": { - "interest_preferences": { - "disabled_interests": disabled_interests, - "disabled_partner_interests": [], - } - } - } - r = self.session.post( - f"{self.v1_api}/account/personalization/p13n_preferences.json", - headers=get_headers(self.session), - json=payload, - ) - return self._verify_response(r) - - def home_timeline(self, limit=math.inf) -> list[dict]: - return self._paginate( - "POST", Operation.HomeTimeline, Operation.default_variables, int(limit) - ) - - def home_latest_timeline(self, limit=math.inf) -> list[dict]: - return self._paginate( - "POST", - Operation.HomeLatestTimeline, - Operation.default_variables, - int(limit), - ) - - def bookmarks(self, limit=math.inf) -> list[dict]: - return self._paginate("GET", Operation.Bookmarks, {}, int(limit)) - - def _paginate( - self, method: str, operation: tuple, variables: dict, limit: int - ) -> list[dict]: - initial_data = self.gql(method, operation, variables) - res = [initial_data] - ids = set(find_key(initial_data, "rest_id")) - dups = 0 - DUP_LIMIT = 3 - - cursor = get_cursor(initial_data) - while (dups < DUP_LIMIT) and cursor: - prev_len = len(ids) - if prev_len >= limit: - return res - - variables["cursor"] = cursor - data = self.gql(method, operation, variables) - - cursor = get_cursor(data) - ids |= set(find_key(data, "rest_id")) - - if prev_len == len(ids): - dups += 1 - - res.append(data) - return res - - def custom_upload_media(self, file: Path) -> int | None: - url = "https://upload.twitter.com/1.1/media/upload.json" - - headers = get_headers(self.session) - with httpx.Client( - headers=headers, cookies=dict(self.session.cookies) - ) as client: - upload_type = "tweet" - media_type = mimetypes.guess_type(file)[0] - media_category = ( - f"{upload_type}_gif" - if "gif" in media_type - else f'{upload_type}_{media_type.split("/")[0]}' - ) - - files = {"media": file.read_bytes()} - - post_data = {} - if media_category is not None: - post_data["media_category"] = media_category - - r = client.post(url=url, json=params, params=post_data, files=files) - - data = self._verify_response(r) - return data["media_id"] - - def upload_media(self, filename: str, is_dm: bool = False) -> int | None: - """ - https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/uploading-media/media-best-practices - """ - - def check_media(category: str, size: int) -> None: - fmt = lambda x: f"{(x / 1e6):.2f} MB" - msg = ( - lambda x: f"cannot upload {fmt(size)} {category}, max size is {fmt(x)}" - ) - if category == "image" and size > MAX_IMAGE_SIZE: - raise Exception(msg(MAX_IMAGE_SIZE)) - if category == "gif" and size > MAX_GIF_SIZE: - raise Exception(msg(MAX_GIF_SIZE)) - if category == "video" and size > MAX_VIDEO_SIZE: - raise Exception(msg(MAX_VIDEO_SIZE)) - - # if is_profile: - # url = 'https://upload.twitter.com/i/media/upload.json' - # else: - # url = 'https://upload.twitter.com/1.1/media/upload.json' - - url = "https://upload.twitter.com/i/media/upload.json" - - file = Path(filename) - total_bytes = file.stat().st_size - headers = get_headers(self.session) - - upload_type = "dm" if is_dm else "tweet" - media_type = mimetypes.guess_type(file)[0] - media_category = ( - f"{upload_type}_gif" - if "gif" in media_type - else f'{upload_type}_{media_type.split("/")[0]}' - ) - - check_media(media_category, total_bytes) - - params = { - "command": "INIT", - "media_type": media_type, - "total_bytes": total_bytes, - "media_category": media_category, - } - r = self.session.post( - url=url, headers=headers, params=params, allow_redirects=True - ) - - data = self._verify_response(r) - media_id = data["media_id"] - - desc = f"uploading: {file.name}" - with tqdm( - total=total_bytes, desc=desc, unit="B", unit_scale=True, unit_divisor=1024 - ) as pbar: - with open(file, "rb") as fp: - i = 0 - while chunk := fp.read(UPLOAD_CHUNK_SIZE): - params = { - "command": "APPEND", - "media_id": media_id, - "segment_index": i, - } - try: - pad = bytes( - "".join(random.choices(ascii_letters, k=16)), - encoding="utf-8", - ) - data = b"".join( - [ - b"------WebKitFormBoundary", - pad, - b'\r\nContent-Disposition: form-data; name="media"; filename="blob"', - b"\r\nContent-Type: application/octet-stream", - b"\r\n\r\n", - chunk, - b"\r\n------WebKitFormBoundary", - pad, - b"--\r\n", - ] - ) - _headers = { - b"content-type": b"multipart/form-data; boundary=----WebKitFormBoundary" - + pad - } - self.session.post( - url=url, - headers=headers | _headers, - params=params, - content=data, - allow_redirects=True, - ) - except Exception as error: - try: - files = {"media": chunk} - self.session.post( - url=url, headers=headers, params=params, files=files - ) - except Exception as error: - return - - i += 1 - pbar.update(fp.tell() - pbar.n) - - params = {"command": "FINALIZE", "media_id": media_id, "allow_async": "true"} - if is_dm: - params |= {"original_md5": hashlib.md5(file.read_bytes()).hexdigest()} - - r = self.session.post( - url=url, headers=headers, params=params, allow_redirects=True - ) - data = self._verify_response(r) - - processing_info = data.get("processing_info") - while processing_info: - state = processing_info["state"] - if error := processing_info.get("error"): - return - if state == MEDIA_UPLOAD_SUCCEED: - break - if state == MEDIA_UPLOAD_FAIL: - return - check_after_secs = processing_info.get( - "check_after_secs", random.randint(1, 5) - ) - - time.sleep(check_after_secs) - params = {"command": "STATUS", "media_id": media_id} - - r = self.session.get( - url=url, headers=headers, params=params, allow_redirects=True - ) - data = self._verify_response(r) - processing_info = data.get("processing_info") - - return media_id - - def _add_alt_text(self, media_id: int, text: str) -> dict: - params = {"media_id": media_id, "alt_text": {"text": text}} - url = f"{self.v1_api}/media/metadata/create.json" - r = self.session.post(url, headers=get_headers(self.session), json=params) - return self._verify_response(r) - - def dm_inbox(self) -> dict: - """ - Get DM inbox metadata. - - @return: inbox as dict - """ - r = self.session.get( - f"{self.v1_api}/dm/inbox_initial_state.json", - headers=get_headers(self.session), - params=dm_params, - ) - return self._verify_response(r) - - # def dm_history(self, conversation_ids: list[str] = None) -> list[dict]: - # """ - # Get DM history. - # - # Call without arguments to get all DMS from all conversations. - # - # @param conversation_ids: optional list of conversation ids - # @return: list of messages as dicts - # """ - # - # def get(session: AsyncClient, conversation_id: str): - # params = deepcopy(dm_params) - # r = session.get( - # f"{self.v1_api}/dm/conversation/{conversation_id}.json", - # params=params, - # ) - # res = (self._verify_response(r)).get("conversation_timeline", {}) - # data = [x.get("message") for x in res.get("entries", [])] - # entry_id = res.get("min_entry_id") - # while entry_id: - # params["max_id"] = entry_id - # r = session.get( - # f"{self.v1_api}/dm/conversation/{conversation_id}.json", - # params=params, - # ) - # res = (self._verify_response(r)).get("conversation_timeline", {}) - # data.extend(x["message"] for x in res.get("entries", [])) - # entry_id = res.get("min_entry_id") - # return data - # - # def process(ids): - # limits = Limits(max_connections=100) - # headers, cookies = get_headers(self.session), self.session.cookies - # async with AsyncClient( - # limits=limits, headers=headers, cookies=cookies, timeout=20 - # ) as c: - # return tqdm_asyncio.gather( - # *(get(c, _id) for _id in ids), desc="Getting DMs" - # ) - # - # if conversation_ids: - # ids = conversation_ids - # else: - # # get all conversations - # inbox = self.dm_inbox() - # ids = list(inbox["inbox_initial_state"]["conversations"]) - # - # return asyncio.run(process(ids)) - - def dm_delete(self, *, conversation_id: str = None, message_id: str = None) -> dict: - """ - Delete operations - - - delete (hide) a single DM - - delete an entire conversation - - @param conversation_id: the conversation id - @param message_id: the message id - @return: result metadata - """ - self.session.headers.update(headers=get_headers(self.session)) - results = {"conversation": None, "message": None} - if conversation_id: - results["conversation"] = self.session.post( - f"{self.v1_api}/dm/conversation/{conversation_id}/delete.json", - ) # not json response - if message_id: - # delete single message - _id, op = Operation.DMMessageDeleteMutation - results["message"] = self.session.post( - f"{self.gql_api}/{_id}/{op}", - json={"queryId": _id, "variables": {"messageId": message_id}}, - ) - return results - - def dm_search(self, query: str) -> dict: - """ - Search DMs by keyword - - @param query: search term - @return: search results as dict - """ - - def get(cursor=None): - if cursor: - params["variables"]["cursor"] = cursor.pop() - _id, op = Operation.DmAllSearchSlice - r = self.session.get( - f"{self.gql_api}/{_id}/{op}", - params=build_params(params), - ) - res = r.json() - cursor = find_key(res, "next_cursor") - return res, cursor - - self.session.headers.update(headers=get_headers(self.session)) - variables = deepcopy(Operation.default_variables) - variables["count"] = 50 # strict limit, errors thrown if exceeded - variables["query"] = query - params = {"variables": variables, "features": Operation.default_features} - res, cursor = get() - data = [res] - while cursor: - res, cursor = get(cursor) - data.append(res) - return {"query": query, "data": data} - - def scheduled_tweets(self, ascending: bool = True) -> dict: - variables = {"ascending": ascending} - return self.gql("GET", Operation.FetchScheduledTweets, variables) - - def delete_scheduled_tweet(self, tweet_id: int) -> dict: - """duplicate, same as `unschedule_tweet()`""" - variables = {"scheduled_tweet_id": tweet_id} - return self.gql("POST", Operation.DeleteScheduledTweet, variables) - - def clear_scheduled_tweets(self) -> None: - user_id = int(re.findall('"u=(\d+)"', self.session.cookies.get("twid"))[0]) - drafts = self.gql("GET", Operation.FetchScheduledTweets, {"ascending": True}) - for _id in set(find_key(drafts, "rest_id")): - if _id != user_id: - self.gql( - "POST", Operation.DeleteScheduledTweet, {"scheduled_tweet_id": _id} - ) - - def draft_tweets(self, ascending: bool = True) -> dict: - variables = {"ascending": ascending} - return self.gql("GET", Operation.FetchDraftTweets, variables) - - def delete_draft_tweet(self, tweet_id: int) -> dict: - variables = {"draft_tweet_id": tweet_id} - return self.gql("POST", Operation.DeleteDraftTweet, variables) - - def clear_draft_tweets(self) -> None: - user_id = int(re.findall('"u=(\d+)"', self.session.cookies.get("twid"))[0]) - drafts = self.gql("GET", Operation.FetchDraftTweets, {"ascending": True}) - for _id in set(find_key(drafts, "rest_id")): - if _id != user_id: - self.gql("POST", Operation.DeleteDraftTweet, {"draft_tweet_id": _id}) - - def notifications(self, params: dict = None) -> dict: - r = self.session.get( - f"{self.v2_api}/notifications/all.json", - headers=get_headers(self.session), - params=params or live_notification_params, - ) - return self._verify_response(r) - - def recommendations(self, params: dict = None) -> dict: - r = self.session.get( - f"{self.v1_api}/users/recommendations.json", - headers=get_headers(self.session), - params=params or recommendations_params, - ) - return self._verify_response(r) - - def fleetline(self, params: dict = None) -> dict: - r = self.session.get( - "https://twitter.com/i/api/fleets/v1/fleetline", - headers=get_headers(self.session), - params=params or {}, - ) - return self._verify_response(r) - - @property - def id(self) -> int: - """Get User ID""" - return int(re.findall('"u=(\d+)"', self.session.cookies.get("twid"))[0]) - - def save_cookies(self, fname: str = None): - """Save cookies to file""" - cookies = self.session.cookies - Path(f'{fname or cookies.get("username")}.cookies').write_bytes( - orjson.dumps(dict(cookies)) - ) diff --git a/twitter_api/constants.py b/twitter_api/constants.py deleted file mode 100644 index 643b8c3..0000000 --- a/twitter_api/constants.py +++ /dev/null @@ -1,801 +0,0 @@ -from dataclasses import dataclass - - -MAX_IMAGE_SIZE = 5_242_880 # ~5 MB -MAX_GIF_SIZE = 15_728_640 # ~15 MB -MAX_VIDEO_SIZE = 536_870_912 # ~530 MB - -UPLOAD_CHUNK_SIZE = 4 * 1024 * 1024 -MEDIA_UPLOAD_SUCCEED = "succeeded" -MEDIA_UPLOAD_FAIL = "failed" - -BLACK = "\x1b[30m" -RED = "\x1b[31m" -GREEN = "\x1b[32m" -YELLOW = "\x1b[33m" -BLUE = "\x1b[34m" -MAGENTA = "\x1b[35m" -CYAN = "\x1b[36m" -WHITE = "\x1b[37m" -BOLD = "\x1b[1m" -RESET = "\x1b[0m" - -LOG_CONFIG = { - "version": 1, - "disable_existing_loggers": False, - "formatters": { - "standard": { - "format": "%(asctime)s.%(msecs)03d [%(levelname)s] :: %(message)s", - "datefmt": "%Y-%m-%d %H:%M:%S", - }, - }, - "handlers": { - "console": { - "class": "logging.StreamHandler", - "level": "DEBUG", - "formatter": "standard", - "stream": "ext://sys.stdout", - }, - "file": { - "class": "logging.FileHandler", - "level": "DEBUG", - "formatter": "standard", - "filename": "twitter.log", - "mode": "a", - }, - }, - "loggers": { - "twitter": { - "handlers": ["console", "file"], - "level": "DEBUG", - } - }, -} - -ID_MAP = { - "Followers": "^user-\d+$", - "Following": "^user-\d+$", - "UserTweets": "^tweet-\d+$", - "Likes": "^tweet-\d+$", - "UserMedia": "^tweet-\d+$", - "TweetResultByRestId": "^tweet-\d+$", - "TweetsAndReplies": "^profile-conversation-\d+-tweet-\d+$", - "TweetDetail": "^conversationthread-\d+-tweet-\d+$", # if another key after tweet-\d+, it's an ad - "Retweeters": "^user-\d+$", - "Favoriters": "^user-\d+$", -} - - -@dataclass -class SearchCategory: - Top = "Top" - Latest = "Latest" - People = "People" - Photos = "Photos" - Videos = "Videos" - - -@dataclass -class SpaceCategory: - Top = "Top" - Live = "Live" - Upcoming = "Upcoming" - - -@dataclass -class SpaceState: - Ended = "Ended" - Canceled = "Canceled" - NotStarted = "NotStarted" - PrePublished = "PrePublished" - Running = "Running" - TimedOut = "TimedOut" - - -@dataclass -class Operation: - # todo: dynamically update - SearchTimeline = ( - {"rawQuery": str, "product": str}, - "nK1dw4oV3k4w5TdtcAdSww", - "SearchTimeline", - ) - AudioSpaceById = {"id": str}, "fYAuJHiY3TmYdBmrRtIKhA", "AudioSpaceById" - AudioSpaceSearch = ( - {"filter": str, "query": str}, - "NTq79TuSz6fHj8lQaferJw", - "AudioSpaceSearch", - ) - UserByScreenName = ( - {"screen_name": str}, - "sLVLhk0bGj3MVFEKTdax1w", - "UserByScreenName", - ) - UserTweets = "HuTx74BxAnezK1gWvYY7zg", "UserTweets" - ProfileSpotlightsQuery = ( - {"screen_name": str}, - "9zwVLJ48lmVUk8u_Gh9DmA", - "ProfileSpotlightsQuery", - ) - UserByRestId = {"userId": int}, "GazOglcBvgLigl3ywt6b3Q", "UserByRestId" - UsersByRestIds = {"userIds": list}, "OJBgJQIrij6e3cjqQ3Zu1Q", "UsersByRestIds" - UserMedia = {"userId": int}, "YqiE3JL1KNgf9nSljYdxaA", "UserMedia" - UserTweetsAndReplies = ( - {"userId": int}, - "RIWc55YCNyUJ-U3HHGYkdg", - "UserTweetsAndReplies", - ) - TweetResultByRestId = ( - {"tweetId": int}, - "D_jNhjWZeRZT5NURzfJZSQ", - "TweetResultByRestId", - ) - TweetDetail = "zXaXQgfyR4GxE21uwYQSyA", "TweetDetail" - TweetStats = {"rest_id": int}, "EvbTkPDT-xQCfupPu0rWMA", "TweetStats" - Likes = {"userId": int}, "nXEl0lfN_XSznVMlprThgQ", "Likes" - Followers = {"userId": int}, "pd8Tt1qUz1YWrICegqZ8cw", "Followers" - Following = {"userId": int}, "wjvx62Hye2dGVvnvVco0xA", "Following" - Retweeters = "0BoJlKAxoNPQUHRftlwZ2w", "Retweeters" - Favoriters = "XRRjv1-uj1HZn3o324etOQ", "Favoriters" - ConnectTabTimeline = ( - {"context": dict}, - "lq02A-gEzbLefqTgD_PFzQ", - "ConnectTabTimeline", - ) - - # Account Operations - useSendMessageMutation = "MaxK2PKX1F9Z-9SwqwavTw", "useSendMessageMutation" - CreateTweet = "7TKRKCPuAGsmYde0CudbVg", "CreateTweet" - DeleteTweet = "VaenaVgh5q5ih7kvyVjgtg", "DeleteTweet" - CreateScheduledTweet = "LCVzRQGxOaGnOnYH01NQXg", "CreateScheduledTweet" - DeleteScheduledTweet = "CTOVqej0JBXAZSwkp1US0g", "DeleteScheduledTweet" - CreateRetweet = "ojPdsZsimiJrUGLR1sjUtA", "CreateRetweet" - DeleteRetweet = "iQtK4dl5hBmXewYZuEOKVw", "DeleteRetweet" - FavoriteTweet = "lI07N6Otwv1PhnEgXILM7A", "FavoriteTweet" - UnfavoriteTweet = "ZYKSe-w7KEslx3JhSIk5LA", "UnfavoriteTweet" - CreateBookmark = "aoDbu3RHznuiSkQ9aNM67Q", "CreateBookmark" - DeleteBookmark = "Wlmlj2-xzyS1GN3a6cj-mQ", "DeleteBookmark" - CreateList = "hQAsnViq2BrMLbPuQ9umDA", "CreateList" - UpdateList = "4dCEFWtxEbhnSLcJdJ6PNg", "UpdateList" - ListsPinMany = "2X4Vqu6XLneR-XZnGK5MAw", "ListsPinMany" - ListPinOne = "2pYlo-kjdXoNOZJoLzI6KA", "ListPinOne" - ListUnpinOne = "c4ce-hzx6V4heV5IzdeBkA", "ListUnpinOne" - ListAddMember = "P8tyfv2_0HzofrB5f6_ugw", "ListAddMember" - ListRemoveMember = "DBZowzFN492FFkBPBptCwg", "ListRemoveMember" - DeleteList = "UnN9Th1BDbeLjpgjGSpL3Q", "DeleteList" - EditListBanner = "Uk0ZwKSMYng56aQdeJD1yw", "EditListBanner" - DeleteListBanner = "-bOKetDVCMl20qXn7YDXIA", "DeleteListBanner" - TopicFollow = "ElqSLWFmsPL4NlZI5e1Grg", "TopicFollow" - TopicUnfollow = "srwjU6JM_ZKTj_QMfUGNcw", "TopicUnfollow" - HomeLatestTimeline = "zhX91JE87mWvfprhYE97xA", "HomeLatestTimeline" - HomeTimeline = "HCosKfLNW1AcOo3la3mMgg", "HomeTimeline" - Bookmarks = "tmd4ifV8RHltzn8ymGg1aw", "Bookmarks" - - # misc/not implemented - AdAccounts = "a8KxGfFQAmm3WxqemuqSRA", "AdAccounts" - ArticleTimeline = "o9FyvnC-xg8mVBXqL4g-rg", "ArticleTimeline" - ArticleTweetsTimeline = "x4ywSpvg6BesoDszkfbFQg", "ArticleTweetsTimeline" - AudienceEstimate = "1LYVUabJBYkPlUAWRabB3g", "AudienceEstimate" - AuthenticatedUserTFLists = "QjN8ZdavFDqxUjNn3r9cig", "AuthenticatedUserTFLists" - BirdwatchAliasSelect = "3ss48WFwGokBH_gj8t_8aQ", "BirdwatchAliasSelect" - BirdwatchCreateAppeal = "TKdL0YFsX4DMOpMKeneLvA", "BirdwatchCreateAppeal" - BirdwatchCreateNote = "36EUZZyaciVmNrq4CRZcmw", "BirdwatchCreateNote" - BirdwatchCreateRating = "bD3AEK9BMCSpRods_ng2fA", "BirdwatchCreateRating" - BirdwatchDeleteNote = "IKS_qrShkDyor6Ri1ahd9g", "BirdwatchDeleteNote" - BirdwatchDeleteRating = "OpvCOyOoQClUND66zDzrnA", "BirdwatchDeleteRating" - BirdwatchEditNotificationSettings = ( - "FLgLReVIssXjB_ui3wcrRQ", - "BirdwatchEditNotificationSettings", - ) - BirdwatchFetchAliasSelfSelectOptions = ( - "szoXMke8AZOErso908iglw", - "BirdwatchFetchAliasSelfSelectOptions", - ) - BirdwatchFetchAliasSelfSelectStatus = ( - "LUEdtkcpBlGktUtms4BvwA", - "BirdwatchFetchAliasSelfSelectStatus", - ) - BirdwatchFetchAuthenticatedUserProfile = ( - "pMbW6Y4LuS5MzlSOEqERJQ", - "BirdwatchFetchAuthenticatedUserProfile", - ) - BirdwatchFetchBirdwatchProfile = ( - "btgGtchypc3D491MJ7XXWA", - "BirdwatchFetchBirdwatchProfile", - ) - BirdwatchFetchContributorNotesSlice = ( - "t6r3Wq7wripUW9gB3FQNBw", - "BirdwatchFetchContributorNotesSlice", - ) - BirdwatchFetchGlobalTimeline = ( - "L3LftPt6fhYqoQ5Vnxm7UQ", - "BirdwatchFetchGlobalTimeline", - ) - BirdwatchFetchNotes = "ZGMhf1M7kPKMOhEk1nz0Yw", "BirdwatchFetchNotes" - BirdwatchFetchOneNote = "GO8BR2MM2WZB63cdOoC7lw", "BirdwatchFetchOneNote" - BirdwatchFetchPublicData = "9bDdJ6AL26RLkcUShEcF-A", "BirdwatchFetchPublicData" - BirdwatchProfileAcknowledgeEarnOut = ( - "cED9wJy8Nd1kZCCYuIq9zQ", - "BirdwatchProfileAcknowledgeEarnOut", - ) - BizProfileFetchUser = "6OFpJ3TH3p8JpwOSgfgyhg", "BizProfileFetchUser" - BlockedAccountsAll = "h52d1F7dumWGE1tJAhQBpg", "BlockedAccountsAll" - BlockedAccountsAutoBlock = "8w-D2OhT0jmGzXaNY--UQA", "BlockedAccountsAutoBlock" - BlockedAccountsImported = "8LDNeOEm0kA98uoDsqXvMg", "BlockedAccountsImported" - BookmarkFolderTimeline = "13H7EUATwethsj-XxX5ohw", "BookmarkFolderTimeline" - BookmarkFoldersSlice = "i78YDd0Tza-dV4SYs58kRg", "BookmarkFoldersSlice" - BookmarksAllDelete = "skiACZKC1GDYli-M8RzEPQ", "BookmarksAllDelete" - Budgets = "mbK3oSQotwcJXyQIBE3uYw", "Budgets" - CardPreviewByTweetText = "jnwTSDR-Eo_HWlSkXPcMGA", "CardPreviewByTweetText" - CheckTweetForNudge = "C2dcvh7H69JALtomErxWlA", "CheckTweetForNudge" - CombinedLists = "rIxum3avpCu7APi7mxTNjw", "CombinedLists" - CommunitiesMainDiscoveryModule = ( - "8UB2fhB8TiYIW2M6vbBFXg", - "CommunitiesMainDiscoveryModule", - ) - CommunitiesMainPageTimeline = ( - "DzcxPzkGYVQk-BD0pqAcZw", - "CommunitiesMainPageTimeline", - ) - CommunitiesMembershipsSlice = ( - "s8-oxdVsoJ3w2CFD0nFt9g", - "CommunitiesMembershipsSlice", - ) - CommunitiesMembershipsTimeline = ( - "QXo-eKTsvhpCyFotNz2u6g", - "CommunitiesMembershipsTimeline", - ) - CommunityAboutTimeline = "plOgdpBzpVVQbTOEVuRc_A", "CommunityAboutTimeline" - CommunityByRestId = "bCVwRBDPi15jrdJQ7NCENQ", "CommunityByRestId" - CommunityCreateRule = "dShPoN6voXRusgxC1uvGog", "CommunityCreateRule" - CommunityDiscoveryTimeline = "b3rceNUXWRyo5mSwVZF74Q", "CommunityDiscoveryTimeline" - CommunityEditBannerMedia = "KVkZwp8Q6xy6iyhlQE5d7Q", "CommunityEditBannerMedia" - CommunityEditName = "SKToKhvm3Z4Rir8ENCJ3YQ", "CommunityEditName" - CommunityEditPurpose = "eMat-u2kx6KocreGTAt-hA", "CommunityEditPurpose" - CommunityEditRule = "9nEl5bNcdteuPGbGCdvEFA", "CommunityEditRule" - CommunityEditTheme = "4OhW6gWJwiu-JTAgBPsU1w", "CommunityEditTheme" - CommunityHashtagsTimeline = "hril1TsnshopHbmnjdUmhQ", "CommunityHashtagsTimeline" - CommunityMemberRelationshipTypeahead = ( - "NEwac2-8ONgf0756ne8oXA", - "CommunityMemberRelationshipTypeahead", - ) - CommunityModerationKeepTweet = ( - "f_YqrHSCc1mPlG-aB7pFRw", - "CommunityModerationKeepTweet", - ) - CommunityModerationTweetCasesSlice = ( - "V-iC7tjWOlzBJ44SanqGzw", - "CommunityModerationTweetCasesSlice", - ) - CommunityRemoveBannerMedia = "lSdK1v30qVhm37rDTgHq0Q", "CommunityRemoveBannerMedia" - CommunityRemoveRule = "EI_g43Ss_Ixg0EC4K7nzlQ", "CommunityRemoveRule" - CommunityReorderRules = "VwluNMGnl5uaNZ3LnlCQ_A", "CommunityReorderRules" - CommunityTweetsRankedTimeline = ( - "P38EspBBPhAfSKPP74-s2Q", - "CommunityTweetsRankedTimeline", - ) - CommunityTweetsTimeline = "2JgHOlqfeLusxAT0yGQJjg", "CommunityTweetsTimeline" - CommunityUpdateRole = "5eq76kkUqfdCzInCtcxQOA", "CommunityUpdateRole" - CommunityUserInvite = "x8hUNaBCOV2tSalqB9cwWQ", "CommunityUserInvite" - CommunityUserRelationshipTypeahead = ( - "gi_UGcUurYp6N6p2BaLJqQ", - "CommunityUserRelationshipTypeahead", - ) - ConversationControlChange = "hb1elGcj6769uT8qVYqtjw", "ConversationControlChange" - ConversationControlDelete = "OoMO_aSZ1ZXjegeamF9QmA", "ConversationControlDelete" - ConvertRitoSuggestedActions = ( - "2njnYoE69O2jdUM7KMEnDw", - "ConvertRitoSuggestedActions", - ) - Coupons = "R1h43jnAl2bsDoUkgZb7NQ", "Coupons" - CreateCommunity = "lRjZKTRcWuqwtYwCWGy9_w", "CreateCommunity" - CreateCustomerPortalSession = ( - "2LHXrd1uYeaMWhciZgPZFw", - "CreateCustomerPortalSession", - ) - CreateDraftTweet = "cH9HZWz_EW9gnswvA4ZRiQ", "CreateDraftTweet" - CreateNoteTweet = "Pyx6nga4XtTVhfTh1gtX1A", "CreateNoteTweet" - CreateQuickPromotion = "oDSoVgHhJxnd5IkckgPZdg", "CreateQuickPromotion" - CreateTrustedFriendsList = "2tP8XUYeLHKjq5RHvuvpZw", "CreateTrustedFriendsList" - CreateTweetDownvote = "Eo65jl-gww30avDgrXvhUA", "CreateTweetDownvote" - CreateTweetReaction = "D7M6X3h4-mJE8UB1Ap3_dQ", "CreateTweetReaction" - DataSaverMode = "xF6sXnKJfS2AOylzxRjf6A", "DataSaverMode" - DeleteBookmarkFolder = "2UTTsO-6zs93XqlEUZPsSg", "DeleteBookmarkFolder" - DeleteDraftTweet = "bkh9G3FGgTldS9iTKWWYYw", "DeleteDraftTweet" - DeletePaymentMethod = "VaaLGwK5KNLoc7wsOmp4uw", "DeletePaymentMethod" - DeleteTweetDownvote = "VNEvEGXaUAMfiExP8Tbezw", "DeleteTweetDownvote" - DeleteTweetReaction = "GKwK0Rj4EdkfwdHQMZTpuw", "DeleteTweetReaction" - DisableUserAccountLabel = "_ckHEj05gan2VfNHG6thBA", "DisableUserAccountLabel" - DisableVerifiedPhoneLabel = "g2m0pAOamawNtVIfjXNMJg", "DisableVerifiedPhoneLabel" - DismissRitoSuggestedAction = "jYvwa61cv3NwNP24iUru6g", "DismissRitoSuggestedAction" - DmAllSearchSlice = "U-QXVRZ6iddb1QuZweh5DQ", "DmAllSearchSlice" - DmGroupSearchSlice = "5zpY1dCR-8NyxQJS_CFJoQ", "DmGroupSearchSlice" - DmMutedTimeline = "lrcWa13oyrQc7L33wRdLAQ", "DmMutedTimeline" - DMMessageDeleteMutation = "BJ6DtxA2llfjnRoRjaiIiw", "DMMessageDeleteMutation" - DmNsfwMediaFilterUpdate = "of_N6O33zfyD4qsFJMYFxA", "DmNsfwMediaFilterUpdate" - DmPeopleSearchSlice = "xYSm8m5kJnzm_gFCn5GH-w", "DmPeopleSearchSlice" - EditBookmarkFolder = "a6kPp1cS1Dgbsjhapz1PNw", "EditBookmarkFolder" - EditDraftTweet = "JIeXE-I6BZXHfxsgOkyHYQ", "EditDraftTweet" - EditScheduledTweet = "_mHkQ5LHpRRjSXKOcG6eZw", "EditScheduledTweet" - EnableLoggedOutWebNotifications = ( - "BqIHKmwZKtiUBPi07jKctg", - "EnableLoggedOutWebNotifications", - ) - EnableVerifiedPhoneLabel = "C3RJFfMsb_KcEytpKmRRkw", "EnableVerifiedPhoneLabel" - EnrollCoupon = "SOyGmNGaEXcvk15s5bqDrA", "EnrollCoupon" - ExplorePage = "fkypGKlR9Xz9kLvUZDLoXw", "ExplorePage" - FeatureSettingsUpdate = "-btar_vkBwWA7s3YWfp_9g", "FeatureSettingsUpdate" - FetchDraftTweets = "ZkqIq_xRhiUme0PBJNpRtg", "FetchDraftTweets" - FetchScheduledTweets = "ITtjAzvlZni2wWXwf295Qg", "FetchScheduledTweets" - FollowersYouKnow = "RvojYJJB90VwJ0rdVhbjMQ", "FollowersYouKnow" - ForYouExplore = "wVEXnyTWzQlEsIuLq_D3tw", "ForYouExplore" - GenericTimelineById = "LZfAdxTdNolKXw6ZkoY_kA", "GenericTimelineById" - GetSafetyModeSettings = "AhxTX0lkbIos4WG53xwzSA", "GetSafetyModeSettings" - GetTweetReactionTimeline = "ihIcULrtrtPGlCuprduRrA", "GetTweetReactionTimeline" - GetUserClaims = "lFi3xnx0auUUnyG4YwpCNw", "GetUserClaims" - GraphQLError = "2V2W3HIBuMW83vEMtfo_Rg", "GraphQLError" - ImmersiveMedia = "UGQD_VslAJBJ4XzigsBYAA", "ImmersiveMedia" - JoinCommunity = "PXO-mA1KfmLqB9I6R-lOng", "JoinCommunity" - LeaveCommunity = "AtiTdhEyRN8ruNFW069ewQ", "LeaveCommunity" - ListByRestId = "wXzyA5vM_aVkBL9G8Vp3kw", "ListByRestId" - ListBySlug = "3-E3eSWorCv24kYkK3CCiQ", "ListBySlug" - ListCreationRecommendedUsers = ( - "Zf8ZwG57EKtss-rPlryIqg", - "ListCreationRecommendedUsers", - ) - ListEditRecommendedUsers = "-F4wsOirYNXjjg-ZjccQpQ", "ListEditRecommendedUsers" - ListLatestTweetsTimeline = "2TemLyqrMpTeAmysdbnVqw", "ListLatestTweetsTimeline" - ListMembers = "vA952kfgGw6hh8KatWnbqw", "ListMembers" - ListMemberships = "BlEXXdARdSeL_0KyKHHvvg", "ListMemberships" - ListOwnerships = "wQcOSjSQ8NtgxIwvYl1lMg", "ListOwnerships" - ListPins = "J0JOhmi8HSsle8LfSWv0cw", "ListPins" - ListProductSubscriptions = "wwdBYgScze0_Jnan79jEUw", "ListProductSubscriptions" - ListRankedTweetsTimeline = "07lytXX9oG9uCld1RY4b0w", "ListRankedTweetsTimeline" - ListSubscribe = "FjvrQI3k-97JIUbEE6Gxcw", "ListSubscribe" - ListSubscribers = "e57wIELAAe0fYt4Hmqsk6g", "ListSubscribers" - ListUnsubscribe = "bXyvW9HoS_Omy4ADhexj8A", "ListUnsubscribe" - ListsDiscovery = "ehnzbxPHA69pyaV2EydN1g", "ListsDiscovery" - ListsManagementPageTimeline = ( - "nhYp4n09Hi5n2hQWseQztg", - "ListsManagementPageTimeline", - ) - LiveCommerceItemsSlice = "-lnNX56S2YrZYrLzbccFAQ", "LiveCommerceItemsSlice" - ModerateTweet = "pjFnHGVqCjTcZol0xcBJjw", "ModerateTweet" - ModeratedTimeline = "hnaqw2Vok5OETdBVa_uexw", "ModeratedTimeline" - MuteList = "ZYyanJsskNUcltu9bliMLA", "MuteList" - MutedAccounts = "-G9eXTmseyiSenbqjrEG6w", "MutedAccounts" - NoteworthyAccountsPage = "3fOJzEwYMnVyzwgLTLIBkw", "NoteworthyAccountsPage" - PaymentMethods = "mPF_G9okpbZuLcD6mN8K9g", "PaymentMethods" - PinReply = "GA2_1uKP9b_GyR4MVAQXAw", "PinReply" - ProfileUserPhoneState = "5kUWP8C1hcd6omvg6HXXTQ", "ProfileUserPhoneState" - PutClientEducationFlag = "IjQ-egg0uPkY11NyPMfRMQ", "PutClientEducationFlag" - QuickPromoteEligibility = "LtpCXh66W-uXh7u7XSRA8Q", "QuickPromoteEligibility" - RemoveFollower = "QpNfg0kpPRfjROQ_9eOLXA", "RemoveFollower" - RemoveTweetFromBookmarkFolder = ( - "2Qbj9XZvtUvyJB4gFwWfaA", - "RemoveTweetFromBookmarkFolder", - ) - RequestToJoinCommunity = "6G66cW5zuxPXmHOeBOjF2w", "RequestToJoinCommunity" - RitoActionedTweetsTimeline = "px9Zbs48D-YdQPEROK6-nA", "RitoActionedTweetsTimeline" - RitoFlaggedAccountsTimeline = ( - "lMzaBZHIbD6GuPqJJQubMg", - "RitoFlaggedAccountsTimeline", - ) - RitoFlaggedTweetsTimeline = "iCuXMibh6yj9AelyjKXDeA", "RitoFlaggedTweetsTimeline" - RitoSuggestedActionsFacePile = ( - "GnQKeEdL1LyeK3dTQCS1yw", - "RitoSuggestedActionsFacePile", - ) - SetDefault = "QEMLEzEMzoPNbeauKCCLbg", "SetDefault" - SetSafetyModeSettings = "qSJIPIpf4gA7Wn21bT3D4w", "SetSafetyModeSettings" - SharingAudiospacesListeningDataWithFollowersUpdate = ( - "5h0kNbk3ii97rmfY6CdgAA", - "SharingAudiospacesListeningDataWithFollowersUpdate", - ) - SubscribeToScheduledSpace = "Sxn4YOlaAwEKjnjWV0h7Mw", "SubscribeToScheduledSpace" - SubscriptionCheckoutUrlWithEligibility = ( - "hKfOOObQr5JmfmxW0YtPvg", - "SubscriptionCheckoutUrlWithEligibility", - ) - SubscriptionProductDetails = "f0dExZDmFWFSWMCPQSAemQ", "SubscriptionProductDetails" - SubscriptionProductFeaturesFetch = ( - "Me2CVcAXxvK2WMr-Nh_Qqg", - "SubscriptionProductFeaturesFetch", - ) - SuperFollowers = "o0YtPFnd4Lk_pOQb9alCvA", "SuperFollowers" - TopicByRestId = "4OUZZOonV2h60I0wdlQb_w", "TopicByRestId" - TopicLandingPage = "mAKQjs1kyTS75VLZzuIXXw", "TopicLandingPage" - TopicNotInterested = "cPCFdDAaqRjlMRYInZzoDA", "TopicNotInterested" - TopicToFollowSidebar = "RPWVYYupHVZkJOnokbt2cw", "TopicToFollowSidebar" - TopicUndoNotInterested = "4tVnt6FoSxaX8L-mDDJo4Q", "TopicUndoNotInterested" - TopicsManagementPage = "Jvdjpe8qzsJD84BpK3qdkQ", "TopicsManagementPage" - TopicsPickerPage = "UvG-XXtWNcJN1LzF0u3ByA", "TopicsPickerPage" - TopicsPickerPageById = "t6kH4v2c_VzWKljc2yNwHA", "TopicsPickerPageById" - TrustedFriendsTypeahead = "RRnOwHttRGscWKC1zY9VRA", "TrustedFriendsTypeahead" - TweetEditHistory = "8eaWKjHszkS-G_hprUd9AA", "TweetEditHistory" - TwitterArticleByRestId = "hwrvh-Qt24lcprL-BDfqRA", "TwitterArticleByRestId" - TwitterArticleCreate = "aV-sm-IkvwplcxdYDoLZHQ", "TwitterArticleCreate" - TwitterArticleDelete = "6st-stMDc7KBqLT8KvWhHg", "TwitterArticleDelete" - TwitterArticleUpdateCoverImage = ( - "fpcVRSAsjvkwmCiN1HheqQ", - "TwitterArticleUpdateCoverImage", - ) - TwitterArticleUpdateData = "XpBTYp_QXwyZ0XT0JXCBJw", "TwitterArticleUpdateData" - TwitterArticleUpdateMedia = "3ojmmegfBC_oHyrmPhxj-g", "TwitterArticleUpdateMedia" - TwitterArticleUpdateTitle = "dvH6Ql989I4e5jWEV7HfaQ", "TwitterArticleUpdateTitle" - TwitterArticleUpdateVisibility = ( - "8M35gHyfpcy3S4UXejUGfA", - "TwitterArticleUpdateVisibility", - ) - TwitterArticlesSlice = "UUPSi_aS8_kHDFTWqSBPUA", "TwitterArticlesSlice" - UnmentionUserFromConversation = ( - "xVW9j3OqoBRY9d6_2OONEg", - "UnmentionUserFromConversation", - ) - UnmoderateTweet = "pVSyu6PA57TLvIE4nN2tsA", "UnmoderateTweet" - UnmuteList = "pMZrHRNsmEkXgbn3tOyr7Q", "UnmuteList" - UnpinReply = "iRe6ig5OV1EzOtldNIuGDQ", "UnpinReply" - UnsubscribeFromScheduledSpace = ( - "Zevhh76Msw574ZSs2NQHGQ", - "UnsubscribeFromScheduledSpace", - ) - UrtFixtures = "I_0j1mjMwv94SdS66S4pqw", "UrtFixtures" - UserAboutTimeline = "dm7ReTFJoeU0qkiZCO1E1g", "UserAboutTimeline" - UserAccountLabel = "rD5gLxVmMvtdtYU1UHWlFQ", "UserAccountLabel" - UserBusinessProfileTeamTimeline = ( - "dq1eUCn3N8v0BywlP4nT7A", - "UserBusinessProfileTeamTimeline", - ) - UserPromotableTweets = "jF-OgMv-9vAym3JaCPUnhQ", "UserPromotableTweets" - UserSessionsList = "vJ-XatpmQSG8bDch8-t9Jw", "UserSessionsList" - UserSuperFollowTweets = "1by3q8-AJWdNYhtltjlPTQ", "UserSuperFollowTweets" - Viewer = "okNaf-6AQWu2DD2H_MAoVw", "Viewer" - ViewerEmailSettings = "JpjlNgn4sLGvS6tgpTzYBg", "ViewerEmailSettings" - ViewerTeams = "D8mVcJSVv66_3NcR7fOf6g", "ViewerTeams" - ViewingOtherUsersTopicsPage = ( - "tYXo6h_rpnHXbdLUFMatZA", - "ViewingOtherUsersTopicsPage", - ) - WriteDataSaverPreferences = "H03etWvZGz41YASxAU2YPg", "WriteDataSaverPreferences" - WriteEmailNotificationSettings = ( - "2qKKYFQift8p5-J1k6kqxQ", - "WriteEmailNotificationSettings", - ) - adFreeArticleDomains = "zwTrX9CtnMvWlBXjsx95RQ", "adFreeArticleDomains" - articleNudgeDomains = "88Bu08U2ddaVVjKmmXjVYg", "articleNudgeDomains" - bookmarkTweetToFolder = "4KHZvvNbHNf07bsgnL9gWA", "bookmarkTweetToFolder" - createBookmarkFolder = "6Xxqpq8TM_CREYiuof_h5w", "createBookmarkFolder" - getAltTextPromptPreference = "PFIxTk8owMoZgiMccP0r4g", "getAltTextPromptPreference" - getCaptionsAlwaysDisplayPreference = ( - "BwgMOGpOViDS0ri7VUgglg", - "getCaptionsAlwaysDisplayPreference", - ) - timelinesFeedback = "vfVbgvTPTQ-dF_PQ5lD1WQ", "timelinesFeedback" - updateAltTextPromptPreference = ( - "aQKrduk_DA46XfOQDkcEng", - "updateAltTextPromptPreference", - ) - updateCaptionsAlwaysDisplayPreference = ( - "uCUQhvZ5sJ9qHinRp6CFlQ", - "updateCaptionsAlwaysDisplayPreference", - ) - - default_variables = { - "count": 1000, - "withSafetyModeUserFields": True, - "includePromotedContent": True, - "withQuickPromoteEligibilityTweetFields": True, - "withVoice": True, - "withV2Timeline": True, - "withDownvotePerspective": False, - "withBirdwatchNotes": True, - "withCommunity": True, - "withSuperFollowsUserFields": True, - "withReactionsMetadata": False, - "withReactionsPerspective": False, - "withSuperFollowsTweetFields": True, - "isMetatagsQuery": False, - "withReplays": True, - "withClientEventToken": False, - "withAttachments": True, - "withConversationQueryHighlights": True, - "withMessageQueryHighlights": True, - "withMessages": True, - } - default_features = { - "blue_business_profile_image_shape_enabled": True, - "creator_subscriptions_tweet_preview_api_enabled": True, - "freedom_of_speech_not_reach_fetch_enabled": True, - "graphql_is_translatable_rweb_tweet_is_translatable_enabled": True, - "graphql_timeline_v2_bookmark_timeline": True, - "hidden_profile_likes_enabled": True, - "highlights_tweets_tab_ui_enabled": True, - "interactive_text_enabled": True, - "longform_notetweets_consumption_enabled": True, - "longform_notetweets_inline_media_enabled": True, - "longform_notetweets_rich_text_read_enabled": True, - "longform_notetweets_richtext_consumption_enabled": True, - "profile_foundations_tweet_stats_enabled": True, - "profile_foundations_tweet_stats_tweet_frequency": True, - "responsive_web_birdwatch_note_limit_enabled": True, - "responsive_web_edit_tweet_api_enabled": True, - "responsive_web_enhance_cards_enabled": False, - "responsive_web_graphql_exclude_directive_enabled": True, - "responsive_web_graphql_skip_user_profile_image_extensions_enabled": False, - "responsive_web_graphql_timeline_navigation_enabled": True, - "responsive_web_media_download_video_enabled": False, - "responsive_web_text_conversations_enabled": False, - "responsive_web_twitter_article_data_v2_enabled": True, - "responsive_web_twitter_article_tweet_consumption_enabled": False, - "responsive_web_twitter_blue_verified_badge_is_enabled": True, - "rweb_lists_timeline_redesign_enabled": True, - "spaces_2022_h2_clipping": True, - "spaces_2022_h2_spaces_communities": True, - "standardized_nudges_misinfo": True, - "subscriptions_verification_info_verified_since_enabled": True, - "tweet_awards_web_tipping_enabled": False, - "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": True, - "tweetypie_unmention_optimization_enabled": True, - "verified_phone_label_enabled": False, - "vibe_api_enabled": True, - "view_counts_everywhere_api_enabled": True, - } - - -trending_params = { - "include_profile_interstitial_type": "1", - "include_blocking": "1", - "include_blocked_by": "1", - "include_followed_by": "1", - "include_want_retweets": "1", - "include_mute_edge": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_verified_type": "1", - "skip_status": "1", - "cards_platform": "Web-12", - "include_cards": "1", - "include_ext_alt_text": "true", - "include_ext_limited_action_results": "false", - "include_quote_count": "true", - "include_reply_count": "1", - "tweet_mode": "extended", - "include_ext_views": "true", - "include_entities": "true", - "include_user_entities": "true", - "include_ext_media_color": "true", - "include_ext_media_availability": "true", - "include_ext_sensitive_media_warning": "true", - "include_ext_trusted_friends_metadata": "true", - "send_error_codes": "true", - "simple_quoted_tweet": "true", - "count": 1000, - "requestContext": "launch", - "include_page_configuration": "true", - "initial_tab_id": "trending", - "entity_tokens": "false", - "ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,enrichments,superFollowMetadata,unmentionInfo,editControl,vibe", -} - -account_settings = { - "address_book_live_sync_enabled": False, - "allow_ads_personalization": False, - "allow_authenticated_periscope_requests": True, - "allow_dm_groups_from": "following", - "allow_dms_from": "following", # all - "allow_location_history_personalization": False, - "allow_logged_out_device_personalization": False, - "allow_media_tagging": "none", # all, following - "allow_sharing_data_for_third_party_personalization": False, - "alt_text_compose_enabled": None, - "always_use_https": True, - "autoplay_disabled": False, - "country_code": "us", - "discoverable_by_email": False, - "discoverable_by_mobile_phone": False, - "display_sensitive_media": True, - "dm_quality_filter": "enabled", # disabled - "dm_receipt_setting": "all_disabled", # all_enabled - "geo_enabled": False, - "include_alt_text_compose": True, - "include_mention_filter": True, - "include_nsfw_admin_flag": True, - "include_nsfw_user_flag": True, - "include_ranked_timeline": True, - "language": "en", - "mention_filter": "unfiltered", - "nsfw_admin": False, - "nsfw_user": False, - "personalized_trends": True, - "protected": False, - "ranked_timeline_eligible": None, - "ranked_timeline_setting": None, - "require_password_login": False, - "requires_login_verification": False, - "settings_metadata": {}, - "sleep_time": {"enabled": False, "end_time": None, "start_time": None}, - "translator_type": "none", - "universal_quality_filtering_enabled": "enabled", - "use_cookie_personalization": False, - ## todo: not yet implemented - requires additional steps - # 'allow_contributor_request': 'all', - # 'protect_password_reset': False, -} -follower_notification_settings = { - "cursor": "-1", - "include_profile_interstitial_type": "1", - "include_blocking": "1", - "include_blocked_by": "1", - "include_followed_by": "1", - "include_want_retweets": "1", - "include_mute_edge": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_verified_type": "1", - "skip_status": "1", -} - -follow_settings = { - "include_profile_interstitial_type": "1", - "include_blocking": "1", - "include_blocked_by": "1", - "include_followed_by": "1", - "include_want_retweets": "1", - "include_mute_edge": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_verified_type": "1", - "skip_status": "1", -} - -account_search_settings = { - "optInFiltering": True, # filter out nsfw content - "optInBlocking": True, # filter out blocked accounts -} - -profile_settings = { - "birthdate_day": int, - "birthdate_month": int, - "birthdate_year": int, # 1985 - "birthdate_visibility": str, # 'self', - "birthdate_year_visibility": str, # 'self', - "displayNameMaxLength": int, # '50', - "url": str, # 'https://example.com', - "name": str, # 'foo', - "description": str, # 'bar', - "location": str, # 'world', -} - -search_config = { - "include_profile_interstitial_type": 1, - "include_blocking": 1, - "include_blocked_by": 1, - "include_followed_by": 1, - "include_want_retweets": 1, - "include_mute_edge": 1, - "include_can_dm": 1, - "include_can_media_tag": 1, - "include_ext_has_nft_avatar": 1, - "include_ext_is_blue_verified": 1, - "include_ext_verified_type": 1, - "skip_status": 1, - "cards_platform": "Web-12", - "include_cards": 1, - "include_ext_alt_text": "true", - "include_ext_limited_action_results": "false", - "include_quote_count": "true", - "include_reply_count": 1, - "tweet_mode": "extended", - "include_ext_collab_control": "true", - "include_ext_views": "true", - "include_entities": "true", - "include_user_entities": "true", - "include_ext_media_color": "true", - "include_ext_media_availability": "true", - "include_ext_sensitive_media_warning": "true", - "include_ext_trusted_friends_metadata": "true", - "send_error_codes": "true", - "simple_quoted_tweet": "true", - "query_source": "typed_query", - "count": 1000, - "q": "", - "requestContext": "launch", - "pc": 1, - "spelling_corrections": 1, - "include_ext_edit_control": "true", - "ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,enrichments,superFollowMetadata,unmentionInfo,editControl,collab_control,vibe", -} - -dm_params = { - "context": "FETCH_DM_CONVERSATION", - "include_profile_interstitial_type": "1", - "include_blocking": "1", - "include_blocked_by": "1", - "include_followed_by": "1", - "include_want_retweets": "1", - "include_mute_edge": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_verified_type": "1", - "include_ext_profile_image_shape": "1", - "skip_status": "1", - "dm_secret_conversations_enabled": "false", - "krs_registration_enabled": "true", - "cards_platform": "Web-12", - "include_cards": "1", - "include_ext_alt_text": "true", - "include_ext_limited_action_results": "false", - "include_quote_count": "true", - "include_reply_count": "1", - "tweet_mode": "extended", - "include_ext_views": "true", - "dm_users": "false", - "include_groups": "true", - "include_inbox_timelines": "true", - "include_ext_media_color": "true", - "supports_reactions": "true", - "include_conversation_info": "true", - "ext": "mediaColor,altText,mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl", -} - -live_notification_params = params = { - "cards_platform": "Web-12", - "count": "50", # max value - "ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl", - "include_blocked_by": "1", - "include_blocking": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_cards": "1", - "include_entities": "true", - "include_ext_alt_text": "true", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_limited_action_results": "true", - "include_ext_media_availability": "true", - "include_ext_media_color": "true", - "include_ext_profile_image_shape": "1", - "include_ext_sensitive_media_warning": "true", - "include_ext_trusted_friends_metadata": "true", - "include_ext_verified_type": "1", - "include_ext_views": "true", - "include_followed_by": "1", - "include_mute_edge": "1", - "include_profile_interstitial_type": "1", - "include_quote_count": "true", - "include_reply_count": "1", - "include_user_entities": "true", - "include_want_retweets": "1", - "send_error_codes": "true", - "simple_quoted_tweet": "true", - "skip_status": "1", - "tweet_mode": "extended", -} - -recommendations_params = { - "include_profile_interstitial_type": "1", - "include_blocking": "1", - "include_blocked_by": "1", - "include_followed_by": "1", - "include_want_retweets": "1", - "include_mute_edge": "1", - "include_can_dm": "1", - "include_can_media_tag": "1", - "include_ext_has_nft_avatar": "1", - "include_ext_is_blue_verified": "1", - "include_ext_verified_type": "1", - "include_ext_profile_image_shape": "1", - "skip_status": "1", - "pc": "true", - "display_location": "profile_accounts_sidebar", - "limit": 100, - "ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl", -} diff --git a/twitter_api/errors.py b/twitter_api/errors.py deleted file mode 100644 index 164289e..0000000 --- a/twitter_api/errors.py +++ /dev/null @@ -1,88 +0,0 @@ -class TwitterError(Exception): - """Base class for Twitter errors""" - - def __init__(self, error_dict: dict): - self.error_dict = error_dict - - @property - def error_message(self) -> str: - if self.error_code == 32: - return "Failed to authenticate account. Check your credentials." - - elif self.error_code == 36: - return "You cannot use your own user ID to report spam call" - - elif self.error_code == 38: - return "The request is missing the parameter (such as media, text, etc.) in the request." - - elif self.error_code == 50: - return "User not found." - - elif self.error_code == 89: - return "The access token used in the request is incorrect or has expired." - - elif self.error_code == 92: - return "SSL is required. Only TLS v1.2 connections are allowed in the API. Update the request to a secure connection." - - elif self.error_code == 139: - return "You have already favorited this tweet. (Duplicate)" - - elif self.error_code == 160: - return "You've already requested to follow the user. (Duplicate)" - - elif self.error_code == 186: - return "Tweet needs to be a bit shorter. The text is too long." - - elif self.error_code == 187: - return "Text of your tweet is identical to another tweet. Change your text. (Duplicate)" - - elif self.error_code == 205: - return "The account limit for reporting spam has been reached. Try again later." - - elif self.error_code == 214: - return "Account is not set up to have open Direct Messages when trying to set up a welcome message." - - elif self.error_code == 220: - return "The authentication token in use is restricted and cannot access the requested resource." - - elif self.error_code == 323: - return "Only one animated GIF may be attached to a single Post." - - elif self.error_code == 325: - return "The media ID attached to the Post was not found." - - elif self.error_code == 327: - return "You cannot repost the same Post more than once." - - elif self.error_code == 349: - return "You does not have privileges to Direct Message the recipient." - - return self.error_dict.get("error_message") - - @property - def error_code(self) -> int: - return self.error_dict.get("error_code") - - -class TwitterAccountSuspended(Exception): - """Raised when account is suspended""" - - pass - - -class CaptchaError(Exception): - """Raised when captcha solving failed""" - - pass - - -class RateLimitError(Exception): - """Raised when rate limit exceeded""" - - pass - - -class IncorrectData(Exception): - """Raised when validation error""" - - pass diff --git a/twitter_api/models/__init__.py b/twitter_api/models/__init__.py deleted file mode 100644 index e80df5c..0000000 --- a/twitter_api/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .tweets import * -from .users import * -from .data import * diff --git a/twitter_api/models/data/__init__.py b/twitter_api/models/data/__init__.py deleted file mode 100644 index f3e0a47..0000000 --- a/twitter_api/models/data/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .bind_account_v2 import * -from .bind_account_v1 import * diff --git a/twitter_api/models/data/bind_account_v1.py b/twitter_api/models/data/bind_account_v1.py deleted file mode 100644 index ad86ea7..0000000 --- a/twitter_api/models/data/bind_account_v1.py +++ /dev/null @@ -1,11 +0,0 @@ -from pydantic import BaseModel, field_validator, HttpUrl - - -class BindAccountParamsV1(BaseModel): - url: HttpUrl - - -class BindAccountDataV1(BaseModel): - url: HttpUrl - oauth_token: str - oauth_verifier: str diff --git a/twitter_api/models/data/bind_account_v2.py b/twitter_api/models/data/bind_account_v2.py deleted file mode 100644 index 81c9c5a..0000000 --- a/twitter_api/models/data/bind_account_v2.py +++ /dev/null @@ -1,20 +0,0 @@ -from pydantic import BaseModel, field_validator, HttpUrl - - -class BindAccountParamsV2(BaseModel): - code_challenge: str - code_challenge_method: str = "plain" - client_id: str - redirect_uri: HttpUrl - response_type: str = "code" - scope: str = "tweet.read users.read follows.read offline.access" - state: str - - @field_validator("redirect_uri", mode="after") - def validate_uri(cls, value): - # url = HttpUrl("https://google.com") - return str(value) - - -class BindAccountDataV2(BaseModel): - code: str diff --git a/twitter_api/models/tweets/__init__.py b/twitter_api/models/tweets/__init__.py deleted file mode 100644 index 1e869f4..0000000 --- a/twitter_api/models/tweets/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from .create_tweet import * -from .delete_tweet import * -from .retweet import * -from .favorite_tweet import * -from .delete_retweet import * -from .delete_favorite_tweet import * -from .bookmark_tweet import * -from .unbookmark_tweet import * -from .create_reply import * -from .scrape_replies import * -from .scrape_favorites import * -from .scrape_retweets import * -from .create_schedule_tweet import * -from .delete_unschedule_tweet import * diff --git a/twitter_api/models/tweets/bookmark_tweet.py b/twitter_api/models/tweets/bookmark_tweet.py deleted file mode 100644 index ee8118c..0000000 --- a/twitter_api/models/tweets/bookmark_tweet.py +++ /dev/null @@ -1,14 +0,0 @@ -from pydantic import BaseModel -from typing import Optional, Dict - - -class CreateBookmarkData(BaseModel): - id: str | int - - -class CreateBookmarkResult(BaseModel): - tweet_bookmark_put: Optional[str] - - -class CreateBookmarkResultData(BaseModel): - data: Optional[CreateBookmarkResult] diff --git a/twitter_api/models/tweets/create_reply.py b/twitter_api/models/tweets/create_reply.py deleted file mode 100644 index b502da5..0000000 --- a/twitter_api/models/tweets/create_reply.py +++ /dev/null @@ -1,150 +0,0 @@ -from pydantic import BaseModel -from typing import Optional, Dict, List, Any - -from .create_tweet import MediaEntity - - -class CreateReplyData(BaseModel): - id: str | int - text: str - media_entities: List[MediaEntity] | None = None - - -class Legacy(BaseModel): - can_dm: Optional[bool] - can_media_tag: Optional[bool] - created_at: Optional[str] - default_profile: Optional[bool] - default_profile_image: Optional[bool] - description: Optional[str] - entities: Optional[Dict[str, Any]] - fast_followers_count: Optional[int] - favourites_count: Optional[int] - followers_count: Optional[int] - friends_count: Optional[int] - has_custom_timelines: Optional[bool] - is_translator: Optional[bool] - listed_count: Optional[int] - location: Optional[str] - media_count: Optional[int] - name: Optional[str] - needs_phone_verification: Optional[bool] - normal_followers_count: Optional[int] - pinned_tweet_ids_str: Optional[List[str]] - possibly_sensitive: Optional[bool] - profile_image_url_https: Optional[str] - profile_interstitial_type: Optional[str] - screen_name: Optional[str] - statuses_count: Optional[int] - translator_type: Optional[str] - verified: Optional[bool] - want_retweets: Optional[bool] - withheld_in_countries: Optional[List[str]] - - -class UserResults(BaseModel): - __typename: Optional[str] - id: Optional[str] - rest_id: Optional[str] - affiliates_highlighted_label: Optional[Dict[str, Any]] - has_graduated_access: Optional[bool] - is_blue_verified: Optional[bool] - profile_image_shape: Optional[str] - legacy: Optional[Legacy] - smart_blocked_by: Optional[bool] - smart_blocking: Optional[bool] - - -class CoreUserResult(BaseModel): - result: Optional[UserResults] - - -class Core(BaseModel): - user_results: Optional[CoreUserResult] - - -class Views(BaseModel): - state: Optional[str] - - -class EditControl(BaseModel): - edit_tweet_ids: Optional[List[str]] - editable_until_msecs: Optional[str] - is_edit_eligible: Optional[bool] - edits_remaining: Optional[str] - - -class Media(BaseModel): - display_url: Optional[str] - expanded_url: Optional[str] - id_str: Optional[str] - indices: Optional[List[int]] - media_url_https: Optional[str] - type: Optional[str] - url: Optional[str] - features: Optional[Dict[str, Any]] - sizes: Optional[Dict[str, Any]] - original_info: Optional[Dict[str, int]] - - -class Entities(BaseModel): - user_mentions: Optional[List[Dict[str, Any]]] - urls: Optional[List[Any]] - hashtags: Optional[List[Any]] - symbols: Optional[List[Any]] - - -class ExtendedEntities(BaseModel): - media: Optional[List[Media]] - - -class Legacy2(BaseModel): - bookmark_count: Optional[int] - bookmarked: Optional[bool] - created_at: Optional[str] - conversation_id_str: Optional[str] - entities: Optional[Entities] - favorite_count: Optional[int] - favorited: Optional[bool] - full_text: Optional[str] - in_reply_to_screen_name: Optional[str] - in_reply_to_status_id_str: Optional[str] - in_reply_to_user_id_str: Optional[str] - is_quote_status: Optional[bool] - lang: Optional[str] - quote_count: Optional[int] - reply_count: Optional[int] - retweet_count: Optional[int] - retweeted: Optional[bool] - user_id_str: Optional[str] - id_str: Optional[str] - - -class UnmentionInfo(BaseModel): - pass - - -class CreateReplyResult(BaseModel): - rest_id: Optional[str] - has_birdwatch_notes: Optional[bool] - core: Optional[Core] - is_translatable: Optional[bool] - views: Optional[Views] - source: Optional[str] - legacy: Optional[Legacy2] - - -class CreateReplyResultDataV3(BaseModel): - result: Optional[CreateReplyResult] - - -class CreateReplyResultDataV2(BaseModel): - tweet_results: Optional[CreateReplyResultDataV3] - - -class CreateReplyResultDataV1(BaseModel): - create_tweet: Optional[CreateReplyResultDataV2] - - -class CreateReplyResultData(BaseModel): - data: Optional[CreateReplyResultDataV1] diff --git a/twitter_api/models/tweets/create_schedule_tweet.py b/twitter_api/models/tweets/create_schedule_tweet.py deleted file mode 100644 index 8e25478..0000000 --- a/twitter_api/models/tweets/create_schedule_tweet.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import List, Optional -from pydantic import BaseModel - -from .create_tweet import MediaEntity - - -class CreateScheduleTweetData(BaseModel): - text: str - date: int | str - media_entities: List[MediaEntity] | None = None - - -class CreateScheduleTweetResult(BaseModel): - rest_id: str - - -class CreateScheduleTweetResultDataV1(BaseModel): - tweet: Optional[CreateScheduleTweetResult] - - -class CreateScheduleTweetResultData(BaseModel): - data: Optional[CreateScheduleTweetResultDataV1] diff --git a/twitter_api/models/tweets/create_tweet.py b/twitter_api/models/tweets/create_tweet.py deleted file mode 100644 index decd5e3..0000000 --- a/twitter_api/models/tweets/create_tweet.py +++ /dev/null @@ -1,156 +0,0 @@ -from typing import List, Optional, Any, Dict - -from pydantic import BaseModel, field_validator -from twitter_api.errors import IncorrectData - - -class MediaEntity(BaseModel): - media_id: int - tagged_users: List[str] | None = [] - - @field_validator("tagged_users") - @classmethod - def validate_users(cls, users: List[str]): - if users: - if len(users) > 10: - raise IncorrectData("Maximum 10 tagged users allowed") - - return users - - -class CreateTweetData(BaseModel): - text: str - media_entities: List[MediaEntity] | None = None - - -class Legacy(BaseModel): - can_dm: Optional[bool] - can_media_tag: Optional[bool] - created_at: Optional[str] - default_profile: Optional[bool] - default_profile_image: Optional[bool] - description: Optional[str] - entities: Optional[Dict[str, Any]] - fast_followers_count: Optional[int] - favourites_count: Optional[int] - followers_count: Optional[int] - friends_count: Optional[int] - has_custom_timelines: Optional[bool] - is_translator: Optional[bool] - listed_count: Optional[int] - location: Optional[str] - media_count: Optional[int] - name: Optional[str] - needs_phone_verification: Optional[bool] - normal_followers_count: Optional[int] - pinned_tweet_ids_str: Optional[List[str]] - possibly_sensitive: Optional[bool] - profile_image_url_https: Optional[str] - profile_interstitial_type: Optional[str] - screen_name: Optional[str] - statuses_count: Optional[int] - translator_type: Optional[str] - verified: Optional[bool] - want_retweets: Optional[bool] - withheld_in_countries: Optional[List[str]] - - -class UserResult(BaseModel): - __typename: Optional[str] - id: Optional[str] - rest_id: Optional[str] - affiliates_highlighted_label: Optional[Dict[str, Any]] - has_graduated_access: Optional[bool] - is_blue_verified: Optional[bool] - profile_image_shape: Optional[str] - legacy: Optional[Legacy] - smart_blocked_by: Optional[bool] - smart_blocking: Optional[bool] - - -class Result(BaseModel): - result: Optional[UserResult] - - -class Core(BaseModel): - user_results: Optional[Result] - - -class Views(BaseModel): - state: Optional[str] - - -class Entities(BaseModel): - user_mentions: Optional[List[Any]] - urls: Optional[List[Any]] - hashtags: Optional[List[Any]] - symbols: Optional[List[Any]] - - -class Legacy2(BaseModel): - bookmark_count: Optional[int] - bookmarked: Optional[bool] - created_at: Optional[str] - conversation_id_str: Optional[str] - display_text_range: Optional[List[int]] - entities: Optional[Entities] - favorite_count: Optional[int] - favorited: Optional[bool] - full_text: Optional[str] - is_quote_status: Optional[bool] - lang: Optional[str] - quote_count: Optional[int] - reply_count: Optional[int] - retweet_count: Optional[int] - retweeted: Optional[bool] - user_id_str: Optional[str] - id_str: Optional[str] - - -class EditControl(BaseModel): - edit_tweet_ids: Optional[List[str]] - editable_until_msecs: Optional[str] - is_edit_eligible: Optional[bool] - edits_remaining: Optional[str] - - -class QuickPromoteEligibility(BaseModel): - eligibility: Optional[str] - - -class UnmentionData(BaseModel): - pass - - -class UnmentionInfo(BaseModel): - pass - - -class CreateTweetResult(BaseModel): - rest_id: Optional[str] - has_birdwatch_notes: Optional[bool] - core: Optional[Core] - unmention_data: Optional[UnmentionData] - edit_control: Optional[EditControl] - is_translatable: Optional[bool] - views: Optional[Views] - source: Optional[str] - legacy: Optional[Legacy2] - quick_promote_eligibility: Optional[QuickPromoteEligibility] - unmention_info: Optional[UnmentionInfo] - - -class CreateTweetResultDataV3(BaseModel): - result: Optional[CreateTweetResult] - - -class CreateTweetResultDataV2(BaseModel): - tweet_results: Optional[CreateTweetResultDataV3] - - -class CreateTweetResultDataV1(BaseModel): - create_tweet: Optional[CreateTweetResultDataV2] - - -class CreateTweetResultData(BaseModel): - data: Optional[CreateTweetResultDataV1] diff --git a/twitter_api/models/tweets/delete_favorite_tweet.py b/twitter_api/models/tweets/delete_favorite_tweet.py deleted file mode 100644 index ca941f1..0000000 --- a/twitter_api/models/tweets/delete_favorite_tweet.py +++ /dev/null @@ -1,14 +0,0 @@ -from pydantic import BaseModel -from typing import Optional - - -class DeleteFavoriteTweetData(BaseModel): - id: int | str - - -class DeleteFavoriteTweetResult(BaseModel): - unfavorite_tweet: Optional[str] - - -class DeleteFavoriteTweetResultData(BaseModel): - data: Optional[DeleteFavoriteTweetResult] diff --git a/twitter_api/models/tweets/delete_retweet.py b/twitter_api/models/tweets/delete_retweet.py deleted file mode 100644 index 57b4268..0000000 --- a/twitter_api/models/tweets/delete_retweet.py +++ /dev/null @@ -1,31 +0,0 @@ -from pydantic import BaseModel -from typing import Optional - - -class DeleteRetweetData(BaseModel): - id: int | str - - -class Legacy(BaseModel): - full_text: Optional[str] - - -class DeleteRetweetResult(BaseModel): - rest_id: Optional[str] - legacy: Optional[Legacy] - - -class DeleteRetweetResultDataV3(BaseModel): - result: Optional[DeleteRetweetResult] - - -class DeleteRetweetResultDataV2(BaseModel): - source_tweet_results: Optional[DeleteRetweetResultDataV3] - - -class DeleteRetweetResultDataV1(BaseModel): - unretweet: Optional[DeleteRetweetResultDataV2] - - -class DeleteRetweetResultData(BaseModel): - data: Optional[DeleteRetweetResultDataV1] diff --git a/twitter_api/models/tweets/delete_tweet.py b/twitter_api/models/tweets/delete_tweet.py deleted file mode 100644 index 4696fc5..0000000 --- a/twitter_api/models/tweets/delete_tweet.py +++ /dev/null @@ -1,21 +0,0 @@ -from pydantic import BaseModel - - -class DeleteTweetData(BaseModel): - id: int | str - - -class DeleteTweetResult(BaseModel): - pass - - -class DeleteTweetResultDataV2(BaseModel): - tweet_results: DeleteTweetResult - - -class DeleteTweetResultDataV1(BaseModel): - delete_tweet: DeleteTweetResultDataV2 - - -class DeleteTweetResultData(BaseModel): - data: DeleteTweetResultDataV1 diff --git a/twitter_api/models/tweets/delete_unschedule_tweet.py b/twitter_api/models/tweets/delete_unschedule_tweet.py deleted file mode 100644 index 7e3d7af..0000000 --- a/twitter_api/models/tweets/delete_unschedule_tweet.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class DeleteScheduleTweetData(BaseModel): - id: str | int - - -class DeleteScheduleTweetResult(BaseModel): - scheduledtweet_delete: Optional[str] - - -class DeleteScheduleTweetResultData(BaseModel): - data: Optional[DeleteScheduleTweetResult] diff --git a/twitter_api/models/tweets/favorite_tweet.py b/twitter_api/models/tweets/favorite_tweet.py deleted file mode 100644 index 30d6d53..0000000 --- a/twitter_api/models/tweets/favorite_tweet.py +++ /dev/null @@ -1,14 +0,0 @@ -from pydantic import BaseModel -from typing import Optional - - -class CreateFavoriteTweetData(BaseModel): - id: int | str - - -class FavoriteTweetResult(BaseModel): - favorite_tweet: Optional[str] - - -class FavoriteTweetResultData(BaseModel): - data: Optional[FavoriteTweetResult] diff --git a/twitter_api/models/tweets/retweet.py b/twitter_api/models/tweets/retweet.py deleted file mode 100644 index 3f7bb55..0000000 --- a/twitter_api/models/tweets/retweet.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class CreateRetweetData(BaseModel): - id: int | str - - -class Legacy(BaseModel): - full_text: Optional[str] - - -class RetweetResult(BaseModel): - rest_id: Optional[str] - legacy: Optional[Legacy] - - -class RetweetResultDataV3(BaseModel): - result: Optional[RetweetResult] - - -class RetweetResultDataV2(BaseModel): - retweet_results: Optional[RetweetResultDataV3] - - -class RetweetResultDataV1(BaseModel): - create_retweet: Optional[RetweetResultDataV2] - - -class RetweetResultData(BaseModel): - data: Optional[RetweetResultDataV1] diff --git a/twitter_api/models/tweets/scrape_favorites.py b/twitter_api/models/tweets/scrape_favorites.py deleted file mode 100644 index 36d1b84..0000000 --- a/twitter_api/models/tweets/scrape_favorites.py +++ /dev/null @@ -1,32 +0,0 @@ -from pydantic import BaseModel, field_validator -from twitter_api.errors import IncorrectData - - -class ScrapeTweetFavoritesData(BaseModel): - id: int | str - limit: int = 200 - - @field_validator("limit") - @classmethod - def limit_must_be_positive(cls, v): - if v < 0: - raise IncorrectData("Limit must be positive integer") - - return v - - -class UserData(BaseModel): - id: int | str - name: str - screen_name: str - profile_image_url: str - favourites_count: int - followers_count: int - friends_count: int - location: str - description: str - created_at: str - - -class ScrapeTweetFavoritesResult(BaseModel): - users: list[UserData] diff --git a/twitter_api/models/tweets/scrape_replies.py b/twitter_api/models/tweets/scrape_replies.py deleted file mode 100644 index e8d7254..0000000 --- a/twitter_api/models/tweets/scrape_replies.py +++ /dev/null @@ -1,37 +0,0 @@ -from pydantic import BaseModel, field_validator -from twitter_api.errors import IncorrectData - - -class ScrapeTweetRepliesData(BaseModel): - id: int | str - limit: int = 200 - - @field_validator("limit") - @classmethod - def limit_must_be_positive(cls, v): - if v < 0: - raise IncorrectData("Limit must be positive integer") - - return v - - -class UserData(BaseModel): - id: int | str - name: str - screen_name: str - profile_image_url: str - favourites_count: int - followers_count: int - friends_count: int - location: str - description: str - created_at: str - - -class ScrapeTweetRepliesResult(BaseModel): - reply_text: str - user_data: UserData - - -class ScrapeTweetRepliesResultData(BaseModel): - replies: list[ScrapeTweetRepliesResult] diff --git a/twitter_api/models/tweets/scrape_retweets.py b/twitter_api/models/tweets/scrape_retweets.py deleted file mode 100644 index 897a0e7..0000000 --- a/twitter_api/models/tweets/scrape_retweets.py +++ /dev/null @@ -1,20 +0,0 @@ -from pydantic import BaseModel, field_validator -from twitter_api.errors import IncorrectData -from .scrape_favorites import UserData - - -class ScrapeTweetRetweetsData(BaseModel): - id: int | str - limit: int = 200 - - @field_validator("limit") - @classmethod - def limit_must_be_positive(cls, v): - if v < 0: - raise IncorrectData("Limit must be positive integer") - - return v - - -class ScrapeTweetRetweetsResult(BaseModel): - users: list[UserData] diff --git a/twitter_api/models/tweets/unbookmark_tweet.py b/twitter_api/models/tweets/unbookmark_tweet.py deleted file mode 100644 index c4425a5..0000000 --- a/twitter_api/models/tweets/unbookmark_tweet.py +++ /dev/null @@ -1,14 +0,0 @@ -from pydantic import BaseModel -from typing import Optional, Dict - - -class DeleteBookmarkData(BaseModel): - id: str | int - - -class DeleteBookmarkResult(BaseModel): - tweet_bookmark_delete: Optional[str] - - -class DeleteBookmarkResultData(BaseModel): - data: Optional[DeleteBookmarkResult] diff --git a/twitter_api/models/users/__init__.py b/twitter_api/models/users/__init__.py deleted file mode 100644 index 4edec9c..0000000 --- a/twitter_api/models/users/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .follows import * -from .user_info import * -from .followers import * diff --git a/twitter_api/models/users/followers.py b/twitter_api/models/users/followers.py deleted file mode 100644 index def57ed..0000000 --- a/twitter_api/models/users/followers.py +++ /dev/null @@ -1,16 +0,0 @@ -from pydantic import BaseModel, field_validator -from typing import Optional, List, Dict, Any -from twitter_api.errors import IncorrectData - - -class UserFollowersData(BaseModel): - username: str - limit: int = 200 - - @field_validator("limit") - @classmethod - def limit_must_be_positive(cls, v): - if v < 0: - raise IncorrectData("Limit must be positive integer") - - return v diff --git a/twitter_api/models/users/follows.py b/twitter_api/models/users/follows.py deleted file mode 100644 index bcf448e..0000000 --- a/twitter_api/models/users/follows.py +++ /dev/null @@ -1,70 +0,0 @@ -from typing import Optional, List - -from pydantic import BaseModel, model_validator -from twitter_api.errors import IncorrectData - - -class UnfollowUserData(BaseModel): - id: int | str = None - username: str = None - - @model_validator(mode="before") - @classmethod - def validate_data(cls, values: dict): - if not values.get("id") and not values.get("username"): - raise IncorrectData("Either id or username must be provided") - - return values - - -class FollowUserData(BaseModel): - id: str | int = None - username: str = None - - @model_validator(mode="before") - @classmethod - def validate_data(cls, values: dict): - if not values.get("id") and not values.get("username"): - raise IncorrectData("Either id or username must be provided") - - return values - - -class FollowsUserResult(BaseModel): - id: Optional[int] - id_str: Optional[str] - name: Optional[str] - screen_name: Optional[str] - location: Optional[str] - description: Optional[str] - url: Optional[str] - protected: Optional[bool] - followers_count: Optional[int] - fast_followers_count: Optional[int] - normal_followers_count: Optional[int] - friends_count: Optional[int] - listed_count: Optional[int] - created_at: Optional[str] - favourites_count: Optional[int] - utc_offset: Optional[int] - time_zone: Optional[str] - geo_enabled: Optional[bool] - verified: Optional[bool] - statuses_count: Optional[int] - media_count: Optional[int] - lang: Optional[str] - profile_image_url: Optional[str] - profile_image_url_https: Optional[str] - profile_banner_url: Optional[str] - pinned_tweet_ids: Optional[List[int]] - pinned_tweet_ids_str: Optional[List[str]] - has_custom_timelines: Optional[bool] - can_dm: Optional[bool] - can_media_tag: Optional[bool] - following: Optional[bool] - follow_request_sent: Optional[bool] - blocking: Optional[bool] - business_profile_state: Optional[str] - followed_by: Optional[bool] - ext_is_blue_verified: Optional[bool] - ext_has_nft_avatar: Optional[bool] diff --git a/twitter_api/models/users/user_info.py b/twitter_api/models/users/user_info.py deleted file mode 100644 index 0e7c4d7..0000000 --- a/twitter_api/models/users/user_info.py +++ /dev/null @@ -1,66 +0,0 @@ -from typing import Optional, List, Dict, Any -from pydantic import BaseModel - - -class UserProfileInfoData(BaseModel): - username: str - - -class UserProfileInfoResult(BaseModel): - id: Optional[int] - id_str: Optional[str] - name: Optional[str] - screen_name: Optional[str] - location: Optional[str] - profile_location: Optional[Dict[str, Any]] - description: Optional[str] - url: Optional[str] - # entities: Optional[Entities] - protected: Optional[bool] - followers_count: Optional[int] - fast_followers_count: Optional[int] - normal_followers_count: Optional[int] - friends_count: Optional[int] - listed_count: Optional[int] - created_at: Optional[str] - favourites_count: Optional[int] - utc_offset: Optional[int] - time_zone: Optional[str] - geo_enabled: Optional[bool] - verified: Optional[bool] - statuses_count: Optional[int] - media_count: Optional[int] - lang: Optional[str] - # status: Optional[Status] - contributors_enabled: Optional[bool] - is_translator: Optional[bool] - is_translation_enabled: Optional[bool] - profile_background_color: Optional[str] - profile_background_image_url: Optional[str] - profile_background_image_url_https: Optional[str] - profile_background_tile: Optional[bool] - profile_image_url: Optional[str] - profile_image_url_https: Optional[str] - profile_banner_url: Optional[str] - profile_link_color: Optional[str] - profile_sidebar_border_color: Optional[str] - profile_sidebar_fill_color: Optional[str] - profile_text_color: Optional[str] - profile_use_background_image: Optional[bool] - has_extended_profile: Optional[bool] - default_profile: Optional[bool] - default_profile_image: Optional[bool] - pinned_tweet_ids: Optional[List[int]] - pinned_tweet_ids_str: Optional[List[str]] - has_custom_timelines: Optional[bool] - can_media_tag: Optional[bool] - followed_by: Optional[bool] - following: Optional[bool] - follow_request_sent: Optional[bool] - notifications: Optional[bool] - advertiser_account_type: Optional[str] - advertiser_account_service_levels: Optional[List[str]] - business_profile_state: Optional[str] - translator_type: Optional[str] - withheld_in_countries: Optional[List[str]] - require_some_consent: Optional[bool] diff --git a/twitter_api/requirements.txt b/twitter_api/requirements.txt deleted file mode 100644 index 260dd0f..0000000 --- a/twitter_api/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -pydantic -orjson -httpx -curl-cffi -tqdm \ No newline at end of file diff --git a/twitter_api/util.py b/twitter_api/util.py deleted file mode 100644 index 861f8fc..0000000 --- a/twitter_api/util.py +++ /dev/null @@ -1,296 +0,0 @@ -import random -import re -import string -import time -import orjson - -from logging import Logger -from pathlib import Path -from urllib.parse import urlsplit, urlencode, urlunsplit, parse_qs, quote -from httpx import Response, Client - -from .constants import GREEN, MAGENTA, RED, RESET, ID_MAP -from .errors import TwitterError - - -def init_session(): - client = Client( - headers={ - "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs=1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", - }, - follow_redirects=True, - ) - r = client.post("https://api.twitter.com/1.1/guest/activate.json").json() - client.headers.update( - { - "content-type": "application/json", - "x-guest-token": r["guest_token"], - "x-twitter-active-user": "yes", - } - ) - return client - - -def batch_ids(ids: list[int], char_limit: int = 4_500) -> list[dict]: - """To avoid 431 errors""" - length = 0 - res, batch = [], [] - for x in map(str, ids): - curr_length = len(x) - if length + curr_length > char_limit: - res.append(batch) - batch = [] - length = 0 - batch.append(x) - length += curr_length - if batch: - res.append(batch) - return res - - -def build_params(params: dict) -> dict: - return {k: orjson.dumps(v).decode() for k, v in params.items()} - - -def save_json(r: Response, path: Path, name: str, **kwargs): - try: - data = r.json() - kwargs.pop("cursor", None) - out = path / "_".join(map(str, kwargs.values())) - out.mkdir(parents=True, exist_ok=True) - (out / f"{time.time_ns()}_{name}.json").write_bytes(orjson.dumps(data)) - except Exception as e: - print(f"Failed to save data: {e}") - - -def flatten(seq: list | tuple) -> list: - flat = [] - for e in seq: - if isinstance(e, list | tuple): - flat.extend(flatten(e)) - else: - flat.append(e) - return flat - - -def get_json(res: list[Response], **kwargs) -> list: - cursor = kwargs.get("cursor") - temp = res - if any(isinstance(r, (list, tuple)) for r in res): - temp = flatten(res) - results = [] - for r in temp: - try: - data = r.json() - if cursor: - results.append([data, cursor]) - else: - results.append(data) - except Exception as e: - print("Cannot parse JSON response", e) - return results - - -def set_qs(url: str, qs: dict, update=False, **kwargs) -> str: - *_, q, f = urlsplit(url) - return urlunsplit( - ( - *_, - urlencode( - qs | parse_qs(q) if update else qs, - doseq=True, - quote_via=quote, - safe=kwargs.get("safe", ""), - ), - f, - ) - ) - - -def get_cursor(data: list | dict) -> str: - # inefficient, but need to deal with arbitrary schema - entries = find_key(data, "entries") - if entries: - for entry in entries.pop(): - entry_id = entry.get("entryId", "") - if ("cursor-bottom" in entry_id) or ("cursor-showmorethreads" in entry_id): - content = entry["content"] - if itemContent := content.get("itemContent"): - return itemContent["value"] # v2 cursor - return content["value"] # v1 cursor - - -def get_headers(session, **kwargs) -> dict: - """ - Get the headers required for authenticated requests - """ - cookies = session.cookies - headers = kwargs | { - "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs=1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", - # "cookie": "; ".join(f"{k}={v}" for k, v in cookies.items()), - "referer": "https://twitter.com/", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", - "x-csrf-token": cookies.get("ct0", ""), - # "x-guest-token": cookies.get("guest_token", ""), - "x-twitter-auth-type": "OAuth2Session" if cookies.get("auth_token") else "", - "x-twitter-active-user": "yes", - "x-twitter-client-language": "en", - } - return dict(sorted({k.lower(): v for k, v in headers.items()}.items())) - - -def find_key(obj: any, key: str) -> list: - """ - Find all values of a given key within a nested dict or list of dicts - - Most data of interest is nested, and sometimes defined by different schemas. - It is not worth our time to enumerate all absolute paths to a given key, then update - the paths in our parsing functions every time Twitter changes their API. - Instead, we recursively search for the key here, then run post-processing functions on the results. - - @param obj: dictionary or list of dictionaries - @param key: key to search for - @return: list of values - """ - - def helper(obj: any, key: str, L: list) -> list: - if not obj: - return L - - if isinstance(obj, list): - for e in obj: - L.extend(helper(e, key, [])) - return L - - if isinstance(obj, dict) and obj.get(key): - L.append(obj[key]) - - if isinstance(obj, dict) and obj: - for k in obj: - L.extend(helper(obj[k], key, [])) - return L - - return helper(obj, key, []) - - -def log(logger: Logger, level: int, r: Response): - def stat(r, txt, data): - if level >= 1: - logger.debug(f"{r.url.path}") - if level >= 2: - logger.debug(f"{r.url}") - if level >= 3: - logger.debug(f"{txt}") - if level >= 4: - logger.debug(f"{data}") - - try: - limits = {k: v for k, v in r.headers.items() if "x-rate-limit" in k} - current_time = int(time.time()) - wait = int(r.headers.get("x-rate-limit-reset", current_time)) - current_time - remaining = limits.get("x-rate-limit-remaining") - limit = limits.get("x-rate-limit-limit") - logger.debug(f"remaining: {MAGENTA}{remaining}/{limit}{RESET} requests") - logger.debug(f"reset: {MAGENTA}{(wait / 60):.2f}{RESET} minutes") - except Exception as e: - logger.error(f"Rate limit info unavailable: {e}") - - try: - status = r.status_code - ( - txt, - data, - ) = ( - r.text, - r.json(), - ) - if "json" in r.headers.get("content-type", ""): - if data.get("errors") and not find_key(data, "instructions"): - logger.error(f"[{RED}error{RESET}] {status} {data}") - else: - logger.debug(fmt_status(status)) - stat(r, txt, data) - else: - logger.debug(fmt_status(status)) - stat(r, txt, {}) - except Exception as e: - logger.error(f"Failed to log: {e}") - - -def fmt_status(status: int) -> str: - color = None - if 200 <= status < 300: - color = GREEN - elif 300 <= status < 400: - color = MAGENTA - elif 400 <= status < 600: - color = RED - return f"[{color}{status}{RESET}]" - - -def get_ids(data: list | dict, operation: tuple) -> set: - expr = ID_MAP[operation[-1]] - return {k for k in find_key(data, "entryId") if re.search(expr, k)} - - -def dump(path: str, **kwargs): - fname, data = list(kwargs.items())[0] - out = Path(path) - out.mkdir(exist_ok=True, parents=True) - (out / f"{fname}_{time.time_ns()}.json").write_bytes( - orjson.dumps(data, option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS) - ) - - -def get_code(cls, retries=5) -> str | None: - """Get verification code from Proton Mail inbox""" - - def poll_inbox(): - inbox = cls.inbox() - for c in inbox.get("Conversations", []): - if c["Senders"][0]["Address"] == "info@twitter.com": - exprs = [ - "Your Twitter confirmation code is (.+)", - "(.+) is your Twitter verification code", - ] - if temp := list( - filter(None, (re.search(expr, c["Subject"]) for expr in exprs)) - ): - return temp[0].group(1) - - for i in range(retries + 1): - if code := poll_inbox(): - return code - if i == retries: - print(f"Max retries exceeded") - return - t = 2**i + random.random() - print(f'Retrying in {f"{t:.2f}"} seconds') - time.sleep(t) - - -def get_random_string(len_: int) -> str: - return "".join( - random.choice(string.ascii_lowercase + string.digits) for _ in range(len_) - ) - - -def get_random_number(len_: int) -> str: - return "".join(random.choice(string.digits) for _ in range(len_)) - - -def generate_random_string() -> str: - return "".join([random.choice(string.ascii_letters + "-_") for _ in range(352)]) - - -def raise_for_status(response): - http_error_msg = "" - if 400 <= response.status_code < 500: - http_error_msg = f"{response.status_code} Client Error for url {response.url}" - - elif 500 <= response.status_code < 600: - http_error_msg = f"{response.status_code} Server Error for url: {response.url}" - - if http_error_msg: - raise TwitterError({"error_message": http_error_msg}) diff --git a/utils/__init__.py b/utils/__init__.py index 15b6a64..6fb0734 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -1 +1,3 @@ -from .main import * +from .console import * +from .file_utils import * +from .load_config import load_config diff --git a/utils/main.py b/utils/console.py similarity index 78% rename from utils/main.py rename to utils/console.py index a9002e9..be60554 100644 --- a/utils/main.py +++ b/utils/console.py @@ -3,7 +3,7 @@ def show_dev_info(): tprint("JamBit") - print("\033[36m" + "VERSION: " + "\033[34m" + "1.0" + "\033[34m") + print("\033[36m" + "VERSION: " + "\033[34m" + "3.0" + "\033[34m") print("\033[36m" + "Channel: " + "\033[34m" + "https://t.me/JamBitPY" + "\033[34m") print( "\033[36m" @@ -16,7 +16,7 @@ def show_dev_info(): "\033[36m" + "DONATION EVM ADDRESS: " + "\033[34m" - + "0x08e3fdbb830ee591c0533C5E58f937D312b07198" + + "0xe23380ae575D990BebB3b81DB2F90Ce7eDbB6dDa" + "\033[0m" ) print() diff --git a/utils/file_utils.py b/utils/file_utils.py new file mode 100644 index 0000000..4b20060 --- /dev/null +++ b/utils/file_utils.py @@ -0,0 +1,12 @@ +import os + +from loguru import logger + + +def export_trees_ids(results: list[tuple[str, str]]): + if not os.path.exists("./trees_results"): + with open("./config/trees_results.txt", "w") as file: + for result in results: + file.write(f"{result[0]}:{result[1]}\n") + + logger.success("Trees IDs exported to trees_results.txt") diff --git a/config/load_config.py b/utils/load_config.py similarity index 66% rename from config/load_config.py rename to utils/load_config.py index 634775c..3665513 100644 --- a/config/load_config.py +++ b/utils/load_config.py @@ -7,7 +7,7 @@ def get_accounts() -> Account: - accounts_path = os.path.join(os.path.dirname(__file__), "accounts.txt") + accounts_path = os.path.join(os.getcwd(), "config", "accounts.txt") if not os.path.exists(accounts_path): logger.error(f"File <<{accounts_path}>> does not exist") exit(1) @@ -36,7 +36,7 @@ def get_accounts() -> Account: def load_config() -> Config: - settings_path = os.path.join(os.path.dirname(__file__), "settings.yaml") + settings_path = os.path.join(os.getcwd(), "config", "settings.yaml") if not os.path.exists(settings_path): logger.error(f"File <<{settings_path}>> does not exist") exit(1) @@ -46,15 +46,19 @@ def load_config() -> Config: REQUIRED_KEYS = ( "referral_code", - "eth_rpc_url", - "sepolia_rpc_url", + "mint_rpc_url", + "arb_rpc_url", "threads", - "min_amount_to_bridge", - "max_amount_to_bridge", "min_delay_before_start", "max_delay_before_start", "spin_turntable_by_percentage_of_energy", "shuffle_accounts", + "comet_bridge_amount_min", + "comet_bridge_amount_max", + "comet_bridge_wallet", + "mint_random_all_nfts", + "delay_between_mint_min", + "delay_between_mint_max", ) for key in REQUIRED_KEYS: @@ -66,15 +70,4 @@ def load_config() -> Config: if settings["shuffle_accounts"]: random.shuffle(accounts) - return Config( - accounts=accounts, - referral_code=settings["referral_code"], - threads=settings["threads"], - min_amount_to_bridge=settings["min_amount_to_bridge"], - max_amount_to_bridge=settings["max_amount_to_bridge"], - eth_rpc_url=settings["eth_rpc_url"], - sepolia_rpc_url=settings["sepolia_rpc_url"], - min_delay_before_start=settings["min_delay_before_start"], - max_delay_before_start=settings["max_delay_before_start"], - spin_turntable_by_percentage_of_energy=settings["spin_turntable_by_percentage_of_energy"], - ) + return Config(accounts=accounts, **settings)