After Width: | Height: | Size: 160 KiB |
@ -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" |
||||
} |
||||
} |
@ -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" |
||||
} |
After Width: | Height: | Size: 656 KiB |
Before Width: | Height: | Size: 374 KiB |
Before Width: | Height: | Size: 2.6 MiB |
Before Width: | Height: | Size: 181 KiB |
Before Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 2.0 KiB |
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> |
@ -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> |
@ -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 |
||||
} |
||||
}) |
||||
|
||||
|
@ -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> |
@ -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> |
@ -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> |
@ -0,0 +1,296 @@ |
||||
<template> |
||||
<div class="container text-center"> |
||||
<img class="img-fluid l2dao" src="../../assets/partners/l2dao.png" /> |
||||
<span class="and">&</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()], |
||||
}) |