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", |
"3": "0xbb056744bB2Ab473058ED7F3e1764FCf4Bb1313D", |
||||||
"4": "0x844d982FDc1F5C8eaD82E95d522F2486a7CBb3EE", |
"4": "0x844d982FDc1F5C8eaD82E95d522F2486a7CBb3EE", |
||||||
"10": "0xA8221890768603210c1a32d88374111084E46E6d", |
"10": "0xA8221890768603210c1a32d88374111084E46E6d", |
||||||
"56": "0xTODO", |
"14": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a", |
||||||
|
"19": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a", |
||||||
"69": "0x0F081cad5BCed7B2acA1c1D22CdafcB21322B280", |
"69": "0x0F081cad5BCed7B2acA1c1D22CdafcB21322B280", |
||||||
"77": "0xf6A44f61030115B5dA382b198B711130D98390d9", |
"77": "0xf6A44f61030115B5dA382b198B711130D98390d9", |
||||||
"97": "0xTODO", |
|
||||||
"100": "0xA8221890768603210c1a32d88374111084E46E6d", |
"100": "0xA8221890768603210c1a32d88374111084E46E6d", |
||||||
"137": "0xB6cf67a0aCE92F357908C6eF716a34c9b196c1DC", |
"137": "0xB6cf67a0aCE92F357908C6eF716a34c9b196c1DC", |
||||||
"568": "0xTODO", |
"250": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a", |
||||||
"2000": "0xTODO", |
"4002": "0xeA2f99fE93E5D07F61334C5Eb9c54c5D5C957a6a", |
||||||
"80001": "0xC74f279E5A7FDAd6624054518773ae4EC77E78D3", |
"80001": "0x8fbff791fCcF596DEf2e788549d0275557F95A21", |
||||||
"42161": "0x4bD57a848c56E6241296a1256FB2bDEbCdbb9dB0", |
"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", |
"10": "0xF20fc12a4955c9d47194B8fEd591Fe01777D2b06", |
||||||
|
"14": "0x2919f0bE09549814ADF72fb0387D1981699fc6D4", |
||||||
|
"19": "0x7e8aB50697C7Abe63Bdab6B155C2FB8D285458cB", |
||||||
"56": "0x4aBf8b364ac4aF048Ea077AAA2EDF3e1e1EC0f9c", |
"56": "0x4aBf8b364ac4aF048Ea077AAA2EDF3e1e1EC0f9c", |
||||||
"69": "0xa1303d259B87f044404536638E2784DEe897B402", |
"69": "0xa1303d259B87f044404536638E2784DEe897B402", |
||||||
"77": "0x7A84e7f48DCe4ab212c3511eC5ade0982eaBa8c4", |
"77": "0x7A84e7f48DCe4ab212c3511eC5ade0982eaBa8c4", |
||||||
"97": "0xTODO", |
|
||||||
"100": "0x7Df67B2ef4eEDf49Fc53Bb6E94e90e9546FC6c6B", |
"100": "0x7Df67B2ef4eEDf49Fc53Bb6E94e90e9546FC6c6B", |
||||||
"137": "0x07884566cdED43eDaec7813C1523624202b060D3", |
"137": "0x07884566cdED43eDaec7813C1523624202b060D3", |
||||||
"568": "0xTODO", |
"250": "0xa97c7AF10ee564EBf452A9347bB9653454Ba69C0", |
||||||
"2000": "0xTODO", |
"4002": "0xa97c7AF10ee564EBf452A9347bB9653454Ba69C0", |
||||||
"80001": "0xC17E9347Ce26D7630A98eC4158Bd7200E54bf4Cd", |
"80001": "0x24799a4AF8e5215Dfe22054ffF91B0A1C428D1A3", |
||||||
"42161": "0xd64A2DF9d73CD1Cb50139A3eC3176070e00C67cA", |
"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 { createStore } from 'vuex'; |
||||||
import network from "./modules/network"; |
import network from "./modules/network"; |
||||||
import user from "./modules/user"; |
import user from "./modules/user"; |
||||||
import degen from "./modules/degen"; |
import punk from "./modules/punk"; |
||||||
|
|
||||||
|
|
||||||
const store = createStore({ |
const store = createStore({ |
||||||
modules: { |
modules: { |
||||||
network, |
network, |
||||||
user, |
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> |
<template> |
||||||
|
<SendTokensComponent /> |
||||||
<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> |
|
||||||
|
|
||||||
</template> |
</template> |
||||||
|
|
||||||
<script lang="ts"> |
<script> |
||||||
import { ethers } from 'ethers'; |
import SendTokensComponent from "../components/SendTokensComponent.vue"; |
||||||
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"; |
|
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "SendTokens", |
name: "SendTokens", |
||||||
|
|
||||||
components: { |
components: { |
||||||
Sidebar |
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.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); |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style scoped> |
|
||||||
#balance { |
|
||||||
text-decoration: underline; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
#balance:hover { |
|
||||||
text-decoration: none; |
|
||||||
} |
|
||||||
|
|
||||||
.domain-error { |
|
||||||
color: red; |
|
||||||
margin-left: 5px; |
|
||||||
} |
|
||||||
</style> |
|
@ -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 { defineConfig } from 'vite' |
||||||
import vue from '@vitejs/plugin-vue' |
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/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({ |
export default defineConfig({ |
||||||
plugins: [ |
plugins: [vue()], |
||||||
vue(), |
}) |
||||||
svelte(), |
|
||||||
inject({ |
|
||||||
util: "util/", |
|
||||||
}), |
|
||||||
], |
|
||||||
optimizeDeps: { |
|
||||||
esbuildOptions: { |
|
||||||
// Node.js global to browser globalThis
|
|
||||||
define: { |
|
||||||
global: "globalThis", |
|
||||||
}, |
|
||||||
// Enable esbuild polyfill plugins
|
|
||||||
plugins: [ |
|
||||||
NodeGlobalsPolyfillPlugin({ |
|
||||||
buffer: true, |
|
||||||
}), |
|
||||||
], |
|
||||||
}, |
|
||||||
}, |
|
||||||
}); |
|