TheDude 1 year ago
parent ea13f6c0e6
commit 17db97525b
  1. 7
      README.md
  2. 6
      index.html
  3. 5902
      package-lock.json
  4. 13
      package.json
  5. BIN
      public/assets/about.jpg
  6. 23489
      public/assets/js/walletConnect.js
  7. 9
      src/App.vue
  8. 1
      src/abi/DeprecateTldOne.json
  9. 1
      src/abi/DeprecateTldTwo.json
  10. 0
      src/abi/FlexiPunkTLD.json
  11. 0
      src/abi/PunkTLD.json
  12. 0
      src/abi/PunkTLDFactory.json
  13. 0
      src/abi/PunkTLDFactoryOld.json
  14. 0
      src/abi/PunkTLDOld.json
  15. 15
      src/abi/addresses.json
  16. 0
      src/abi/angel/AngelWhitelist.json
  17. 2
      src/abi/angel/PunkAngelMinter.json
  18. 0
      src/abi/angel/PunkAngelTraits.json
  19. 2
      src/abi/partners/huwa/HuwaMinter.json
  20. 1
      src/abi/partners/l2dao/L2DaoPunkDomains.json
  21. 1
      src/abi/partners/unstoppable/UDPolygonRefund.json
  22. 1
      src/abi/partners/wildbunch/WildBunchMinter.json
  23. 13
      src/abi/resolver.json
  24. 61
      src/abi/tlds.json
  25. 34
      src/abi/tokens.json
  26. BIN
      src/assets/angels/angels.gif
  27. BIN
      src/assets/anons/anons.gif
  28. BIN
      src/assets/anons/anons1.gif
  29. BIN
      src/assets/anons/nft.jpg
  30. BIN
      src/assets/architecture2.png
  31. 21
      src/assets/logo-white-300.svg
  32. 15
      src/assets/logo_white.svg
  33. 152
      src/components/FeaturedDomains.vue
  34. 18
      src/components/Footer.vue
  35. 34
      src/components/MyDomain.vue
  36. 2
      src/components/MyTlds.vue
  37. 39
      src/components/Navbar.vue
  38. 2
      src/components/Referral.vue
  39. 521
      src/components/SendTokensComponent.vue
  40. 8
      src/components/Sidebar.vue
  41. 18
      src/components/domainEdit/EditOtherData.vue
  42. 12
      src/components/domainEdit/EditPfp.vue
  43. 14
      src/components/domainEdit/EditUrl.vue
  44. 225
      src/hooks/useChainHelpers.ts
  45. 38
      src/index.css
  46. 9
      src/main.ts
  47. 69
      src/router.ts
  48. 4
      src/store/index.ts
  49. 137
      src/store/modules/network.ts
  50. 6
      src/store/modules/punk.ts
  51. 12
      src/store/modules/user.ts
  52. 79
      src/views/About.vue
  53. 12
      src/views/BrowserExtension.vue
  54. 23
      src/views/DomainDetails.vue
  55. 2
      src/views/Error404.vue
  56. 18
      src/views/Home.vue
  57. 69
      src/views/HowItWorks.vue
  58. 4
      src/views/Profile.vue
  59. 25
      src/views/ProfileSendTokens.vue
  60. 2
      src/views/SearchDomains.vue
  61. 509
      src/views/SendTokens.vue
  62. 4
      src/views/TldBuy.vue
  63. 4
      src/views/TldDetails.vue
  64. 6
      src/views/TransferDomain.vue
  65. 417
      src/views/deprecate/DeprecatePolygon.vue
  66. 425
      src/views/deprecate/DeprecateWeb3.vue
  67. 118
      src/views/nft/PunkAngelMint.vue
  68. 32
      src/views/nft/PunkAngelNft.vue
  69. 31
      src/views/partners/Huwa.vue
  70. 296
      src/views/partners/L2Dao.vue
  71. 233
      src/views/partners/MisieAdmin.vue
  72. 343
      src/views/partners/UnstoppablePolygonRefund.vue
  73. 331
      src/views/partners/WildBunch.vue
  74. 27
      vite.config.ts
  75. 3915
      yarn.lock

@ -1,6 +1,6 @@
# Degen Domain Name Service
# DegenDNS - frontend
DegenDNS - Domains for Web3 Degens
Degen Domains - Domains for Degens
https://degendomains.io
@ -28,6 +28,3 @@ VITE_ALCHEMY_ETHEREUM_KEY=value
Develop on the `develop` branch (or a temporary branch which is then merged to develop). Never develop directly on the `main` branch.
When you want to push your changes to production, merge `develop` branch into the `main` branch.
- Development server: https://degen-domains-develop.netlify.app/
- Production server: https://degendomains.io/

@ -15,7 +15,7 @@
<meta name="description" content="DegenDNS is a Web3 Domain Name Service with top-level domains (.pepe, .ben, .meme etc.) on multiple blockchains.">
<meta name="keywords" content="web3, domains, domain, DNS, TLD, blockchain, crypto, ethereum, polygon, arbitrum, binance, chain">
<meta name="author" content="DegenDomains">
<meta name="author" content="Cipher Labs">
<meta property="og:title" content="DegenDNS - Domains for Degens" />
<meta property="og:description" content="DegenDNS is a Web3 Domain Name Service with top-level domains (.pepe, .ben, .meme etc.) on multiple blockchains." />
@ -25,9 +25,11 @@
<meta name="twitter:site" content="@Degen_DNS">
<meta name="twitter:creator" content="@Degen_DNS">
<meta name="twitter:title" content="DegenDNS - Domains for Degens">
<meta name="twitter:description" content="DegenDNS is a Web3 Domain Name Service with top-level domains (.pepe, .ben, .meme etc.) running on multiple blockchains.">
<meta name="twitter:description" content="DegenDNS is a Web3 Domain Name Service with top-level domains (.pepe, .ben, .meme etc.) on multiple blockchains.">
<meta name="twitter:image" content="https://degendomains.io/assets/cover.png">
<!-- Google tag (gtag.js) -->
</head>
<body>
<div id="app"></div>

5902
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
{
"name": "degen-domains-frontend",
"name": "punk-domains-frontend",
"version": "1.0.0",
"scripts": {
"dev": "vite",
@ -7,10 +7,8 @@
"serve": "vite preview"
},
"dependencies": {
"@popperjs/core": "^2.11.5",
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.7.2",
"buffer": "^6.0.3",
"ethers": "^5.6.9",
"vue": "^3.2.16",
"vue-dapp": "^0.4.2",
@ -21,13 +19,6 @@
"devDependencies": {
"@vitejs/plugin-vue": "^1.9.2",
"typescript": "^4.4.3",
"vite": "^2.8.0",
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
"@rollup/plugin-inject": "^4.0.4",
"svelte": "^3.44.0",
"svelte-check": "^2.2.7",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
"svelte-preprocess": "^4.9.8",
"util": "^0.12.4"
"vite": "^2.6.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

File diff suppressed because one or more lines are too long

@ -1,4 +1,5 @@
<template>
<Navbar />
<div class="main-container">
@ -18,7 +19,7 @@ import { mapActions, mapGetters, mapMutations } from 'vuex';
import Navbar from './components/Navbar.vue';
import Footer from './components/Footer.vue';
import tldsJson from './abi/tlds.json';
import tldAbi from './abi/DegenTLD.json';
import tldAbi from './abi/PunkTLD.json';
export default {
components: {
@ -30,12 +31,12 @@ export default {
this.fetchReferrer();
// reset localstorage
const v2 = localStorage.getItem("degenv2");
const v2 = localStorage.getItem("punkv2");
if (!v2) {
localStorage.clear();
localStorage.setItem("connected", "null");
localStorage.setItem("degenv2", "true");
localStorage.setItem("punkv2", "true");
}
},
@ -45,7 +46,7 @@ export default {
},
methods: {
...mapActions("degen", ["fetchTlds"]),
...mapActions("punk", ["fetchTlds"]),
...mapActions("user", ["fetchUserDomainNames"]),
...mapMutations("user", ["setUserData"]),

@ -0,0 +1 @@
[{"inputs":[{"internalType":"uint256","name":"_refundAmount","type":"uint256"},{"internalType":"address","name":"_deprecatedTld","type":"address"},{"internalType":"string","name":"_altTldName","type":"string"},{"internalType":"address","name":"_altTldAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"user","type":"address"},{"indexed":true,"internalType":"string","name":"domainName","type":"string"}],"name":"RefundClaimed","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"string","name":"_tldName","type":"string"},{"internalType":"address","name":"_tldAddress","type":"address"}],"name":"addAltTld","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_notEligibleDomains","type":"uint256[]"}],"name":"addNonEligibleDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"altTld","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRefundAmount","type":"uint256"}],"name":"changeRefundAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deprecatedTld","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isNotRefundEligible","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_oldDomainName","type":"string"},{"internalType":"string","name":"_newDomainName1","type":"string"},{"internalType":"string","name":"_altTldName1","type":"string"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_tldName","type":"string"}],"name":"removeAltTld","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_notEligibleDomains","type":"uint256[]"}],"name":"removeNonEligibleDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

@ -0,0 +1 @@
[{"type":"constructor","inputs":[{"type":"uint256","name":"_refundAmount","internalType":"uint256"},{"type":"address","name":"_deprecatedTld","internalType":"address"},{"type":"string","name":"_altTldName","internalType":"string"},{"type":"address","name":"_altTldAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addAltTld","inputs":[{"type":"string","name":"_tldName","internalType":"string"},{"type":"address","name":"_tldAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addNonEligibleDomains","inputs":[{"type":"uint256[]","name":"_notEligibleDomains","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"altTld","inputs":[{"type":"string","name":"","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeRefundAmount","inputs":[{"type":"uint256","name":"_newRefundAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"deprecatedTld","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isNotRefundEligible","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverERC20","inputs":[{"type":"address","name":"tokenAddress_","internalType":"address"},{"type":"uint256","name":"tokenAmount_","internalType":"uint256"},{"type":"address","name":"recipient_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverERC721","inputs":[{"type":"address","name":"tokenAddress_","internalType":"address"},{"type":"uint256","name":"tokenId_","internalType":"uint256"},{"type":"address","name":"recipient_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"refund","inputs":[{"type":"string","name":"_oldDomainName","internalType":"string"},{"type":"string","name":"_newDomainName1","internalType":"string"},{"type":"string","name":"_altTldName1","internalType":"string"},{"type":"string","name":"_newDomainName2","internalType":"string"},{"type":"string","name":"_altTldName2","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"refundAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeAltTld","inputs":[{"type":"string","name":"_tldName","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeNonEligibleDomains","inputs":[{"type":"uint256[]","name":"_notEligibleDomains","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"togglePaused","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false},{"type":"event","name":"RefundClaimed","inputs":[{"type":"address","name":"user","indexed":true},{"type":"string","name":"domainName","indexed":true}],"anonymous":false},{"type":"receive"},{"type":"fallback"}]

@ -1,18 +1,19 @@
{
"DegenTLDFactory": {
"PunkTLDFactory": {
"3": "0xbb056744bB2Ab473058ED7F3e1764FCf4Bb1313D",
"4": "0x844d982FDc1F5C8eaD82E95d522F2486a7CBb3EE",
"10": "0xA8221890768603210c1a32d88374111084E46E6d",
"56": "0xTODO",
"14": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a",
"19": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a",
"69": "0x0F081cad5BCed7B2acA1c1D22CdafcB21322B280",
"77": "0xf6A44f61030115B5dA382b198B711130D98390d9",
"97": "0xTODO",
"100": "0xA8221890768603210c1a32d88374111084E46E6d",
"137": "0xB6cf67a0aCE92F357908C6eF716a34c9b196c1DC",
"568": "0xTODO",
"2000": "0xTODO",
"80001": "0xC74f279E5A7FDAd6624054518773ae4EC77E78D3",
"250": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a",
"4002": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a",
"80001": "0x8fbff791fCcF596DEf2e788549d0275557F95A21",
"42161": "0x4bD57a848c56E6241296a1256FB2bDEbCdbb9dB0",
"421611": "0x844d982FDc1F5C8eaD82E95d522F2486a7CBb3EE"
"421611": "0x844d982FDc1F5C8eaD82E95d522F2486a7CBb3EE",
"1313161555": "0x2f5cd4366c16AFC3b04A4b2327BbFf9e3955dbC1"
}
}

File diff suppressed because one or more lines are too long

@ -1 +1 @@
[{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_tldAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"price_","type":"uint256"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"referral_","type":"uint256"}],"name":"ReferralChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"royalty_","type":"uint256"}],"name":"RoyaltyChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"changePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referral","type":"uint256"}],"name":"changeReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royalty","type":"uint256"}],"name":"changeRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_domainHolder","type":"address"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tldContract","outputs":[{"internalType":"contract IFlexiDegenTLD","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
[{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_tldAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"price_","type":"uint256"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"referral_","type":"uint256"}],"name":"ReferralChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"royalty_","type":"uint256"}],"name":"RoyaltyChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"changePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referral","type":"uint256"}],"name":"changeReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royalty","type":"uint256"}],"name":"changeRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_domainHolder","type":"address"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tldContract","outputs":[{"internalType":"contract IFlexiPunkTLD","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

@ -0,0 +1 @@
[{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_tldAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":[{"internalType":"address","name":"_nftAddress","type":"address"}],"name":"addWhitelistedNftContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"canUserMint","outputs":[{"internalType":"bool","name":"canMint","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLength","type":"uint256"}],"name":"changeMaxDomainNameLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_description","type":"string"}],"name":"changeTldDescription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"changeTldPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referral","type":"uint256"}],"name":"changeTldReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getSupportedNftsArray","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedNftsArrayLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_nftTokenId","type":"uint256"}],"name":"isNftIdAlreadyUsed","outputs":[{"internalType":"bool","name":"used","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"minted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_domainHolder","type":"address"}],"name":"ownerMintDomain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nftIndex","type":"uint256"}],"name":"removeWhitelistedNftContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedNfts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tldAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTldOwner","type":"address"}],"name":"transferTldOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

@ -0,0 +1 @@
[{"inputs":[{"internalType":"address","name":"_tldAddress","type":"address"},{"internalType":"uint256","name":"_refund","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"user","type":"address"},{"indexed":true,"internalType":"string","name":"domainName","type":"string"}],"name":"RefundClaimed","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"canClaimRefund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"domainName","type":"string"}],"name":"claimRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"domainNames","type":"string[]"}],"name":"claimRefundBulk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tldContract","outputs":[{"internalType":"contract PunkTLD","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

@ -0,0 +1 @@
[{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_tldAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_domainHolder","type":"address"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenAmount_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"recipient_","type":"address"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tldContract","outputs":[{"internalType":"contract IFlexiPunkTLD","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

@ -1,14 +1,17 @@
{
"1": "0x985ecBD12566dD8BC05F4Df96729Ee84dE67F519",
"10": "0xF20fc12a4955c9d47194B8fEd591Fe01777D2b06",
"14": "0x2919f0bE09549814ADF72fb0387D1981699fc6D4",
"19": "0x7e8aB50697C7Abe63Bdab6B155C2FB8D285458cB",
"56": "0x4aBf8b364ac4aF048Ea077AAA2EDF3e1e1EC0f9c",
"69": "0xa1303d259B87f044404536638E2784DEe897B402",
"77": "0x7A84e7f48DCe4ab212c3511eC5ade0982eaBa8c4",
"97": "0xTODO",
"100": "0x7Df67B2ef4eEDf49Fc53Bb6E94e90e9546FC6c6B",
"137": "0x07884566cdED43eDaec7813C1523624202b060D3",
"568": "0xTODO",
"2000": "0xTODO",
"80001": "0xC17E9347Ce26D7630A98eC4158Bd7200E54bf4Cd",
"250": "0xa97c7AF10ee564EBf452A9347bB9653454Ba69C0",
"4002": "0xa97c7AF10ee564EBf452A9347bB9653454Ba69C0",
"80001": "0x24799a4AF8e5215Dfe22054ffF91B0A1C428D1A3",
"42161": "0xd64A2DF9d73CD1Cb50139A3eC3176070e00C67cA",
"421611": "0xe2b9bC4c1d65B5F5583144d9d5c5F0683158C372"
"421611": "0xe2b9bC4c1d65B5F5583144d9d5c5F0683158C372",
"1313161555": "0x4aBf8b364ac4aF048Ea077AAA2EDF3e1e1EC0f9c"
}

@ -1,20 +1,25 @@
{
"1": {
".pepe": "0xC3E8922657686EC63eaaa9FC1Fe06826802e7e0f",
".ben": "0xC3E8922657686EC63eaaa9FC1Fe06826802e7e0f",
".turbo": "0xC3E8922657686EC63eaaa9FC1Fe06826802e7e0f"
".wildbunch": "0xaa9E5Ade68C9C3Ea967Dc5dde731fd1f797152Cb"
},
"10": {
".wagmi": "0xC3E8922657686EC63eaaa9FC1Fe06826802e7e0f",
".l2": "0x9A7657d1593032C75d70950707870c3cC7ca45DC",
".op": "0xC16aCAdf99E4540E6f4E6Da816fd6D2A2C6E1d4F",
".optimism": "0xBca24d86e4Ad1e011278FaEFc4fF191a731411EC",
".spartan": "0x3490C9817C45A2a394b11A3807f58a8325235aE0"
".spartan": "0x3490C9817C45A2a394b11A3807f58a8325235aE0",
".pool": "0xf2C9E463592BD440f0D422E944E5F95c79404586"
},
"14": {
".flr": "0xBDACF94dDCAB51c39c2dD50BffEe60Bb8021949a"
},
"19": {
".sgb": "0xBDACF94dDCAB51c39c2dD50BffEe60Bb8021949a",
".satrap": "0xeFBE0b46649B7A0F1e1D49CCa98aD9CF6bcFB096"
},
"56": {
".meme": "0xBDACF94dDCAB51c39c2dD50BffEe60Bb8021949a"
".safu": "0xBDACF94dDCAB51c39c2dD50BffEe60Bb8021949a",
".huwa": "0xeFBE0b46649B7A0F1e1D49CCa98aD9CF6bcFB096"
},
"69": {
".optitest": "0xAc63b035e63d280c408549f5AFA64be7469470de",
@ -24,47 +29,57 @@
"77": {
".testdao": "0x110cc3f64cdf8ffadc785dfa53906bcff76b3846"
},
"97": {
".bsctest": "0xTODO"
},
"100": {
".gnosis": "0xC3E8922657686EC63eaaa9FC1Fe06826802e7e0f",
".xdai": "0xbca24d86e4ad1e011278faefc4ff191a731411ec",
".bright": "0x3490c9817c45a2a394b11a3807f58a8325235ae0"
".bright": "0x3490c9817c45a2a394b11a3807f58a8325235ae0",
".giveth": "0xEEa3e593CDAf9D18780f9D58BAD142AF6Bd9522a"
},
"137": {
".crew": "0xTODO",
".poly": "0x70Ac07C50131b7bb2c8Bd9466D8d2add30B7759f",
".ape": "0x794a8390D94E32b086908D2bA9D66300aA163C62",
".degen": "0xC4999A3e91ef87c9EC5d8186D02B77F9A62458b9",
".web3": "0xb6Cf2874588d0fdFAf9d1b5E254ee6C49110C68B",
".klima": "0xe8b97542A433e7eCc7bB791872af04DF02A1a6E4",
".basin": "0x4bF5A99eA2F8De061f7D77BA9edd749503D945Da",
".polygon": "0xa450bc33d0940d25fB0961c592fb440Fa63ABE03"
},
"568": {
".testdoge": "0xTODO"
"250": {
".fantom": "0xbdacf94ddcab51c39c2dd50bffee60bb8021949a"
},
"2000": {
".doge": "0xTODO",
".yode": "0xTODO"
"324": {
".zksoul": "0xe36507aD67Ac0aE6D27D22b407A9338b136315df"
},
"4002": {
".testfantom": "0xbdacf94ddcab51c39c2dd50bffee60bb8021949a"
},
"80001": {
".d3g3n": "0x841Caa03f076fB37E66c496FA777453da1E36BFf",
".testsafu": "0x755F461d6a5854203b9B30C76f680356cC67556D",
".newflexi": "0xd3CEdCfAa00de70DB408528351665c55E1fFA603",
".freytest": "0x71C60ebce37cd6ee27807D5285b1acf9752e17Ee",
".testpoly": "0x4fd04c33E692B967F663B75A1976a1671E93B4dd",
".testanon": "0xBF113092d7ceabB5b891C4B232C910CDF2153AC5"
".testangel": "0xBF113092d7ceabB5b891C4B232C910CDF2153AC5"
},
"42161": {
".arbi": "0xe97456E0fB121F65422F43ccbd4A07a0e269B534",
".arbitrum": "0x337EB5061943ECd247649d58D35Dbab0b40D67E0",
".aidoge": "0xE0d972817e94c5FF9BDc49a63d8927A0bA833E4f",
".mumu": "0xcC66213645474a7B61BAf95330D01e50789eaF4b"
".smol": "0xE0d972817e94c5FF9BDc49a63d8927A0bA833E4f",
".punkangel": "0xcC66213645474a7B61BAf95330D01e50789eaF4b",
".misie": "0x526Ff108F5d422d0e1d6650E2Bc015BBE1fdb058",
".ppl": "0xbC9d19e5f97a572f428F7292DBf3dc182Cc05C82"
},
"421611": {
".fltestarbi": "0x396E60B4c971b053A2959296646B2eA5DD1f2160",
".smoltest": "0x0eB60B697428597CE58650173eFEd2F32ADD7E93",
".twbtest": "0xEEAEED736cc6A6e68CC2F62be19Cf7E06ad9E94A",
".testcrew": "0x49651e70df13b8fd5684B0b82b1b3D7Cdc8cF80f",
".testhuwa": "0x49651e70df13b8fd5684B0b82b1b3D7Cdc8cF80f",
".arbitest": "0xC6a628b1FF1aD4e304bEeACAff915559786deA2e",
".anontest": "0x61c567b26eB1B1965A1bD49febE1C1997237C519"
".angeltest": "0x61c567b26eB1B1965A1bD49febE1C1997237C519"
},
"421613": {
".testoasis": "0xBDACF94dDCAB51c39c2dD50BffEe60Bb8021949a"
},
"1313161555": {
".testrora": "0x4087fb91a1fbdef05761c02714335d232a2bf3a1"
}
}

@ -1,8 +1,6 @@
{
"1": {
"ETH": "0x0",
"PEPE": "0x6982508145454ce325ddbe47a25d4ec3d2311933",
"BEN": "0x9bf1d7d63dd7a4ce167cf4866388226eeefa702e"
"ETH": "0x0"
},
"3": {
"ETH": "0x0"
@ -15,13 +13,19 @@
"sUSD": "0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9",
"SNX": "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4"
},
"14": {
"FLR": "0x0"
},
"19": {
"SGB": "0x0"
},
"56": {
"BNB": "0x0",
"ETH": "0x2170ed0880ac9a755fd29b2688956bd959f933f8",
"USDC": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
"WBNB": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
"BUSD": "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56",
"CREW": "0x03a2A7E95eCe3112b8d33F9bCC21F0c9BA843e35"
"HUWA": "0x03a2A7E95eCe3112b8d33F9bCC21F0c9BA843e35"
},
"69": {
"ETH": "0x0",
@ -31,13 +35,6 @@
"77": {
"SPOA": "0x0"
},
"97": {
"BNB": "0x0",
"ETH": "0x8babbb98678facc7342735486c851abd7a0d17ca",
"USDT": "0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684",
"WBNB": "0xae13d989dac2f0debff460ac112a837c89baa7cd",
"BUSD": "0x78867BbEeF44f2326bF8DDd1941a4439382EF2A7"
},
"100": {
"XDAI": "0x0",
"USDC": "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83",
@ -53,18 +50,11 @@
"DAI": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
"USDC": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
},
"568": {
"DOGE": "0x0",
"ETH": "0xTODAO",
"DAI": "0xTODO",
"USDC": "0xTODO"
"250": {
"FTM": "0x0"
},
"2000": {
"DOGE": "0x0",
"WDOGE": "0xb7ddc6414bf4f5515b52d8bdd69973ae205ff101",
"ETH": "0xb44a9b6905af7c801311e8f4e76932ee959c663c",
"BUSD": "0x332730a4f6e03d9c55829435f10360e13cfa41ff",
"USDC": "0x765277eebeca2e31912c9946eae1021199b39c61"
"4002": {
"FTM": "0x0"
},
"80001": {
"MATIC": "0x0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="34.348 16.797 238.87 271.74" width="238.87" height="271.74">
<g enable-background="new" transform="matrix(1.729551, 0, 0, 1.729551, -99.430664, -49.282986)" style="">
<g id="Layer-1" data-name="Layer">
<clipPath id="cp0">
<path transform="matrix(1,0,0,-1,0,283.465)" d="M 0 283.465 L 283.465 283.465 L 283.465 0 L 0 0 Z "></path>
</clipPath>
<g clip-path="url(#cp0)">
<path
transform="matrix(1,0,0,-1,100.9067,85.6357)"
d="M 0 0 C .105 .107 .201 .22 .307 .326 C 2.755 2.776 5.401 4.907 8.193 6.719 C 26.725 18.744 51.706 16.712 68.066 .636 C 86.548 -18.206 86.414 -48.431 67.719 -67.141 C 67.613 -67.248 67.59 -67.262 67.483 -67.367 C 67.483 -67.367 90.607 -90.355 90.732 -90.414 C 86.161 -81.059 79.218 -68.579 74.779 -59.343 C 85.139 -59.685 99.695 -59.853 110.106 -60.055 C 101.48 -53.653 90.139 -45.447 81.875 -39.027 C 91.307 -34.72 105.055 -28.543 114.553 -24.272 C 104.311 -22.116 89.834 -19.621 79.493 -17.625 C 86.126 -10.012 96.023 1.912 102.626 9.894 C 92.551 7.299 78.203 3.409 68.081 .65 C 70.939 10.781 74.614 25.553 77.153 35.568 C 69.229 28.807 57.681 18.661 49.822 12.073 C 48.031 22.067 45.177 37.32 43.088 47.429 C 38.72 37.922 32.64 23.948 28.438 14.458 C 22.278 22.728 13.505 34.793 7.171 43.318 C 7.474 32.906 7.802 17.796 8.14 7.354 C -1.087 12.103 -14.293 19.169 -23.558 23.775 C -23.499 23.65 0 0 0 0 "
fill="#fff">
</path>
<path
transform="matrix(1,0,0,-1,107.9644,195.3227)"
d="M 0 0 L -15.751 15.751 L -15.754 77.163 C -15.453 100.597 3.853 119.653 27.281 119.653 C 51.014 119.653 70.323 100.344 70.323 76.61 C 70.323 53.03 51.14 33.722 27.562 33.569 L 27.213 33.567 L 27.213 33.58 L 19.371 33.563 L 19.423 83.439 L 35.126 67.735 L 35.129 50.479 C 46.578 53.915 54.565 64.646 54.565 76.61 C 54.565 91.655 42.326 103.895 27.281 103.895 C 12.59 103.895 .357 91.946 .011 77.258 L 0 76.919 Z "
fill="#fff">
</path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="283.465pt" height="283.465pt" viewBox="0 0 283.465 283.465">
<g enable-background="new">
<g id="Layer-1" data-name="Layer">
<clipPath id="cp0">
<path transform="matrix(1,0,0,-1,0,283.465)" d="M 0 283.465 L 283.465 283.465 L 283.465 0 L 0 0 Z "/>
</clipPath>
<g clip-path="url(#cp0)">
<path transform="matrix(1,0,0,-1,100.9067,85.6357)" d="M 0 0 C .105 .107 .201 .22 .307 .326 C 2.755 2.776 5.401 4.907 8.193 6.719 C 26.725 18.744 51.706 16.712 68.066 .636 C 86.548 -18.206 86.414 -48.431 67.719 -67.141 C 67.613 -67.248 67.59 -67.262 67.483 -67.367 C 67.483 -67.367 90.607 -90.355 90.732 -90.414 C 86.161 -81.059 79.218 -68.579 74.779 -59.343 C 85.139 -59.685 99.695 -59.853 110.106 -60.055 C 101.48 -53.653 90.139 -45.447 81.875 -39.027 C 91.307 -34.72 105.055 -28.543 114.553 -24.272 C 104.311 -22.116 89.834 -19.621 79.493 -17.625 C 86.126 -10.012 96.023 1.912 102.626 9.894 C 92.551 7.299 78.203 3.409 68.081 .65 C 70.939 10.781 74.614 25.553 77.153 35.568 C 69.229 28.807 57.681 18.661 49.822 12.073 C 48.031 22.067 45.177 37.32 43.088 47.429 C 38.72 37.922 32.64 23.948 28.438 14.458 C 22.278 22.728 13.505 34.793 7.171 43.318 C 7.474 32.906 7.802 17.796 8.14 7.354 C -1.087 12.103 -14.293 19.169 -23.558 23.775 C -23.499 23.65 0 0 0 0 " fill="#ffffff"/>
<path transform="matrix(1,0,0,-1,107.9644,195.3227)" d="M 0 0 L -15.751 15.751 L -15.754 77.163 C -15.453 100.597 3.853 119.653 27.281 119.653 C 51.014 119.653 70.323 100.344 70.323 76.61 C 70.323 53.03 51.14 33.722 27.562 33.569 L 27.213 33.567 L 27.213 33.58 L 19.371 33.563 L 19.423 83.439 L 35.126 67.735 L 35.129 50.479 C 46.578 53.915 54.565 64.646 54.565 76.61 C 54.565 91.655 42.326 103.895 27.281 103.895 C 12.59 103.895 .357 91.946 .011 77.258 L 0 76.919 Z " fill="#ffffff"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -0,0 +1,152 @@
<template>
<div class="container text-center">
<h3>Featured Degen Domains</h3>
<div class="row mt-4">
<div class="col-2 mb-3">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.pepe
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.ben
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.mong
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.turbo
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.psyop
</p>
</div>
</a>
</div>
<div class="col-2">
<router-link tag="a" to="">
<div class="container text-center">
<p class="text-break mt-3">
.bob
</p>
</div>
</router-link>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.meme
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.apefi
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.ganja
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.aidoge
</p>
</div>
</a>
</div>
<div class="col-2">
<a target="_blank" href="">
<div class="container text-center">
<p class="text-break mt-3">
.dons
</p>
</div>
</a>
</div>
<div class="col-2">
<router-link tag="a" to="">
<div class="container text-center">
<p class="text-break mt-3">
.trump
</p>
</div>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'FeaturedDomains'
}
</script>
<style scoped>
a {
text-decoration: none;
font-size: 1.2em;
}
a:active {
transform: scale(0.8);
}
a:hover {
border-color: white;
opacity: 0.8;
font-size: 1.4em;
}
</style>

@ -12,8 +12,12 @@
<span> | </span>
<router-link to="/profile">Affiliates</router-link>
<router-link to="/profile">Affiliates</router-link>
<span> | </span>
<a target="_blank" href="">For Projects</a>
</div>
<div class="container-fluid text-center">
@ -22,11 +26,15 @@
<a class="icons" target="_blank" href="https://git.cipherlabs.org/DegenDNS"><i class="bi bi-github"></i></a>
<a class="icons" target="_blank" href="https://twitter.com/Degen_DNS"><i class="bi bi-twitter"></i></a>
</div>
<div class="container-fluid text-center">
<a href="https://alchemy.com/?r=308828085a2bd8cc" target="_blank">
<img id="badge-button" style="height:43px" src="https://static.alchemyapi.io/images/marketing/badge.png" alt="Alchemy Supercharged" />
</a>
</div>
</template>
<script>
@ -76,7 +84,7 @@ a:hover {
}
.polygon svg circle {
fill: #DBDFEA;
fill: #fff;
}
.polygon:hover svg circle {

@ -2,7 +2,7 @@
<td>
<span>{{domain}}</span>
</td>
<td>
<td v-if="!isDeprecatedWeb3 && !isDeprecatedPolygon">
<span
class="text-click"
@click="this.$router.push({name: 'DomainDetails', params: {domainChain: getChainId, tld: domain.split('.')[1], domainName: domain.split('.')[0]}})"
@ -10,6 +10,22 @@
Edit domain data
</span>
</td>
<td v-if="isDeprecatedWeb3">
<span
class="text-click"
@click="this.$router.push({name: 'DeprecateWeb3'})"
>
Deprecated. Claim refund here.
</span>
</td>
<td v-if="isDeprecatedPolygon">
<span
class="text-click"
@click="this.$router.push({name: 'DeprecatePolygon'})"
>
Deprecated. Claim refund here.
</span>
</td>
<td>
<span
class="text-click"
@ -43,6 +59,22 @@ export default {
computed: {
...mapGetters("network", ["getChainId"]),
...mapGetters("user", ["getUserSelectedName"]),
isDeprecatedPolygon() {
if (this.domain.endsWith(".polygon")) {
return true;
} else {
return false;
}
},
isDeprecatedWeb3() {
if (this.domain.endsWith(".web3")) {
return true;
} else {
return false;
}
}
},
methods: {

@ -44,7 +44,7 @@ export default {
computed: {
...mapGetters("network", ["getChainId"]),
...mapGetters("degen", ["getTlds", "getTldAddresses", "getTldAbi"]),
...mapGetters("punk", ["getTlds", "getTldAddresses", "getTldAbi"]),
},
methods: {

@ -2,8 +2,8 @@
<nav class="navbar sticky-top navbar-expand-lg navbar-dark">
<div class="container-fluid">
<router-link to="/" class="navbar-brand">
<img src="../assets/logo.png" alt="WEB3 DOMAINS" width="120" class="d-inline-block navbar-img">
DEGEN DOMAIN NAME SERVICE
<img src="../assets/logo.png" alt="Web3 Domains" width="120" class="d-inline-block navbar-img">
DEGEN DOMAINS
</router-link>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
@ -13,10 +13,30 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<div class="d-flex ms-auto">
<div v-if="isActivated" class="navbar-menu-buttons">
<div class="navbar-menu-buttons">
<div class="btn-group mx-2 navbar-menu-btn navbar-other-item">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton2" data-bs-toggle="dropdown" aria-expanded="false">
Partners
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton2">
<router-link tag="li" class="dropdown-item" to="">HappyGanjaClub (.Ganja SOON)</router-link>
<router-link tag="li" class="dropdown-item" to="">LangDAO (.LangDAO SOON)</router-link>
</ul>
</div>
<!--
<div class="btn-group mx-2 navbar-menu-btn navbar-other-item">
<router-link tag="button" class="btn btn-primary" to="/buy-tld">Buy a TLD</router-link>
</div>
-->
<div v-if="isActivated" class="btn-group mx-2 navbar-menu-btn">
<router-link tag="button" class="btn btn-primary" to="/send-tokens">Send Tokens</router-link>
</div>
<div class="btn-group mx-2 navbar-menu-btn">
<div v-if="isActivated" class="btn-group mx-2 navbar-menu-btn">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
{{getNetworkName}}
</button>
@ -42,13 +62,14 @@
<router-link tag="li" class="dropdown-item" to="/search-domain">Search domain</router-link>
<router-link tag="li" class="dropdown-item" to="/send-tokens">Send tokens</router-link>
<router-link tag="li" class="dropdown-item" to="/profile">Affiliates</router-link>
<router-link tag="li" class="dropdown-item" to="/browser">Browser extension</router-link>
<li class="dropdown-item" @click="openUrl('http://docs.degendomains.io')">Docs</li>
<li class="dropdown-item" @click="logout">Disconnect</li>
</ul>
</div>
</div>
<button v-else class="btn btn-primary" @click="open">Connect wallet</button>
<button v-if="!isActivated" class="btn btn-primary" @click="open">Connect wallet</button>
</div>
</div>
@ -119,14 +140,18 @@ export default {
.navbar-brand {
font-family: 'Panda-font', cursive;
font-size: 50px;
}
.navbar-dark .navbar-brand {
color: #DBDFEA;
color: #fff;
}
.navbar-dark {
background: rgb(63,94,251);
background: #1488CC; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #2B32B2, #1488CC); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #2B32B2, #1488CC); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
border-radius: 0px 0px 10px 10px;
padding: 20px;

@ -2,7 +2,7 @@
<div class="row">
<div class="col-md-12 mt-3">
<div class="container text-center">
<h3>Affiliates</h3>
<h3>Referrals</h3>
<p>
Share this referral link and earn rewards from new domain mints!

@ -0,0 +1,521 @@
<template>
<div class="container text-center">
<h3>Send tokens to a domain</h3>
<!-- Recipient -->
<div class="row mt-5">
<div class="col-md-6 offset-md-3">
<input
v-model="receiver"
class="form-control text-center border-2 border-light"
placeholder="Enter the receiver's domain name"
>
</div>
</div>
<!-- Tokens -->
<div class="row mt-4">
<div class="col-md-4 offset-md-4">
<div class="input-group">
<input
type="text"
class="form-control text-end border-2 border-end-0 border-light"
v-model="tokenAmount"
placeholder="0.0"
/>
<button
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{{selectedToken}}
</button>
<div class="dropdown-menu p-2">
<div class="mb-3">
<input
class="form-control mb-2"
placeholder="Filter tokens"
v-model="filterTokens"
/>
<li>
<button
class="dropdown-item"
type="button"
:key="token"
v-for="token in getTokenNames"
@click="selectToken(token)"
>{{token}}</button>
</li>
</div>
</div>
</div>
<small>
Balance:
<span id="balance" @click="tokenAmount=tokenBalance">{{formatTokenBalance}} {{selectedToken}}</span>
</small>
</div>
</div>
<button
class="btn btn-primary mt-4 mb-5"
:disabled="notValid || waiting"
@click="validateDomainName"
data-bs-toggle="modal" data-bs-target="#sendTokensModal"
>
<span v-if="waiting" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Send tokens
</button>
</div>
<!-- Send tokens modal -->
<div v-if="selectedToken" class="modal fade text-start" id="sendTokensModal" tabindex="-1" aria-labelledby="sendTokensModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="sendTokensModalLabel">Confirm sending {{selectedToken}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>
Please review the data before you send {{selectedToken}} to {{domainLowerCase}}.
</p>
<div class="row mb-3 mt-4">
<div class="col-sm-3">
<strong>Recipient</strong>
</div>
<div class="col-sm-9">
<span>{{domainLowerCase}}</span>
<span class="domain-error" v-if="domainError">Error: {{domainError}}</span>
</div>
</div>
<div class="row mb-3 mt-2" v-if="receiverAddress">
<div class="col-sm-3">
<strong>Recipient address</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{receiverAddress}}</span>
<span class="domain-error" v-if="receiverAddress == address">Error: You are sending tokens to yourself.</span>
</div>
</div>
<div class="row mb-3 mt-2">
<div class="col-sm-3">
<strong>Amount</strong>
</div>
<div class="col-sm-9">
<span v-if="selectedToken" class="text-break">{{tokenAmount}} {{selectedToken}}</span>
</div>
</div>
<div class="row mb-3 mt-2" v-if="getTokens[selectedToken] !== '0x0'">
<div class="col-sm-3">
<strong>Token address</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{getTokens[selectedToken]}}</span>
</div>
</div>
<div class="row mb-3 mt-2">
<div class="col-sm-3">
<strong>Network</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{getNetworkName}}</span>
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
@click="send"
:disabled="waiting || domainError || validating"
>
<span v-if="validating">Validating...</span>
<span v-if="validating" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span v-if="!validating">Send {{selectedToken}}</span>
</button>
<button id="closeSendModal" type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { ethers } from 'ethers';
import { mapGetters } from 'vuex';
import { useEthers } from 'vue-dapp';
import { useToast, TYPE } from "vue-toastification";
import Erc20Abi from "../abi/Erc20.json";
import tldsJson from '../abi/tlds.json';
import tldAbi from '../abi/PunkTLD.json';
import WaitingToast from "../components/toasts/WaitingToast.vue";
import useChainHelpers from "../hooks/useChainHelpers";
export default {
name: "SendTokensComponent",
data() {
return {
domainError: null,
filterTokens: null,
receiver: null,
receiverAddress: null,
tokenBalance: 0, // max token balance of sender
selectedToken: null,
selectedTokenDecimals: null,
tokenAmount: null, // amount to be sent
waiting: false,
validating: false
}
},
created() {
if (this.address && this.getTokens) {
this.selectedToken = Object.keys(this.getTokens)[0]; // ETH or other chain native token
this.tokenBalance = ethers.utils.formatEther(this.balance); // ETH or other chain native token
if (this.selectedToken) {
this.getTokenBalance(this.selectedToken);
}
}
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getChainId", "getNetworkName", "getTokens"]),
...mapGetters("user", ["getUserBalance"]),
...mapGetters("tld", ["getTldAddress"]),
domainLowerCase() {
if (this.receiver) {
return this.receiver.toLowerCase();
}
return null;
},
formatTokenBalance() {
if (this.tokenBalance > 100) {
return Number(this.tokenBalance).toFixed(2);
} else {
return Number(this.tokenBalance).toFixed(4);
}
},
getTokenNames() {
if (this.getTokens && !this.filterTokens) {
return Object.keys(this.getTokens); // all tokens
} else if (this.getTokens && this.filterTokens) {
return Object.keys(this.getTokens).filter(item => item.includes(this.filterTokens.toUpperCase())); //filtered
}
},
notValid() {
if (!this.receiver) {
return true;
} else if (!this.receiver.includes(".")) {
return true;
} else if (this.receiver.includes(" ")) {
return true;
} else if (this.receiver.includes("%")) {
return true;
} else if (this.receiver.includes("&")) {
return true;
} else if (this.receiver.includes("?")) {
return true;
} else if (this.receiver.includes("#")) {
return true;
} else if (this.receiver.includes("/")) {
return true;
} else if (!this.tokenAmount) {
return true;
} else if (isNaN(this.tokenAmount)) {
return true;
} else if (Number(this.tokenAmount) <= 0) {
return true;
} else if (Number(this.tokenAmount) > Number(this.tokenBalance)) {
return true;
}
return false;
}
},
methods: {
async getTokenBalance(tokenName) {
const tokenAddr = this.getTokens[tokenName];
if (tokenAddr === "0x0") { // ETH or other chain native token
this.tokenBalance = ethers.utils.formatEther(this.balance); // ETH or other chain native token
} else {
const intfc = new ethers.utils.Interface(Erc20Abi);
const tokenContract = new ethers.Contract(tokenAddr, intfc, this.signer);
const balanceWei = await tokenContract.balanceOf(this.address);
if (Number(balanceWei) > 0) {
const decimals = await tokenContract.decimals();
this.selectedTokenDecimals = Number(decimals);
this.tokenBalance = ethers.utils.formatUnits(balanceWei, this.selectedTokenDecimals);
} else {
this.tokenBalance = 0;
}
}
},
async selectToken(tokenName) {
this.selectedToken = tokenName;
this.getTokenBalance(tokenName);
},
send() {
if (this.getTokens[this.selectedToken] === "0x0") {
this.sendNativeTokens(); // ETH or other chain native token
} else {
this.sendErc20Tokens();
}
},
async sendErc20Tokens() {
this.waiting = true;
try {
const sToken = this.selectedToken;
const tAmount = this.tokenAmount;
const recDomain = this.domainLowerCase;
const valueWei = ethers.utils.parseUnits(tAmount, this.selectedTokenDecimals);
const tokenAddr = this.getTokens[sToken];
const intfc = new ethers.utils.Interface(Erc20Abi);
const tokenContract = new ethers.Contract(tokenAddr, intfc, this.signer);
const tx = await tokenContract.transfer(this.receiverAddress, valueWei);
document.getElementById('closeSendModal').click();
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully sent " + tAmount + " " + sToken + " to " + recDomain + "!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.waiting = false;
this.getTokenBalance(sToken);
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
this.waiting = false;
console.log(e);
this.toast(e.message, {type: TYPE.ERROR});
}
},
async sendNativeTokens() {
// ETH or other chain native token
this.waiting = true;
try {
const sToken = this.selectedToken;
const tAmount = this.tokenAmount;
const recDomain = this.domainLowerCase;
const valueWei = ethers.utils.parseEther(tAmount);
const tx = await this.signer.sendTransaction({
to: this.receiverAddress,
value: valueWei
});
document.getElementById('closeSendModal').click();
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully sent " + tAmount + " " + sToken + " to " + recDomain + "!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.waiting = false;
this.getTokenBalance(sToken);
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
this.waiting = false;
console.log(e);
this.toast(e.message, {type: TYPE.ERROR});
}
},
async validateDomainName() {
this.validating = true;
this.domainError = null;
this.receiverAddress = null;
const intfc = new ethers.utils.Interface(tldAbi);
try {
if (this.domainLowerCase && this.domainLowerCase.split(".").length === 2) { // likely a domain name
// split into two (domain name and TLD)
const domArr = this.domainLowerCase.split(".");
for (let netId in tldsJson) { // iterate through different chains
if (tldsJson[netId]["."+domArr[1]]) { // find the correct TLD
// get fallback provider based on network ID
const fProvider = this.getFallbackProvider(Number(netId));
// create TLD contract
const tldContractRead = new ethers.Contract(tldsJson[netId]["."+domArr[1]], intfc, fProvider);
// fetch domain holder
const recDomainHolder = await tldContractRead.getDomainHolder(domArr[0]);
if (recDomainHolder !== ethers.constants.AddressZero) {
// if domain exists, set as receiver address
this.receiverAddress = recDomainHolder;
this.validating = false;
return
} else {
this.domainError = "This domain name has not been registered yet.";
this.validating = false;
return
}
break;
}
}
if (!ethers.utils.isAddress(this.recipient)) {
this.domainError = "This TLD does not exist.";
this.validating = false;
return;
}
}
} catch {
this.domainError = "You have entered an incorrect domain.";
this.validating = false;
return;
}
}
},
setup() {
const { address, balance, signer } = useEthers()
const toast = useToast();
const { getFallbackProvider } = useChainHelpers();
return { address, balance, getFallbackProvider, signer, toast }
},
watch: {
address() {
if (this.address && this.getTokens) {
this.selectedToken = Object.keys(this.getTokens)[0];
this.tokenBalance = this.getUserBalance;
if (this.selectedToken) {
this.getTokenBalance(this.selectedToken);
}
}
},
balance() {
if (this.address && this.getTokens) {
this.selectedToken = Object.keys(this.getTokens)[0];
this.tokenBalance = this.getUserBalance;
if (this.selectedToken) {
this.getTokenBalance(this.selectedToken);
}
}
},
getChainId() {
if (this.getChainId >= 1 && this.getTokens) {
this.selectedToken = Object.keys(this.getTokens)[0];
this.tokenBalance = this.getUserBalance;
if (this.selectedToken) {
this.getTokenBalance(this.selectedToken);
}
}
}
}
}
</script>
<style scoped>
#balance {
text-decoration: underline;
cursor: pointer;
}
#balance:hover {
text-decoration: none;
}
.domain-error {
color: red;
margin-left: 5px;
}
</style>

@ -21,7 +21,7 @@
<i class="bi bi-search"></i> Search domain
</router-link>
<router-link class="btn btn-sidebar text-start" to="/send-tokens">
<router-link class="btn btn-sidebar text-start" to="/profile/send-tokens">
<i class="bi bi-send"></i> Send tokens
</router-link>
@ -79,14 +79,14 @@ export default {
.btn-sidebar, .btn-sidebar:focus {
padding: 10px;
width: 100%;
color: #DBDFEA;
color: #fff;
text-decoration: none;
box-shadow: none;
}
.btn-sidebar:hover {
color: #DBDFEA;
border-color: #DBDFEA;
color: #fff;
border-color: #fff;
border-radius: 10px;
}

@ -1,10 +1,10 @@
<template>
<div class="mb-3 row domain-data mt-4" v-if="customData" v-for="(dataValue, dataKey) in customData">
<div class="col-sm-3 degen-title">
<div class="col-sm-3 punk-title">
{{dataKey.charAt(0).toUpperCase() + dataKey.slice(1)}}
</div>
<div class="col-sm-9 degen-text text-break">
<div class="col-sm-9 punk-text text-break">
<span v-if="dataKey=='url'"><a target="_blank" :href="dataValue">{{dataValue}}</a></span>
<span v-else-if="dataKey=='twitter'"><a target="_blank" :href="getTwitterUrl(dataValue)">{{dataValue}}</a></span>
<span v-else>{{dataValue}}</span>
@ -67,7 +67,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" @click="editData" :disabled="btnInactive">Edit data</button>
<button type="button" class="btn btn-secondary" @click="editData" :disabled="btnInactive">Submit</button>
<button id="closeCustomDataModal" type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
@ -98,7 +98,7 @@ export default {
},
computed: {
...mapGetters("degen", ["getTldAddresses", "getTldAbi"]),
...mapGetters("punk", ["getTldAddresses", "getTldAbi"]),
...mapGetters("network", ["getBlockExplorerBaseUrl"]),
customData() {
@ -248,7 +248,7 @@ export default {
}
if(this.fields.findIndex(x => x.dataKey == "imgChainId") === -1) {
this.fields.push({dataKey: "ImgChainId", dataValue: "", valuePlaceholder: "Only needed if NFT is on a different chain than domain"});
this.fields.push({dataKey: "imgChainId", dataValue: "", valuePlaceholder: "Only needed if NFT is on a different chain than domain"});
}
if(this.fields.findIndex(x => x.dataKey == "url") === -1) {
@ -269,19 +269,19 @@ export default {
<style scoped>
.form-control-plaintext {
color: #DBDFEA;
color: #fff;
}
.degen-text {
.punk-text {
text-align: left;
}
@media only screen and (max-width: 767px) {
.degen-text {
.punk-text {
text-align: center;
}
.degen-title {
.punk-title {
font-size: 1.1em;
margin-bottom: 5px;
font-weight: bold;

@ -1,10 +1,10 @@
<template>
<div class="mb-3 row domain-data mt-4" v-if="domainData">
<div class="col-sm-3 degen-title">
<div class="col-sm-3 punk-title">
Custom PFP
</div>
<div class="col-sm-9 degen-text">
<div class="col-sm-9 punk-text">
<span>{{customPfp}}</span>
<button
@ -80,7 +80,7 @@ export default {
},
computed: {
...mapGetters("degen", ["getTldAddresses", "getTldAbi"]),
...mapGetters("punk", ["getTldAddresses", "getTldAbi"]),
...mapGetters("network", ["getBlockExplorerBaseUrl"]),
customPfp() {
@ -225,16 +225,16 @@ export default {
</script>
<style scoped>
.degen-text {
.punk-text {
text-align: left;
}
@media only screen and (max-width: 767px) {
.degen-text {
.punk-text {
text-align: center;
}
.degen-title {
.punk-title {
font-size: 1.1em;
margin-bottom: 5px;
font-weight: bold;

@ -1,10 +1,10 @@
<template>
<div class="mb-3 row domain-data mt-4" v-if="domainData">
<div class="col-sm-3 degen-title">
<div class="col-sm-3 punk-title">
URL
</div>
<div class="col-sm-9 degen-text">
<div class="col-sm-9 punk-text">
<span>{{urlData}}</span>
<button
@ -25,7 +25,7 @@
</div>
<div class="modal-body">
<p>
Anyone who's using the DegenDNS browser extension will get redirected to this URL if they enter
Anyone who's using the Degen browser extension will get redirected to this URL if they enter
{{domainName}}.{{tld}} in the browser URL bar.
</p>
@ -68,7 +68,7 @@ export default {
},
computed: {
...mapGetters("degen", ["getTldAddresses", "getTldAbi"]),
...mapGetters("punk", ["getTldAddresses", "getTldAbi"]),
...mapGetters("network", ["getBlockExplorerBaseUrl"]),
isOwner() {
@ -170,16 +170,16 @@ export default {
</script>
<style scoped>
.degen-text {
.punk-text {
text-align: left;
}
@media only screen and (max-width: 767px) {
.degen-text {
.punk-text {
text-align: center;
}
.degen-title {
.punk-title {
font-size: 1.1em;
margin-bottom: 5px;
font-weight: bold;

@ -3,38 +3,40 @@ import { ethers } from 'ethers';
export default function useChainHelpers() {
function getChainName(chainId) {
if (chainId === 137) {
return "Polygon";
} else if (chainId === 1) {
if (chainId === 1) {
return "Ethereum";
} else if (chainId === 10) {
return "Optimism";
} else if (chainId === 14) {
return "Flare";
} else if (chainId === 16) {
return "Coston Testnet";
} else if (chainId === 19) {
return "Songbird";
} else if (chainId === 56) {
return "BNB Smart Chain";
} else if (chainId === 97) {
return "BSC Testnet";
} else if (chainId === 69) {
return "Optimism Testnet";
} else if (chainId === 77) {
return "Gnosis Testnet";
} else if (chainId === 100) {
return "Gnosis Chain";
} else if (chainId === 137) {
return "Polygon";
} else if (chainId === 250) {
return "Fantom";
} else if (chainId === 324) {
return "zkSync Era";
} else if (chainId === 369) {
return "PulseChain";
} else if (chainId === 4002) {
return "Fantom Testnet";
} else if (chainId === 42161) {
return "Arbitrum";
} else if (chainId === 2000) {
return "Dogechain";
} else if (chainId === 421611) {
return "Arbitrum Testnet";
} else if (chainId === 80001) {
return "Polygon Testnet";
} else if (chainId === 3) {
return "Ropsten";
} else if (chainId === 4) {
return "Rinkeby";
} else if (chainId === 568) {
return "Doge Testnet";
} else if (chainId === 421611) {
return "Arbitrum Testnet";
} else if (chainId === 1313161555) {
return "Aurora Testnet";
} else {
return "Unsupported Network";
}
@ -46,35 +48,32 @@ export default function useChainHelpers() {
if (networkId === 1) {
// Ethereum
urls = [
"https://eth-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_ETHEREUM_KEY
"https://rpc.ankr.com/eth"
];
} else if (networkId === 137) {
// Polygon PoS Chain
} else if (networkId === 10) {
// Optimism
urls = [
"https://rpc.ankr.com/optimism"
];
} else if (networkId === 14) {
// Flare
urls = [
"https://polygon-rpc.com/",
"https://polygon-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_POLYGON_KEY
"https://flare-api.flare.network/ext/C/rpc"
];
} else if (networkId === 80001) {
// Mumbai testnet (Polygon testnet)
} else if (networkId === 16) {
// Coston testnet
urls = [
"https://matic-mumbai.chainstacklabs.com",
"https://polygon-mumbai.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_MUMBAI_KEY
]
} else if (networkId === 10) {
// Optimism
"https://coston-api.flare.network/ext/C/rpc"
];
} else if (networkId === 19) {
// Songbird
urls = [
"https://mainnet.optimism.io",
"https://opt-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_OPTIMISM_KEY
"https://sgb.ftso.com.au/ext/bc/C/rpc"
];
} else if (networkId === 56) {
// BSC mainnet
urls = [
"https://bscrpc.com"
];
} else if (networkId === 97) {
// BSC testnet
urls = [
"https://data-seed-prebsc-2-s2.binance.org:8545"
"https://rpc.ankr.com/bsc"
];
} else if (networkId === 77) {
// Gnosis Chain testnet (Sokol)
@ -84,29 +83,54 @@ export default function useChainHelpers() {
} else if (networkId === 100) {
// Gnosis Chain
urls = [
"https://rpc.xdaichain.com",
"https://rpc.gnosischain.com"
"https://rpc.ankr.com/gnosis"
];
} else if (networkId === 137) {
// Polygon PoS Chain
urls = [
"https://rpc.ankr.com/polygon"
];
} else if (networkId === 250) {
// Fantom Mainnet
urls = [
"https://rpc.ankr.com/fantom",
];
} else if (networkId === 324) {
// zkSync Era Mainnet
urls = [
"https://mainnet.era.zksync.io",
];
} else if (networkId === 369) {
// PulseChain Mainnet
urls = [
"https://scan.pulsechain.com",
];
} else if (networkId === 4002) {
// Fantom Testnet
urls = [
"https://rpc.ankr.com/fantom_testnet",
//"https://rpc.testnet.fantom.network",
"https://fantom-testnet.public.blastapi.io"
];
} else if (networkId === 42161) {
// Arbitrum
urls = [
"https://arb1.arbitrum.io/rpc",
"https://arb-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_ARBITRUM_KEY
"https://rpc.ankr.com/arbitrum"
];
} else if (networkId === 80001) {
// Mumbai testnet (Polygon testnet)
urls = [
"https://matic-mumbai.chainstacklabs.com"
]
} else if (networkId === 421611) {
// Arbitrum testnet
urls = [
"https://rinkeby.arbitrum.io/rpc"
];
} else if (networkId === 2000) {
// Dogechain
} else if (networkId === 1313161555) {
// Aurora testnet
urls = [
"https://rpc.dogechain.dog"
];
} else if (networkId === 568) {
// Doge Testnet
urls = [
"https://rpc-testnet.dogechain.dog"
"https://testnet.aurora.dev"
];
}
@ -125,12 +149,6 @@ export default function useChainHelpers() {
if (networkName == "Ethereum") {
method = "wallet_switchEthereumChain"
params = [{ chainId: "0x1" }]
} else if (networkName == "Ropsten") {
method = "wallet_switchEthereumChain"
params = [{ chainId: "0x3" }]
} else if (networkName == "Rinkeby") {
method = "wallet_switchEthereumChain"
params = [{ chainId: "0x4" }]
} else if (networkName == "Polygon Testnet") {
method = "wallet_addEthereumChain"
params = [{
@ -156,7 +174,7 @@ export default function useChainHelpers() {
chainId: "0xA4B1",
chainName: "Arbitrum One",
nativeCurrency: { decimals: 18, name: "ETH", symbol: "ETH" },
rpcUrls: ["https://arb1.arbitrum.io/rpc"]
rpcUrls: ["https://rpc.ankr.com/arbitrum"]
}]
} else if (networkName == "Optimism") {
method = "wallet_addEthereumChain"
@ -165,7 +183,7 @@ export default function useChainHelpers() {
chainId: "0xA",
chainName: "Optimism",
nativeCurrency: { decimals: 18, name: "ETH", symbol: "ETH" },
rpcUrls: ["https://mainnet.optimism.io"]
rpcUrls: ["https://rpc.ankr.com/optimism"]
}]
} else if (networkName == "Optimism Testnet") {
method = "wallet_addEthereumChain"
@ -183,7 +201,7 @@ export default function useChainHelpers() {
chainId: "0x89",
chainName: "Polygon PoS Chain",
nativeCurrency: { decimals: 18, name: "MATIC", symbol: "MATIC" },
rpcUrls: ["https://polygon-rpc.com/"]
rpcUrls: ["https://rpc.ankr.com/polygon"]
}]
} else if (networkName == "Gnosis Testnet") {
method = "wallet_addEthereumChain"
@ -201,7 +219,7 @@ export default function useChainHelpers() {
chainId: "0x64",
chainName: "Gnosis Chain",
nativeCurrency: { decimals: 18, name: "XDAI", symbol: "XDAI" },
rpcUrls: ["https://rpc.gnosischain.com"]
rpcUrls: ["https://rpc.gnosis.gateway.fm"]
}]
} else if (networkName == "BNB Smart Chain") {
method = "wallet_addEthereumChain"
@ -210,35 +228,80 @@ export default function useChainHelpers() {
chainId: "0x38",
chainName: "BNB Smart Chain",
nativeCurrency: { decimals: 18, name: "BNB", symbol: "BNB" },
rpcUrls: ["https://bscrpc.com"]
}]
} else if (networkName == "BSC Testnet") {
rpcUrls: ["https://rpc.ankr.com/bsc"]
}]
} else if (networkName == "Aurora Testnet") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://testnet.bscscan.com/" ],
chainId: "0x61",
chainName: "BSC Testnet",
nativeCurrency: { decimals: 18, name: "BNB", symbol: "BNB" },
rpcUrls: ["https://data-seed-prebsc-1-s3.binance.org:8545"]
}]
} else if (networkName == "Dogechain") {
blockExplorerUrls: [ "https://testnet.aurorascan.dev/" ],
chainId: "0x4E454153",
chainName: "Aurora Testnet",
nativeCurrency: { decimals: 18, name: "ETH", symbol: "ETH" },
rpcUrls: ["https://testnet.aurora.dev"]
}]
} else if (networkName == "Songbird") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://explorer.dogechain.dog/" ],
chainId: "0x7D0",
chainName: "Dogechain",
nativeCurrency: { decimals: 18, name: "DOGE", symbol: "DOGE" },
rpcUrls: ["https://rpc.dogechain.dog"]
blockExplorerUrls: [ "https://songbird-explorer.flare.network/" ],
chainId: "0x13",
chainName: "Songbird",
nativeCurrency: { decimals: 18, name: "SGB", symbol: "SGB" },
rpcUrls: ["https://sgb.ftso.com.au/ext/bc/C/rpc"]
}]
} else if (networkName == "Coston Testnet") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://coston-explorer.flare.network" ],
chainId: "0x10",
chainName: "Coston Testnet",
nativeCurrency: { decimals: 18, name: "FLR", symbol: "FLR" },
rpcUrls: ["https://coston-api.flare.network/ext/C/rpc"]
}]
} else if (networkName == "Flare") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://flare-explorer.flare.network" ],
chainId: "0xE",
chainName: "Flare",
nativeCurrency: { decimals: 18, name: "FLR", symbol: "FLR" },
rpcUrls: ["https://flare-api.flare.network/ext/C/rpc"]
}]
} else if (networkName == "Fantom") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://ftmscan.com" ],
chainId: "0xFA",
chainName: "Fantom",
nativeCurrency: { decimals: 18, name: "FTM", symbol: "FTM" },
rpcUrls: ["https://rpc.ankr.com/fantom"]
}]
} else if (networkName == "Fantom Testnet") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://testnet.ftmscan.com" ],
chainId: "0xFA2",
chainName: "Fantom Testnet",
nativeCurrency: { decimals: 18, name: "FTM", symbol: "FTM" },
rpcUrls: ["https://rpc.ankr.com/fantom_testnet"]
}]
} else if (networkName == "zkSync Era") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://explorer.zksync.io/" ],
chainId: "0x144",
chainName: "zkSync Era",
nativeCurrency: { decimals: 18, name: "ETH", symbol: "ETH" },
rpcUrls: ["https://mainnet.era.zksync.io"]
}]
} else if (networkName == "Doge Testnet") {
} else if (networkName == "PulseChain") {
method = "wallet_addEthereumChain"
params = [{
blockExplorerUrls: [ "https://explorer-testnet.dogechain.dog/" ],
chainId: "0x238",
chainName: "Doge Testnet",
nativeCurrency: { decimals: 18, name: "DOGE", symbol: "DOGE" },
rpcUrls: ["https://rpc-testnet.dogechain.dog"]
}]
blockExplorerUrls: [ "https://scan.pulsechain.com" ],
chainId: "0x171",
chainName: "PulseChain",
nativeCurrency: { decimals: 18, name: "PLS", symbol: "PLS" },
rpcUrls: ["https://rpc.pulsechain.com"]
}]
}
return {

@ -6,12 +6,12 @@
}
@font-face {
font-family: "bamboo";
src: url("assets/font/BalsamiqSans-Regular.ttf");
font-family: "Impact";
src: url("assets/font/impact.ttf");
}
a {
color: #DBDFEA;
color: #fff;
}
a:hover {
@ -19,9 +19,13 @@ a:hover {
}
body {
font-family: 'bamboo';
background: rgb(63,94,251);
color: #DBDFEA;
font-family: 'Roboto Condensed', sans-serif;
background: #1488CC; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #2B32B2, #1488CC); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #2B32B2, #1488CC); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
color: #fff;
}
p {
@ -33,14 +37,14 @@ div {
}
hr {
background-color: #DBDFEA;
background-color: #fff;
}
.btn-primary, .btn-primary:active, .btn-primary:focus, .btn-primary:disabled {
background: transparent;
border-color: #DBDFEA;
box-shadow: none;
color: #DBDFEA;
border-color: #fff;
box-shadow: 0 3px 10px rgb(0 0 0 / 0.2);
color: #fff;
}
.btn-primary:hover {
@ -52,7 +56,7 @@ hr {
.btn-secondary, .btn-secondary:active, .btn-secondary:focus, .btn-secondary:disabled {
background: white;
border-color: black;
box-shadow: none;
box-shadow: 0 3px 10px rgb(0 0 0 / 0.2);
color: black;
}
@ -66,7 +70,8 @@ hr {
background: transparent;
padding: 20px;
border-radius: 10px;
border: 1px solid #DBDFEA;
border: 1.5px solid #fff;
box-shadow: 0 3px 10px rgb(0 0 0 / 0.2);
}
.img-thumbnail {
@ -88,18 +93,15 @@ hr {
}
.Vue-Toastification__toast--info {
background-color: #3a1174;
border: 1px solid #DBDFEA;
background-color: #332C49;
}
.Vue-Toastification__toast--success {
background-color: #4b7411;
border: 1px solid #DBDFEA;
background-color: #0e7c66;
}
.Vue-Toastification__toast--error {
background-color: #741911;
border: 1px solid #DBDFEA;
background-color: #D00013;
}
@media only screen and (max-width: 767px) {

@ -9,9 +9,6 @@ import Toast, { POSITION, TYPE } from "vue-toastification";
import "vue-toastification/dist/index.css";
import './index.css'
import { VueDapp } from 'vue-dapp'
import { Buffer } from 'buffer';
window.Buffer = Buffer;
const app = createApp(App)
@ -20,7 +17,7 @@ const options = {
hideProgressBar: true,
closeButton: "button",
position:POSITION.TOP_LEFT,
toastClassName: "degen-toast-class",
toastClassName: "punk-toast-class",
closeOnClick: false,
toastDefaults: {
@ -36,9 +33,7 @@ app.use(router)
app.use(store)
app.use(VueDapp, {
infuraId: 'wallet',
appName: 'Domain',
appUrl: 'localhost'
//infuraId: '',
})
app.use(Toast, options);

@ -2,11 +2,24 @@ import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import About from './views/About.vue'
import BrowserExtension from './views/BrowserExtension.vue'
import DeprecateWeb3 from './views/deprecate/DeprecateWeb3.vue'
import DeprecatePolygon from './views/deprecate/DeprecatePolygon.vue'
import DomainDetails from './views/DomainDetails.vue'
import Home from './views/Home.vue'
import HowItWorks from './views/HowItWorks.vue'
import Pepe from './views/memes/Pepe.vue'
import L2Dao from './views/partners/L2Dao.vue'
import Huwa from './views/partners/Huwa.vue'
import MisieAdmin from './views/partners/MisieAdmin.vue'
import UnstoppablePolygonRefund from './views/partners/UnstoppablePolygonRefund.vue'
import WildBunch from './views/partners/WildBunch.vue'
import Profile from './views/Profile.vue'
import ProfileSendTokens from './views/ProfileSendTokens.vue'
import PunkAngelNft from './views/nft/PunkAngelNft.vue'
import PunkAngelMint from './views/nft/PunkAngelMint.vue'
import SearchDomains from './views/SearchDomains.vue'
import SendTokens from './views/SendTokens.vue'
import TldBuy from './views/TldBuy.vue'
@ -32,6 +45,16 @@ const routes: Array<RouteRecordRaw> = [
name: 'BrowserExtension',
component: BrowserExtension,
},
{
path: '/deprecate/polygon',
name: 'DeprecatePolygon',
component: DeprecatePolygon,
},
{
path: '/deprecate/web3',
name: 'DeprecateWeb3',
component: DeprecateWeb3,
},
{
path: '/domain/:domainChain/:tld/:domainName',
name: 'DomainDetails',
@ -44,9 +67,42 @@ const routes: Array<RouteRecordRaw> = [
component: HowItWorks,
},
{
path: '/memes/pepe',
name: 'Pepe',
component: Pepe,
path: '/nft/angel',
name: 'PunkAngelMint',
component: PunkAngelMint,
},
{
path: '/punkangel',
name: 'PunkAngelMint',
component: PunkAngelMint,
},
{
path: '/partners/l2dao',
name: 'L2Dao',
component: L2Dao,
props: true
},
{
path: '/partners/huwa',
name: 'Huwa',
component: Huwa,
props: true
},
{
path: '/partners/misie/admin',
name: 'MisieAdmin',
component: MisieAdmin,
props: true
},
{
path: '/partners/udpolygon',
name: 'UnstoppablePolygonRefund',
component: DeprecatePolygon,
},
{
path: '/partners/wildbunch',
name: 'WildBunch',
component: WildBunch,
props: true
},
{
@ -54,6 +110,11 @@ const routes: Array<RouteRecordRaw> = [
name: 'Profile',
component: Profile,
},
{
path: '/profile/send-tokens',
name: 'ProfileSendTokens',
component: ProfileSendTokens,
},
{
path: '/search-domain',
name: 'SearchDomains',

@ -1,14 +1,14 @@
import { createStore } from 'vuex';
import network from "./modules/network";
import user from "./modules/user";
import degen from "./modules/degen";
import punk from "./modules/punk";
const store = createStore({
modules: {
network,
user,
degen
punk
}
})

@ -12,10 +12,11 @@ export default {
networkName: "Unsupported Network",
supportedNetworks: {
1: "Ethereum",
137: "Polygon",
42161: "Arbitrum",
56: "BNB Smart Chain",
421611: "Arbitrum Testnet"
80001: "Polygon Testnet",
369: "PulseChain"
}
}),
@ -29,28 +30,70 @@ export default {
return "https://rinkeby.etherscan.io";
} else if (chainId.value === 10) {
return "https://optimistic.etherscan.io";
} else if (chainId.value === 19) {
return "https://songbird-explorer.flare.network";
} else if (chainId.value === 56) {
return "https://bscscan.com";
} else if (chainId.value === 97) {
return "https://testnet.bscscan.com";
} else if (chainId.value === 69) {
return "https://kovan-optimistic.etherscan.io";
} else if (chainId.value === 77) {
return "https://blockscout.com/poa/sokol";
} else if (chainId.value === 100) {
return "https://blockscout.com/xdai/mainnet";
return "https://gnosisscan.io";
} else if (chainId.value === 137) {
return "https://polygonscan.com";
} else if (chainId.value === 250) {
return "https://ftmscan.com";
} else if (chainId.value === 369) {
return "https://scan.pulsechain.com";
} else if (chainId.value === 4002) {
return "https://testnet.ftmscan.com";
} else if (chainId.value === 42161) {
return "https://arbiscan.io";
} else if (chainId.value === 80001) {
return "https://mumbai.polygonscan.com";
} else if (chainId.value === 421611) {
return "https://testnet.arbiscan.io";
} else if (chainId.value === 2000) {
return "https://explorer.dogechain.dog/";
} else if (chainId.value === 568) {
return "https://explorer-testnet.dogechain.dog/";
} else if (chainId.value === 1313161555) {
return "https://testnet.aurorascan.dev";
}
},
getBlockExplorerBaseUrlFromId: () => (netId: Number) => {
if (netId === 1) {
return "https://etherscan.io";
} else if (netId === 3) {
return "https://ropsten.etherscan.io";
} else if (netId === 4) {
return "https://rinkeby.etherscan.io";
} else if (netId === 10) {
return "https://optimistic.etherscan.io";
} else if (netId === 19) {
return "https://songbird-explorer.flare.network";
} else if (netId === 56) {
return "https://bscscan.com";
} else if (netId === 69) {
return "https://kovan-optimistic.etherscan.io";
} else if (netId === 77) {
return "https://blockscout.com/poa/sokol";
} else if (netId === 100) {
return "https://gnosisscan.io";
} else if (netId === 137) {
return "https://polygonscan.com";
} else if (netId === 250) {
return "https://ftmscan.com";
} else if (chainId.value === 369) {
return "https://scan.pulsechain.com";
} else if (netId === 4002) {
return "https://testnet.ftmscan.com";
} else if (netId === 42161) {
return "https://arbiscan.io";
} else if (netId === 80001) {
return "https://mumbai.polygonscan.com";
} else if (netId === 421611) {
return "https://testnet.arbiscan.io";
} else if (netId === 1313161555) {
return "https://testnet.aurorascan.dev";
}
},
@ -64,7 +107,7 @@ export default {
if (networkId === 1) {
// Ethereum
urls = [
"https://eth-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_ETHEREUM_KEY
"https://rpc.ankr.com/eth"
];
} else if (networkId === 3) {
// Ropsten testnet
@ -73,18 +116,17 @@ export default {
} else if (networkId === 10) {
// Optimism
urls = [
"https://mainnet.optimism.io",
"https://opt-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_OPTIMISM_KEY
"https://rpc.ankr.com/optimism",
];
} else if (networkId === 19) {
// Songbird
urls = [
"https://sgb.ftso.com.au/ext/bc/C/rpc"
];
} else if (networkId === 56) {
// BSC mainnet
urls = [
"https://bscrpc.com"
];
} else if (networkId === 97) {
// BSC testner
urls = [
"https://data-seed-prebsc-1-s1.binance.org:8545"
"https://rpc.ankr.com/bsc"
];
} else if (networkId === 69) {
// Optimism testnet
@ -99,20 +141,29 @@ export default {
} else if (networkId === 100) {
// Gnosis Chain
urls = [
"https://rpc.xdaichain.com",
"https://rpc.gnosischain.com"
"https://rpc.ankr.com/gnosis"
];
} else if (networkId === 137) {
// Polygon PoS Chain
urls = [
"https://polygon-rpc.com/",
"https://polygon-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_POLYGON_KEY
"https://rpc.ankr.com/polygon",
];
} else if (networkId === 250) {
// Fantom Mainnet
urls = [
"https://rpc.ankr.com/fantom"
];
} else if (networkId === 4002) {
// Fantom Testnet
urls = [
"https://rpc.ankr.com/fantom_testnet",
//"https://rpc.testnet.fantom.network",
"https://fantom-testnet.public.blastapi.io"
];
} else if (networkId === 42161) {
// Arbitrum
urls = [
"https://arb1.arbitrum.io/rpc",
"https://arb-mainnet.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_ARBITRUM_KEY
"https://rpc.ankr.com/arbitrum",
];
} else if (networkId === 80001) {
// Mumbai testnet (Polygon testnet)
@ -121,19 +172,19 @@ export default {
"https://polygon-mumbai.g.alchemy.com/v2/" + import.meta.env.VITE_ALCHEMY_MUMBAI_KEY
]
} else if (networkId === 421611) {
// Arbitrum testnet
// Arbitrum Rinkeby testnet
urls = [
"https://rinkeby.arbitrum.io/rpc"
];
} else if (networkId === 568) {
// Dogechain testnet
} else if (networkId === 421613) {
// Arbitrum Goerli testnet
urls = [
"https://rpc-testnet.dogechain.dog"
"https://goerli-rollup.arbitrum.io/rpc"
];
} else if (networkId === 2000) {
// Dogechain Mainnet
} else if (networkId === 1313161555) {
// Aurora testnet
urls = [
"https://rpc02-sg.dogechain.dog"
"https://testnet.aurora.dev"
];
}
@ -197,6 +248,9 @@ export default {
} else if (chainId.value === 10) {
state.networkName = "Optimism";
state.networkCurrency = "ETH";
} else if (chainId.value === 19) {
state.networkName = "Songbird";
state.networkCurrency = "SGB";
} else if (chainId.value === 56) {
state.networkName = "BNB Smart Chain";
state.networkCurrency = "BNB";
@ -212,27 +266,36 @@ export default {
} else if (chainId.value === 137) {
state.networkName = "Polygon";
state.networkCurrency = "MATIC";
} else if (chainId.value === 250) {
state.networkName = "Fantom";
state.networkCurrency = "FTM";
} else if (chainId.value === 369) {
state.networkName = "PulseChain";
state.networkCurrency = "PLS";
} else if (chainId.value === 4002) {
state.networkName = "Fantom Testnet";
state.networkCurrency = "FTM";
} else if (chainId.value === 42161) {
state.networkName = "Arbitrum";
state.networkCurrency = "ETH";
} else if (chainId.value === 421611) {
state.networkName = "Arbitrum Testnet";
state.networkCurrency = "ETH";
} else if (chainId.value === 421613) {
state.networkName = "Arbitrum Goerli Testnet";
state.networkCurrency = "ETH";
} else if (chainId.value === 80001) {
state.networkName = "Polygon Testnet";
state.networkCurrency = "MATIC";
} else if (chainId.value === 3) {
state.networkName = "Ropsten";
state.networkCurrency = "ETH";
} else if (chainId.value === 568) {
state.networkName = "Doge Testnet";
state.networkCurrency = "DOGE";
} else if (chainId.value === 2000) {
state.networkName = "Dogechain";
state.networkCurrency = "DOGE";
} else if (chainId.value === 4) {
state.networkName = "Rinkeby";
state.networkCurrency = "ETH";
} else if (chainId.value === 1313161555) {
state.networkName = "Aurora Testnet";
state.networkCurrency = "ETH";
} else {
state.networkName = "Unsupported Network";
state.networkCurrency = "ETH";

@ -2,8 +2,8 @@ import { ethers } from 'ethers';
import { useEthers } from 'vue-dapp';
import addresses from "../../abi/addresses.json";
import tldsJson from "../../abi/tlds.json";
import factoryAbi from "../../abi/DegenTLDFactory.json";
import tldAbi from "../../abi/DegenTLD.json";
import factoryAbi from "../../abi/PunkTLDFactory.json";
import tldAbi from "../../abi/PunkTLD.json";
const { chainId, signer } = useEthers();
@ -42,7 +42,7 @@ export default {
actions: {
async fetchTlds({ dispatch, commit, state, getters }) {
let networkId = 1;
let networkId = 137;
if (chainId.value) {
networkId = chainId.value;

@ -139,9 +139,9 @@ export default {
}
// fetch user's default names
for (let tldName of rootState.degen.tlds) {
const intfc = new ethers.utils.Interface(rootGetters["degen/getTldAbi"]);
const contract = new ethers.Contract(rootState.degen.tldAddresses[tldName], intfc, signer.value);
for (let tldName of rootState.punk.tlds) {
const intfc = new ethers.utils.Interface(rootGetters["punk/getTldAbi"]);
const contract = new ethers.Contract(rootState.punk.tldAddresses[tldName], intfc, signer.value);
const userDefaultName = await contract.defaultNames(address.value);
@ -177,9 +177,9 @@ export default {
const name = nameArr[0];
const domain = "." + nameArr[1];
if (name && rootState.degen.tldAddresses[domain]) {
const intfc = new ethers.utils.Interface(rootGetters["degen/getTldAbi"]);
const contract = new ethers.Contract(rootState.degen.tldAddresses[domain], intfc, signer.value);
if (name && rootState.punk.tldAddresses[domain]) {
const intfc = new ethers.utils.Interface(rootGetters["punk/getTldAbi"]);
const contract = new ethers.Contract(rootState.punk.tldAddresses[domain], intfc, signer.value);
const nameData = await contract.domains(name);

@ -1,60 +1,81 @@
<template>
<div class="container">
<h1 class="text-center">What are Degen Domains?</h1>
<h1 class="text-center">About Degen Domains</h1>
<div class="row mt-3">
<div class="col-md-8 offset-md-2">
<p>
Degen Domains are NFT <strong>domain names</strong> for Web3 communities.
Degen Domains allows you to <strong>register a domain name</strong> attached to your account address.
</p>
<h3>What are Degen Domains used for?</h3>
<h3>Why would anyone need that?</h3>
<p>
Well, your crypto address is hard to remember. It starts with <code>0x</code>, but then continues with 40 random
characters (digits from <code>0</code> to <code>9</code> and letters from <code>a</code> to <code>f</code>).
</p>
<p>
If you want someone to send you tokens, sure you could send them your address and they could copy-paste it
into their wallet. But wouldn't it be great if they could just enter a domain name, like
<code>ilove.pepe</code>, instead of the whole address?
</p>
<p>
Degen Domains can be used for Crypto communities, DAOs and Influencers. A short easy to remember <code>.project</code> domain is more brandable and a new revenue stream for projects.
Web3 communities can get there own brandable <code>.project</code> domains, influencers and community members can .
This is what they can do with <code>Degen Domains</code> (on the Send Tokens page).
</p>
<p>
Web3 games, decentralized social networks and other dApps could display the wallet's domain name as the <strong>username</strong>.
Instead of your username being <code>0xc3674D</code>, it could be <code>degen.pepe</code>.
Another usecase is to have a domain name as your <strong>username</strong> in various web3 dApps, games and
upcoming social networks. Instead of your username being <code>0xb2945D</code>, it could be
<code>coolguy.pepe</code>.
</p>
<p>
Degen Domains are a fun way to show support for your favorite Web3 community. Refer your friends and earn <strong>high paying Affilate commissions</strong>.
Our referral program is coded directly into the DegenDNS smart contracts!
An additional feature that Degen Domains provide is a <strong>browser extension</strong> that takes you to a designated URL
address if you type a domain name into browser URL bar.
</p>
<h3>But isn't all that what ENS is doing already?</h3>
<h3>What makes Degen Domains different from ENS and other projects like it?</h3>
<p>
Yes, but they only do it on Ethereum L1 and (for now) only with <code>.eth</code>. Degen Domains allows
many different top-level domains (TLDs), such as <code>.pepe</code>, <code>.ben</code>,
<code>.meme</code> etc. And it runs on L2 chains.
</p>
<p>
Degen Domains has more top-level domains (TLDs), like <code>.pepe</code>, <code>.ben</code>,
<code>.turbo</code> and others. Degen Domains is can be made available on any EVM network supporting Solidity Smart Contracts.
Degen Domain Service provides additional ongoing income for projects and influencers. The Degen Domain protocol features a referral system writen into our smart contracts.
Degen Domains enables anyone to buy a TLD, operate it and earn revenue from it. For example, a DeFi protocol
like Aave could create a TLD named <code>.aave</code>, and the revenue from each purchase would go to
Aave treasury.
</p>
<p>
Degen Domains architecture is <strong>very flexible</strong> and it allows for various domain business
models. The first one is a one-time domain purchase (no renewals), but new ones will be added in the
future (like time-restricted domain ownership).
</p>
<h3>An NFT domain name with utility</h3>
<h3>Not just about domains</h3>
<p>
Degen Domains is more than a vanity it provides the base for your <strong>full decentralization</strong> Web3 digital identity owned by You! Attach your metadata to level up your
pseudonymous <strong>identity</strong>.
Degen Domains is not just about domains (in the web2 sense of the word). It's about <strong>identity</strong>
in the web3 world. Domain name gives you a digital identity, and data attached to this identity strengthen it.
</p>
<hr>
<p>
DegenDNS is looking to partner with DAOs and Communities:
<ul>
<li>Your Project Here: <a href="#" target="_blank">.project domain</a></li>
</ul>
Another thing that Degen Domains cherishes is <strong>full decentralization</strong>. The contracts are
non-upgradable and don't need any keepers (or similar outside software) to properly operate. The only
thing not decentralized is the main factory contract ownership.
</p>
<hr>
<p>
<em>
(If you want a more technical overview on how Degen Domains works, <router-link to="/how">click here</router-link>.)
</em>
</p>
</div>
</div>
@ -62,9 +83,9 @@
</template>
<script lang="ts">
export default {
name: "About"
}
export default {
name: "About"
}
</script>
<style scoped>

@ -10,10 +10,10 @@
<div class="col-md-12 mb-3">
<div class="container text-center">
<h3>COMING SOON!</h3>
<h3>Browser Extension/Plugin</h3>
<p class="text-wrap p-4">
Degen Domains browser extension allows you to enter a Degen domain name in the URL bar and the
DegenDNS browser extension allows you to enter a Degen Domain Name in the URL bar and the
extension will redirect you to the URL that is set for that domain. If no URL is set, the extension
will redirect you to the domain page on the Degen Domains website.
</p>
@ -30,13 +30,13 @@
<p>
<small><em>
<a target="_blank" href="https://chrome.google.com/webstore/#">
<a target="_blank" href="https://chrome.google.com/webstore/detail/">
Download
</a>
</em></small>
</p>
<a target="_blank" href="https://chrome.google.com/webstore/#">
<a target="_blank" href="https://chrome.google.com/webstore/detail/">
<img class="img-fluid browser-img mb-3" src="../assets/chrome-logo.png" />
</a>
</div>
@ -48,13 +48,13 @@
<p>
<small><em>
<a target="_blank" href="https://addons.mozilla.org/#">
<a target="_blank" href="https://addons.mozilla.org/en-GB/firefox/addon/">
Download
</a>
</em></small>
</p>
<a target="_blank" href="https://addons.mozilla.org/#">
<a target="_blank" href="https://addons.mozilla.org/en-GB/firefox/addon/">
<img class="img-fluid browser-img mb-3" src="../assets/firefox-logo.png" />
</a>
</div>

@ -17,21 +17,24 @@
</div>
<div class="mb-3 row domain-data mt-4" v-if="domainData">
<div class="col-sm-3 degen-title">
<div class="col-sm-3 punk-title">
Holder address
</div>
<div class="col-sm-9 degen-text text-break">
<div class="col-sm-9 punk-text text-break">
{{holderData}}
<a :href="getBlockExplorerBaseUrlFromId(Number(this.domainChain))+'/address/'+holderData" target="_blank">
<i class="bi bi-box-arrow-up-right"></i>
</a>
</div>
</div>
<div class="mb-3 row domain-data mt-4">
<div class="col-sm-3 degen-title">
<div class="col-sm-3 punk-title">
Network
</div>
<div class="col-sm-9 degen-text text-break">
<div class="col-sm-9 punk-text text-break">
{{getChainName(Number(domainChain))}} (this is where domain is registered)
</div>
</div>
@ -76,7 +79,7 @@ import { mapGetters } from 'vuex';
import { useEthers } from 'vue-dapp';
import { useToast, TYPE } from "vue-toastification";
import tldsJson from '../abi/tlds.json';
import tldAbi from '../abi/DegenTLD.json';
import tldAbi from '../abi/PunkTLD.json';
import EditOtherData from "../components/domainEdit/EditOtherData.vue";
import EditPfp from "../components/domainEdit/EditPfp.vue";
import EditUrl from "../components/domainEdit/EditUrl.vue";
@ -113,8 +116,8 @@ export default {
},
computed: {
...mapGetters("degen", ["getTldAddresses", "getTldAbi"]),
...mapGetters("network", ["getBlockExplorerBaseUrl", "getChainId", "getFallbackProvider", "getSupportedNetworks", "isNetworkSupported"]),
...mapGetters("punk", ["getTldAddresses", "getTldAbi"]),
...mapGetters("network", ["getBlockExplorerBaseUrl", "getBlockExplorerBaseUrlFromId", "getChainId", "getFallbackProvider", "getSupportedNetworks", "isNetworkSupported"]),
holderData() {
if (this.domainData.holder !== ethers.constants.AddressZero) {
@ -240,16 +243,16 @@ export default {
max-width: 200px;
}
.degen-text {
.punk-text {
text-align: left;
}
@media only screen and (max-width: 767px) {
.degen-text {
.punk-text {
text-align: center;
}
.degen-title {
.punk-title {
font-size: 1.1em;
margin-bottom: 5px;
font-weight: bold;

@ -10,7 +10,7 @@
-->
<p class="logo">
degendomains.io
Degen Domains
</p>
<div class="flex flex-row justify-center space-x-4">

@ -1,6 +1,6 @@
<template>
<div class="container text-center">
<h1 class="mt-5">DegenDNS - Domains for Degens</h1>
<h1 class="mt-5">Domains for Degens</h1>
<div v-if="isActivated" class="dropdown mt-5">
Choose network:
@ -39,7 +39,7 @@
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><span class="dropdown-item" v-for="tld in enabledBuyingTlds" @click="changeTld(tld)">{{tld}}</span></li>
<li><span class="dropdown-item" :key="tld" v-for="tld in enabledBuyingTlds" @click="changeTld(tld)">{{tld}}</span></li>
</ul>
</div>
</div>
@ -60,6 +60,8 @@
</button>
</div>
<FeaturedDomains class="mt-3" />
</template>
@ -71,9 +73,15 @@ import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../components/toasts/WaitingToast.vue";
import useDomainHelpers from "../hooks/useDomainHelpers";
import useChainHelpers from "../hooks/useChainHelpers";
import FeaturedDomains from '../components/FeaturedDomains.vue';
export default {
name: "Home",
components: {
FeaturedDomains,
},
data() {
return {
@ -93,7 +101,7 @@ export default {
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getNetworkName", "getNetworkCurrency", "getSupportedNetworks", "getSupportedNetworkNames"]),
...mapGetters("degen", ["getTlds", "getTldAddresses", "getDomainPrices", "getTldAbi"]),
...mapGetters("punk", ["getTlds", "getTldAddresses", "getDomainPrices", "getTldAbi"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
@ -237,6 +245,10 @@ export default {
this.selectedPrice = this.getDomainPrices[this.selectedTld];
},
openUrl(url) {
window.open(url, '_blank').focus();
},
parseValue(someVal) {
if (someVal) {
return ethers.utils.formatEther(someVal);

@ -1,11 +1,12 @@
<template>
<div class="container">
<h1 class="text-center">Degen Domain Smart Contracts</h1>
<h1 class="text-center">How it works</h1>
<div class="row mt-3">
<div class="col-md-8 offset-md-2">
<p class="text-center">
An Overview of <strong>TLD Factories</strong>, <strong>TLD Contracts</strong> and <strong>Domains</strong>.
<p>
Let's take a more technical overview of Degen Domains. The main Degen Domains engines are TLD
<strong>Factory</strong> contracts.
</p>
<p class="text-center">
@ -15,40 +16,61 @@
<h3>TLD Factories</h3>
<p>
The Degen Domain protocol starts with TLD Factory contracts. Each TLD Factory contract defines the logic for creating
new TLD contracts. This logic includes the price and any royalty for each domain.
Each factory has a TLD template that defines its business logic. Currently, there's only one factory contract
which allows for one-time TLD and domain purchases. This means that these domains never expire (holders can
hold them forever).
</p>
<p>
To prevent two factories from creating the same TLD, the <code>DegenForbiddenTlds</code> contract holds a list of already
used or restricted TLD names (<code>.eth</code> is an example of a forbidden TLD name, because it's used in ENS).
In the future, new TLD factories will be added, each with a different business logic and each with its own
mix of one-time and/or renewable TLDs/domains rules (and perhaps new business models that we haven't thought yet about).
</p>
<h3>DegenTLD contracts</h3>
<h3>Restricted TLD names</h3>
<p>
Degen TLD contracts are minted from the TLD Factory contract for price defined by the TLD Factory logic. The
price logic should be high enough to discourge domain spamming and squatting. But not so high the general public will reject it.
TLD factories need to communicate in order to avoid TLD collision (meaning two factories producing the
same TLD).
</p>
<p>New TLD mints can be temporarily restricted to the factory owner only. The TLD owner can set domain prices and can stop domain sales
anytime they wish.
<p>
In order to prevent collisions, there's a contract called <code>PunkForbiddenTlds</code>, which has a list of already
used or restricted TLD names (<code>.eth</code> is an example of a forbidden TLD name, because it's used in ENS).
</p>
<h3>TLD contracts</h3>
<p>
The factory owner can set a royalty for each domain purchase, but the royalty can never exceed 50% of the
domain price (in reallity it around 1% to 10% and some cases 0%).
A TLD needs to be purchased (minted) from a TLD Factory for a certain price. There
needs to be a (high enough) price to avoid spamming and squatting.
</p>
<h3>Domains</h3>
<p>(Note that a TLD Factory can temporarily restrict new TLD mints to the factory owner only.)</p>
<p>
A TLD contract can be owned by anyone. The TLD owner can set domain prices and can stop domain sales
anytime they want.
</p>
<p>
<ul>
<li>Example of a TLD: <code>.ben</code></li>
<li>Example of a domain: <code>ilove.ben</code></li>
<li>Example of a TLD: <code>.wagmi</code></li>
<li>Example of a domain: <code>techie.wagmi</code></li>
</ul>
</p>
<p>
The factory owner can set a royalty for each domain purchase, but the royalty can never exceed 50% of the
domain price (in reallity it will be much lower).
</p>
<p>
The TLD owner cannot confiscate domain from its holder, just like Factory owner cannot confiscate a TLD
from its owner. Factory owner can only set a royalty in the TLD contract and nothing else.
</p>
<h3>Domains</h3>
<p>A domain can only be held by one address, but one address can hold many domains.</p>
<p>
@ -68,6 +90,15 @@
Each domain is an ERC-721 NFT and can be sold on NFT marketplaces.
</p>
<h3>Resources</h3>
<p>
<ul>
<li><a target="_blank" href="http://docs.degendomains.io">Docs</a></li>
<li><a target="_blank" href="https://git.cipherlabs.org/DegenDNS">GitHub</a></li>
<li><a target="_blank" href="https://twitter.com/Degen_DNS">Twitter</a></li>
</ul>
</p>
</div>
</div>
</div>

@ -127,7 +127,7 @@ export default {
computed: {
...mapGetters("user", ["getUserAddress", "getUserBalance", "getUserAllDomainNames", "getUserSelectedNameData"]),
...mapGetters("network", ["getNetworkCurrency"]),
...mapGetters("degen", ["getTlds", "getTldAddresses", "getTldAbi"]),
...mapGetters("punk", ["getTlds", "getTldAddresses", "getTldAbi"]),
customData() {
if (this.getUserSelectedNameData) {
@ -207,7 +207,7 @@ export default {
.table {
--bs-table-bg: transparent;
color: #DBDFEA;
color: #fff;
}
.table:hover {

@ -0,0 +1,25 @@
<template>
<div class="row">
<div class="col-md-3" id="sidebar-container">
<Sidebar />
</div>
<div class="col-md-9">
<SendTokensComponent />
</div>
</div>
</template>
<script>
import SendTokensComponent from "../components/SendTokensComponent.vue";
import Sidebar from '../components/Sidebar.vue';
export default {
name: "ProfileSendTokens",
components: {
SendTokensComponent,
Sidebar
}
}
</script>

@ -141,7 +141,7 @@ export default {
}
}
this.toast("Top-level domain ." + domArr[1] + " does not exist (if this is a mistake, contact us on Discord).", {type: TYPE.ERROR});
this.toast("Top-level domain ." + domArr[1] + " does not exist (if this is a mistake, contact us on Twitter).", {type: TYPE.ERROR});
this.waiting = false;
return;
} else {

@ -1,512 +1,15 @@
<template>
<div class="row">
<div class="col-md-3" id="sidebar-container">
<Sidebar />
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-12 mb-3">
<div class="container text-center">
<h3>Send tokens to a domain</h3>
<!-- Recipient -->
<div class="row mt-5">
<div class="col-md-6 offset-md-3">
<input
v-model="receiver"
class="form-control text-center"
placeholder="Enter the receiver's domain name"
>
</div>
</div>
<!-- Tokens -->
<div class="row mt-4">
<div class="col-md-4 offset-md-4">
<div class="input-group">
<input
type="text"
class="form-control text-end"
v-model="tokenAmount"
placeholder="0.0"
/>
<button
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{{selectedToken}}
</button>
<div class="dropdown-menu p-2">
<div class="mb-3">
<input
class="form-control mb-2"
placeholder="Filter tokens"
v-model="filterTokens"
/>
<li>
<button
class="dropdown-item"
type="button"
v-for="token in getTokenNames"
@click="selectToken(token)"
>{{token}}</button>
</li>
</div>
</div>
</div>
<small>
Balance:
<span id="balance" @click="tokenAmount=tokenBalance">{{formatTokenBalance}} {{selectedToken}}</span>
</small>
</div>
</div>
<button
class="btn btn-primary mt-4 mb-5"
:disabled="notValid || waiting"
@click="validateDomainName"
data-bs-toggle="modal" data-bs-target="#sendTokensModal"
>
<span v-if="waiting" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Send tokens
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Send tokens modal -->
<div class="modal fade text-start" id="sendTokensModal" tabindex="-1" aria-labelledby="sendTokensModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="sendTokensModalLabel">Confirm sending {{selectedToken}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>
Please review the data before you send {{selectedToken}} to {{domainLowerCase}}.
</p>
<div class="row mb-3 mt-4">
<div class="col-sm-3">
<strong>Recipient</strong>
</div>
<div class="col-sm-9">
<span>{{domainLowerCase}}</span>
<span class="domain-error" v-if="domainError">Error: {{domainError}}</span>
</div>
</div>
<div class="row mb-3 mt-2" v-if="receiverAddress">
<div class="col-sm-3">
<strong>Recipient address</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{receiverAddress}}</span>
<span class="domain-error" v-if="receiverAddress == address">Error: You are sending tokens to yourself.</span>
</div>
</div>
<div class="row mb-3 mt-2">
<div class="col-sm-3">
<strong>Amount</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{tokenAmount}} {{selectedToken}}</span>
</div>
</div>
<div class="row mb-3 mt-2" v-if="getTokens[selectedToken] !== '0x0'">
<div class="col-sm-3">
<strong>Token address</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{getTokens[selectedToken]}}</span>
</div>
</div>
<div class="row mb-3 mt-2">
<div class="col-sm-3">
<strong>Network</strong>
</div>
<div class="col-sm-9">
<span class="text-break">{{getNetworkName}}</span>
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
@click="send"
:disabled="waiting || domainError || validating"
>
<span v-if="validating">Validating...</span>
<span v-if="validating" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span v-if="!validating">Send {{selectedToken}}</span>
</button>
<button id="closeSendModal" type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<SendTokensComponent />
</template>
<script lang="ts">
import { ethers } from 'ethers';
import { mapGetters } from 'vuex';
import { useEthers } from 'vue-dapp';
import { useToast, TYPE } from "vue-toastification";
import Sidebar from '../components/Sidebar.vue';
import Erc20Abi from "../abi/Erc20.json";
import tldsJson from '../abi/tlds.json';
import tldAbi from '../abi/DegenTLD.json';
import WaitingToast from "../components/toasts/WaitingToast.vue";
<script>
import SendTokensComponent from "../components/SendTokensComponent.vue";
export default {
name: "SendTokens",
components: {
Sidebar
},
data() {
return {
domainError: null,
filterTokens: null,
receiver: null,
receiverAddress: null,
tokenBalance: 0, // max token balance of sender
selectedToken: null,
selectedTokenDecimals: null,
tokenAmount: null, // amount to be sent
waiting: false,
validating: false
}
},
created() {
if (this.getChainId >= 1) {
this.selectedToken = Object.keys(this.getTokens)[0];
this.tokenBalance = ethers.utils.formatEther(this.balance);
}
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getChainId", "getFallbackProvider", "getNetworkName", "getTokens"]),
...mapGetters("user", ["getUserBalance"]),
...mapGetters("degen", ["getTldAddresses", "getTldAbi"]),
domainLowerCase() {
if (this.receiver) {
return this.receiver.toLowerCase();
}
return null;
},
formatTokenBalance() {
if (this.tokenBalance > 100) {
return Number(this.tokenBalance).toFixed(2);
} else {
return Number(this.tokenBalance).toFixed(4);
}
},
getTokenNames() {
if (this.getTokens && !this.filterTokens) {
return Object.keys(this.getTokens); // all tokens
} else if (this.getTokens && this.filterTokens) {
return Object.keys(this.getTokens).filter(item => item.includes(this.filterTokens.toUpperCase())); //filtered
}
},
notValid() {
if (!this.receiver) {
return true;
} else if (!this.receiver.includes(".")) {
return true;
} else if (this.receiver.includes(" ")) {
return true;
} else if (this.receiver.includes("%")) {
return true;
} else if (this.receiver.includes("&")) {
return true;
} else if (this.receiver.includes("?")) {
return true;
} else if (this.receiver.includes("#")) {
return true;
} else if (this.receiver.includes("/")) {
return true;
} else if (!this.tokenAmount) {
return true;
} else if (isNaN(this.tokenAmount)) {
return true;
} else if (Number(this.tokenAmount) <= 0) {
return true;
} else if (Number(this.tokenAmount) > Number(this.tokenBalance)) {
return true;
}
return false;
}
},
methods: {
async getTokenBalance(tokenName) {
const tokenAddr = this.getTokens[tokenName];
if (tokenAddr === "0x0") {
this.tokenBalance = ethers.utils.formatEther(this.balance);
} else {
const intfc = new ethers.utils.Interface(Erc20Abi);
const tokenContract = new ethers.Contract(tokenAddr, intfc, this.signer);
const balanceWei = await tokenContract.balanceOf(this.address);
if (Number(balanceWei) > 0) {
const decimals = await tokenContract.decimals();
this.selectedTokenDecimals = Number(decimals);
this.tokenBalance = ethers.utils.formatUnits(balanceWei, this.selectedTokenDecimals);
} else {
this.tokenBalance = 0;
}
}
},
selectToken(tokenName) {
this.selectedToken = tokenName;
this.getTokenBalance(tokenName);
},
send() {
if (this.getTokens[this.selectedToken] === "0x0") {
this.sendNativeTokens();
} else {
this.sendErc20Tokens();
}
},
async sendErc20Tokens() {
this.waiting = true;
try {
const sToken = this.selectedToken;
const tAmount = this.tokenAmount;
const recDomain = this.domainLowerCase;
const valueWei = ethers.utils.parseUnits(tAmount, this.selectedTokenDecimals);
const tokenAddr = this.getTokens[sToken];
const intfc = new ethers.utils.Interface(Erc20Abi);
const tokenContract = new ethers.Contract(tokenAddr, intfc, this.signer);
const tx = await tokenContract.transfer(this.receiverAddress, valueWei);
document.getElementById('closeSendModal').click();
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully sent " + tAmount + " " + sToken + " to " + recDomain + "!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.waiting = false;
this.getTokenBalance(sToken);
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
this.waiting = false;
console.log(e);
this.toast(e.message, {type: TYPE.ERROR});
}
},
async sendNativeTokens() {
this.waiting = true;
try {
const sToken = this.selectedToken;
const tAmount = this.tokenAmount;
const recDomain = this.domainLowerCase;
const valueWei = ethers.utils.parseEther(tAmount);
const tx = await this.signer.sendTransaction({
to: this.receiverAddress,
value: valueWei
});
document.getElementById('closeSendModal').click();
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully sent " + tAmount + " " + sToken + " to " + recDomain + "!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.waiting = false;
this.getTokenBalance(sToken);
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
this.waiting = false;
console.log(e);
this.toast(e.message, {type: TYPE.ERROR});
}
},
async validateDomainName() {
this.validating = true;
this.domainError = null;
this.receiverAddress = null;
const intfc = new ethers.utils.Interface(tldAbi);
try {
if (this.domainLowerCase && this.domainLowerCase.split(".").length === 2) { // likely a domain name
// split into two (domain name and TLD)
const domArr = this.domainLowerCase.split(".");
for (let netId in tldsJson) { // iterate through different chains
if (tldsJson[netId]["."+domArr[1]]) { // find the correct TLD
// get fallback provider based on network ID
const fProvider = this.getFallbackProvider(Number(netId));
// create TLD contract
const tldContractRead = new ethers.Contract(tldsJson[netId]["."+domArr[1]], intfc, fProvider);
// fetch domain holder
const recDomainHolder = await tldContractRead.getDomainHolder(domArr[0]);
if (recDomainHolder !== ethers.constants.AddressZero) {
// if domain exists, set as receiver address
this.receiverAddress = recDomainHolder;
this.validating = false;
return
} else {
this.domainError = "This domain name has not been registered yet.";
this.validating = false;
return
}
break;
}
}
if (!ethers.utils.isAddress(this.recipient)) {
this.domainError = "This TLD does not exist.";
this.validating = false;
return;
}
}
} catch {
this.domainError = "You have entered an incorrect domain.";
this.validating = false;
return;
}
}
},
setup() {
const { address, balance, signer } = useEthers()
const toast = useToast();
return { address, balance, signer, toast }
},
watch: {
getChainId() {
if (this.getChainId >= 1) {
this.selectedToken = Object.keys(this.getTokens)[0];
this.tokenBalance = this.getUserBalance;
}
},
address() {
this.getTokenBalance(this.selectedToken);
}
SendTokensComponent
}
}
</script>
<style scoped>
#balance {
text-decoration: underline;
cursor: pointer;
}
#balance:hover {
text-decoration: none;
}
.domain-error {
color: red;
margin-left: 5px;
}
</style>
</script>

@ -5,8 +5,8 @@
<div class="row mt-3">
<div class="col-md-8 offset-md-2">
<p class="text-center">
Degen Domain Service allows anyone to create and own a top-level domain. As a TLD holder you have complete
control over it and you earn revenue from selling domains.
Degen Domains protocol creates top-level domains on the blockchain. TLD holders have complete
control over it and earn revenue from selling domains.
</p>
<div class="d-flex justify-content-center domain-input-container mt-5">

@ -136,7 +136,7 @@ export default {
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getNetworkCurrency"]),
...mapGetters("degen", ["getTldAddresses", "getDomainPrices", "getTldAbi"]),
...mapGetters("punk", ["getTldAddresses", "getDomainPrices", "getTldAbi"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
@ -148,7 +148,7 @@ export default {
},
methods: {
...mapActions("degen", ["fetchTlds"]),
...mapActions("punk", ["fetchTlds"]),
...mapMutations("user", ["addDomainManually"]),
async buyDomain() {

@ -27,7 +27,7 @@
<input
v-model="recipient"
class="form-control text-center"
placeholder="Enter recipient address"
placeholder="Enter recipient address or domain"
>
</div>
</div>
@ -56,7 +56,7 @@ import { mapActions, mapGetters } from 'vuex';
import { useEthers } from 'vue-dapp';
import { useToast, TYPE } from "vue-toastification";
import tldsJson from '../abi/tlds.json';
import tldAbi from '../abi/DegenTLD.json';
import tldAbi from '../abi/PunkTLD.json';
import Sidebar from '../components/Sidebar.vue';
import WaitingToast from "../components/toasts/WaitingToast.vue";
@ -114,7 +114,7 @@ export default {
}
if (!ethers.utils.isAddress(this.recipient)) {
this.toast("Top-level domain ." + domArr[1] + " does not exist (if this is a mistake, contact us on Discord).", {type: TYPE.ERROR});
this.toast("Top-level domain ." + domArr[1] + " does not exist (if this is a mistake, contact us on Twitter).", {type: TYPE.ERROR});
this.waiting = false;
}
} else if (this.recipient) { // valid address

@ -0,0 +1,417 @@
<template>
<div class="container text-center">
<h1 class="mt-5">.polygon Domain Refund + $2k in UD credits</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
In order to avoid domain collisions, Degen Domains .polygon TLD is shutting down. Each .polygon domain holder
will receive 14 MATIC, a new .poly domain, and $2000 in credits from Unstoppable Domains.
</p>
<p>
Claim these benefits by sending your .polygon domain to the burn contract using the form below. The
refund of 14 MATIC will automatically be sent to you for each burned domain.
</p>
<p>
In addition, you will receive a .poly domain for free.
</p>
<p>
After claiming the refund, submit
<a target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSdAR7BND4o7axj0PsFfDQyFyd2EItKKnjJek3kqCYnUe9naBA/viewform">the Google Form here</a>
to claim $2000 in UD credits.
</p>
</div>
</div>
<h3 class="mt-4">Domain to burn:</h3>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="domain"
placeholder="Enter the .polygon domain to burn"
type="text"
class="form-control text-center"
>
</div>
</div>
<h3 class="mt-4">Mint new .poly domain for free (.poly):</h3>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="newDomainOne"
placeholder="Enter new domain name"
type="text"
class="form-control text-center"
>
<button class="btn btn-outline-light" @click="checkDomainAvailability(newDomainOne)" type="button" id="button-addon2">Check availability</button>
</div>
</div>
<div class="d-flex justify-content-center alert alert-danger" v-if="contractBalance && contractBalance < 60">
The refund contract balance is {{contractBalance}} MATIC. Please notify Degen Domains on Discord to refill the contract balance.
</div>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="approveOrBurnDomain" :disabled="waiting || paused || !canClaim">
<span v-if="waiting || loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!paused && !loading && canClaim && approved">Claim refund</span>
<span v-if="!paused && !loading && canClaim && !approved">Approve domain burn</span>
<span v-if="paused">Paused</span>
<span v-if="!paused && !canClaim">Not eligible</span>
</button>
<div v-if="!paused && !loading && canClaim && !approved" class="mb-2">
You will need to do two transactions: Approve + Claim refund
</div>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork('Polygon')">Switch to Polygon</button>
</div>
</div>
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapActions, mapGetters, mapMutations } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import useChainHelpers from "../../hooks/useChainHelpers";
import tldAbi from '../../abi/PunkTLD.json';
import DeprecateTld from '../../abi/DeprecateTldOne.json';
export default {
name: "DeprecatePolygon",
data() {
return {
approved: false,
canClaim: false,
contractBalance: null,
domain: null,
domainPrice: null,
loading: false, // loading data
newDomainOne: null,
newTldAddress: null,
paused: true,
refundAddress: null,
tld: ".polygon",
refundContract: null,
tldAddress: null,
waiting: false, // waiting for TX to complete
}
},
created() {
this.setContracts();
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.chainId === 137 || this.chainId === 77) {
return true;
}
}
return false;
}
},
methods: {
...mapActions("user", ["removeDomainFromUserDomains"]),
...mapMutations("user", ["addDomainManually"]),
approveOrBurnDomain() {
if (!this.approved) {
this.approveDomain();
} else {
this.burnDomain();
}
},
async approveDomain() {
this.waiting = true;
const intfc = new ethers.utils.Interface(tldAbi);
const tldContractSigner = new ethers.Contract(this.tldAddress, intfc, this.signer);
try {
const tx = await tldContractSigner.setApprovalForAll(this.refundAddress, true);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully approved the domain for processing! Now proceed with the Burn & Claim step.", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.approved = true;
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
async burnDomain() {
this.waiting = true;
// remove all whitespace
const domainNoSpaces = this.domain.replace(/ /g,'');
// make string lowercase & replace the .polygon extension (only domain name need to be sent)
const domainNoExtension = domainNoSpaces.toLowerCase().replace(this.tld, "");
const intfc = new ethers.utils.Interface(DeprecateTld);
const refundContractSigner = new ethers.Contract(this.refundAddress, intfc, this.signer);
// get new domain names and extensions
const newDomainOneNoSpaces = this.newDomainOne.replace(/ /g,'').toLowerCase();
const domArrOne = newDomainOneNoSpaces.split(".");
const tldIntfc = new ethers.utils.Interface(tldAbi);
const contract = new ethers.Contract(this.tldAddress, tldIntfc, this.fProvider);
// check if user owns that .polygon domain
const deprecatedDomainHolder = await contract.getDomainHolder(String(domainNoExtension).toLowerCase());
if (deprecatedDomainHolder !== this.address) {
this.toast("Your currently connected address does not own " + domainNoSpaces, {type: TYPE.ERROR});
this.waiting = false;
return;
}
try {
const tx = await refundContractSigner.refund(
domainNoExtension, // old domain name
domArrOne[0], // new domain 1 name
"."+domArrOne[1] // new domain 1 TLD
);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully claimed the refund!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.removeDomainFromUserDomains(domainNoSpaces.toLowerCase());
this.addDomainManually(newDomainOneNoSpaces);
this.waiting = false;
this.setContracts();
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(networkName) {
const networkData = this.switchNetwork(networkName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
},
async checkDomainAvailability(fullDomainName) {
if (fullDomainName && fullDomainName.split(".").length === 2) {
const domArr = fullDomainName.split(".");
console.log(String(domArr[0]).toLowerCase());
const tldIntfc = new ethers.utils.Interface(tldAbi);
const contract = new ethers.Contract(this.newTldAddress, tldIntfc, this.fProvider);
// check if domain is already taken
const existingHolder = await contract.getDomainHolder(String(domArr[0]).toLowerCase());
if (existingHolder !== ethers.constants.AddressZero) {
this.toast("Sorry, but this domain name is already taken...", {type: TYPE.ERROR});
} else {
this.toast("This domain is available. Nice!", {type: TYPE.SUCCESS});
}
} else {
this.toast("Please enter a full domain name, for example: tempe.poly", {
type: TYPE.ERROR
});
}
},
async setContracts() {
this.loading = true;
if (this.chainId === 137) { // Polygon Mainnet
this.fProvider = this.getFallbackProvider(137);
this.tld = ".polygon";
this.tldAddress = "0xa450bc33d0940d25fB0961c592fb440Fa63ABE03"; // .polygon
this.newTldAddress = "0x70Ac07C50131b7bb2c8Bd9466D8d2add30B7759f"; // .poly
this.refundAddress = "0x38f4D3D62DeC57F3CaeEAA4191e670A1034569b3";
} else if (this.chainId === 77) { // Gnosis Chain Testnet (Sokol)
this.fProvider = this.getFallbackProvider(77);
this.tld = ".gnosis";
this.tldAddress = "0x0744d775804BB81efD3fF630402988b2F7eB284B"; // .gnosis
this.newTldAddress = "0x110Cc3f64CdF8ffAdC785dFA53906bCfF76b3846"; // .testdao
this.refundAddress = "0xd43E3C6d04f40C6FDCf63C62C9b24A858C275b26";
}
if (this.fProvider) {
const intfc = new ethers.utils.Interface(DeprecateTld);
this.refundContract = new ethers.Contract(this.refundAddress, intfc, this.fProvider);
const isPaused = await this.refundContract.paused();
this.paused = isPaused;
const balanceContract = await this.fProvider.getBalance(this.refundAddress);
this.contractBalance = ethers.utils.formatEther(balanceContract);
}
if (this.address) {
const tldIntfc = new ethers.utils.Interface(tldAbi);
this.tldContract = new ethers.Contract(this.tldAddress, tldIntfc, this.fProvider);
// check if address is .polygon holder
const oldTldBalance = await this.tldContract.balanceOf(this.address);
if (oldTldBalance > 0) {
this.canClaim = true;
}
const isApproved = await this.tldContract.isApprovedForAll(this.address, this.refundAddress);
this.approved = isApproved;
}
this.loading = false;
},
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { switchNetwork } = useChainHelpers();
return { address, chainId, isActivated, open, signer, switchNetwork, toast }
},
watch: {
address() {
this.setContracts();
},
chainId() {
this.setContracts();
},
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.1em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 10px;
}
.error {
color: #fff;
}
.l2dao {
width: 50px;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -0,0 +1,425 @@
<template>
<div class="container text-center">
<h1 class="mt-5">.web3 Domain Refund</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
In order to avoid domain collisions, Degen Domains .web3 TLD is shutting down. All .web3 users can get a refund
in the form of two new .poly domains (and MATIC refund if they paid for their .web3 domain).
</p>
<p>
Claim the refund by sending your .web3 domain to the burn contract using the form below. Also choose the new
.poly domains that you'd like to have minted. If you've paid for your .web3 domain, you'll also receive a MATIC refund.
</p>
</div>
</div>
<h3 class="mt-4">Domain to burn:</h3>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="domain"
placeholder="Enter the .web3 domain to burn"
type="text"
class="form-control text-center"
>
</div>
</div>
<h3 class="mt-4">Mint two new domains for free (<code>.poly</code>):</h3>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="newDomainOne"
placeholder="Enter new domain #1"
type="text"
class="form-control text-center"
>
<button class="btn btn-outline-light" @click="checkDomainAvailability(newDomainOne)" type="button" id="button-addon2">Check availability</button>
</div>
</div>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="newDomainTwo"
placeholder="Enter new domain #2"
type="text"
class="form-control text-center"
>
<button class="btn btn-outline-light" @click="checkDomainAvailability(newDomainTwo)" type="button" id="button-addon2">Check availability</button>
</div>
</div>
<div class="d-flex justify-content-center alert alert-danger" v-if="contractBalance && contractBalance < 60">
The refund contract balance is {{contractBalance}} MATIC. Please notify Degen Domains on Discord to refill the contract balance.
</div>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="approveOrBurnDomain" :disabled="waiting || paused || !canClaim">
<span v-if="waiting || loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!paused && !loading && canClaim && approved">Claim refund</span>
<span v-if="!paused && !loading && canClaim && !approved">Approve domain burn</span>
<span v-if="paused">Paused</span>
<span v-if="!paused && !canClaim">Not eligible</span>
</button>
<div v-if="!paused && !loading && canClaim && !approved" class="mb-2">
You will need to do two transactions: Approve + Claim refund
</div>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork('Polygon')">Switch to Polygon</button>
</div>
</div>
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapActions, mapGetters, mapMutations } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import useChainHelpers from "../../hooks/useChainHelpers";
import tldAbi from '../../abi/PunkTLD.json';
import DeprecateTld from '../../abi/DeprecateTldTwo.json';
export default {
name: "DeprecateWeb3",
data() {
return {
approved: false,
canClaim: false,
contractBalance: null,
domain: null,
domainPrice: null,
loading: false, // loading data
newDomainOne: null,
newDomainTwo: null,
newTldAddress: null,
paused: true,
refundAddress: null,
tld: ".web3",
refundContract: null,
tldAddress: null,
waiting: false, // waiting for TX to complete
}
},
created() {
this.setContracts();
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.chainId === 137 || this.chainId === 77) {
return true;
}
}
return false;
}
},
methods: {
...mapActions("user", ["removeDomainFromUserDomains"]),
...mapMutations("user", ["addDomainManually"]),
approveOrBurnDomain() {
if (!this.approved) {
this.approveDomain();
} else {
this.burnDomain();
}
},
async approveDomain() {
this.waiting = true;
const intfc = new ethers.utils.Interface(tldAbi);
const tldContractSigner = new ethers.Contract(this.tldAddress, intfc, this.signer);
try {
const tx = await tldContractSigner.setApprovalForAll(this.refundAddress, true);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully approved the domain for processing! Now proceed with the Burn & Claim step.", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.approved = true;
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
async burnDomain() {
this.waiting = true;
// remove all whitespace
const domainNoSpaces = this.domain.replace(/ /g,'');
// make string lowercase & replace the .web3 extension (only domain name need to be sent)
const domainNoExtension = domainNoSpaces.toLowerCase().replace(this.tld, "");
const intfc = new ethers.utils.Interface(DeprecateTld);
const refundContractSigner = new ethers.Contract(this.refundAddress, intfc, this.signer);
// get new domain names and extensions
const newDomainOneNoSpaces = this.newDomainOne.replace(/ /g,'').toLowerCase();
const domArrOne = newDomainOneNoSpaces.split(".");
const newDomainTwoNoSpaces = this.newDomainTwo.replace(/ /g,'').toLowerCase();
const domArrTwo = newDomainTwoNoSpaces.split(".");
const tldIntfc = new ethers.utils.Interface(tldAbi);
const contract = new ethers.Contract(this.tldAddress, tldIntfc, this.fProvider);
// check if user owns that .web3 domain
const deprecatedDomainHolder = await contract.getDomainHolder(String(domainNoExtension).toLowerCase());
if (deprecatedDomainHolder !== this.address) {
this.toast("Your currently connected address does not own " + domainNoSpaces, {type: TYPE.ERROR});
this.waiting = false;
return;
}
try {
const tx = await refundContractSigner.refund(
domainNoExtension, // old domain name
domArrOne[0], // new domain 1 name
"."+domArrOne[1], // new domain 1 TLD
domArrTwo[0], // new domain 2 name
"."+domArrTwo[1] // new domain 2 TLD
);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully claimed the refund!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.removeDomainFromUserDomains(domainNoSpaces.toLowerCase());
this.addDomainManually(newDomainOneNoSpaces);
this.addDomainManually(newDomainTwoNoSpaces);
this.waiting = false;
this.setContracts();
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(networkName) {
const networkData = this.switchNetwork(networkName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
},
async checkDomainAvailability(fullDomainName) {
if (fullDomainName && fullDomainName.split(".").length === 2) {
const domArr = fullDomainName.split(".");
console.log(String(domArr[0]).toLowerCase());
const tldIntfc = new ethers.utils.Interface(tldAbi);
const contract = new ethers.Contract(this.newTldAddress, tldIntfc, this.fProvider);
// check if domain is already taken
const existingHolder = await contract.getDomainHolder(String(domArr[0]).toLowerCase());
if (existingHolder !== ethers.constants.AddressZero) {
this.toast("Sorry, but this domain name is already taken...", {type: TYPE.ERROR});
} else {
this.toast("This domain is available. Nice!", {type: TYPE.SUCCESS});
}
} else {
this.toast("Please enter a full domain name, for example: tempe.poly", {
type: TYPE.ERROR
});
}
},
async setContracts() {
this.loading = true;
if (this.chainId === 137) { // Polygon Mainnet
this.fProvider = this.getFallbackProvider(137);
this.tld = ".web3";
this.tldAddress = "0xb6Cf2874588d0fdFAf9d1b5E254ee6C49110C68B"; // .web3
this.newTldAddress = "0x70Ac07C50131b7bb2c8Bd9466D8d2add30B7759f"; // .poly
this.refundAddress = "0x6724c95Af33e396d85D2Fc93609C60D23490878B";
} else if (this.chainId === 77) { // Gnosis Chain Testnet (Sokol)
this.fProvider = this.getFallbackProvider(77);
this.tld = ".gnosis";
this.tldAddress = "0x0744d775804BB81efD3fF630402988b2F7eB284B"; // .gnosis
this.newTldAddress = "0x110Cc3f64CdF8ffAdC785dFA53906bCfF76b3846"; // .testdao
this.refundAddress = "0xd43E3C6d04f40C6FDCf63C62C9b24A858C275b26";
}
if (this.fProvider) {
const intfc = new ethers.utils.Interface(DeprecateTld);
this.refundContract = new ethers.Contract(this.refundAddress, intfc, this.fProvider);
const isPaused = await this.refundContract.paused();
this.paused = isPaused;
const balanceContract = await this.fProvider.getBalance(this.refundAddress);
this.contractBalance = ethers.utils.formatEther(balanceContract);
}
if (this.address) {
const tldIntfc = new ethers.utils.Interface(tldAbi);
this.tldContract = new ethers.Contract(this.tldAddress, tldIntfc, this.fProvider);
// check if address is .web3 holder
const oldTldBalance = await this.tldContract.balanceOf(this.address);
if (oldTldBalance > 0) {
this.canClaim = true;
}
const isApproved = await this.tldContract.isApprovedForAll(this.address, this.refundAddress);
this.approved = isApproved;
}
this.loading = false;
},
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { switchNetwork } = useChainHelpers();
return { address, chainId, isActivated, open, signer, switchNetwork, toast }
},
watch: {
address() {
this.setContracts();
},
chainId() {
this.setContracts();
},
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.1em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 10px;
}
.error {
color: #fff;
}
.l2dao {
width: 50px;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -1,14 +1,14 @@
<template>
<div class="container text-center">
<h1 class="mt-5">Mint a Degen Anon domain!</h1>
<h1 class="mt-5">Get yourself a Punk Angel domain!</h1>
<h4 class="mt-3">(domain + unique PFP)</h4>
<h4 class="mt-3">(Web3 domain + unique PFP)</h4>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
<img class="img-fluid anon-img rounded-3" src="../../assets/anons/nft.jpg" />
<img class="img-fluid angel-img rounded-3" src="../../assets/angels/angels.gif" />
</p>
</div>
</div>
@ -16,8 +16,8 @@
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
Degen Anon is our first domain which gives you both a unique domain name, and also a generative art
profile picture (all in one NFT).
Punk Angel is a new kind of web3 domains, which gives you both a unique domain name and also a generative art
profile picture (all-in-one).
</p>
</div>
</div>
@ -103,9 +103,9 @@
</div>
<div class="row mt-5">
<div class="col-md-6 offset-md-3">
<table class="table table-bordered" style="color:#DBDFEA;border-style:none;">
<thead>
<div class="col-md-6 offset-md-3 table-container">
<table class="table table-borderless table-domain">
<thead class="table-light">
<tr>
<th scope="col">Domain length</th>
<th scope="col">Price</th>
@ -114,23 +114,23 @@
<tbody>
<tr>
<td>1 character</td>
<td>$10 000</td>
<td>$9999</td>
</tr>
<tr>
<td>2 characters</td>
<td>$3 000</td>
<td>$4999</td>
</tr>
<tr>
<td>3 characters</td>
<td>$999</td>
<td>$2999</td>
</tr>
<tr>
<td>4 characters</td>
<td>$199</td>
<td>$1999</td>
</tr>
<tr>
<td>5+ characters</td>
<td>$69</td>
<td>$999</td>
</tr>
</tbody>
</table>
@ -144,16 +144,16 @@
<h4 class="mt-4">What is the max/total supply?</h4>
<p class="mt-3">
Max/total supply is between 44 and 6377 domains. It depends on the prices that domains are bought at.
If all domains are bought at $69, the max supply is 6377 domains. If some domains are bought at a
higher price, the total supply will be lower. If all domains are bought at $10k, the total supply
Max/total supply is between 44 and 425 domains. It depends on the prices that domains are bought at.
If all domains are bought at $999, the max supply is 425 domains. If some domains are bought at a
higher price, the total supply will be lower. If all domains are bought at $9999, the total supply
is capped at 44 domains.
</p>
<h4 class="mt-5">Can I buy/sell these PFP domains on NFT marketplaces?</h4>
<h4 class="mt-5">Can I buy/sell these PFP domains on marketplaces?</h4>
<p class="mt-3">
Yes, Degen Anon is available on NFT marketplaces. You can also filter domains by attributes such as
Yes, Punk Angel is available on marketplaces. You can also filter domains by attributes such as
domain length, colors in the domain image, expressions (serious, smiling, surprised) and
accessories (VR glasses, gas mask).
</p>
@ -161,8 +161,8 @@
<h4 class="mt-5">Where are the images stored?</h4>
<p class="mt-3">
Degen Anon images are stored completely on-chain in a form of SVG code. We don't rely on any centralized servers
or third-party storage solutions such as IPFS. All data is stored within Degen Anon smart contracts on the
Punk Angel images are stored completely on-chain in a form of SVG code. We don't rely on any centralized servers
or third-party storage solutions such as IPFS. All data is stored within Punk Angel smart contracts on the
blockchain. This means that the images will exist forever (or at least as long as Ethereum exists).
</p>
</div>
@ -170,7 +170,7 @@
</div>
<Referral v-if="isActivated" :urlpath="'nft/anon'" />
<Referral v-if="isActivated" :urlpath="'nft/angel'" />
<!-- Approve payment token modal -->
<div class="modal fade" id="approveTokenModal" tabindex="-1" aria-labelledby="approveTokenModalLabel" aria-hidden="true" modal-dialog-centered>
@ -219,18 +219,18 @@ import WaitingToast from "../../components/toasts/WaitingToast.vue";
import Referral from '../../components/Referral.vue';
import useDomainHelpers from "../../hooks/useDomainHelpers";
import useChainHelpers from "../../hooks/useChainHelpers";
import MinterAbi from "../../abi/anon/DegenAnonMinter.json";
import TraitsJson from "../../abi/anon/DegenAnonTraits.json";
import tldAbi from '../../abi/FlexiDegenTLD.json';
import MinterAbi from "../../abi/angel/PunkAngelMinter.json";
import TraitsJson from "../../abi/angel/PunkAngelTraits.json";
import tldAbi from '../../abi/FlexiPunkTLD.json';
import Erc20Abi from '../../abi/Erc20.json';
export default {
name: "DegenAnonMint",
name: "PunkAngelMint",
data() {
return {
canMint: true,
chosenAllowance: 69,
chosenAllowance: 999,
chosenDomainName: null,
domainPrice: null,
idMainnet: 42161,
@ -250,12 +250,12 @@ export default {
payTokenName: "USDC",
randomFeatureIds: [],
randomFeaturesAmount: 3,
tld: ".degen",
tld: ".punkangel",
tldAddressTestnet: "0xBF113092d7ceabB5b891C4B232C910CDF2153AC5",
tldAddressMainnet: "0xcC66213645474a7B61BAf95330D01e50789eaF4b",
tldContract: null,
tldMainnet: ".degen",
tldTestnet: ".testanon",
tldMainnet: ".punkangel",
tldTestnet: ".testangel",
waiting: false, // waiting for TX to complete
}
},
@ -275,17 +275,17 @@ export default {
getDomainPrice() {
if (this.chosenDomainName) {
if (this.chosenDomainName.length === 1) {
return 10000;
return 9999;
} else if (this.chosenDomainName.length === 2) {
return 3000;
return 4999;
} else if (this.chosenDomainName.length === 3) {
return 999;
return 2999;
} else if (this.chosenDomainName.length === 4) {
return 199;
return 1999;
}
}
return 69;
return 999;
},
domainLowerCase() {
@ -602,32 +602,13 @@ export default {
chainId() {
this.setContracts();
},
/*
chosenDomainName() {
if (this.chosenDomainName) {
if (this.chosenDomainName.length === 1) {
this.domainPrice = 10000;
} else if (this.chosenDomainName.length === 2) {
this.domainPrice = 3000;
} else if (this.chosenDomainName.length === 3) {
this.domainPrice = 999;
} else if (this.chosenDomainName.length === 4) {
this.domainPrice = 199;
} else {
this.domainPrice = 69;
}
} else {
this.domainPrice = 69;
}
}*/
}
}
}
</script>
<style scoped>
.anon-img {
.angel-img {
width: 15em;
}
@ -644,17 +625,42 @@ export default {
}
.error {
color: #DBDFEA;
color: #fff;
}
.l2dao {
width: 50px;
}
.table-light {
color: #4443f1;
}
.table-domain {
border: 2px solid white;
border-radius: 10px !important;
border-collapse: separate;
color: white;
}
.tld-addon {
background-color: white;
}
th:first-of-type {
border-top-left-radius: 10px;
border-collapse: separate;
}
th:last-of-type {
border-top-right-radius: 10px;
}
tr:last-of-type td:first-of-type {
border-bottom-left-radius: 10px;
}
tr:last-of-type td:last-of-type {
border-bottom-right-radius: 10px;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;

@ -1,11 +1,11 @@
<template>
<div class="container text-center">
<h1 class="mt-5">Get whitelisted for the Degen Anon NFT mint!</h1>
<h1 class="mt-5">Get whitelisted for the Punk Angel NFT mint!</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
<img class="img-fluid anon-img" src="../../assets/anons/nft.jpg" />
<img class="img-fluid angel-img" src="../../assets/angels/angels.gif" />
</p>
</div>
</div>
@ -26,12 +26,12 @@
<p>
To grow the Degen Domains team, expand our marketing operations, get more DAO partnerships, and build cool new
features which will make Degen Domains a major web3 domains protocol.
See <a target="_blank" href="https://docs.degendomains.io/roadmap/">our roadmap here</a>!
See <a target="_blank" href="https://docs.punk.domains/roadmap/">our roadmap here</a>!
</p>
<a
target="_blank"
href="https://forms.gle/#"
href="https://forms.gle/RK1zww1Ae5MBLBwZA"
class="btn btn-primary btn-lg mt-4 mb-5">
Join Waitlist
</a>
@ -87,7 +87,7 @@
<h3 class="mt-1">Get notified!</h3>
<p>
<a target="_blank" href="https://#">
<a target="_blank" href="https://449ly163251.typeform.com/to/onXpPaG2">
Click here to get notified about the launch!
</a>
</p>
@ -103,12 +103,12 @@ import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { useToast, TYPE } from "vue-toastification";
import { mapGetters } from 'vuex';
import AnonWhitelistAbi from "../../abi/anon/AnonWhitelist.json";
import AngelWhitelistAbi from "../../abi/angel/AngelWhitelist.json";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
export default {
name: "DegenAnonNft",
name: "PunkAngelNft",
data() {
return {
@ -127,17 +127,10 @@ export default {
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl"]),
// NFT Whitelist Contracts
getContractAddress() {
if (this.chainId === 10) {
// Optimism
return "0xa562fD780b05B4c6d895ba78D5519Ddf0a5d25D6";
} else if (this.chainId === 56) {
// BNB Mainnet TODO
return "0xC08214D6F73D8F5D06e515862D4A528090f142F5";
} else if (this.chainId === 97) {
// BNB testnet TODO
return "0xC08214D6F73D8F5D06e515862D4A528090f142F5";
} else if (this.chainId === 100) {
// Gnosis Chain
return "0xC08214D6F73D8F5D06e515862D4A528090f142F5";
@ -150,9 +143,6 @@ export default {
} else if (this.chainId === 80001) {
// Mumbai
return "0x7d7143649d8ca8f4BB10A4C43Cd03255E2eB060c";
} else if (this.chainId === 2000) {
// Dogechain TODO
return "0x7d7143649d8ca8f4BB10A4C43Cd03255E2eB060c";
}
return null;
@ -177,7 +167,7 @@ export default {
this.waiting = true;
const amountUsd = Number(this.amount) * 500;
const intfc = new ethers.utils.Interface(AnonWhitelistAbi);
const intfc = new ethers.utils.Interface(AngelWhitelistAbi);
const contract = new ethers.Contract(this.getContractAddress, intfc, this.signer);
try {
@ -228,7 +218,7 @@ export default {
if (this.isActivated) {
this.loading = true;
const intfc = new ethers.utils.Interface(AnonWhitelistAbi);
const intfc = new ethers.utils.Interface(AngelWhitelistAbi);
const contract = new ethers.Contract(this.getContractAddress, intfc, this.signer);
this.paused = await contract.paused();
@ -255,7 +245,7 @@ export default {
</script>
<style scoped>
.anon-img {
.angel-img {
width: 15em;
}
@ -272,7 +262,7 @@ export default {
}
.error {
color: #DBDFEA;
color: #fff;
}
@media only screen and (max-width: 767px) {

@ -1,13 +1,14 @@
<template>
<div class="container text-center">
<h1 class="mt-5">Get your a {{tld}} domain today!</h1>
<h1 class="mt-5">Get yourself a {{tld}} domain!</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
Show your support for the PEPE community with a {{tld}} domain.
show your support for $Pepe with your own .pepe domain.
{{tld}} domain is the official domain of
<a href="https://discord.com/invite/jTHR6vAsSu" target="_blank">the Huwa DAO community</a>,
and is powered by the Degen Domains protocol.
</p>
</div>
</div>
@ -93,7 +94,7 @@
</div>
<Referral v-if="isActivated" :urlpath="'memes/pepe'" />
<Referral v-if="isActivated" :urlpath="'partners/huwa'" />
<!-- Approve payment token modal -->
<div class="modal fade" id="approveTokenModal" tabindex="-1" aria-labelledby="approveTokenModalLabel" aria-hidden="true" modal-dialog-centered>
@ -142,12 +143,12 @@ import WaitingToast from "../../components/toasts/WaitingToast.vue";
import Referral from '../../components/Referral.vue';
import useDomainHelpers from "../../hooks/useDomainHelpers";
import useChainHelpers from "../../hooks/useChainHelpers";
import MinterAbi from "../../abi/memes/pepe/PepeMinter.json";
import tldAbi from '../../abi/FlexiDegenTLD.json';
import MinterAbi from "../../abi/partners/huwa/HuwaMinter.json";
import tldAbi from '../../abi/FlexiPunkTLD.json';
import Erc20Abi from '../../abi/Erc20.json';
export default {
name: "Pepe",
name: "Huwa",
data() {
return {
@ -155,13 +156,13 @@ export default {
chosenAllowance: 20,
chosenDomainName: null,
domainPrice: null,
idMainnet: 1,
idTestnet: 3,
idMainnet: 56,
idTestnet: 421611,
loading: false, // loading data
mintAddressTestnet: "0xe3116Fe0b4526290c4231A59D2094605E581d8B6",
mintAddressMainnet: "0xA8221890768603210c1a32d88374111084E46E6d",
mintContract: null,
networkName: "Ethereum",
networkName: "BNB Smart Chain",
paused: true,
payTokenAddressTestnet: "0xD1d656845AD2a15934C314e46977554FFe85383E",
payTokenAddressMainnet: "0x03a2A7E95eCe3112b8d33F9bCC21F0c9BA843e35",
@ -169,13 +170,13 @@ export default {
payTokenBalance: 0,
payTokenContract: null,
payTokenDecimals: 4,
payTokenName: "PEPE",
tld: ".pepe",
payTokenName: "HUWA",
tld: ".huwa",
tldAddressTestnet: "0x49651e70df13b8fd5684B0b82b1b3D7Cdc8cF80f",
tldAddressMainnet: "0xeFBE0b46649B7A0F1e1D49CCa98aD9CF6bcFB096",
tldContract: null,
tldMainnet: ".pepe",
tldTestnet: ".testpepe",
tldMainnet: ".huwa",
tldTestnet: ".testhuwa",
waiting: false, // waiting for TX to complete
}
},
@ -520,7 +521,7 @@ export default {
}
.error {
color: #DBDFEA;
color: #fff;
}
.l2dao {

@ -0,0 +1,296 @@
<template>
<div class="container text-center">
<img class="img-fluid l2dao" src="../../assets/partners/l2dao.png" />
<span class="and">&amp;</span>
<img class="img-fluid l2dao" src="../../assets/logo-white-300.svg" />
<h1 class="mt-5">Get yourself a .L2 Domain!</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
.L2 domain is the official domain of Layer2DAO and powered by the Degen Domains protocol.
</p>
</div>
</div>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="chosenDomainName"
placeholder="enter domain name"
type="text"
class="form-control text-end"
aria-label="Text input with dropdown button"
>
<span class="input-group-text tld-addon">
<span v-if="loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!loading">{{tld}}</span>
</span>
</div>
</div>
<p class="error" v-if="buyNotValid(chosenDomainName).invalid">
<small>
<em>{{ buyNotValid(chosenDomainName).message }}</em>
</small>
</p>
<p class="mt-4">
Domain price: {{domainPrice}} ETH
</p>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="buyDomain" :disabled="waiting || buyNotValid(chosenDomainName).invalid || paused">
<span v-if="waiting" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!paused">Buy domain</span>
<span v-if="paused">Buying disabled</span>
</button>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork('Optimism')">Switch to Optimism</button>
</div>
</div>
<Referral v-if="isActivated" :urlpath="'partners/l2dao'" />
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapGetters, mapMutations } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import Referral from '../../components/Referral.vue';
import useDomainHelpers from "../../hooks/useDomainHelpers";
import useChainHelpers from "../../hooks/useChainHelpers";
import L2DaoPunkDomainsAbi from "../../abi/partners/l2dao/L2DaoPunkDomains.json";
import tldAbi from '../../abi/PunkTLD.json';
export default {
name: "L2Dao",
data() {
return {
chosenDomainName: null,
domainPrice: null,
loading: false, // loading data
mintContract: null,
paused: true,
tld: ".L2",
tldContract: null,
waiting: false, // waiting for TX to complete
}
},
components: {
Referral
},
created() {
this.setContracts();
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.chainId === 10 || this.chainId === 69) {
return true;
}
}
return false;
}
},
methods: {
...mapMutations("user", ["addDomainManually"]),
async buyDomain() {
this.waiting = true;
const fullDomainName = this.domainLowerCase + this.tld.toLowerCase();
// mint contract
let tldAddr = "0x9A7657d1593032C75d70950707870c3cC7ca45DC"; // on Optimism Mainnet
if (this.chainId === 69) {
tldAddr = "0xB5B8AF8199777d471c0320BC11022433df6D100e"; // on Optimism Testnet
}
const tldIntfc = new ethers.utils.Interface(tldAbi);
const tldContract2 = new ethers.Contract(tldAddr, tldIntfc, this.signer);
const existingHolder = await tldContract2.getDomainHolder(this.domainLowerCase);
if (existingHolder !== ethers.constants.AddressZero) {
this.toast("Sorry, but this domain name is already taken...", {type: TYPE.ERROR});
this.waiting = false;
return;
}
try {
let referral = localStorage.getItem("referral");
if (!referral || !ethers.utils.isAddress(referral)) {
referral = ethers.constants.AddressZero;
}
const tx = await tldContract2.mint(
this.domainLowerCase,
this.address,
referral,
{
value: ethers.utils.parseEther(this.domainPrice)
}
);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully bought the domain!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.setContracts();
this.addDomainManually(fullDomainName);
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(networkName) {
const networkData = this.switchNetwork(networkName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
},
async setContracts() {
this.loading = true;
let fProvider = this.getFallbackProvider(10);
let tldAddr = "0x9A7657d1593032C75d70950707870c3cC7ca45DC"; // .L2
this.tld = ".L2";
if (this.chainId === 69) { // Optimism Testnet
fProvider = this.getFallbackProvider(69);
tldAddr = "0xB5B8AF8199777d471c0320BC11022433df6D100e"; // .L2TEST
this.tld = ".L2test";
}
// TLD contract
const tldIntfc = new ethers.utils.Interface(tldAbi);
this.tldContract = new ethers.Contract(tldAddr, tldIntfc, fProvider);
const priceWei = await this.tldContract.price();
this.domainPrice = ethers.utils.formatEther(priceWei);
const buyingEnabled = await this.tldContract.buyingEnabled();
this.paused = !buyingEnabled;
this.loading = false;
},
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { buyNotValid } = useDomainHelpers();
const { switchNetwork } = useChainHelpers();
return { address, buyNotValid, chainId, isActivated, open, signer, switchNetwork, toast }
},
watch: {
address() {
this.setContracts();
},
chainId() {
this.setContracts();
},
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.2em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 30px;
}
.error {
color: #fff;
}
.l2dao {
width: 50px;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -0,0 +1,233 @@
<template>
<div class="container text-center">
<h1 class="mt-5">Misie Admin</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
This is the admin page for the .misie domain.
</p>
</div>
</div>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-1 domain-input input-group-lg">
<input
v-model="chosenDomainName"
placeholder="enter domain name"
type="text"
class="form-control text-end"
aria-label="Text input with dropdown button"
>
<span class="input-group-text tld-addon">
<span v-if="loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!loading">{{tld}}</span>
</span>
</div>
</div>
<div class="d-flex justify-content-center mt-2">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="receiverAddress"
placeholder="enter receiver address"
type="text"
class="form-control text-center"
>
</div>
</div>
<p class="error" v-if="buyNotValidFlexi(chosenDomainName).invalid">
<small>
<em>{{ buyNotValidFlexi(chosenDomainName).message }}</em>
</small>
</p>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="buyDomain" :disabled="waiting || buyNotValidFlexi(chosenDomainName).invalid">
<span v-if="waiting" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span>Mint domain</span>
</button>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork('Arbitrum')">Switch to Arbitrum</button>
</div>
</div>
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapGetters, mapMutations } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import useDomainHelpers from "../../hooks/useDomainHelpers";
import useChainHelpers from "../../hooks/useChainHelpers";
import tldAbi from '../../abi/FlexiPunkTLD.json';
export default {
name: "MisieAdmin",
data() {
return {
chosenDomainName: null,
receiverAddress: null,
domainPrice: null,
loading: false, // loading data
tld: ".misie",
tldContract: null,
waiting: false, // waiting for TX to complete
}
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.chainId === 42161) {
return true;
}
}
return false;
}
},
methods: {
...mapMutations("user", ["addDomainManually"]),
async buyDomain() {
this.waiting = true;
const fullDomainName = this.domainLowerCase + this.tld.toLowerCase();
// mint contract
let tldAddr = "0x526Ff108F5d422d0e1d6650E2Bc015BBE1fdb058"; // on Arbitrum Mainnet
const tldIntfc = new ethers.utils.Interface(tldAbi);
const tldContract2 = new ethers.Contract(tldAddr, tldIntfc, this.signer);
const existingHolder = await tldContract2.getDomainHolder(this.domainLowerCase);
if (existingHolder !== ethers.constants.AddressZero) {
this.toast("Sorry, but this domain name is already taken...", {type: TYPE.ERROR});
this.waiting = false;
return;
}
try {
const tx = await tldContract2.mint(
this.domainLowerCase,
this.receiverAddress,
ethers.constants.AddressZero,
{
value: ethers.utils.parseEther("0")
}
);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully minted the domain!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(networkName) {
const networkData = this.switchNetwork(networkName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
}
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { buyNotValidFlexi } = useDomainHelpers();
const { switchNetwork } = useChainHelpers();
return { address, buyNotValidFlexi, chainId, isActivated, open, signer, switchNetwork, toast }
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.2em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 30px;
}
.error {
color: #fff;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -0,0 +1,343 @@
<template>
<div class="container text-center">
<h1 class="mt-5">.polygon Domain Refund</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
In order to avoid domain collisions, Degen Domains .polygon TLD is shutting down. Each .polygon domain holder
will receive 14 MATIC and $2000 in credits from Unstoppable Domains.
</p>
<p>
Claim these benefits by sending your .polygon domain(s) to the burn contract using the form below. The
refund of 14 MATIC will automatically be sent to you for each burned domain.
</p>
<p>
After claiming this refund, submit
<a target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSdAR7BND4o7axj0PsFfDQyFyd2EItKKnjJek3kqCYnUe9naBA/viewform">the Google Form here</a>
to claim $2000 in UD credits.
</p>
</div>
</div>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="domains"
placeholder="enter domains (separate multiple domains with a comma)"
type="text"
class="form-control text-center"
>
</div>
</div>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="approveOrBurnDomains" :disabled="waiting || paused || !canClaim">
<span v-if="waiting || loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!paused && !loading && canClaim && approved">Burn and claim refund</span>
<span v-if="!paused && !loading && canClaim && !approved">Approve domains</span>
<span v-if="paused">Paused</span>
<span v-if="!paused && !canClaim">Not eligible</span>
</button>
<div v-if="!paused && !loading && canClaim && !approved" class="mb-2">
You will need to do two transactions: Approve + Claim
</div>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork('Polygon')">Switch to Polygon</button>
</div>
</div>
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapActions, mapGetters } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import useChainHelpers from "../../hooks/useChainHelpers";
import tldAbi from '../../abi/PunkTLD.json';
import UDPolygonRefund from '../../abi/partners/unstoppable/UDPolygonRefund.json';
export default {
name: "UnstoppablePolygonRefund",
data() {
return {
approved: false,
canClaim: false,
domains: null,
domainPrice: null,
loading: false, // loading data
paused: true,
refundAddress: null,
tld: ".polygon",
refundContract: null,
tldAddress: null,
waiting: false, // waiting for TX to complete
}
},
created() {
this.setContracts();
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.chainId === 137 || this.chainId === 80001) {
return true;
}
}
return false;
}
},
methods: {
...mapActions("user", ["removeDomainFromUserDomains"]),
approveOrBurnDomains() {
if (!this.approved) {
this.approveDomains();
} else {
this.burnDomains();
}
},
async approveDomains() {
this.waiting = true;
const intfc = new ethers.utils.Interface(tldAbi);
const tldContractSigner = new ethers.Contract(this.tldAddress, intfc, this.signer);
try {
const tx = await tldContractSigner.setApprovalForAll(this.refundAddress, true);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully approved domains! Now proceed with the Burn & Claim step.", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.approved = true;
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
async burnDomains() {
this.waiting = true;
// remove all whitespace
const domainsNoSpaces = this.domains.replace(/ /g,'');
// make string lowercase & replace all .polygon extensions (only domain names need to be sent)
const domainsNoExtension = domainsNoSpaces.toLowerCase().replaceAll(this.tld, "");
// split by comma
const domainsList = domainsNoExtension.split(",");
console.log(domainsList);
const intfc = new ethers.utils.Interface(UDPolygonRefund);
const refundContractSigner = new ethers.Contract(this.refundAddress, intfc, this.signer);
try {
const tx = await refundContractSigner.claimRefundBulk(domainsList);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully claimed the refund!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
for (let domainName of domainsList) {
this.removeDomainFromUserDomains(domainName+this.tld);
}
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(networkName) {
const networkData = this.switchNetwork(networkName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
},
async setContracts() {
this.loading = true;
let fProvider;
if (this.chainId === 137) { // Polygon Mainnet
fProvider = this.getFallbackProvider(137);
this.tld = ".polygon";
this.tldAddress = "0xBca24d86e4Ad1e011278FaEFc4fF191a731411EC"; // .polygon
this.refundAddress = "";
} else if (this.chainId === 80001) { // Polygon Testnet (Mumbai)
fProvider = this.getFallbackProvider(80001);
this.tld = ".polygontest";
this.tldAddress = "0xDEF098948F47F9Fbe80fF2D966c27965DFB47F26"; // .polygontest
this.refundAddress = "0x1d28fFd63979165c779D80f319457250545217dA";
}
if (fProvider) {
const intfc = new ethers.utils.Interface(UDPolygonRefund);
this.refundContract = new ethers.Contract(this.refundAddress, intfc, fProvider);
const isPaused = await this.refundContract.paused();
this.paused = isPaused;
}
if (this.address) {
const canClaimRefund = await this.refundContract.canClaimRefund(this.address);
this.canClaim = canClaimRefund;
const tldIntfc = new ethers.utils.Interface(tldAbi);
this.tldContract = new ethers.Contract(this.tldAddress, tldIntfc, fProvider);
const isApproved = await this.tldContract.isApprovedForAll(this.address, this.refundAddress);
this.approved = isApproved;
}
this.loading = false;
},
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { switchNetwork } = useChainHelpers();
return { address, chainId, isActivated, open, signer, switchNetwork, toast }
},
watch: {
address() {
this.setContracts();
},
chainId() {
this.setContracts();
},
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.1em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 30px;
}
.error {
color: #fff;
}
.l2dao {
width: 50px;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -0,0 +1,331 @@
<template>
<div class="container text-center">
<h1 class="mt-5">Get yourself a {{tld}} domain!</h1>
<div class="row mt-5">
<div class="col-md-8 offset-md-2">
<p>
{{tld}} domain is the official domain of
<a href="https://thewildbunch.io/" target="_blank">The Wild Bunch NFT community</a>,
and is powered by the Degen Domains protocol.
</p>
</div>
</div>
<div class="d-flex justify-content-center domain-input-container">
<div class="input-group mb-3 domain-input input-group-lg">
<input
v-model="chosenDomainName"
placeholder="enter domain name"
type="text"
class="form-control text-end"
aria-label="Text input with dropdown button"
>
<span class="input-group-text tld-addon">
<span v-if="loading" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!loading">{{tld}}</span>
</span>
</div>
</div>
<p class="error" v-if="buyNotValidFlexi(chosenDomainName).invalid">
<small>
<em>{{ buyNotValidFlexi(chosenDomainName).message }}</em>
</small>
</p>
<p class="mt-4">
Domain price: {{domainPrice}} ETH
</p>
<button v-if="isActivated && isNetworkSupported" class="btn btn-primary btn-lg mt-3 buy-button" @click="buyDomain" :disabled="waiting || buyNotValidFlexi(chosenDomainName).invalid || paused || !canMint">
<span v-if="waiting" class="spinner-border spinner-border-sm mx-1" role="status" aria-hidden="true"></span>
<span v-if="!paused && canMint">Buy domain</span>
<span v-if="!paused && !canMint">No TWB NFT</span>
<span v-if="paused">Buying disabled</span>
</button>
<div v-if="!isActivated" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="open">Connect wallet</button>
</div>
<div v-if="isActivated && !isNetworkSupported" class="mt-4 buy-button">
<button class="btn btn-primary btn-lg" @click="changeNetwork(networkName)">Switch to {{networkName}}</button>
</div>
</div>
<Referral v-if="isActivated" :urlpath="'partners/wildbunch'" />
</template>
<script>
import { ethers } from 'ethers';
import { useBoard, useEthers } from 'vue-dapp';
import { mapGetters, mapMutations } from 'vuex';
import { useToast, TYPE } from "vue-toastification";
import WaitingToast from "../../components/toasts/WaitingToast.vue";
import Referral from '../../components/Referral.vue';
import useDomainHelpers from "../../hooks/useDomainHelpers";
import useChainHelpers from "../../hooks/useChainHelpers";
import MinterAbi from "../../abi/partners/wildbunch/WildBunchMinter.json";
import tldAbi from '../../abi/FlexiPunkTLD.json';
export default {
name: "WildBunch",
data() {
return {
canMint: false,
chosenDomainName: null,
domainPrice: null,
idMainnet: 1,
idTestnet: 421611,
loading: false, // loading data
mintAddressTestnet: "0x6b5E4D2Bc94F356B3557AaEc35422d21FdcA66c9",
mintAddressMainnet: "0xA8221890768603210c1a32d88374111084E46E6d",
mintContract: null,
nftAddressTestnet: "0x247934a3Cd3293AB0B334F0c5571B6fF05d1Dc11",
nftAddressMainnet: "0xe9A1a323b4c8FD5Ce6842edaa0cd8af943cBdf22",
nftContract: null,
networkName: "Ethereum",
paused: true,
tld: ".wildbunch",
tldAddressTestnet: "0xEEAEED736cc6A6e68CC2F62be19Cf7E06ad9E94A",
tldAddressMainnet: "0xaa9E5Ade68C9C3Ea967Dc5dde731fd1f797152Cb",
tldContract: null,
waiting: false, // waiting for TX to complete
}
},
components: {
Referral
},
created() {
this.setContracts();
},
computed: {
...mapGetters("network", ["getBlockExplorerBaseUrl", "getFallbackProvider"]),
domainLowerCase() {
return this.chosenDomainName.toLowerCase();
},
isNetworkSupported() {
if (this.isActivated) {
if (this.networkName.includes("Testnet") && this.chainId === this.idTestnet) {
return true;
} else if (!this.networkName.includes("Testnet") && this.chainId === this.idMainnet) {
return true;
}
}
return false;
},
},
methods: {
...mapMutations("user", ["addDomainManually"]),
async buyDomain() {
this.waiting = true;
const fullDomainName = this.domainLowerCase + this.tld.toLowerCase();
// check if domain is available
const existingHolder = await this.tldContract.getDomainHolder(this.domainLowerCase);
if (existingHolder !== ethers.constants.AddressZero) {
this.toast("Sorry, but this domain name is already taken...", {type: TYPE.ERROR});
this.waiting = false;
return;
}
// set up minting contract
let mintAddress = this.mintAddressMainnet;
if (this.chainId === this.idTestnet) {
mintAddress = this.mintAddressTestnet;
}
const mintIntfc = new ethers.utils.Interface(MinterAbi);
this.mintContract = new ethers.Contract(mintAddress, mintIntfc, this.signer);
try {
let referral = localStorage.getItem("referral");
if (!referral || !ethers.utils.isAddress(referral)) {
referral = ethers.constants.AddressZero;
}
const tx = await this.mintContract.mint(
this.domainLowerCase,
this.address,
referral,
{
value: ethers.utils.parseEther(this.domainPrice)
}
);
const toastWait = this.toast(
{
component: WaitingToast,
props: {
text: "Please wait for your transaction to confirm. Click on this notification to see transaction in the block explorer."
}
},
{
type: TYPE.INFO,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
}
);
const receipt = await tx.wait();
if (receipt.status === 1) {
this.toast.dismiss(toastWait);
this.toast("You have successfully bought a " + this.tld + " domain!", {
type: TYPE.SUCCESS,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
this.setContracts();
this.addDomainManually(fullDomainName);
this.waiting = false;
} else {
this.toast.dismiss(toastWait);
this.toast("Transaction has failed.", {
type: TYPE.ERROR,
onClick: () => window.open(this.getBlockExplorerBaseUrl+"/tx/"+tx.hash, '_blank').focus()
});
console.log(receipt);
this.waiting = false;
}
} catch (e) {
console.log(e)
this.waiting = false;
this.toast(e.message, {type: TYPE.ERROR});
}
this.waiting = false;
},
changeNetwork(nName) {
const networkData = this.switchNetwork(nName);
window.ethereum.request({
method: networkData.method,
params: networkData.params
});
},
async setContracts() {
this.loading = true;
// testnet data
let fProvider = this.getFallbackProvider(this.idMainnet);
let tldAddr = this.tldAddressMainnet;
let mintAddr = this.mintAddressMainnet;
let nftAddr = this.nftAddressMainnet;
this.tld = ".wildbunch";
// testnet data
if (this.chainId === this.idTestnet) {
fProvider = this.getFallbackProvider(this.idTestnet);
tldAddr = this.tldAddressTestnet;
mintAddr = this.mintAddressTestnet;
nftAddr = this.nftAddressTestnet;
this.tld = ".twbtest";
}
// TLD contract
const tldIntfc = new ethers.utils.Interface(tldAbi); // note: interface must be defined as const, not as component data var!
this.tldContract = new ethers.Contract(tldAddr, tldIntfc, fProvider);
const priceWei = await this.tldContract.price();
this.domainPrice = ethers.utils.formatEther(priceWei);
if (this.address) {
// NFT contract
const nftIntfc = new ethers.utils.Interface([
"function balanceOf(address) external view returns (uint256)"
]);
this.nftContract = new ethers.Contract(nftAddr, nftIntfc, fProvider);
const balance = await this.nftContract.balanceOf(this.address);
if (balance > 0) {
this.canMint = true;
}
}
// minting contract
const mintIntfc = new ethers.utils.Interface(MinterAbi);
this.mintContract = new ethers.Contract(mintAddr, mintIntfc, fProvider);
this.paused = await this.mintContract.paused();
this.loading = false;
}
},
setup() {
const { open } = useBoard();
const { address, chainId, isActivated, signer } = useEthers();
const toast = useToast();
const { buyNotValidFlexi } = useDomainHelpers();
const { switchNetwork } = useChainHelpers();
return { address, buyNotValidFlexi, chainId, isActivated, open, signer, switchNetwork, toast }
},
watch: {
address() {
this.setContracts();
},
chainId() {
this.setContracts();
},
}
}
</script>
<style scoped>
.and {
font-size: 1.7em;
vertical-align: bottom;
padding-left: 0.2em;
padding-right: 0.2em;
}
.buy-button {
margin-bottom: 50px;
}
.domain-input {
width: 50%;
}
.domain-input-container {
margin-top: 30px;
}
.error {
color: #fff;
}
.l2dao {
width: 50px;
}
.tld-addon {
background-color: white;
}
@media only screen and (max-width: 767px) {
.domain-input {
width: 100%;
}
}
</style>

@ -1,30 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";
import inject from "@rollup/plugin-inject";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
svelte(),
inject({
util: "util/",
}),
],
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true,
}),
],
},
},
});
plugins: [vue()],
})

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save