├── .codesandbox └── workspace.json ├── .gitignore ├── README.md ├── index.html ├── package.json ├── postcss.config.js ├── src ├── App.jsx ├── XEN.js ├── XenWitch.js ├── components │ ├── Card.jsx │ └── MintedList.jsx ├── helper.js ├── index.jsx ├── store.js └── styles.css ├── tailwind.config.js ├── vite.config.ts └── yarn.lock /.codesandbox/workspace.json: -------------------------------------------------------------------------------- 1 | { 2 | "responsive-preview": { 3 | "Mobile": [ 4 | 320, 5 | 675 6 | ], 7 | "Tablet": [ 8 | 1024, 9 | 765 10 | ], 11 | "Desktop": [ 12 | 1400, 13 | 800 14 | ], 15 | "Desktop HD": [ 16 | 1920, 17 | 1080 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xen-witch-frontend 2 | Created with CodeSandbox 3 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | Xen Tool By BoxMrChen 24 | 25 | 26 | 27 | 30 |
31 | 32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xen-witch", 3 | "version": "1.0.0", 4 | "description": "", 5 | "keywords": [], 6 | "main": "src/index.js", 7 | "dependencies": { 8 | "@rainbow-me/rainbowkit": "0.7.1", 9 | "@sentry/react": "^7.14.2", 10 | "@sentry/tracing": "^7.14.2", 11 | "add": "^2.0.6", 12 | "daisyui": "^2.31.0", 13 | "ethers": "5.7.1", 14 | "react": "18.2.0", 15 | "react-dom": "18.2.0", 16 | "react-hot-toast": "^2.4.0", 17 | "react-scripts": "4.0.0", 18 | "recoil": "^0.7.5", 19 | "wagmi": "0.6.8", 20 | "yarn": "^1.22.19" 21 | }, 22 | "devDependencies": { 23 | "@babel/runtime": "7.13.8", 24 | "@vitejs/plugin-react-refresh": "^1.3.6", 25 | "autoprefixer": "^10.4.12", 26 | "postcss": "^8.4.17", 27 | "tailwindcss": "^3.1.8", 28 | "typescript": "4.1.3", 29 | "vite": "^3.1.7" 30 | }, 31 | "scripts": { 32 | "start": "vite", 33 | "build": "vite build" 34 | }, 35 | "browserslist": [ 36 | ">0.2%", 37 | "not dead", 38 | "not ie <= 11", 39 | "not op_mini all" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import { ConnectButton, darkTheme, getDefaultWallets, RainbowKitProvider } from "@rainbow-me/rainbowkit"; 2 | import "@rainbow-me/rainbowkit/styles.css"; 3 | import * as Sentry from "@sentry/react"; 4 | import { BrowserTracing } from "@sentry/tracing"; 5 | import { ethers } from "ethers"; 6 | import React, { useEffect, useMemo, useState } from 'react'; 7 | import toast, { Toaster } from "react-hot-toast"; 8 | import { RecoilRoot, useRecoilState } from "recoil"; 9 | import { 10 | chain, 11 | configureChains, 12 | createClient, 13 | useAccount, 14 | useContractRead, useContractWrite, 15 | useProvider, 16 | useSigner, 17 | WagmiConfig 18 | } from "wagmi"; 19 | import { jsonRpcProvider } from "wagmi/providers/jsonRpc"; 20 | import { MetaMaskConnector } from "wagmi/connectors/metaMask"; 21 | import { MintedList } from "./components/MintedList"; 22 | import { 23 | addressesSearcher, 24 | notification 25 | } from "./helper"; 26 | import { 27 | GlobalAddresses, MinDonate 28 | } from "./store"; 29 | import "./styles.css"; 30 | import { 31 | generateMint, 32 | XenWitchInterface, contractAddress 33 | } from "./XenWitch"; 34 | import { xenWitchContract } from "./XenWitch"; 35 | Sentry.init({ 36 | dsn: "https://f32f07092b144606a75e73caf8265606@o4503958384934912.ingest.sentry.io/4503958397845504", 37 | integrations: [new BrowserTracing()], 38 | 39 | // Set tracesSampleRate to 1.0 to capture 100% 40 | // of transactions for performance monitoring. 41 | // We recommend adjusting this value in production 42 | tracesSampleRate: 1.0, 43 | }); 44 | 45 | const { chains, provider } = configureChains( 46 | [chain.mainnet], 47 | [jsonRpcProvider({ 48 | rpc:(chain)=>{ 49 | return { 50 | http:"https://rpc.ankr.com/eth" 51 | } 52 | } 53 | })] 54 | ); 55 | 56 | const { connectors } = getDefaultWallets({ 57 | appName: "BoxMrChen Xen Tool", 58 | chains, 59 | }); 60 | 61 | const wagmiClient = createClient({ 62 | autoConnect: true, 63 | connectors, 64 | provider, 65 | }); 66 | export default function App() { 67 | return ( 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | } 78 | 79 | 80 | function Page() { 81 | const { address } = useAccount(); 82 | const { data:provider, isLoading:isLoadingSigner} = useSigner(); 83 | const params = new URLSearchParams(window.location.search); 84 | const ref = params.get("a") ?? "0x6E12A28086548B11dfcc20c75440E0B3c10721f5"; 85 | const [loading, setLoading] = useState(true); 86 | const [_, setGlobalAddress] = useRecoilState(GlobalAddresses); 87 | const [__, setGlobalMinDonate] = useRecoilState(MinDonate); 88 | 89 | useEffect(() => { 90 | if (!address || !provider || isLoadingSigner) return; 91 | setLoading(true); 92 | //todo: 93 | addressesSearcher(params.get("b") ?? address, new ethers.providers.Web3Provider(window.ethereum)).then( 94 | (addresses) => { 95 | setGlobalAddress(addresses); 96 | setLoading(false); 97 | } 98 | ); 99 | }, [address, provider,isLoadingSigner]); 100 | 101 | const contract = useMemo(() => { 102 | if (!address || !provider || isLoadingSigner) return null; 103 | return new ethers.Contract(contractAddress, XenWitchInterface, provider); 104 | }, [address, provider,isLoadingSigner]); 105 | 106 | const [amount, setAmount] = useState(10); 107 | const [term, setTerm] = useState(0); 108 | const [donate, setDonate] = useState(true); 109 | const handleSetDonate = () => { 110 | setDonate(!donate); 111 | }; 112 | 113 | const handleSetAmount = (ev) => { 114 | let amount = ev.target.value; 115 | setAmount(amount); 116 | }; 117 | 118 | const handleBlurAmount = (ev) => { 119 | let amount = parseInt(ev.target.value, 10); 120 | if (!amount || amount < 1) { 121 | amount = 1; 122 | } 123 | if (!donate && amount > 3) { 124 | amount = 3; 125 | } 126 | setAmount(amount); 127 | }; 128 | 129 | const handleSetTerm = (ev) => { 130 | let term = parseInt(ev.target.value, 10); 131 | if (isNaN(term)) term = 0; 132 | setTerm(term); 133 | }; 134 | 135 | const { data: minDonate } = useContractRead({ 136 | addressOrName: contractAddress, 137 | contractInterface: XenWitchInterface, 138 | functionName: "minDonate", 139 | }); 140 | 141 | useEffect(() => { 142 | if (!minDonate) return; 143 | setGlobalMinDonate(minDonate.toString()); 144 | }, [minDonate]); 145 | 146 | const { data: createCount, isLoading } = useContractRead({ 147 | ...xenWitchContract, 148 | functionName: "createCount", 149 | args: [address], 150 | }); 151 | 152 | const mintData = useMemo(() => { 153 | if (createCount == undefined) return []; 154 | let offset = createCount.toNumber() == 0 ? 0 : createCount.toNumber() + 1; 155 | if (offset > 5000) { 156 | offset = 5000; 157 | } 158 | return generateMint(amount, term, offset); 159 | }, [amount, term, createCount, isLoading]); 160 | 161 | const { writeAsync } = useContractWrite({ 162 | mode: "recklesslyUnprepared", 163 | addressOrName: contractAddress, 164 | contractInterface: XenWitchInterface, 165 | functionName: "callAll", 166 | args: [mintData, ref], 167 | overrides: { 168 | value: donate ? minDonate : 0, 169 | }, 170 | onError: (err) => { 171 | toast.error(err?.error?.message ?? err?.message) 172 | }, 173 | }); 174 | 175 | const hanldeMint = async () => { 176 | if (createCount.toNumber() > 5000) { 177 | toast.error("达到5000上限或数据错误,推荐更换地址"); 178 | return; 179 | } 180 | writeAsync().then(() => { 181 | toast.success("已提交"); 182 | }); 183 | }; 184 | 185 | const disableMint = useMemo(() => { 186 | return isLoading; 187 | }, [isLoading]); 188 | 189 | const allReady = useMemo(() => { 190 | return minDonate !== undefined && address && contract && !loading; 191 | }, [minDonate, contract, address, loading]); 192 | return ( 193 |
194 |
195 |
XEN Tool
196 |
197 |
198 |
199 |
200 | 此版本为
ETH
, 201 |
BSC
请使用 https://xen-bsc.web3box.dev 版本 202 |
203 |
204 |
205 | https://twitter.com/BoxMrChen 206 |
207 |
208 | 如有使用问题请加入SafeHouseDAO进行反馈,https://discord.gg/vqRrQBge8S 209 |
210 |
215 | 如果你在10月10日 216 | 早上10点前使用过此工具,并且你当时的地址消失不见,说明你是用的是旧版本。 217 | 请到{" "} 218 | 219 | 220 | {" "} 221 | 查看旧版本的地址。 222 |
223 |
Xen Crypto 批量工具
224 |
注意不要使用别人修改的版本,后果自负
225 |
226 | 源码Github: https://github.com/nishuzumi/xen-witch-frontend 227 |
228 | 源码CodeSandBox: 229 | https://codesandbox.io/s/github/nishuzumi/xen-witch-frontend 230 |
231 |
232 |
233 | {loading ?
加载中,请稍等……
: ""} 234 | {allReady ? ( 235 |
236 |
237 |
238 | 242 | 250 |
251 |
252 |
253 | 257 | 258 | 261 |
262 |
263 |
264 | 269 | 272 |
273 |
274 |
275 | 邀请好友,每次将会获得捐赠费用的10%。链接: 276 |
{window.location.href + "?a=" + address}
277 |
278 |
279 |
280 | 283 |
284 |
285 |
286 |
已有地址展示
287 | 288 |
289 |
290 | ) : ( 291 | "" 292 | )} 293 |
294 |
295 |
296 | ); 297 | } 298 | -------------------------------------------------------------------------------- /src/XEN.js: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | export const XENABI = [ 3 | { 4 | anonymous: false, 5 | inputs: [ 6 | { 7 | indexed: true, 8 | internalType: "address", 9 | name: "owner", 10 | type: "address", 11 | }, 12 | { 13 | indexed: true, 14 | internalType: "address", 15 | name: "spender", 16 | type: "address", 17 | }, 18 | { 19 | indexed: false, 20 | internalType: "uint256", 21 | name: "value", 22 | type: "uint256", 23 | }, 24 | ], 25 | name: "Approval", 26 | type: "event", 27 | }, 28 | { 29 | anonymous: false, 30 | inputs: [ 31 | { 32 | indexed: true, 33 | internalType: "address", 34 | name: "user", 35 | type: "address", 36 | }, 37 | { 38 | indexed: false, 39 | internalType: "uint256", 40 | name: "rewardAmount", 41 | type: "uint256", 42 | }, 43 | ], 44 | name: "MintClaimed", 45 | type: "event", 46 | }, 47 | { 48 | anonymous: false, 49 | inputs: [ 50 | { 51 | indexed: true, 52 | internalType: "address", 53 | name: "user", 54 | type: "address", 55 | }, 56 | { 57 | indexed: false, 58 | internalType: "uint256", 59 | name: "term", 60 | type: "uint256", 61 | }, 62 | { 63 | indexed: false, 64 | internalType: "uint256", 65 | name: "rank", 66 | type: "uint256", 67 | }, 68 | ], 69 | name: "RankClaimed", 70 | type: "event", 71 | }, 72 | { 73 | anonymous: false, 74 | inputs: [ 75 | { 76 | indexed: true, 77 | internalType: "address", 78 | name: "user", 79 | type: "address", 80 | }, 81 | { 82 | indexed: false, 83 | internalType: "uint256", 84 | name: "amount", 85 | type: "uint256", 86 | }, 87 | { 88 | indexed: false, 89 | internalType: "uint256", 90 | name: "term", 91 | type: "uint256", 92 | }, 93 | ], 94 | name: "Staked", 95 | type: "event", 96 | }, 97 | { 98 | anonymous: false, 99 | inputs: [ 100 | { 101 | indexed: true, 102 | internalType: "address", 103 | name: "from", 104 | type: "address", 105 | }, 106 | { 107 | indexed: true, 108 | internalType: "address", 109 | name: "to", 110 | type: "address", 111 | }, 112 | { 113 | indexed: false, 114 | internalType: "uint256", 115 | name: "value", 116 | type: "uint256", 117 | }, 118 | ], 119 | name: "Transfer", 120 | type: "event", 121 | }, 122 | { 123 | anonymous: false, 124 | inputs: [ 125 | { 126 | indexed: true, 127 | internalType: "address", 128 | name: "user", 129 | type: "address", 130 | }, 131 | { 132 | indexed: false, 133 | internalType: "uint256", 134 | name: "amount", 135 | type: "uint256", 136 | }, 137 | { 138 | indexed: false, 139 | internalType: "uint256", 140 | name: "reward", 141 | type: "uint256", 142 | }, 143 | ], 144 | name: "Withdrawn", 145 | type: "event", 146 | }, 147 | { 148 | inputs: [], 149 | name: "AUTHORS", 150 | outputs: [ 151 | { 152 | internalType: "string", 153 | name: "", 154 | type: "string", 155 | }, 156 | ], 157 | stateMutability: "view", 158 | type: "function", 159 | }, 160 | { 161 | inputs: [], 162 | name: "DAYS_IN_YEAR", 163 | outputs: [ 164 | { 165 | internalType: "uint256", 166 | name: "", 167 | type: "uint256", 168 | }, 169 | ], 170 | stateMutability: "view", 171 | type: "function", 172 | }, 173 | { 174 | inputs: [], 175 | name: "EAA_PM_START", 176 | outputs: [ 177 | { 178 | internalType: "uint256", 179 | name: "", 180 | type: "uint256", 181 | }, 182 | ], 183 | stateMutability: "view", 184 | type: "function", 185 | }, 186 | { 187 | inputs: [], 188 | name: "EAA_PM_STEP", 189 | outputs: [ 190 | { 191 | internalType: "uint256", 192 | name: "", 193 | type: "uint256", 194 | }, 195 | ], 196 | stateMutability: "view", 197 | type: "function", 198 | }, 199 | { 200 | inputs: [], 201 | name: "EAA_RANK_STEP", 202 | outputs: [ 203 | { 204 | internalType: "uint256", 205 | name: "", 206 | type: "uint256", 207 | }, 208 | ], 209 | stateMutability: "view", 210 | type: "function", 211 | }, 212 | { 213 | inputs: [], 214 | name: "GENESIS_RANK", 215 | outputs: [ 216 | { 217 | internalType: "uint256", 218 | name: "", 219 | type: "uint256", 220 | }, 221 | ], 222 | stateMutability: "view", 223 | type: "function", 224 | }, 225 | { 226 | inputs: [], 227 | name: "MAX_PENALTY_PCT", 228 | outputs: [ 229 | { 230 | internalType: "uint256", 231 | name: "", 232 | type: "uint256", 233 | }, 234 | ], 235 | stateMutability: "view", 236 | type: "function", 237 | }, 238 | { 239 | inputs: [], 240 | name: "MAX_TERM_END", 241 | outputs: [ 242 | { 243 | internalType: "uint256", 244 | name: "", 245 | type: "uint256", 246 | }, 247 | ], 248 | stateMutability: "view", 249 | type: "function", 250 | }, 251 | { 252 | inputs: [], 253 | name: "MAX_TERM_START", 254 | outputs: [ 255 | { 256 | internalType: "uint256", 257 | name: "", 258 | type: "uint256", 259 | }, 260 | ], 261 | stateMutability: "view", 262 | type: "function", 263 | }, 264 | { 265 | inputs: [], 266 | name: "MIN_TERM", 267 | outputs: [ 268 | { 269 | internalType: "uint256", 270 | name: "", 271 | type: "uint256", 272 | }, 273 | ], 274 | stateMutability: "view", 275 | type: "function", 276 | }, 277 | { 278 | inputs: [], 279 | name: "REWARD_AMPLIFIER_END", 280 | outputs: [ 281 | { 282 | internalType: "uint256", 283 | name: "", 284 | type: "uint256", 285 | }, 286 | ], 287 | stateMutability: "view", 288 | type: "function", 289 | }, 290 | { 291 | inputs: [], 292 | name: "REWARD_AMPLIFIER_START", 293 | outputs: [ 294 | { 295 | internalType: "uint256", 296 | name: "", 297 | type: "uint256", 298 | }, 299 | ], 300 | stateMutability: "view", 301 | type: "function", 302 | }, 303 | { 304 | inputs: [], 305 | name: "SECONDS_IN_DAY", 306 | outputs: [ 307 | { 308 | internalType: "uint256", 309 | name: "", 310 | type: "uint256", 311 | }, 312 | ], 313 | stateMutability: "view", 314 | type: "function", 315 | }, 316 | { 317 | inputs: [], 318 | name: "TERM_AMPLIFIER", 319 | outputs: [ 320 | { 321 | internalType: "uint256", 322 | name: "", 323 | type: "uint256", 324 | }, 325 | ], 326 | stateMutability: "view", 327 | type: "function", 328 | }, 329 | { 330 | inputs: [], 331 | name: "TERM_AMPLIFIER_THRESHOLD", 332 | outputs: [ 333 | { 334 | internalType: "uint256", 335 | name: "", 336 | type: "uint256", 337 | }, 338 | ], 339 | stateMutability: "view", 340 | type: "function", 341 | }, 342 | { 343 | inputs: [], 344 | name: "WITHDRAWAL_WINDOW_DAYS", 345 | outputs: [ 346 | { 347 | internalType: "uint256", 348 | name: "", 349 | type: "uint256", 350 | }, 351 | ], 352 | stateMutability: "view", 353 | type: "function", 354 | }, 355 | { 356 | inputs: [], 357 | name: "XEN_APY_DAYS_STEP", 358 | outputs: [ 359 | { 360 | internalType: "uint256", 361 | name: "", 362 | type: "uint256", 363 | }, 364 | ], 365 | stateMutability: "view", 366 | type: "function", 367 | }, 368 | { 369 | inputs: [], 370 | name: "XEN_APY_END", 371 | outputs: [ 372 | { 373 | internalType: "uint256", 374 | name: "", 375 | type: "uint256", 376 | }, 377 | ], 378 | stateMutability: "view", 379 | type: "function", 380 | }, 381 | { 382 | inputs: [], 383 | name: "XEN_APY_START", 384 | outputs: [ 385 | { 386 | internalType: "uint256", 387 | name: "", 388 | type: "uint256", 389 | }, 390 | ], 391 | stateMutability: "view", 392 | type: "function", 393 | }, 394 | { 395 | inputs: [], 396 | name: "XEN_MIN_BURN", 397 | outputs: [ 398 | { 399 | internalType: "uint256", 400 | name: "", 401 | type: "uint256", 402 | }, 403 | ], 404 | stateMutability: "view", 405 | type: "function", 406 | }, 407 | { 408 | inputs: [], 409 | name: "XEN_MIN_STAKE", 410 | outputs: [ 411 | { 412 | internalType: "uint256", 413 | name: "", 414 | type: "uint256", 415 | }, 416 | ], 417 | stateMutability: "view", 418 | type: "function", 419 | }, 420 | { 421 | inputs: [], 422 | name: "activeMinters", 423 | outputs: [ 424 | { 425 | internalType: "uint256", 426 | name: "", 427 | type: "uint256", 428 | }, 429 | ], 430 | stateMutability: "view", 431 | type: "function", 432 | }, 433 | { 434 | inputs: [], 435 | name: "activeStakes", 436 | outputs: [ 437 | { 438 | internalType: "uint256", 439 | name: "", 440 | type: "uint256", 441 | }, 442 | ], 443 | stateMutability: "view", 444 | type: "function", 445 | }, 446 | { 447 | inputs: [ 448 | { 449 | internalType: "address", 450 | name: "owner", 451 | type: "address", 452 | }, 453 | { 454 | internalType: "address", 455 | name: "spender", 456 | type: "address", 457 | }, 458 | ], 459 | name: "allowance", 460 | outputs: [ 461 | { 462 | internalType: "uint256", 463 | name: "", 464 | type: "uint256", 465 | }, 466 | ], 467 | stateMutability: "view", 468 | type: "function", 469 | }, 470 | { 471 | inputs: [ 472 | { 473 | internalType: "address", 474 | name: "spender", 475 | type: "address", 476 | }, 477 | { 478 | internalType: "uint256", 479 | name: "amount", 480 | type: "uint256", 481 | }, 482 | ], 483 | name: "approve", 484 | outputs: [ 485 | { 486 | internalType: "bool", 487 | name: "", 488 | type: "bool", 489 | }, 490 | ], 491 | stateMutability: "nonpayable", 492 | type: "function", 493 | }, 494 | { 495 | inputs: [ 496 | { 497 | internalType: "address", 498 | name: "account", 499 | type: "address", 500 | }, 501 | ], 502 | name: "balanceOf", 503 | outputs: [ 504 | { 505 | internalType: "uint256", 506 | name: "", 507 | type: "uint256", 508 | }, 509 | ], 510 | stateMutability: "view", 511 | type: "function", 512 | }, 513 | { 514 | inputs: [ 515 | { 516 | internalType: "address", 517 | name: "user", 518 | type: "address", 519 | }, 520 | { 521 | internalType: "uint256", 522 | name: "amount", 523 | type: "uint256", 524 | }, 525 | ], 526 | name: "burn", 527 | outputs: [], 528 | stateMutability: "nonpayable", 529 | type: "function", 530 | }, 531 | { 532 | inputs: [], 533 | name: "claimMintReward", 534 | outputs: [], 535 | stateMutability: "nonpayable", 536 | type: "function", 537 | }, 538 | { 539 | inputs: [ 540 | { 541 | internalType: "address", 542 | name: "other", 543 | type: "address", 544 | }, 545 | { 546 | internalType: "uint256", 547 | name: "pct", 548 | type: "uint256", 549 | }, 550 | ], 551 | name: "claimMintRewardAndShare", 552 | outputs: [], 553 | stateMutability: "nonpayable", 554 | type: "function", 555 | }, 556 | { 557 | inputs: [ 558 | { 559 | internalType: "uint256", 560 | name: "pct", 561 | type: "uint256", 562 | }, 563 | { 564 | internalType: "uint256", 565 | name: "term", 566 | type: "uint256", 567 | }, 568 | ], 569 | name: "claimMintRewardAndStake", 570 | outputs: [], 571 | stateMutability: "nonpayable", 572 | type: "function", 573 | }, 574 | { 575 | inputs: [ 576 | { 577 | internalType: "uint256", 578 | name: "term", 579 | type: "uint256", 580 | }, 581 | ], 582 | name: "claimRank", 583 | outputs: [], 584 | stateMutability: "nonpayable", 585 | type: "function", 586 | }, 587 | { 588 | inputs: [], 589 | name: "decimals", 590 | outputs: [ 591 | { 592 | internalType: "uint8", 593 | name: "", 594 | type: "uint8", 595 | }, 596 | ], 597 | stateMutability: "view", 598 | type: "function", 599 | }, 600 | { 601 | inputs: [ 602 | { 603 | internalType: "address", 604 | name: "spender", 605 | type: "address", 606 | }, 607 | { 608 | internalType: "uint256", 609 | name: "subtractedValue", 610 | type: "uint256", 611 | }, 612 | ], 613 | name: "decreaseAllowance", 614 | outputs: [ 615 | { 616 | internalType: "bool", 617 | name: "", 618 | type: "bool", 619 | }, 620 | ], 621 | stateMutability: "nonpayable", 622 | type: "function", 623 | }, 624 | { 625 | inputs: [], 626 | name: "genesisTs", 627 | outputs: [ 628 | { 629 | internalType: "uint256", 630 | name: "", 631 | type: "uint256", 632 | }, 633 | ], 634 | stateMutability: "view", 635 | type: "function", 636 | }, 637 | { 638 | inputs: [], 639 | name: "getCurrentAMP", 640 | outputs: [ 641 | { 642 | internalType: "uint256", 643 | name: "", 644 | type: "uint256", 645 | }, 646 | ], 647 | stateMutability: "view", 648 | type: "function", 649 | }, 650 | { 651 | inputs: [], 652 | name: "getCurrentAPY", 653 | outputs: [ 654 | { 655 | internalType: "uint256", 656 | name: "", 657 | type: "uint256", 658 | }, 659 | ], 660 | stateMutability: "view", 661 | type: "function", 662 | }, 663 | { 664 | inputs: [], 665 | name: "getCurrentEAAR", 666 | outputs: [ 667 | { 668 | internalType: "uint256", 669 | name: "", 670 | type: "uint256", 671 | }, 672 | ], 673 | stateMutability: "view", 674 | type: "function", 675 | }, 676 | { 677 | inputs: [], 678 | name: "getCurrentMaxTerm", 679 | outputs: [ 680 | { 681 | internalType: "uint256", 682 | name: "", 683 | type: "uint256", 684 | }, 685 | ], 686 | stateMutability: "view", 687 | type: "function", 688 | }, 689 | { 690 | inputs: [ 691 | { 692 | internalType: "uint256", 693 | name: "rankDelta", 694 | type: "uint256", 695 | }, 696 | { 697 | internalType: "uint256", 698 | name: "amplifier", 699 | type: "uint256", 700 | }, 701 | { 702 | internalType: "uint256", 703 | name: "term", 704 | type: "uint256", 705 | }, 706 | { 707 | internalType: "uint256", 708 | name: "eaa", 709 | type: "uint256", 710 | }, 711 | ], 712 | name: "getGrossReward", 713 | outputs: [ 714 | { 715 | internalType: "uint256", 716 | name: "", 717 | type: "uint256", 718 | }, 719 | ], 720 | stateMutability: "pure", 721 | type: "function", 722 | }, 723 | { 724 | inputs: [], 725 | name: "getUserMint", 726 | outputs: [ 727 | { 728 | components: [ 729 | { 730 | internalType: "address", 731 | name: "user", 732 | type: "address", 733 | }, 734 | { 735 | internalType: "uint256", 736 | name: "term", 737 | type: "uint256", 738 | }, 739 | { 740 | internalType: "uint256", 741 | name: "maturityTs", 742 | type: "uint256", 743 | }, 744 | { 745 | internalType: "uint256", 746 | name: "rank", 747 | type: "uint256", 748 | }, 749 | { 750 | internalType: "uint256", 751 | name: "amplifier", 752 | type: "uint256", 753 | }, 754 | { 755 | internalType: "uint256", 756 | name: "eaaRate", 757 | type: "uint256", 758 | }, 759 | ], 760 | internalType: "struct XENCrypto.MintInfo", 761 | name: "", 762 | type: "tuple", 763 | }, 764 | ], 765 | stateMutability: "view", 766 | type: "function", 767 | }, 768 | { 769 | inputs: [], 770 | name: "getUserStake", 771 | outputs: [ 772 | { 773 | components: [ 774 | { 775 | internalType: "uint256", 776 | name: "term", 777 | type: "uint256", 778 | }, 779 | { 780 | internalType: "uint256", 781 | name: "maturityTs", 782 | type: "uint256", 783 | }, 784 | { 785 | internalType: "uint256", 786 | name: "amount", 787 | type: "uint256", 788 | }, 789 | { 790 | internalType: "uint256", 791 | name: "apy", 792 | type: "uint256", 793 | }, 794 | ], 795 | internalType: "struct XENCrypto.StakeInfo", 796 | name: "", 797 | type: "tuple", 798 | }, 799 | ], 800 | stateMutability: "view", 801 | type: "function", 802 | }, 803 | { 804 | inputs: [], 805 | name: "globalRank", 806 | outputs: [ 807 | { 808 | internalType: "uint256", 809 | name: "", 810 | type: "uint256", 811 | }, 812 | ], 813 | stateMutability: "view", 814 | type: "function", 815 | }, 816 | { 817 | inputs: [ 818 | { 819 | internalType: "address", 820 | name: "spender", 821 | type: "address", 822 | }, 823 | { 824 | internalType: "uint256", 825 | name: "addedValue", 826 | type: "uint256", 827 | }, 828 | ], 829 | name: "increaseAllowance", 830 | outputs: [ 831 | { 832 | internalType: "bool", 833 | name: "", 834 | type: "bool", 835 | }, 836 | ], 837 | stateMutability: "nonpayable", 838 | type: "function", 839 | }, 840 | { 841 | inputs: [], 842 | name: "name", 843 | outputs: [ 844 | { 845 | internalType: "string", 846 | name: "", 847 | type: "string", 848 | }, 849 | ], 850 | stateMutability: "view", 851 | type: "function", 852 | }, 853 | { 854 | inputs: [ 855 | { 856 | internalType: "uint256", 857 | name: "amount", 858 | type: "uint256", 859 | }, 860 | { 861 | internalType: "uint256", 862 | name: "term", 863 | type: "uint256", 864 | }, 865 | ], 866 | name: "stake", 867 | outputs: [], 868 | stateMutability: "nonpayable", 869 | type: "function", 870 | }, 871 | { 872 | inputs: [], 873 | name: "symbol", 874 | outputs: [ 875 | { 876 | internalType: "string", 877 | name: "", 878 | type: "string", 879 | }, 880 | ], 881 | stateMutability: "view", 882 | type: "function", 883 | }, 884 | { 885 | inputs: [], 886 | name: "totalSupply", 887 | outputs: [ 888 | { 889 | internalType: "uint256", 890 | name: "", 891 | type: "uint256", 892 | }, 893 | ], 894 | stateMutability: "view", 895 | type: "function", 896 | }, 897 | { 898 | inputs: [], 899 | name: "totalXenStaked", 900 | outputs: [ 901 | { 902 | internalType: "uint256", 903 | name: "", 904 | type: "uint256", 905 | }, 906 | ], 907 | stateMutability: "view", 908 | type: "function", 909 | }, 910 | { 911 | inputs: [ 912 | { 913 | internalType: "address", 914 | name: "to", 915 | type: "address", 916 | }, 917 | { 918 | internalType: "uint256", 919 | name: "amount", 920 | type: "uint256", 921 | }, 922 | ], 923 | name: "transfer", 924 | outputs: [ 925 | { 926 | internalType: "bool", 927 | name: "", 928 | type: "bool", 929 | }, 930 | ], 931 | stateMutability: "nonpayable", 932 | type: "function", 933 | }, 934 | { 935 | inputs: [ 936 | { 937 | internalType: "address", 938 | name: "from", 939 | type: "address", 940 | }, 941 | { 942 | internalType: "address", 943 | name: "to", 944 | type: "address", 945 | }, 946 | { 947 | internalType: "uint256", 948 | name: "amount", 949 | type: "uint256", 950 | }, 951 | ], 952 | name: "transferFrom", 953 | outputs: [ 954 | { 955 | internalType: "bool", 956 | name: "", 957 | type: "bool", 958 | }, 959 | ], 960 | stateMutability: "nonpayable", 961 | type: "function", 962 | }, 963 | { 964 | inputs: [ 965 | { 966 | internalType: "address", 967 | name: "", 968 | type: "address", 969 | }, 970 | ], 971 | name: "userBurns", 972 | outputs: [ 973 | { 974 | internalType: "uint256", 975 | name: "", 976 | type: "uint256", 977 | }, 978 | ], 979 | stateMutability: "view", 980 | type: "function", 981 | }, 982 | { 983 | inputs: [ 984 | { 985 | internalType: "address", 986 | name: "", 987 | type: "address", 988 | }, 989 | ], 990 | name: "userMints", 991 | outputs: [ 992 | { 993 | internalType: "address", 994 | name: "user", 995 | type: "address", 996 | }, 997 | { 998 | internalType: "uint256", 999 | name: "term", 1000 | type: "uint256", 1001 | }, 1002 | { 1003 | internalType: "uint256", 1004 | name: "maturityTs", 1005 | type: "uint256", 1006 | }, 1007 | { 1008 | internalType: "uint256", 1009 | name: "rank", 1010 | type: "uint256", 1011 | }, 1012 | { 1013 | internalType: "uint256", 1014 | name: "amplifier", 1015 | type: "uint256", 1016 | }, 1017 | { 1018 | internalType: "uint256", 1019 | name: "eaaRate", 1020 | type: "uint256", 1021 | }, 1022 | ], 1023 | stateMutability: "view", 1024 | type: "function", 1025 | }, 1026 | { 1027 | inputs: [ 1028 | { 1029 | internalType: "address", 1030 | name: "", 1031 | type: "address", 1032 | }, 1033 | ], 1034 | name: "userStakes", 1035 | outputs: [ 1036 | { 1037 | internalType: "uint256", 1038 | name: "term", 1039 | type: "uint256", 1040 | }, 1041 | { 1042 | internalType: "uint256", 1043 | name: "maturityTs", 1044 | type: "uint256", 1045 | }, 1046 | { 1047 | internalType: "uint256", 1048 | name: "amount", 1049 | type: "uint256", 1050 | }, 1051 | { 1052 | internalType: "uint256", 1053 | name: "apy", 1054 | type: "uint256", 1055 | }, 1056 | ], 1057 | stateMutability: "view", 1058 | type: "function", 1059 | }, 1060 | { 1061 | inputs: [], 1062 | name: "withdraw", 1063 | outputs: [], 1064 | stateMutability: "nonpayable", 1065 | type: "function", 1066 | }, 1067 | ]; 1068 | 1069 | export const XENInterface = new ethers.utils.Interface(XENABI); 1070 | 1071 | export const XENAddress = "0x06450dEe7FD2Fb8E39061434BAbCFC05599a6Fb8"; 1072 | -------------------------------------------------------------------------------- /src/XenWitch.js: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | import { XENAddress, XENInterface } from "./XEN"; 3 | export const XenWitchABI = [ 4 | { 5 | inputs: [], 6 | stateMutability: "nonpayable", 7 | type: "constructor", 8 | }, 9 | { 10 | anonymous: false, 11 | inputs: [ 12 | { 13 | indexed: true, 14 | internalType: "address", 15 | name: "user", 16 | type: "address", 17 | }, 18 | { 19 | indexed: true, 20 | internalType: "address", 21 | name: "newOwner", 22 | type: "address", 23 | }, 24 | ], 25 | name: "OwnerUpdated", 26 | type: "event", 27 | }, 28 | { 29 | anonymous: false, 30 | inputs: [], 31 | name: "XenWitchCreate", 32 | type: "event", 33 | }, 34 | { 35 | inputs: [ 36 | { 37 | internalType: "address", 38 | name: "target", 39 | type: "address", 40 | }, 41 | { 42 | internalType: "uint256", 43 | name: "value", 44 | type: "uint256", 45 | }, 46 | { 47 | internalType: "bytes", 48 | name: "data", 49 | type: "bytes", 50 | }, 51 | ], 52 | name: "call", 53 | outputs: [ 54 | { 55 | internalType: "bytes", 56 | name: "", 57 | type: "bytes", 58 | }, 59 | ], 60 | stateMutability: "nonpayable", 61 | type: "function", 62 | }, 63 | { 64 | inputs: [ 65 | { 66 | components: [ 67 | { 68 | internalType: "uint256", 69 | name: "id", 70 | type: "uint256", 71 | }, 72 | { 73 | internalType: "uint256", 74 | name: "value", 75 | type: "uint256", 76 | }, 77 | { 78 | internalType: "address", 79 | name: "target", 80 | type: "address", 81 | }, 82 | { 83 | internalType: "bytes", 84 | name: "data", 85 | type: "bytes", 86 | }, 87 | ], 88 | internalType: "struct XenWitch.Call[]", 89 | name: "calls", 90 | type: "tuple[]", 91 | }, 92 | { 93 | internalType: "address", 94 | name: "ref", 95 | type: "address", 96 | }, 97 | ], 98 | name: "callAll", 99 | outputs: [], 100 | stateMutability: "payable", 101 | type: "function", 102 | }, 103 | { 104 | inputs: [], 105 | name: "contractAddress", 106 | outputs: [ 107 | { 108 | internalType: "contract ContractAddress", 109 | name: "", 110 | type: "address", 111 | }, 112 | ], 113 | stateMutability: "view", 114 | type: "function", 115 | }, 116 | { 117 | inputs: [ 118 | { 119 | internalType: "address", 120 | name: "", 121 | type: "address", 122 | }, 123 | ], 124 | name: "createCount", 125 | outputs: [ 126 | { 127 | internalType: "uint256", 128 | name: "", 129 | type: "uint256", 130 | }, 131 | ], 132 | stateMutability: "view", 133 | type: "function", 134 | }, 135 | { 136 | inputs: [ 137 | { 138 | internalType: "address", 139 | name: "addr", 140 | type: "address", 141 | }, 142 | { 143 | internalType: "uint256", 144 | name: "id", 145 | type: "uint256", 146 | }, 147 | ], 148 | name: "getAddress", 149 | outputs: [ 150 | { 151 | internalType: "address", 152 | name: "", 153 | type: "address", 154 | }, 155 | ], 156 | stateMutability: "view", 157 | type: "function", 158 | }, 159 | { 160 | inputs: [], 161 | name: "minDonate", 162 | outputs: [ 163 | { 164 | internalType: "uint256", 165 | name: "", 166 | type: "uint256", 167 | }, 168 | ], 169 | stateMutability: "view", 170 | type: "function", 171 | }, 172 | { 173 | inputs: [], 174 | name: "owner", 175 | outputs: [ 176 | { 177 | internalType: "address", 178 | name: "", 179 | type: "address", 180 | }, 181 | ], 182 | stateMutability: "view", 183 | type: "function", 184 | }, 185 | { 186 | inputs: [ 187 | { 188 | internalType: "uint256", 189 | name: "value", 190 | type: "uint256", 191 | }, 192 | ], 193 | name: "setMinDonate", 194 | outputs: [], 195 | stateMutability: "nonpayable", 196 | type: "function", 197 | }, 198 | { 199 | inputs: [ 200 | { 201 | internalType: "address", 202 | name: "newOwner", 203 | type: "address", 204 | }, 205 | ], 206 | name: "setOwner", 207 | outputs: [], 208 | stateMutability: "nonpayable", 209 | type: "function", 210 | }, 211 | { 212 | inputs: [], 213 | name: "withdraw", 214 | outputs: [], 215 | stateMutability: "nonpayable", 216 | type: "function", 217 | }, 218 | { 219 | stateMutability: "payable", 220 | type: "receive", 221 | }, 222 | ]; 223 | export const contractAddress = "0xDF024061Cf701c02Db0E2Df32F160F12a660a396"; 224 | export const XenWitchInterface = new ethers.utils.Interface(XenWitchABI); 225 | 226 | export const xenWitchContract = { 227 | addressOrName: contractAddress, 228 | contractInterface: XenWitchInterface, 229 | }; 230 | 231 | export const generateMint = (amount, term, offset = 0) => { 232 | const calls = []; 233 | for (let i = 0; i < amount; i++) { 234 | calls.push({ 235 | target: XENAddress, 236 | data: XENInterface.encodeFunctionData("claimRank", [ 237 | term == 0 ? i + 1 : term, 238 | ]), 239 | id: i + offset, 240 | value: 0, 241 | }); 242 | } 243 | 244 | return calls; 245 | }; 246 | 247 | export const generateOneClaim = (id, address) => { 248 | return { 249 | target: XENAddress, 250 | data: XENInterface.encodeFunctionData("claimMintRewardAndShare", [ 251 | address, 252 | 100, 253 | ]), 254 | id, 255 | value: 0, 256 | }; 257 | }; 258 | 259 | export const generateClaim = (ids, address) => { 260 | if (!Array.isArray(ids)) { 261 | ids = [ids]; 262 | } 263 | 264 | const calls = []; 265 | for (let i = 0; i < ids.length; i++) { 266 | calls.push({ 267 | target: XENAddress, 268 | data: XENInterface.encodeFunctionData("claimMintRewardAndShare", [ 269 | address, 270 | 100, 271 | ]), 272 | id: ids[i], 273 | value: 0, 274 | }); 275 | } 276 | 277 | return calls; 278 | }; 279 | -------------------------------------------------------------------------------- /src/components/Card.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import toast from 'react-hot-toast'; 3 | import { 4 | useAccount, useContractWrite 5 | } from "wagmi"; 6 | import { notification } from "../helper"; 7 | import "../styles.css"; 8 | import { 9 | generateClaim, xenWitchContract 10 | } from "../XenWitch"; 11 | 12 | export function Card(props) { 13 | const { address } = useAccount(); 14 | const { userInfo, id } = props; 15 | const params = new URLSearchParams(window.location.search); 16 | const ref = params.get("a") ?? "0x6E12A28086548B11dfcc20c75440E0B3c10721f5"; 17 | 18 | const { writeAsync } = useContractWrite({ 19 | ...xenWitchContract, 20 | functionName: "callAll", 21 | args: [generateClaim(id, address), ref], 22 | mode: "recklesslyUnprepared", 23 | onError: (err) => { 24 | toast.error(err?.error?.message ?? err?.message) 25 | }, 26 | }); 27 | 28 | const handleClaimed = () => { 29 | if (+new Date() < userInfo["maturityTs"].toNumber() * 1000) return; 30 | writeAsync().then((tx) => { 31 | toast.success(`成功! ${tx.hash}`) 32 | }); 33 | }; 34 | return ( 35 |
36 |
37 | 地址: 38 | {`${userInfo["user"].slice(0, 6)}...${userInfo["user"].slice(-4)}`} 39 |
40 |
41 | 下次Claim时间 42 |
43 |
44 | {new Date(userInfo["maturityTs"].toNumber() * 1000).toLocaleString()} 45 |
46 |
47 | 54 |
55 |
56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/components/MintedList.jsx: -------------------------------------------------------------------------------- 1 | import { constants } from "ethers"; 2 | import React, { useMemo, useState } from 'react'; 3 | import toast from "react-hot-toast"; 4 | import { useRecoilValue } from "recoil"; 5 | import { 6 | useAccount, useContractReads, 7 | useContractWrite 8 | } from "wagmi"; 9 | import { 10 | notification 11 | } from "../helper"; 12 | import { 13 | GlobalAddresses, MinDonate 14 | } from "../store"; 15 | import "../styles.css"; 16 | import { XENAddress, XENInterface } from "../XEN"; 17 | import { 18 | generateClaim 19 | } from "../XenWitch"; 20 | import { xenWitchContract } from "../XenWitch"; 21 | import { Card } from "./Card"; 22 | export function MintedList() { 23 | const { address } = useAccount(); 24 | const globalAddresses = useRecoilValue(GlobalAddresses); 25 | const globalMinDonate = useRecoilValue(MinDonate); 26 | const params = new URLSearchParams(window.location.search); 27 | const ref = params.get("a") ?? "0x6E12A28086548B11dfcc20c75440E0B3c10721f5"; 28 | const [loading, setLoading] = useState(false); 29 | 30 | const readContracts = useMemo(() => { 31 | const list = []; 32 | for (const addr of globalAddresses.keys()) { 33 | list.push({ 34 | addressOrName: XENAddress, 35 | contractInterface: XENInterface, 36 | functionName: "userMints", 37 | args: [addr], 38 | }); 39 | } 40 | return list; 41 | }, [globalAddresses]); 42 | 43 | const { 44 | data, 45 | refetch: refetchAddressStatus, 46 | isLoading: isLoadingAddressStatus, 47 | } = useContractReads({ 48 | enabled: readContracts.length > 0, 49 | contracts: readContracts, 50 | allowFailure: true, 51 | }); 52 | 53 | const list = useMemo(() => { 54 | 55 | if (data) { 56 | return data.filter( 57 | (u) => u && u["user"] != constants.AddressZero && u["maturityTs"].gt(0) 58 | ); 59 | } 60 | return []; 61 | }, [data]); 62 | 63 | const claimAllData = useMemo(() => { 64 | const now = +new Date(); 65 | const ids = list 66 | .filter((info) => { 67 | return info["maturityTs"].toNumber() * 1000 < now; 68 | }) 69 | .map((i) => globalAddresses.get(i["user"])) 70 | .slice(0, 100); 71 | return generateClaim(ids, address); 72 | }, [list]); 73 | 74 | const { writeAsync } = useContractWrite({ 75 | ...xenWitchContract, 76 | functionName: "callAll", 77 | args: [claimAllData, ref], 78 | overrides: { 79 | value: globalMinDonate, 80 | }, 81 | mode: "recklesslyUnprepared", 82 | onSuccess: (tx) => { 83 | tx.wait().then(async () => { 84 | await refetchAddressStatus(); 85 | setLoading(false); 86 | }); 87 | }, 88 | onError: (err) => { 89 | toast.error(err?.error?.message ?? err?.message) 90 | }, 91 | }); 92 | 93 | const canOneClick = useMemo(() => { 94 | return claimAllData.length > 0 && !isLoadingAddressStatus && !loading; 95 | }, [claimAllData, isLoadingAddressStatus, loading]); 96 | 97 | const handleOneClick = () => { 98 | setLoading(true); 99 | writeAsync().then((tx) => { 100 | toast.success("交易发送成功\n" + `hash: ${tx.hash}`) 101 | }); 102 | }; 103 | 104 | return ( 105 |
106 |
111 | 114 |
115 |
116 | {data 117 | ? list.map((userInfo) => ( 118 | 123 | )) 124 | : ""} 125 |
126 |
127 | ); 128 | } 129 | -------------------------------------------------------------------------------- /src/helper.js: -------------------------------------------------------------------------------- 1 | import { utils } from "ethers"; 2 | import { getAddress, keccak256, solidityPack } from "ethers/lib/utils"; 3 | import { XenWitchInterface,contractAddress } from "./XenWitch"; 4 | const CACreationCode = [ 5 | "0x3d602d80600a3d3981f3363d3d373d3d3d363d73", 6 | "DaA6A0dAF1179780698e63671C0b23E8e344562A".toLowerCase(), 7 | "5af43d82803e903d91602b57fd5bf3", 8 | ].join(""); 9 | export function getContractAddress(address, count) { 10 | return utils.getAddress( 11 | `0x${keccak256( 12 | `0x${[ 13 | "ff", 14 | contractAddress, 15 | keccak256(solidityPack(["address", "uint256"], [address, count])), 16 | keccak256(CACreationCode), 17 | ] 18 | .map((x) => x.replace(/0x/, "")) 19 | .join("")}` 20 | ).slice(-40)}` 21 | ); 22 | } 23 | 24 | 25 | export const notification = { 26 | insert: "top", 27 | container: "top-right", 28 | animationIn: ["animate__animated animate__fadeIn"], // `animate.css v4` classes 29 | animationOut: ["animate__animated animate__fadeOut"], // `animate.css v4` classes 30 | dismiss: { 31 | duration: 5000, 32 | onScreen: true, 33 | }, 34 | }; 35 | const KEY = "2EiFzbjrGf6ELZQi9VMtoBQ88gf"; 36 | export const addressesSearcher = async (address, provider) => { 37 | const header = new Headers(); 38 | header.append("X-API-KEY", KEY); 39 | header.append("Content-Type", "application/json"); 40 | 41 | const txsList = []; 42 | let page = 1; 43 | while (page) { 44 | const result = await fetch( 45 | `https://api.chainbase.online/v1/account/txs?chain_id=1&address=${address}&contract_address=${contractAddress}&limit=100&page=${page}`, 46 | { 47 | method: "GET", 48 | headers: header, 49 | redirect: "follow", 50 | } 51 | ); 52 | const { data: txsData, next_page } = await result.json(); 53 | if (!txsData) break; 54 | page = next_page; 55 | txsList.push(...txsData); 56 | } 57 | 58 | const tasks = []; 59 | for (const tx of txsList) { 60 | tasks.push(provider.getTransactionReceipt(tx["transaction_hash"])); 61 | } 62 | 63 | const data = await Promise.all(tasks); 64 | const addresses = new Map(); 65 | 66 | // XenWitchInterface.decodeFunctionData('callAll',one.input) 67 | for (let i = 0; i < data.length; i++) { 68 | if (!txsList[i]["input"].startsWith("0x98f6264")) continue; 69 | const { calls } = XenWitchInterface.decodeFunctionData( 70 | "callAll", 71 | txsList[i]["input"] 72 | ); 73 | calls.map((call) => { 74 | addresses.set( 75 | getAddress(getContractAddress(address, call.id.toNumber())), 76 | call.id.toNumber() 77 | ); 78 | }); 79 | } 80 | return addresses; 81 | }; 82 | -------------------------------------------------------------------------------- /src/index.jsx: -------------------------------------------------------------------------------- 1 | import React,{ StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | 4 | import App from "./App"; 5 | 6 | const rootElement = document.getElementById("root"); 7 | const root = createRoot(rootElement); 8 | 9 | root.render( 10 | 11 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import { atom, selector } from "recoil"; 2 | export const GlobalAddresses = atom({ 3 | key: "GlobalAddresses", 4 | default: new Map(), 5 | }); 6 | 7 | export const GlobalAddressList = selector({ 8 | key: "GlobalAddressList", 9 | get: ({ get }) => { 10 | const map = get(GlobalAddresses); 11 | return [...map.keys()]; 12 | }, 13 | }); 14 | 15 | export const GlobalXENs = atom({ 16 | key: "GlobalXENs", 17 | default: [], 18 | }); 19 | 20 | export const MinDonate = atom({ 21 | key: "MinDonate", 22 | default: "0", 23 | }); 24 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | .App { 5 | font-family: sans-serif; 6 | text-align: center; 7 | } 8 | 9 | .big-text { 10 | font-size: 25px; 11 | } 12 | 13 | .center { 14 | display: flex; 15 | justify-content: center; 16 | } 17 | 18 | .bd { 19 | border: 1px solid gray; 20 | padding: 4px; 21 | } 22 | 23 | .card-list { 24 | margin-top: 20px; 25 | display: flex; 26 | flex-wrap: wrap; 27 | gap: 10px; 28 | justify-content: space-between; 29 | } 30 | 31 | body{ 32 | min-height: 100vh; 33 | height: 100%; 34 | } 35 | 36 | 37 | .card{ 38 | @apply bg-base-100 39 | } -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/**/*.{js,jsx,ts,tsx}", 5 | ], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [require("daisyui")], 10 | } 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import reactRefresh from '@vitejs/plugin-react-refresh' 3 | 4 | export default defineConfig({ 5 | plugins: [reactRefresh()] 6 | }) --------------------------------------------------------------------------------