From 1161c00b8eaf93a1f63f8d18aa1c3cb0dce736c1 Mon Sep 17 00:00:00 2001 From: Sergei Merenkov Date: Wed, 21 Jul 2021 18:46:33 +0300 Subject: [PATCH] UNS support (#50) * remove crypto validation except .zil (#42) * remove crypto validation except .zil * remove specific domain constant * Added ERC721 metadata methods (#43) * Added erc methods * rename cns to uns * rename files and update resolver abi * fix metadata api request * get and use new config files * clean up * clean * parse cnsRegistry as well * review updates * Redme and tests * fix buildContract and cns * fix xcode * correctly parse both registry contracts * remove unused resolver contract entry * move tests from mainnet to rinkeby * Update isSupportedDomain (#46) * update proxy reader abi * fix abi parsing due to new abi * isSupportedDomain * update tests * don't check for isSupported under the hood, instead if ending is on .zil use zns otherwise use uns * code clean issupported * add tests for new tlds * try to make async call instead of sync on tokensOwnedBy * make calls async * clean up * Use newuri for unhash (#47) * Use event for unhash * Add pulling registry from proxy reader * Tests for abicoder, remove unused code * Update CryptoSwift to newest version. Remove EthereumAddress dependency (moved to support files) (#49) * Revert "Merge pull request #41 from unstoppabledomains/removeEns" (#48) * Revert "Merge pull request #41 from unstoppabledomains/removeEns" This reverts commit a1cbfea1fb09231fc3010d6f6b7ac44c4f22b61b, reversing changes made to 4ea6607114698bf1bccaf83d8839622ad68f87e6. * changelog * update getServiceOf * revert he changes in podspec * make sure uns will not recognize the ens domains * Update Sources/UnstoppableDomainsResolution/Resolution.swift * Update Sources/UnstoppableDomainsResolution/NamingServices/ENS.swift * my fixes Co-authored-by: Sergei Merenkov * allow any network as long as proxyReader contract is defined * allow zns to use custom network * better error when ens or zns doesn't receive registry address with custom network * update changelog * update changelog * expand changelog * fix dependency * Update changelog * Update changelog Co-authored-by: JohnnyJumper Co-authored-by: Mike <5020980+DancingAxolotl@users.noreply.github.com> Co-authored-by: Gentelman John Co-authored-by: Kirill Beresnev --- CHANGELOG.md | 17 + Package.resolved | 13 +- Package.swift | 20 +- README.md | 42 +- Resolution.xcodeproj/project.pbxproj | 163 +- .../xcshareddata/swiftpm/Package.resolved | 13 +- .../xcschemes/resolution.xcscheme | 8 +- .../ABI/ABICoder.swift | 1 + .../ABI/EthereumABI/ABIDecoder.swift | 1 - .../ABI/EthereumABI/ABIEncoder.swift | 1 - .../ABI/EthereumABI/ABIParameterTypes.swift | 1 - .../ABI/EthereumABI/ABIParsing.swift | 3 +- .../APIRequest.swift | 24 + .../Configurations.swift | 19 +- .../Contract.swift | 9 +- .../UnstoppableDomainsResolution/Errors.swift | 1 + .../Helpers/TokenUriMetadata.swift | 69 + .../Helpers/Types.swift | 9 + .../NamingServices/CommonNamingService.swift | 25 +- .../NamingServices/ENS.swift | 182 ++ .../NamingServices/{CNS.swift => UNS.swift} | 239 +- .../NamingServices/ZNS.swift | 24 +- .../Protocols/NamingService.swift | 7 +- .../Resolution.swift | 147 +- .../Resources/CNS/cnsProxyReader.json | 639 ----- .../Resources/CNS/cnsResolver.json | 402 --- .../Resources/CNS/network-config.json | 98 - .../Resources/CNS/supported-keys.json | 648 ----- .../Resources/ENS/ensRegistry.json | 108 + .../Resources/ENS/ensResolver.json | 357 +++ .../Resources/{CNS => UNS}/cnsRegistry.json | 1 + .../Resources/UNS/supported-keys.json | 2375 +++++++++++++++++ .../Resources/UNS/uns-config.json | 236 ++ .../Resources/UNS/unsProxyReader.json | 539 ++++ .../Resources/UNS/unsRegistry.json | 981 +++++++ .../Resources/UNS/unsResolver.json | 265 ++ .../Support/Base58Swift/Base58.swift | 107 + .../Support/Base58Swift/README.md | 86 + .../EthereumAddress/EthereumAddress.swift | 139 + Tests/ABICoderTests/ABICoderTests.swift | 124 + Tests/ABICoderTests/Info.plist | 22 + Tests/EthereumABITests/EthereumABITests.swift | 1 - Tests/HelpersTests/Info.plist | 22 + .../HelpersTests/TokenUriMetadataTests.swift | 81 + Tests/LinuxMain.swift | 2 + Tests/ResolutionTests/ResolutionTests.swift | 476 +++- Tests/ResolutionTests/XCTestManifests.swift | 4 +- UnstoppableDomainsResolution.podspec | 3 +- 48 files changed, 6679 insertions(+), 2075 deletions(-) create mode 100644 Sources/UnstoppableDomainsResolution/Helpers/TokenUriMetadata.swift create mode 100644 Sources/UnstoppableDomainsResolution/NamingServices/ENS.swift rename Sources/UnstoppableDomainsResolution/NamingServices/{CNS.swift => UNS.swift} (53%) delete mode 100644 Sources/UnstoppableDomainsResolution/Resources/CNS/cnsProxyReader.json delete mode 100644 Sources/UnstoppableDomainsResolution/Resources/CNS/cnsResolver.json delete mode 100644 Sources/UnstoppableDomainsResolution/Resources/CNS/network-config.json delete mode 100644 Sources/UnstoppableDomainsResolution/Resources/CNS/supported-keys.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/ENS/ensRegistry.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/ENS/ensResolver.json rename Sources/UnstoppableDomainsResolution/Resources/{CNS => UNS}/cnsRegistry.json (99%) create mode 100644 Sources/UnstoppableDomainsResolution/Resources/UNS/supported-keys.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/UNS/unsProxyReader.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/UNS/unsRegistry.json create mode 100644 Sources/UnstoppableDomainsResolution/Resources/UNS/unsResolver.json create mode 100644 Sources/UnstoppableDomainsResolution/Support/Base58Swift/Base58.swift create mode 100644 Sources/UnstoppableDomainsResolution/Support/Base58Swift/README.md create mode 100644 Sources/UnstoppableDomainsResolution/Support/EthereumAddress/EthereumAddress.swift create mode 100644 Tests/ABICoderTests/ABICoderTests.swift create mode 100644 Tests/ABICoderTests/Info.plist create mode 100644 Tests/HelpersTests/Info.plist create mode 100644 Tests/HelpersTests/TokenUriMetadataTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 628a454..b3337ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Resolution-swift CHANGELOG +## 2.0.0 + +### Breaking changes + +- `Resolution#isSupported` is now making an async call. Method signature was changed. +- `Configurations` class accepts `uns` configs instead of `cns`. + - For example: `let resolution = try Resolution(configs: Configurations(uns: NamingServiceConfig(...uns config)));` + +### New methods and features + +- Support new TLD's ( .888, .nft, .coin, .blockchain, .wallet, .x, .bitcoin, .dao ) +- Introduce Resolution#tokenURI - Retrieves the tokenURI from the registry smart contract +- Introduce Resolution#tokenURIMetadata - Retrieves the data from the endpoint provided by tokenURI from the registry smart contract. +- Introduce Resolution#unhash - Retrieves the domain name from token metadata that is provided by tokenURI from the registry smart contract +- Return `ENS` support +- Allowed custom networks for each of the naming services. If custom network has been set, it is required to set the proxyReader contract address for UNS and registryAddress for ENS && ZNS (see `./Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json`) + ## 1.0.0 - Remove Ens support ([#41](https://github.com/unstoppabledomains/resolution-swift/pull/41)) via [@JohnnyJumper](https://github.com/JohnnyJumper) diff --git a/Package.resolved b/Package.resolved index cb0f393..68c5ebc 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,17 +15,8 @@ "repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift.git", "state": { "branch": null, - "revision": "3a2acbb32ab68215ee1596ee6004da8e90c3721b", - "version": "1.0.0" - } - }, - { - "package": "EthereumAddress", - "repositoryURL": "https://github.com/shamatar/EthereumAddress.git", - "state": { - "branch": null, - "revision": "a8eb4fc1dc03c068bf88585d8f5a2dd3572664ca", - "version": "1.3.0" + "revision": "8d4f6384e0a8cc41f2005247241dd553963a492a", + "version": "1.4.1" } } ] diff --git a/Package.swift b/Package.swift index 83347cc..97f3f9c 100644 --- a/Package.swift +++ b/Package.swift @@ -13,20 +13,20 @@ let package = Package( targets: ["UnstoppableDomainsResolution"]) ], dependencies: [ - .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.0.0"), - .package(url: "https://github.com/attaswift/BigInt.git", from: "5.0.0"), - .package(url: "https://github.com/shamatar/EthereumAddress.git", from: "1.3.0") + .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.3.8"), + .package(url: "https://github.com/attaswift/BigInt.git", from: "5.0.0") ], targets: [ .target( name: "UnstoppableDomainsResolution", - dependencies: ["CryptoSwift", "BigInt", "EthereumAddress"], + dependencies: ["CryptoSwift", "BigInt"], resources: [ - .process("Resources/CNS/supported-keys.json"), - .process("Resources/CNS/cnsProxyReader.json"), - .process("Resources/CNS/cnsRegistry.json"), - .process("Resources/CNS/cnsResolver.json"), - .process("Resources/CNS/network-config.json"), + .process("Resources/UNS/supported-keys.json"), + .process("Resources/UNS/unsProxyReader.json"), + .process("Resources/UNS/unsRegistry.json"), + .process("Resources/UNS/cnsRegistry.json"), + .process("Resources/UNS/unsResolver.json"), + .process("Resources/UNS/uns-config.json"), .process("Resources/ENS/ensRegistry.json"), .process("Resources/ENS/ensResolver.json") ], @@ -35,7 +35,7 @@ let package = Package( .testTarget( name: "ResolutionTests", dependencies: ["UnstoppableDomainsResolution"], - exclude:["Info.plist"], + exclude: ["Info.plist"], swiftSettings: [.define("INSIDE_PM")] ) ] diff --git a/README.md b/README.md index e3f23bf..774d2c6 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,24 @@ Resolution is primarily built and maintained by [Unstoppable Domains](https://un Resoultion supports decentralized domains across three main zones: -- Crypto Name Service (CNS) +- Crypto Name Service (uns) - `.crypto` -- Zilliqa Name Service (ZNS) + - `.coin` + - `.wallet` + - `.bitcoin` + - `.blockchain` + - `.x` + - `.888` + - `.nft` + - `.dao` +- Zilliqa Name Service (zns) - `.zil` +- Ethereum Name Service (ENS) + - `.eth` + - `.kred` + - `.xyz` + - `.luxe` + # Installation into the project ## Cocoa Pods @@ -120,16 +134,19 @@ resolution.record(domain: "ryan.crypto", record: "custom.record.value") { result Version 0.3.0 introduced the `Configurations` struct that is used for configuring each connected naming service. Library can offer three naming services at the moment: -* `cns` resolves `.crypto` domains, +* `uns` resolves `.crypto` , `.coin`, `.wallet`, `.bitcoin`, `.blockchain`, `.x`, `.888`, `.nft`, `.dao` domains, +* `ens` resolves `.eth`, `.kred`, `.xyz`, `.luxe` domains * `zns` resolves `.zil` domains By default, each of them is using the mainnet network via infura provider. -Unstoppable domains are using the infura key with no restriction for CNS. +Unstoppable domains are using the infura key with no restriction for UNS. +Unstoppable domains recommends setting up your own provider for ENS, as we don't guarantee ENS Infura key availability. + You can update each naming service separately ```swift let resolution = try Resolution(configs: Configurations( - cns: NamingServiceConfig( + uns: NamingServiceConfig( providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", network: "rinkeby" ) @@ -147,13 +164,26 @@ resolution.addr(domain: "udtestdev-creek.crypto", ticker: "eth") { (result) in XCTFail("Expected Eth Address, but got \(error)") } } + +// naming services that hasn't been touched by Configrations struct are using default settings +// the following will look up monkybrain.eth on the mainnet via infura provider + +resolution.addr(domain: "monkybrain.eth", ticker: "eth") { (result) in + switch result { + case .success(let returnValue): + ethENSAddress = returnValue + domainEthReceived.fulfill() + case .failure(let error): + XCTFail("Expected Eth Address, but got \(error)") + } +} ``` ## Batch requesting of owners Version 0.1.3 introduced the `batchOwners(domains: _, completion: _ )` method which adds additional convenience when making multiple domain owner queries. -> This method is only compatible with CNS-based domains. Using this method with any other domain type will throw the error: `ResolutionError.methodNotSupported`. +> This method is only compatible with uns-based domains. Using this method with any other domain type will throw the error: `ResolutionError.methodNotSupported`. As opposed to the single `owner(domain: _, completion: _)` method, this batch request will return an array of owners `[String?]`. If the the domain is not registered or its value is `null`, the corresponding array element of the response will be `nil` without throwing an error. diff --git a/Resolution.xcodeproj/project.pbxproj b/Resolution.xcodeproj/project.pbxproj index 48a3efa..e8e7b65 100644 --- a/Resolution.xcodeproj/project.pbxproj +++ b/Resolution.xcodeproj/project.pbxproj @@ -3,36 +3,44 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 30A69245251385A70079EC69 /* cnsProxyReader.json in Resources */ = {isa = PBXBuildFile; fileRef = 30A69244251385A70079EC69 /* cnsProxyReader.json */; }; - 30AE8615257A8CCD003A0142 /* network-config.json in Resources */ = {isa = PBXBuildFile; fileRef = 30AE8614257A8CCD003A0142 /* network-config.json */; }; + 30A69245251385A70079EC69 /* unsProxyReader.json in Resources */ = {isa = PBXBuildFile; fileRef = 30A69244251385A70079EC69 /* unsProxyReader.json */; }; 3E105520258C95D300652FC7 /* DnsType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E10551F258C95D300652FC7 /* DnsType.swift */; }; 3E105524258CB73400652FC7 /* DnsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E105523258CB73400652FC7 /* DnsUtils.swift */; }; 3E10552E258CBD0900652FC7 /* DnsRecordsError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E10552D258CBD0900652FC7 /* DnsRecordsError.swift */; }; - 3E2AC91C24E4FA28008EBC39 /* CNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E2AC91B24E4FA28008EBC39 /* CNS.swift */; }; + 3E2AC91C24E4FA28008EBC39 /* UNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E2AC91B24E4FA28008EBC39 /* UNS.swift */; }; 3E2AC91F24E4FA35008EBC39 /* NamingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E2AC91E24E4FA35008EBC39 /* NamingService.swift */; }; - 3E2AC93E24E4FC9F008EBC39 /* cnsResolver.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E2AC93C24E4FC9F008EBC39 /* cnsResolver.json */; }; - 3E2AC93F24E4FC9F008EBC39 /* cnsRegistry.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E2AC93D24E4FC9F008EBC39 /* cnsRegistry.json */; }; + 3E2AC93E24E4FC9F008EBC39 /* unsResolver.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E2AC93C24E4FC9F008EBC39 /* unsResolver.json */; }; + 3E2AC93F24E4FC9F008EBC39 /* unsRegistry.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E2AC93D24E4FC9F008EBC39 /* unsRegistry.json */; }; 3E33F99925DCFAB400627C71 /* Configurations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E33F99825DCFAB400627C71 /* Configurations.swift */; }; 3E65912824E381E900D7EC35 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E65912724E381E900D7EC35 /* Errors.swift */; }; 3E65913124E4ADAC00D7EC35 /* Contract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E65913024E4ADAC00D7EC35 /* Contract.swift */; }; + 3E889CC8268AF94E000C5330 /* TokenUriMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E889CC7268AF94E000C5330 /* TokenUriMetadata.swift */; }; + 3E889CCE268AFA83000C5330 /* supported-keys.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E889CCD268AFA83000C5330 /* supported-keys.json */; }; + 3E889D12268B1BBB000C5330 /* uns-config.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E889D11268B1BBB000C5330 /* uns-config.json */; }; + 3E889D1E268D51CF000C5330 /* cnsRegistry.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E889D1D268D51CF000C5330 /* cnsRegistry.json */; }; 3EAFA3F724EB59DA008791E9 /* ABICoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAFA3F624EB59DA008791E9 /* ABICoder.swift */; }; 3EAFA3FE24EE03E0008791E9 /* JSON_RPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAFA3FD24EE03E0008791E9 /* JSON_RPC.swift */; }; 3EAFA40024EE0CFD008791E9 /* APIRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAFA3FF24EE0CFD008791E9 /* APIRequest.swift */; }; 3EAFA40224EE312A008791E9 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAFA40124EE312A008791E9 /* Utilities.swift */; }; 3EAFA40424EE32B2008791E9 /* CommonNamingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAFA40324EE32B2008791E9 /* CommonNamingService.swift */; }; + 3EC9E0482697F2E0001521B4 /* ensResolver.json in Resources */ = {isa = PBXBuildFile; fileRef = 8449EDFB2513BA3D00DABB57 /* ensResolver.json */; }; 3ECD84AE25A6AEE1001772DD /* UsdtVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECD84AD25A6AEE1001772DD /* UsdtVersion.swift */; }; 3EE4DA0D24E367720097540B /* Resolution.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EE4DA0324E367720097540B /* Resolution.framework */; }; 3EE4DA1224E367720097540B /* ResolutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE4DA1124E367720097540B /* ResolutionTests.swift */; }; 3EE4DA1424E367720097540B /* resolution.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EE4DA0624E367720097540B /* resolution.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3EE4DA1E24E367D40097540B /* Resolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE4DA1D24E367D40097540B /* Resolution.swift */; }; 8402F708250935FE0007F01D /* ContractZNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8402F707250935FD0007F01D /* ContractZNS.swift */; }; + 8449EDFA25139F2500DABB57 /* ensRegistry.json in Resources */ = {isa = PBXBuildFile; fileRef = 8449EDF925139F2500DABB57 /* ensRegistry.json */; }; + 845B401D251389A4006AB08E /* ENS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B401C251389A4006AB08E /* ENS.swift */; }; 848E21092507890A008707D2 /* ZNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848E21082507890A008707D2 /* ZNS.swift */; }; 848E210C25079D61008707D2 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848E210B25079D61008707D2 /* Types.swift */; }; + B650B487269F23460054727E /* EthereumAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B650B486269F23460054727E /* EthereumAddress.swift */; }; B6B202C8260226B700A72AF2 /* BigInt in Frameworks */ = {isa = PBXBuildFile; productRef = B6B202C7260226B700A72AF2 /* BigInt */; }; + B6E79938260223CE00F65894 /* Base58.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E79936260223CE00F65894 /* Base58.swift */; }; B6F2075425DBD89800140CE3 /* ABIEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F2074C25DBD89800140CE3 /* ABIEncoder.swift */; }; B6F2075525DBD89800140CE3 /* ABIDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F2074D25DBD89800140CE3 /* ABIDecoder.swift */; }; B6F2075625DBD89800140CE3 /* ABIElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F2074E25DBD89800140CE3 /* ABIElements.swift */; }; @@ -43,7 +51,6 @@ B6F2075B25DBD89800140CE3 /* ABIParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F2075325DBD89800140CE3 /* ABIParsing.swift */; }; B6F2076125DBD8C800140CE3 /* EthereumABITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F2075F25DBD8C700140CE3 /* EthereumABITests.swift */; }; B6F2076D25DBD93900140CE3 /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = B6F2076C25DBD93900140CE3 /* CryptoSwift */; }; - B6F2077B25DBD99F00140CE3 /* EthereumAddress in Frameworks */ = {isa = PBXBuildFile; productRef = B6F2077A25DBD99F00140CE3 /* EthereumAddress */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -58,23 +65,30 @@ /* Begin PBXFileReference section */ 3045D148251E2C6200B65A06 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; - 30A69244251385A70079EC69 /* cnsProxyReader.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = cnsProxyReader.json; sourceTree = ""; }; - 30AE8614257A8CCD003A0142 /* network-config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "network-config.json"; sourceTree = ""; }; + 30A69244251385A70079EC69 /* unsProxyReader.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = unsProxyReader.json; sourceTree = ""; }; 3E10551F258C95D300652FC7 /* DnsType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DnsType.swift; sourceTree = ""; }; 3E105523258CB73400652FC7 /* DnsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DnsUtils.swift; sourceTree = ""; }; 3E10552D258CBD0900652FC7 /* DnsRecordsError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DnsRecordsError.swift; sourceTree = ""; }; - 3E2AC91B24E4FA28008EBC39 /* CNS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CNS.swift; sourceTree = ""; }; + 3E2AC91B24E4FA28008EBC39 /* UNS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UNS.swift; sourceTree = ""; }; 3E2AC91E24E4FA35008EBC39 /* NamingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NamingService.swift; sourceTree = ""; }; - 3E2AC93C24E4FC9F008EBC39 /* cnsResolver.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = cnsResolver.json; sourceTree = ""; }; - 3E2AC93D24E4FC9F008EBC39 /* cnsRegistry.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = cnsRegistry.json; sourceTree = ""; }; + 3E2AC93C24E4FC9F008EBC39 /* unsResolver.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = unsResolver.json; sourceTree = ""; }; + 3E2AC93D24E4FC9F008EBC39 /* unsRegistry.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = unsRegistry.json; sourceTree = ""; }; + 3E322BA0269F5542007023A6 /* ABICoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ABICoderTests.swift; path = ABICoderTests/ABICoderTests.swift; sourceTree = ""; }; + 3E322BA1269F5552007023A6 /* TokenUriMetadataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TokenUriMetadataTests.swift; path = HelpersTests/TokenUriMetadataTests.swift; sourceTree = ""; }; 3E33F99825DCFAB400627C71 /* Configurations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configurations.swift; sourceTree = ""; }; 3E65912724E381E900D7EC35 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; 3E65913024E4ADAC00D7EC35 /* Contract.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contract.swift; sourceTree = ""; }; + 3E889CC7268AF94E000C5330 /* TokenUriMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenUriMetadata.swift; sourceTree = ""; }; + 3E889CCD268AFA83000C5330 /* supported-keys.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "supported-keys.json"; sourceTree = ""; }; + 3E889D11268B1BBB000C5330 /* uns-config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "uns-config.json"; sourceTree = ""; }; + 3E889D1D268D51CF000C5330 /* cnsRegistry.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = cnsRegistry.json; sourceTree = ""; }; 3EAFA3F624EB59DA008791E9 /* ABICoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ABICoder.swift; sourceTree = ""; }; 3EAFA3FD24EE03E0008791E9 /* JSON_RPC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON_RPC.swift; sourceTree = ""; }; 3EAFA3FF24EE0CFD008791E9 /* APIRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIRequest.swift; sourceTree = ""; }; 3EAFA40124EE312A008791E9 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; }; 3EAFA40324EE32B2008791E9 /* CommonNamingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonNamingService.swift; sourceTree = ""; }; + 3EC9E04B2697FF84001521B4 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; + 3EC9E04E2698002F001521B4 /* UnstoppableDomainsResolution.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnstoppableDomainsResolution.podspec; sourceTree = ""; }; 3ECD84AD25A6AEE1001772DD /* UsdtVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsdtVersion.swift; sourceTree = ""; }; 3EE4DA0324E367720097540B /* Resolution.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Resolution.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3EE4DA0624E367720097540B /* resolution.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = resolution.h; sourceTree = ""; }; @@ -85,10 +99,16 @@ 3EE4DA1D24E367D40097540B /* Resolution.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Resolution.swift; sourceTree = ""; }; 8402F707250935FD0007F01D /* ContractZNS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContractZNS.swift; sourceTree = ""; }; 8425AED824FFBADF00BBCBBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 8449EDF925139F2500DABB57 /* ensRegistry.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ensRegistry.json; sourceTree = ""; }; + 8449EDFB2513BA3D00DABB57 /* ensResolver.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ensResolver.json; sourceTree = ""; }; + 845B401C251389A4006AB08E /* ENS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENS.swift; sourceTree = ""; }; 848E21082507890A008707D2 /* ZNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZNS.swift; sourceTree = ""; }; 848E210B25079D61008707D2 /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = ""; }; 849E07CC24F946CA00A793D3 /* LinuxMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinuxMain.swift; sourceTree = ""; }; 849E07D124F9499900A793D3 /* XCTestManifests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = ""; }; + B650B486269F23460054727E /* EthereumAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthereumAddress.swift; sourceTree = ""; }; + B6E79935260223CE00F65894 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + B6E79936260223CE00F65894 /* Base58.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base58.swift; sourceTree = ""; }; B6F2074C25DBD89800140CE3 /* ABIEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ABIEncoder.swift; sourceTree = ""; }; B6F2074D25DBD89800140CE3 /* ABIDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ABIDecoder.swift; sourceTree = ""; }; B6F2074E25DBD89800140CE3 /* ABIElements.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ABIElements.swift; sourceTree = ""; }; @@ -108,7 +128,6 @@ files = ( B6B202C8260226B700A72AF2 /* BigInt in Frameworks */, B6F2076D25DBD93900140CE3 /* CryptoSwift in Frameworks */, - B6F2077B25DBD99F00140CE3 /* EthereumAddress in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -126,7 +145,8 @@ 3045D143251E071200B65A06 /* Resources */ = { isa = PBXGroup; children = ( - 3E2AC92124E4FA3E008EBC39 /* CNS */, + 3E2AC92124E4FA3E008EBC39 /* UNS */, + 8449EDF825139F2500DABB57 /* ENS */, ); path = Resources; sourceTree = ""; @@ -145,7 +165,8 @@ isa = PBXGroup; children = ( 3EAFA40324EE32B2008791E9 /* CommonNamingService.swift */, - 3E2AC91B24E4FA28008EBC39 /* CNS.swift */, + 3E2AC91B24E4FA28008EBC39 /* UNS.swift */, + 845B401C251389A4006AB08E /* ENS.swift */, 848E21082507890A008707D2 /* ZNS.swift */, ); path = NamingServices; @@ -169,20 +190,24 @@ path = ABI; sourceTree = ""; }; - 3E2AC92124E4FA3E008EBC39 /* CNS */ = { + 3E2AC92124E4FA3E008EBC39 /* UNS */ = { isa = PBXGroup; children = ( - 3E2AC93D24E4FC9F008EBC39 /* cnsRegistry.json */, - 3E2AC93C24E4FC9F008EBC39 /* cnsResolver.json */, - 30A69244251385A70079EC69 /* cnsProxyReader.json */, - 30AE8614257A8CCD003A0142 /* network-config.json */, - ); - path = CNS; + 3E889D11268B1BBB000C5330 /* uns-config.json */, + 3E889D1D268D51CF000C5330 /* cnsRegistry.json */, + 3E889CCD268AFA83000C5330 /* supported-keys.json */, + 3E2AC93D24E4FC9F008EBC39 /* unsRegistry.json */, + 3E2AC93C24E4FC9F008EBC39 /* unsResolver.json */, + 30A69244251385A70079EC69 /* unsProxyReader.json */, + ); + path = UNS; sourceTree = ""; }; 3EE4D9F924E367720097540B = { isa = PBXGroup; children = ( + 3EC9E04E2698002F001521B4 /* UnstoppableDomainsResolution.podspec */, + 3EC9E04B2697FF84001521B4 /* CHANGELOG.md */, 8425AED824FFBADF00BBCBBA /* README.md */, 3045D148251E2C6200B65A06 /* LICENSE.md */, 840B552D24F94B5A00618935 /* Sources */, @@ -204,6 +229,7 @@ 3EE4DA0524E367720097540B /* Resolution */ = { isa = PBXGroup; children = ( + B6E79933260223CE00F65894 /* Support */, 3045D143251E071200B65A06 /* Resources */, 848E210A25079D43008707D2 /* Helpers */, 3E2AC92024E4FA3E008EBC39 /* ABI */, @@ -240,10 +266,20 @@ path = Sources; sourceTree = ""; }; + 8449EDF825139F2500DABB57 /* ENS */ = { + isa = PBXGroup; + children = ( + 8449EDF925139F2500DABB57 /* ensRegistry.json */, + 8449EDFB2513BA3D00DABB57 /* ensResolver.json */, + ); + path = ENS; + sourceTree = ""; + }; 848E210A25079D43008707D2 /* Helpers */ = { isa = PBXGroup; children = ( 3E10551E258C95BD00652FC7 /* DNS */, + 3E889CC7268AF94E000C5330 /* TokenUriMetadata.swift */, 3EAFA40124EE312A008791E9 /* Utilities.swift */, 848E210B25079D61008707D2 /* Types.swift */, 3ECD84AD25A6AEE1001772DD /* UsdtVersion.swift */, @@ -254,6 +290,8 @@ 849E07CB24F946CA00A793D3 /* Tests */ = { isa = PBXGroup; children = ( + 3E322BA1269F5552007023A6 /* TokenUriMetadataTests.swift */, + 3E322BA0269F5542007023A6 /* ABICoderTests.swift */, 849E07CC24F946CA00A793D3 /* LinuxMain.swift */, B6F2075E25DBD8C700140CE3 /* EthereumABITests */, 3EE4DA1024E367720097540B /* ResolutionTests */, @@ -261,6 +299,14 @@ path = Tests; sourceTree = ""; }; + B650B485269F23460054727E /* EthereumAddress */ = { + isa = PBXGroup; + children = ( + B650B486269F23460054727E /* EthereumAddress.swift */, + ); + path = EthereumAddress; + sourceTree = ""; + }; B6E2A65C251BA87B00E927FC /* Frameworks */ = { isa = PBXGroup; children = ( @@ -268,6 +314,24 @@ name = Frameworks; sourceTree = ""; }; + B6E79933260223CE00F65894 /* Support */ = { + isa = PBXGroup; + children = ( + B6E79934260223CE00F65894 /* Base58Swift */, + B650B485269F23460054727E /* EthereumAddress */, + ); + path = Support; + sourceTree = ""; + }; + B6E79934260223CE00F65894 /* Base58Swift */ = { + isa = PBXGroup; + children = ( + B6E79936260223CE00F65894 /* Base58.swift */, + B6E79935260223CE00F65894 /* README.md */, + ); + path = Base58Swift; + sourceTree = ""; + }; B6F2074B25DBD89800140CE3 /* EthereumABI */ = { isa = PBXGroup; children = ( @@ -311,11 +375,11 @@ buildConfigurationList = 3EE4DA1724E367720097540B /* Build configuration list for PBXNativeTarget "UnstoppableDomainsResolution" */; buildPhases = ( 3EE4D9FE24E367720097540B /* Headers */, + 3E889CD3268B0D7F000C5330 /* Fetch network configurations */, 3EE4D9FF24E367720097540B /* Sources */, 84412BFF25029A0E0025EE78 /* Run swiftlint */, 3EE4DA0024E367720097540B /* Frameworks */, 3EE4DA0124E367720097540B /* Resources */, - 30D54741253F006A00818D62 /* ShellScript */, ); buildRules = ( ); @@ -324,7 +388,6 @@ name = UnstoppableDomainsResolution; packageProductDependencies = ( B6F2076C25DBD93900140CE3 /* CryptoSwift */, - B6F2077A25DBD99F00140CE3 /* EthereumAddress */, B6B202C7260226B700A72AF2 /* BigInt */, ); productName = resolution; @@ -356,7 +419,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1160; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1250; ORGANIZATIONNAME = "Unstoppable Domains"; TargetAttributes = { 3EE4DA0224E367720097540B = { @@ -379,7 +442,6 @@ mainGroup = 3EE4D9F924E367720097540B; packageReferences = ( B6F2076B25DBD93900140CE3 /* XCRemoteSwiftPackageReference "CryptoSwift" */, - B6F2077925DBD99F00140CE3 /* XCRemoteSwiftPackageReference "EthereumAddress" */, B6B202C6260226B700A72AF2 /* XCRemoteSwiftPackageReference "BigInt" */, ); productRefGroup = 3EE4DA0424E367720097540B /* Products */; @@ -397,10 +459,14 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 30AE8615257A8CCD003A0142 /* network-config.json in Resources */, - 30A69245251385A70079EC69 /* cnsProxyReader.json in Resources */, - 3E2AC93E24E4FC9F008EBC39 /* cnsResolver.json in Resources */, - 3E2AC93F24E4FC9F008EBC39 /* cnsRegistry.json in Resources */, + 3EC9E0482697F2E0001521B4 /* ensResolver.json in Resources */, + 3E889D1E268D51CF000C5330 /* cnsRegistry.json in Resources */, + 3E889D12268B1BBB000C5330 /* uns-config.json in Resources */, + 30A69245251385A70079EC69 /* unsProxyReader.json in Resources */, + 3E2AC93E24E4FC9F008EBC39 /* unsResolver.json in Resources */, + 3E2AC93F24E4FC9F008EBC39 /* unsRegistry.json in Resources */, + 8449EDFA25139F2500DABB57 /* ensRegistry.json in Resources */, + 3E889CCE268AFA83000C5330 /* supported-keys.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -414,22 +480,24 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 30D54741253F006A00818D62 /* ShellScript */ = { + 3E889CD3268B0D7F000C5330 /* Fetch network configurations */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + alwaysOutOfDate = 1; + buildActionMask = 12; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); + name = "Fetch network configurations"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncurl \"https://raw.githubusercontent.com/unstoppabledomains/uns/main/uns-config.json\" -o \"$PROJECT_DIR/Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json\"\ncurl \"https://raw.githubusercontent.com/unstoppabledomains/dot-crypto/master/src/supported-keys/supported-keys.json\" -o \"$PROJECT_DIR/Sources/UnstoppableDomainsResolution/Resources/UNS/supported-keys.json\"\n"; }; 84412BFF25029A0E0025EE78 /* Run swiftlint */ = { isa = PBXShellScriptBuildPhase; @@ -457,7 +525,8 @@ buildActionMask = 2147483647; files = ( 3ECD84AE25A6AEE1001772DD /* UsdtVersion.swift in Sources */, - 3E2AC91C24E4FA28008EBC39 /* CNS.swift in Sources */, + 3E2AC91C24E4FA28008EBC39 /* UNS.swift in Sources */, + 845B401D251389A4006AB08E /* ENS.swift in Sources */, 3E33F99925DCFAB400627C71 /* Configurations.swift in Sources */, B6F2075825DBD89800140CE3 /* ABIParameterTypes.swift in Sources */, B6F2075A25DBD89800140CE3 /* ABIExtensions.swift in Sources */, @@ -466,7 +535,10 @@ 3E2AC91F24E4FA35008EBC39 /* NamingService.swift in Sources */, B6F2075525DBD89800140CE3 /* ABIDecoder.swift in Sources */, 848E21092507890A008707D2 /* ZNS.swift in Sources */, + B6E79938260223CE00F65894 /* Base58.swift in Sources */, + B650B487269F23460054727E /* EthereumAddress.swift in Sources */, 3E65912824E381E900D7EC35 /* Errors.swift in Sources */, + 3E889CC8268AF94E000C5330 /* TokenUriMetadata.swift in Sources */, 3EAFA3F724EB59DA008791E9 /* ABICoder.swift in Sources */, 3E105520258C95D300652FC7 /* DnsType.swift in Sources */, B6F2075725DBD89800140CE3 /* ABITypeParser.swift in Sources */, @@ -557,7 +629,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -615,7 +687,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -638,7 +710,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Sources/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -664,7 +736,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Sources/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -764,15 +836,7 @@ repositoryURL = "https://github.com/krzyzanowskim/CryptoSwift.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.0.0; - }; - }; - B6F2077925DBD99F00140CE3 /* XCRemoteSwiftPackageReference "EthereumAddress" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/shamatar/EthereumAddress.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.3.0; + minimumVersion = 1.4.0; }; }; /* End XCRemoteSwiftPackageReference section */ @@ -788,11 +852,6 @@ package = B6F2076B25DBD93900140CE3 /* XCRemoteSwiftPackageReference "CryptoSwift" */; productName = CryptoSwift; }; - B6F2077A25DBD99F00140CE3 /* EthereumAddress */ = { - isa = XCSwiftPackageProductDependency; - package = B6F2077925DBD99F00140CE3 /* XCRemoteSwiftPackageReference "EthereumAddress" */; - productName = EthereumAddress; - }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 3EE4D9FA24E367720097540B /* Project object */; diff --git a/Resolution.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Resolution.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index cb0f393..68c5ebc 100644 --- a/Resolution.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Resolution.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,17 +15,8 @@ "repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift.git", "state": { "branch": null, - "revision": "3a2acbb32ab68215ee1596ee6004da8e90c3721b", - "version": "1.0.0" - } - }, - { - "package": "EthereumAddress", - "repositoryURL": "https://github.com/shamatar/EthereumAddress.git", - "state": { - "branch": null, - "revision": "a8eb4fc1dc03c068bf88585d8f5a2dd3572664ca", - "version": "1.3.0" + "revision": "8d4f6384e0a8cc41f2005247241dd553963a492a", + "version": "1.4.1" } } ] diff --git a/Resolution.xcodeproj/xcshareddata/xcschemes/resolution.xcscheme b/Resolution.xcodeproj/xcshareddata/xcschemes/resolution.xcscheme index 67e228c..2a83712 100644 --- a/Resolution.xcodeproj/xcshareddata/xcschemes/resolution.xcscheme +++ b/Resolution.xcodeproj/xcshareddata/xcschemes/resolution.xcscheme @@ -1,6 +1,6 @@ + ReferencedContainer = "container:Resolution.xcodeproj"> @@ -35,7 +35,7 @@ BlueprintIdentifier = "3EE4DA0B24E367720097540B" BuildableName = "ResolutionTests.xctest" BlueprintName = "ResolutionTests" - ReferencedContainer = "container:resolution.xcodeproj"> + ReferencedContainer = "container:Resolution.xcodeproj"> @@ -63,7 +63,7 @@ BlueprintIdentifier = "3EE4DA0224E367720097540B" BuildableName = "Resolution.framework" BlueprintName = "UnstoppableDomainsResolution" - ReferencedContainer = "container:resolution.xcodeproj"> + ReferencedContainer = "container:Resolution.xcodeproj"> diff --git a/Sources/UnstoppableDomainsResolution/ABI/ABICoder.swift b/Sources/UnstoppableDomainsResolution/ABI/ABICoder.swift index 77c3440..d87f22c 100644 --- a/Sources/UnstoppableDomainsResolution/ABI/ABICoder.swift +++ b/Sources/UnstoppableDomainsResolution/ABI/ABICoder.swift @@ -78,4 +78,5 @@ internal class ABICoder { let encoded = encodedData.toHexString().addHexPrefix() return encoded } + } diff --git a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIDecoder.swift b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIDecoder.swift index eca3575..9ad5abb 100755 --- a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIDecoder.swift +++ b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIDecoder.swift @@ -8,7 +8,6 @@ import Foundation import BigInt -import EthereumAddress public struct ABIDecoder { diff --git a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIEncoder.swift b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIEncoder.swift index 02768a9..f8ddbde 100755 --- a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIEncoder.swift +++ b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIEncoder.swift @@ -8,7 +8,6 @@ import Foundation import BigInt -import EthereumAddress public struct ABIEncoder { diff --git a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParameterTypes.swift b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParameterTypes.swift index eb06410..5897a1a 100755 --- a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParameterTypes.swift +++ b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParameterTypes.swift @@ -8,7 +8,6 @@ import Foundation import BigInt -import EthereumAddress extension ABI.Element { diff --git a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParsing.swift b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParsing.swift index 6c285ae..22a8d12 100755 --- a/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParsing.swift +++ b/Sources/UnstoppableDomainsResolution/ABI/EthereumABI/ABIParsing.swift @@ -76,8 +76,9 @@ private func parseFunction(abiRecord: ABI.Record) throws -> ABI.Element.Function }) let abiOutputs = outputs != nil ? outputs! : [ABI.Element.InOut]() let name = abiRecord.name != nil ? abiRecord.name! : "" + let payable = abiRecord.stateMutability != nil ? - (abiRecord.stateMutability == "payable" || abiRecord.payable!) : false + (abiRecord.stateMutability == "payable" || (abiRecord.payable != nil && abiRecord.payable!)) : false let constant = (abiRecord.constant == true || abiRecord.stateMutability == "view" || abiRecord.stateMutability == "pure") let functionElement = ABI.Element.Function(name: name, inputs: abiInputs, outputs: abiOutputs, constant: constant, payable: payable) return functionElement diff --git a/Sources/UnstoppableDomainsResolution/APIRequest.swift b/Sources/UnstoppableDomainsResolution/APIRequest.swift index 7ad1758..9703237 100644 --- a/Sources/UnstoppableDomainsResolution/APIRequest.swift +++ b/Sources/UnstoppableDomainsResolution/APIRequest.swift @@ -22,6 +22,7 @@ public protocol NetworkingLayer { httpHeaderContentType: String, httpBody: Data, completion: @escaping(Result) -> Void) + func makeHttpGetRequest(url: URL, completion: @escaping TokenUriMetadataResultConsumer ) } struct APIRequest { @@ -94,4 +95,27 @@ public struct DefaultNetworkingLayer: NetworkingLayer { } dataTask.resume() } + + public func makeHttpGetRequest(url: URL, completion: @escaping TokenUriMetadataResultConsumer ) { + var urlRequest = URLRequest(url: url) + urlRequest.httpMethod = "GET" + urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") + + let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, _ in + guard let httpResponse = response as? HTTPURLResponse, + httpResponse.statusCode == 200, + let jsonData = data else { + completion(.failure(ResolutionError.badRequestOrResponse)) + return + } + + do { + let result = try JSONDecoder().decode(TokenUriMetadata.self, from: jsonData) + completion(.success(result)) + } catch { + completion(.failure(ResolutionError.badRequestOrResponse)) + } + } + dataTask.resume() + } } diff --git a/Sources/UnstoppableDomainsResolution/Configurations.swift b/Sources/UnstoppableDomainsResolution/Configurations.swift index a7b49c1..c8f7bde 100644 --- a/Sources/UnstoppableDomainsResolution/Configurations.swift +++ b/Sources/UnstoppableDomainsResolution/Configurations.swift @@ -12,31 +12,42 @@ public struct NamingServiceConfig { let network: String let providerUrl: String let networking: NetworkingLayer + let proxyReader: String? + let registryAddresses: [String]? public init( providerUrl: String, network: String = "", - networking: NetworkingLayer = DefaultNetworkingLayer() + networking: NetworkingLayer = DefaultNetworkingLayer(), + proxyReader: String? = nil, + registryAddresses: [String]? = nil ) { self.network = network self.providerUrl = providerUrl self.networking = networking + self.proxyReader = proxyReader + self.registryAddresses = registryAddresses } } public struct Configurations { - let cns: NamingServiceConfig + let uns: NamingServiceConfig let zns: NamingServiceConfig + let ens: NamingServiceConfig public init( - cns: NamingServiceConfig = NamingServiceConfig( + uns: NamingServiceConfig = NamingServiceConfig( providerUrl: "https://mainnet.infura.io/v3/3c25f57353234b1b853e9861050f4817", network: "mainnet"), + ens: NamingServiceConfig = NamingServiceConfig( + providerUrl: "https://mainnet.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee", + network: "mainnet"), zns: NamingServiceConfig = NamingServiceConfig( providerUrl: "https://api.zilliqa.com", network: "mainnet") ) { - self.cns = cns + self.uns = uns + self.ens = ens self.zns = zns } } diff --git a/Sources/UnstoppableDomainsResolution/Contract.swift b/Sources/UnstoppableDomainsResolution/Contract.swift index 3dd2cb5..693b9ea 100644 --- a/Sources/UnstoppableDomainsResolution/Contract.swift +++ b/Sources/UnstoppableDomainsResolution/Contract.swift @@ -111,7 +111,7 @@ internal class Contract { guard err == nil else { throw err! } - return resp?[0].result + return resp?[0].result } private func postBatchRequest(_ bodyArray: [JsonRpcPayload]) throws -> [IdentifiableResult?] { @@ -143,4 +143,11 @@ internal class Contract { } return parsedResponseArray } + + private func stringParamElementToData(_ param: ParamElement?) throws -> Data { + guard case .string(let paramString) = param else { + throw ResolutionError.badRequestOrResponse + } + return Data(hex: paramString) + } } diff --git a/Sources/UnstoppableDomainsResolution/Errors.swift b/Sources/UnstoppableDomainsResolution/Errors.swift index ece8567..594458c 100644 --- a/Sources/UnstoppableDomainsResolution/Errors.swift +++ b/Sources/UnstoppableDomainsResolution/Errors.swift @@ -17,6 +17,7 @@ public enum ResolutionError: Error { case unspecifiedResolver case unknownError(Error) case proxyReaderNonInitialized + case registryAddressIsNotProvided case inconsistenDomainArray case methodNotSupported case tooManyResponses diff --git a/Sources/UnstoppableDomainsResolution/Helpers/TokenUriMetadata.swift b/Sources/UnstoppableDomainsResolution/Helpers/TokenUriMetadata.swift new file mode 100644 index 0000000..db8b457 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Helpers/TokenUriMetadata.swift @@ -0,0 +1,69 @@ +import Foundation + +public struct TokenUriMetadata: Codable { + let name: String + let description: String + let externalUrl: String + let image: String + let attributes: [TokenUriMetadataAttribute] + var backgroundColor: String? + var animationUrl: String? + var youtubeUrl: String? + var externalLink: String? + var imageData: String? + + enum CodingKeys: String, CodingKey { + case name + case description + case externalUrl = "external_url" + case image + case attributes + case backgroundColor = "background_color" + case animationUrl = "animation_url" + case youtubeUrl = "youtube_url" + case externalLink = "external_link" + case imageData = "image_data" + } +} + +// MARK: - Attribute +public struct TokenUriMetadataAttribute: Codable { + let displayType: String? + let traitType: String? + let value: TokenUriMetadataValue + + enum CodingKeys: String, CodingKey { + case displayType = "display_type" + case traitType = "trait_type" + case value + } +} + +struct TokenUriMetadataValue: Codable { + let value: String + + init(_ value: String) { + self.value = value + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + // attempt to decode from all JSON primitives + if let str = try? container.decode(String.self) { + value = str + } else if let int = try? container.decode(Int.self) { + value = int.description + } else if let double = try? container.decode(Double.self) { + value = double.description + } else if let bool = try? container.decode(Bool.self) { + value = bool.description + } else { + throw DecodingError.typeMismatch(String.self, .init(codingPath: decoder.codingPath, debugDescription: "Failed to decode token metadata attribute value.")) + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(value) + } +} diff --git a/Sources/UnstoppableDomainsResolution/Helpers/Types.swift b/Sources/UnstoppableDomainsResolution/Helpers/Types.swift index 0cb4525..1e993d7 100644 --- a/Sources/UnstoppableDomainsResolution/Helpers/Types.swift +++ b/Sources/UnstoppableDomainsResolution/Helpers/Types.swift @@ -12,3 +12,12 @@ public typealias StringResultConsumer = (Result) -> Voi public typealias StringsArrayResultConsumer = (Result<[String?], ResolutionError>) -> Void public typealias DictionaryResultConsumer = (Result<[String: String], ResolutionError>) -> Void public typealias DnsRecordsResultConsumer = (Result<[DnsRecord], Error>) -> Void +public typealias TokenUriMetadataResultConsumer = (Result) -> Void +public typealias BoolResultConsumer = (Result) -> Void + +public enum NamingServiceName: String { + case uns + case ens + case zns +} +public let ethCoinIndex = 60 diff --git a/Sources/UnstoppableDomainsResolution/NamingServices/CommonNamingService.swift b/Sources/UnstoppableDomainsResolution/NamingServices/CommonNamingService.swift index 4926cbb..9bd531e 100644 --- a/Sources/UnstoppableDomainsResolution/NamingServices/CommonNamingService.swift +++ b/Sources/UnstoppableDomainsResolution/NamingServices/CommonNamingService.swift @@ -12,12 +12,14 @@ class CommonNamingService { static let hexadecimalPrefix = "0x" static let jsonExtension = "json" - let name: String + let name: NamingServiceName let providerUrl: String let networking: NetworkingLayer enum ContractType: String { - case registry = "Registry" + case unsRegistry = "UNSRegistry" + case cnsRegistry = "CNSRegistry" + case ensRegistry = "ENSRegistry" case resolver = "Resolver" case proxyReader = "ProxyReader" @@ -26,7 +28,7 @@ class CommonNamingService { } } - init(name: String, providerUrl: String, networking: NetworkingLayer) { + init(name: NamingServiceName, providerUrl: String, networking: NetworkingLayer) { self.name = name self.providerUrl = providerUrl self.networking = networking @@ -35,10 +37,14 @@ class CommonNamingService { func buildContract(address: String, type: ContractType) throws -> Contract { let jsonFileName: String - let nameLowCased = name.lowercased() + let nameLowCased = name.rawValue.lowercased() switch type { - case .registry: + case .unsRegistry: jsonFileName = "\(nameLowCased)Registry" + case .ensRegistry: + jsonFileName = "\(nameLowCased)Registry" + case .cnsRegistry: + jsonFileName = "cnsRegistry" case .resolver: jsonFileName = "\(nameLowCased)Resolver" case .proxyReader: @@ -86,7 +92,7 @@ class CommonNamingService { } extension CommonNamingService { - static let networkConfigFileName = "network-config" + static let networkConfigFileName = "uns-config" static let networkIds = ["mainnet": "1", "ropsten": "3", "rinkeby": "4", @@ -104,6 +110,7 @@ extension CommonNamingService { struct ContractAddressEntry: Decodable { let address: String let legacyAddresses: [String] + let deploymentBlock: String } static func parseContractAddresses(network: String) throws -> [String: ContractAddressEntry]? { @@ -113,14 +120,12 @@ extension CommonNamingService { let bundler = Bundle(for: self) #endif - guard let idString = networkIds[network] else { throw ResolutionError.unsupportedNetwork } + guard let idString = networkIds[network] else { return nil } if let filePath = bundler.url(forResource: Self.networkConfigFileName, withExtension: "json") { guard let data = try? Data(contentsOf: filePath) else { return nil } guard let info = try? JSONDecoder().decode(NewtorkConfigJson.self, from: data) else { return nil } - guard let currentNetwork = info.networks[idString] else { - return nil - } + guard let currentNetwork = info.networks[idString] else { return nil } return currentNetwork.contracts } return nil diff --git a/Sources/UnstoppableDomainsResolution/NamingServices/ENS.swift b/Sources/UnstoppableDomainsResolution/NamingServices/ENS.swift new file mode 100644 index 0000000..7f69e62 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/NamingServices/ENS.swift @@ -0,0 +1,182 @@ +// +// ENS.swift +// resolution +// +// Created by Serg Merenkov on 9/14/20. +// Copyright © 2020 Unstoppable Domains. All rights reserved. +// + +import Foundation + +internal class ENS: CommonNamingService, NamingService { + let network: String + let registryAddress: String + let registryMap: [String: String] = [ + "mainnet": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "ropsten": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "rinkeby": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "goerli": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" + ] + + init(_ config: NamingServiceConfig) throws { + + self.network = config.network.isEmpty + ? try Self.getNetworkId(providerUrl: config.providerUrl, networking: config.networking) + : config.network + + var registryAddress: String? = registryMap[self.network] + if config.registryAddresses != nil && !config.registryAddresses!.isEmpty { + registryAddress = config.registryAddresses![0] + } + + guard registryAddress != nil else { + throw ResolutionError.registryAddressIsNotProvided + } + self.registryAddress = registryAddress! + super.init(name: .ens, providerUrl: config.providerUrl, networking: config.networking) + } + + func isSupported(domain: String) -> Bool { + return domain ~= "^[^-]*[^-]*\\.(eth|luxe|xyz|kred|addr\\.reverse)$" + } + + func owner(domain: String) throws -> String { + let tokenId = super.namehash(domain: domain) + guard let ownerAddress = try askRegistryContract(for: "owner", with: [tokenId]), + Utillities.isNotEmpty(ownerAddress) else { + throw ResolutionError.unregisteredDomain + } + return ownerAddress + } + + func batchOwners(domains: [String]) throws -> [String?] { + throw ResolutionError.methodNotSupported + } + + func addr(domain: String, ticker: String) throws -> String { + guard ticker.uppercased() == "ETH" else { + throw ResolutionError.recordNotSupported + } + + let tokenId = super.namehash(domain: domain) + let resolverAddress = try resolver(tokenId: tokenId) + let resolverContract = try super.buildContract(address: resolverAddress, type: .resolver) + + guard let dict = try resolverContract.callMethod(methodName: "addr", args: [tokenId, ethCoinIndex]) as? [String: Data], + let dataAddress = dict["0"], + let address = EthereumAddress(dataAddress), + Utillities.isNotEmpty(address.address) else { + throw ResolutionError.recordNotFound + } + return address.address + } + + // MARK: - Get Record + func record(domain: String, key: String) throws -> String { + let tokenId = super.namehash(domain: domain) + return try self.record(tokenId: tokenId, key: key) + } + + func record(tokenId: String, key: String) throws -> String { + if key == "ipfs.html.value" { + let hash = try self.getContentHash(tokenId: tokenId) + return hash + } + + let resolverAddress = try resolver(tokenId: tokenId) + let resolverContract = try super.buildContract(address: resolverAddress, type: .resolver) + + let ensKeyName = self.fromUDNameToEns(record: key) + + guard let dict = try resolverContract.callMethod(methodName: "text", args: [tokenId, ensKeyName]) as? [String: String], + let result = dict["0"], + Utillities.isNotEmpty(result) else { + throw ResolutionError.recordNotFound + } + return result + } + + func records(keys: [String], for domain: String) throws -> [String: String] { + // TODO: Add some batch request and collect all keys by few request + throw ResolutionError.recordNotSupported + } + + func tokensOwnedBy(address: String) throws -> [String] { + throw ResolutionError.methodNotSupported + } + + func getTokenUri(tokenId: String) throws -> String { + throw ResolutionError.methodNotSupported + } + + func getDomainName(tokenId: String) throws -> String { + throw ResolutionError.methodNotSupported + } + + // MARK: - get Resolver + func resolver(domain: String) throws -> String { + let tokenId = super.namehash(domain: domain) + return try self.resolver(tokenId: tokenId) + } + + func resolver(tokenId: String) throws -> String { + guard let resolverAddress = try askRegistryContract(for: "resolver", with: [tokenId]), + Utillities.isNotEmpty(resolverAddress) else { + throw ResolutionError.unspecifiedResolver + } + return resolverAddress + } + + // MARK: - Helper functions + private func askRegistryContract(for methodName: String, with args: [String]) throws -> String? { + let registryContract: Contract = try super.buildContract(address: self.registryAddress, type: .ensRegistry) + guard let ethereumAddress = try registryContract.callMethod(methodName: methodName, args: args) as? [String: EthereumAddress], + let address = ethereumAddress["0"] else { + return nil + } + return address.address + } + + private func fromUDNameToEns(record: String) -> String { + let mapper: [String: String] = [ + "ipfs.redirect_domain.value": "url", + "whois.email.value": "email", + "gundb.username.value": "gundb_username", + "gundb.public_key.value": "gundb_public_key" + ] + return mapper[record] ?? record + } + + /* + //https://ethereum.stackexchange.com/questions/17094/how-to-store-ipfs-hash-using-bytes32 + getIpfsHashFromBytes32(bytes32Hex) { + // Add our default ipfs values for first 2 bytes: + // function:0x12=sha2, size:0x20=256 bits + // and cut off leading "0x" + const hashHex = "1220" + bytes32Hex.slice(2) + const hashBytes = Buffer.from(hashHex, 'hex'); + const hashStr = bs58.encode(hashBytes) + return hashStr + } + */ + private func getContentHash(tokenId: String) throws -> String { + + let resolverAddress = try resolver(tokenId: tokenId) + let resolverContract = try super.buildContract(address: resolverAddress, type: .resolver) + + let hash = try resolverContract.callMethod(methodName: "contenthash", args: [tokenId]) as? [String: Any] + guard let data = hash?["0"] as? Data else { + throw ResolutionError.recordNotFound + } + + let contentHash = [UInt8](data) + guard let codec = Array(contentHash[0..<1]).last, + codec == 0xE3 // 'ipfs-ns' + else { + throw ResolutionError.recordNotFound + } + + return Base58.base58Encode(Array(contentHash[4.. Bool { - return domain.hasSuffix(Self.specificDomain) + if domain ~= "^[^-]*[^-]*\\.(eth|luxe|xyz|kred|addr\\.reverse)$" { + return false + } + let split = domain.split(separator: ".") + let tld = split.suffix(1).joined(separator: "") + if tld == "zil" { + return false + } + let tokenId = self.namehash(domain: tld) + if let response = try? self.proxyReaderContract?.callMethod(methodName: Self.existName, args: [tokenId]) { + guard + let result = response as? [String: Bool], + let isExist = result["0"] else { + return false + } + return isExist + } + return false } struct OwnerResolverRecord { @@ -93,41 +139,78 @@ internal class CNS: CommonNamingService, NamingService { } } - func tokensOwnedBy(address: String) throws -> [String] { - let registryContract = try self.buildContract(address: self.contracts.registryAddress, type: .registry) - let origin = self.getOriginBlockFrom(network: self.network) - - let transferLogs = try registryContract.callLogs( + private func parseContractForNewUri( + contract: Contract, + for address: String, + since origin: String + ) throws -> [String] { + do { + let transferLogs = try contract.callLogs( fromBlock: origin, signatureHash: Self.TransferEventSignature, for: address.normalized32, isTransfer: true - ).compactMap { - $0.topics[3] - } - - let domainsData = try transferLogs.compactMap { - try registryContract.callLogs( - fromBlock: origin, - signatureHash: Self.NewURIEventSignature, - for: $0.normalized32, - isTransfer: false - )[0].data + ).compactMap { $0.topics[3] } + + let domainsData = try transferLogs.compactMap { + try contract.callLogs( + fromBlock: origin, + signatureHash: Self.NewURIEventSignature, + for: $0.normalized32, + isTransfer: false + )[0].data + } + + let possibleDomains = Array(Set( + domainsData.compactMap { + ABIDecoder.decodeSingleType(type: .string, data: Data(hex: $0)).value as? String + } + ) + ) + return possibleDomains + } catch { + return [] } + } - let possibleDomains = Array(Set( - domainsData.compactMap { - ABIDecoder.decodeSingleType(type: .string, data: Data(hex: $0)).value as? String + func tokensOwnedBy(address: String) throws -> [String] { + let asyncGroup = DispatchGroup() + var possibleDomains: [String] = [] + + self.nsRegistries.forEach { registry in + asyncGroup.enter() + DispatchQueue.global().async { [weak self] in + guard let self = self else { return } + do { + let domainsFromLogs = try self.parseContractForNewUri( + contract: registry.contract, + for: address, + since: registry.deploymentBlock + ) + possibleDomains += domainsFromLogs + asyncGroup.leave() + } catch { + asyncGroup.leave() } - ) - ) + } + } - let owners = try batchOwners(domains: possibleDomains) var domains: [String] = [] - - for (ind, addr) in owners.enumerated() where addr == address { - domains.append(possibleDomains[ind]) + let semaphore = DispatchSemaphore(value: 0) + asyncGroup.notify(queue: .global()) { [weak self] in + guard let self = self else { return } + do { + let owners = try self.batchOwners(domains: possibleDomains) + for (ind, addr) in owners.enumerated() where addr == address { + domains.append(possibleDomains[ind]) + } + semaphore.signal() + } catch { + domains = [] + semaphore.signal() + } } + semaphore.wait() return domains } @@ -203,6 +286,46 @@ internal class CNS: CommonNamingService, NamingService { return returnValue } + func getTokenUri(tokenId: String) throws -> String { + do { + if let result = try proxyReaderContract? + .callMethod(methodName: Self.tokenURIMethodName, + args: [tokenId]) { + let dict = result as? [String: Any] + if let val = dict?["0"] as? String { + return val + } + throw ResolutionError.unregisteredDomain + } + throw ResolutionError.proxyReaderNonInitialized + } catch APIError.decodingError { + throw ResolutionError.unregisteredDomain + } + } + + func getDomainName(tokenId: String) throws -> String { + do { + let registryAddress = try self.getRegistryAddress(tokenId: tokenId) + let registryContract = try self.buildContract(address: registryAddress, type: .unsRegistry) + let result = try registryContract.callLogs( + fromBlock: "earliest", + signatureHash: Self.NewURIEventSignature, + for: tokenId, + isTransfer: false) + + guard result.count > 0 else { + throw ResolutionError.unregisteredDomain + } + + if let domainName = ABIDecoder.decodeSingleType(type: .string, data: Data(hex: result[0].data)).value as? String { + return domainName + } + throw ResolutionError.unregisteredDomain + } catch APIError.decodingError { + throw ResolutionError.unregisteredDomain + } + } + // MARK: - Helper functions private func unfoldAddress (_ incomingData: T) -> String? { if let eth = incomingData as? EthereumAddress { @@ -232,17 +355,6 @@ internal class CNS: CommonNamingService, NamingService { return nil } - private func getOriginBlockFrom(network: String) -> String { - switch network { - case "mainnet": - return "0x8A958B" - case "rinkeby": - return "0x7232BC" - default: - return "earliest" - } - } - private func getOwnerResolverRecord(tokenId: String, key: String) throws -> OwnerResolverRecord { let res = try self.getDataForMany(keys: [key], for: [tokenId]) if let dict = res as? [String: Any] { @@ -272,6 +384,23 @@ internal class CNS: CommonNamingService, NamingService { args: [keys, tokenIds]) { return result } throw ResolutionError.proxyReaderNonInitialized } + + private func getRegistryAddress(tokenId: String) throws -> String { + do { + if let result = try proxyReaderContract? + .callMethod(methodName: Self.registryOfMethodName, + args: [tokenId]) { + let dict = result as? [String: Any] + if let val = dict?["0"] as? EthereumAddress { + return val.address + } + throw ResolutionError.unregisteredDomain + } + throw ResolutionError.proxyReaderNonInitialized + } catch APIError.decodingError { + throw ResolutionError.unregisteredDomain + } + } } fileprivate extension String { diff --git a/Sources/UnstoppableDomainsResolution/NamingServices/ZNS.swift b/Sources/UnstoppableDomainsResolution/NamingServices/ZNS.swift index cd81380..0099160 100644 --- a/Sources/UnstoppableDomainsResolution/NamingServices/ZNS.swift +++ b/Sources/UnstoppableDomainsResolution/NamingServices/ZNS.swift @@ -1,5 +1,5 @@ // -// ZNS.swift +// zns.swift // Resolution // // Created by Serg Merenkov on 9/8/20. @@ -18,14 +18,18 @@ internal class ZNS: CommonNamingService, NamingService { ] init(_ config: NamingServiceConfig) throws { + self.network = config.network - guard let registryAddress = registryMap[config.network] else { - throw ResolutionError.unsupportedNetwork + var registryAddress: String? = registryMap[self.network] + if config.registryAddresses != nil && !config.registryAddresses!.isEmpty { + registryAddress = config.registryAddresses![0] } - self.network = config.network - self.registryAddress = registryAddress - super.init(name: "ZNS", providerUrl: config.providerUrl, networking: config.networking) + guard registryAddress != nil else { + throw ResolutionError.registryAddressIsNotProvided + } + self.registryAddress = registryAddress! + super.init(name: .zns, providerUrl: config.providerUrl, networking: config.networking) } func isSupported(domain: String) -> Bool { @@ -75,6 +79,14 @@ internal class ZNS: CommonNamingService, NamingService { return filtered } + func getTokenUri(tokenId: String) throws -> String { + throw ResolutionError.methodNotSupported + } + + func getDomainName(tokenId: String) throws -> String { + throw ResolutionError.methodNotSupported + } + // MARK: - get Resolver func resolver(domain: String) throws -> String { let recordAddresses = try self.recordsAddresses(domain: domain) diff --git a/Sources/UnstoppableDomainsResolution/Protocols/NamingService.swift b/Sources/UnstoppableDomainsResolution/Protocols/NamingService.swift index b3b704f..e365628 100644 --- a/Sources/UnstoppableDomainsResolution/Protocols/NamingService.swift +++ b/Sources/UnstoppableDomainsResolution/Protocols/NamingService.swift @@ -9,9 +9,10 @@ import Foundation protocol NamingService { - var name: String { get } + var name: NamingServiceName { get } var network: String { get } var providerUrl: String { get } + var networking: NetworkingLayer { get } func namehash(domain: String) -> String func isSupported(domain: String) -> Bool @@ -25,4 +26,8 @@ protocol NamingService { func record(domain: String, key: String) throws -> String func records(keys: [String], for domain: String) throws -> [String: String] + + func getTokenUri(tokenId: String) throws -> String + + func getDomainName(tokenId: String) throws -> String } diff --git a/Sources/UnstoppableDomainsResolution/Resolution.swift b/Sources/UnstoppableDomainsResolution/Resolution.swift index 006446c..a96ce37 100644 --- a/Sources/UnstoppableDomainsResolution/Resolution.swift +++ b/Sources/UnstoppableDomainsResolution/Resolution.swift @@ -10,12 +10,18 @@ import Foundation /// /// Supported domain zones: /// -/// *CNS:* +/// *uns:* /// .crypto /// -/// *ZNS* +/// *zns* /// .zil /// +/// *ENS* +/// .eth +/// .kred +/// .xyz +/// .luxe +/// /// ```swift /// let resolution = try Resolution(); /// resolution.addr(domain: "brad.crypto", ticker: "btc") { (result) in @@ -34,7 +40,7 @@ import Foundation /// ```swift /// let resolution = try Resolution( /// configs: Configurations( -/// cns: NamingServiceConfig( +/// uns: NamingServiceConfig( /// providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", /// network: "rinkeby" /// ) @@ -59,7 +65,7 @@ public class Resolution { /// Returns a network that NamingService was configure with public func getNetwork(from serviceName: String) throws -> String { - guard let service = services.first(where: {$0.name == serviceName.uppercased() }) else { + guard let service = services.first(where: {$0.name.rawValue == serviceName.lowercased() }) else { throw ResolutionError.unsupportedServiceName } return service.network @@ -67,23 +73,29 @@ public class Resolution { /// Checks if the domain name is valid according to naming service rules for valid domain names. /// - /// - Parameter domain: domain name to be checked + /// **Example:** ENS doesn't allow domains that start from '-' symbol. /// - /// - Returns: The return true or false. + /// - Parameter domain: domain name to be checked + /// - Parameter completion: A callback that resolves `Result` with a `Bool` value /// - public func isSupported(domain: String) -> Bool { - do { - let preparedDomain = prepare(domain: domain) - return try getServiceOf(domain: preparedDomain).isSupported(domain: preparedDomain) - } catch { - return false + public func isSupported(domain: String, completion: @escaping BoolResultConsumer) { + let preparedDomain = prepare(domain: domain) + DispatchQueue.global(qos: .utility).async { [weak self] in + do { + guard self?.services.first(where: {$0.isSupported(domain: preparedDomain)}) != nil else { + throw ResolutionError.unsupportedDomain + } + completion(.success(true)) + } catch { + completion(.success(false)) + } } } /// Resolves a hash of the `domain` according to https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md /// - Parameter domain: - domain name to be converted /// - Returns: Produces a namehash from supported naming service in hex format with 0x prefix. - /// Corresponds to ERC721 token id. + /// Corresponds to ERC721 token id in case of Ethereum based naming service like ENS or UNS. /// - Throws: ```ResolutionError.unsupportedDomain``` if domain extension is unknown /// public func namehash(domain: String) throws -> String { @@ -148,10 +160,12 @@ public class Resolution { public func tokensOwnedBy(address: String, service: String, completion: @escaping StringsArrayResultConsumer ) { DispatchQueue.global(qos: .utility).async { [weak self] in do { - guard let service = self?.services.first(where: { $0.name == service }) else { + + guard let serviceName = NamingServiceName(rawValue: service), + let namingService = self?.services.first(where: { $0.name == serviceName }) else { throw ResolutionError.unsupportedServiceName } - let result = try service.tokensOwnedBy(address: address) + let result = try namingService.tokensOwnedBy(address: address) completion(.success(result)) } catch { self?.catchError(error, completion: completion) @@ -184,7 +198,8 @@ public class Resolution { let preparedDomain = prepare(domain: domain) DispatchQueue.global(qos: .utility).async { [weak self] in do { - guard let service = try self?.getServiceOf(domain: preparedDomain) else { + guard let service = try self?.getServiceOf(domain: preparedDomain), + service.name != .ens else { throw ResolutionError.methodNotSupported } let recordKey = "crypto.\(ticker.uppercased()).version.\(chain.uppercased()).address" @@ -285,7 +300,7 @@ public class Resolution { DispatchQueue.global(qos: .utility).async { [weak self] in do { guard let service = try self?.getServiceOf(domain: preparedDomain), - service.name == "CNS" else { + service.name == .uns else { throw ResolutionError.methodNotSupported } @@ -333,6 +348,51 @@ public class Resolution { } } + /// Retrieves the tokenURI from the registry smart contract. + /// - Parameter domain: - domain name to be resolved + /// - Parameter completion: A callback that resolves `Result` with a `tokenURI` for a specific domain or `Error` + public func tokenURI(domain: String, completion:@escaping StringResultConsumer) { + do { + let namehash = try self.namehash(domain: domain) + let result = try self.getServiceOf(domain: domain).getTokenUri(tokenId: namehash) + completion(.success(result)) + } catch { + self.catchError(error, completion: completion) + } + } + + /// Retrieves the data from the endpoint provided by tokenURI from the registry smart contract. + /// - Parameter domain: - domain name to be resolved + /// - Parameter completion: A callback that resolves `Result` with a `TokenUriMetadata` for a specific domain or `Error` + public func tokenURIMetadata(domain: String, completion:@escaping TokenUriMetadataResultConsumer) { + do { + let namehash = try self.namehash(domain: domain) + let tokenURI = try self.getServiceOf(domain: domain).getTokenUri(tokenId: namehash) + try self.fetchTokenUriMetadata(tokenURI: tokenURI, completion: completion) + } catch { + self.catchError(error, completion: completion) + } + } + + /// Retrieves the domain name from token metadata that is provided by tokenURI from the registry smart contract. + /// The function will throw an error if the domain in the metadata does not match the hash (e.g. if the metadata is outdated). + /// - Parameter hash: - domain hash to be resolved + /// - Parameter serviceName: - name of the service to use to get metadata + /// - Parameter completion: A callback that resolves `Result` with a `domainName` for a specific domain or `Error` + public func unhash(hash: String, serviceName: NamingServiceName, completion:@escaping StringResultConsumer) { + do { + let domain = try self.findService(name: serviceName).getDomainName(tokenId: hash) + + let receivedHash = try self.namehash(domain: domain) + if receivedHash != hash { + completion(.failure(ResolutionError.badRequestOrResponse)) + } + completion(.success(domain)) + } catch { + self.catchError(error, completion: completion) + } + } + // MARK: - Uttilities function /// this returns [NamingService] from the configurations @@ -340,7 +400,13 @@ public class Resolution { var networkServices: [NamingService] = [] var errorService: Error? do { - networkServices.append(try CNS(configs.cns)) + networkServices.append(try UNS(configs.uns)) + } catch { + errorService = error + } + + do { + networkServices.append(try ENS(configs.ens)) } catch { errorService = error } @@ -359,10 +425,13 @@ public class Resolution { /// This returns the correct naming service based on the `domain` asked for private func getServiceOf(domain: String) throws -> NamingService { - guard let service = services.first(where: {$0.isSupported(domain: domain)}) else { - throw ResolutionError.unsupportedDomain + if domain.hasSuffix(".zil") { + return try self.findService(name: .zns) } - return service + if domain ~= "^[^-]*[^-]*\\.(eth|luxe|xyz|kred|addr\\.reverse)$" { + return try self.findService(name: .ens) + } + return try self.findService(name: .uns) } /// This returns the correct naming service based on the `domain`'s array asked for @@ -371,8 +440,8 @@ public class Resolution { throw ResolutionError.unsupportedDomain } - let possibleServices = domains.compactMap { domain in - return services.first(where: {$0.isSupported(domain: domain)}) + let possibleServices = try domains.compactMap { domain in + return try self.getServiceOf(domain: domain) } guard possibleServices.count == domains.count else { throw ResolutionError.unsupportedDomain @@ -386,6 +455,29 @@ public class Resolution { return service! } + /// This returns the correct naming service based on the service name asked for + private func findService(name: NamingServiceName) throws -> NamingService { + guard let service = services.first(where: {$0.name == name}) else { + throw ResolutionError.unsupportedServiceName + } + return service + } + + /// Gets the token metadata from metadata API + private func fetchTokenUriMetadata(tokenURI: String, completion:@escaping TokenUriMetadataResultConsumer) throws { + let networking = try findService(name: .uns).networking + let url = URL(string: tokenURI) + networking.makeHttpGetRequest(url: url!, + completion: {result in + switch result { + case .success(let response): + completion(.success(response)) + case .failure(let error): + self.catchError(error, completion: completion) + } + }) + } + /// Preproccess the `domain` private func prepare(domain: String) -> String { return domain.lowercased() @@ -429,4 +521,13 @@ public class Resolution { } completion(.failure(catched)) } + + /// Process the 'error' + private func catchError(_ error: Error, completion:@escaping TokenUriMetadataResultConsumer ) { + guard let catched = error as? ResolutionError else { + completion(.failure(.unknownError(error))) + return + } + completion(.failure(catched)) + } } diff --git a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsProxyReader.json b/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsProxyReader.json deleted file mode 100644 index 330931c..0000000 --- a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsProxyReader.json +++ /dev/null @@ -1,639 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract Registry", - "name": "registry", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "constant": true, - "inputs": [], - "name": "NAME", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "isApprovedOrOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "resolverOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "string", - "name": "label", - "type": "string" - } - ], - "name": "childIdOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isController", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "root", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "nonceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "get", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getMany", - "outputs": [ - { - "internalType": "string[]", - "name": "", - "type": "string[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "keyHash", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getByHash", - "outputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "string", - "name": "value", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256[]", - "name": "keyHashes", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getManyByHash", - "outputs": [ - { - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, - { - "internalType": "string[]", - "name": "values", - "type": "string[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getData", - "outputs": [ - { - "internalType": "address", - "name": "resolver", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "string[]", - "name": "values", - "type": "string[]" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, - { - "internalType": "uint256[]", - "name": "tokenIds", - "type": "uint256[]" - } - ], - "name": "getDataForMany", - "outputs": [ - { - "internalType": "address[]", - "name": "resolvers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "owners", - "type": "address[]" - }, - { - "internalType": "string[][]", - "name": "values", - "type": "string[][]" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256[]", - "name": "keyHashes", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getDataByHash", - "outputs": [ - { - "internalType": "address", - "name": "resolver", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, - { - "internalType": "string[]", - "name": "values", - "type": "string[]" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256[]", - "name": "keyHashes", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "tokenIds", - "type": "uint256[]" - } - ], - "name": "getDataByHashForMany", - "outputs": [ - { - "internalType": "address[]", - "name": "resolvers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "owners", - "type": "address[]" - }, - { - "internalType": "string[][]", - "name": "keys", - "type": "string[][]" - }, - { - "internalType": "string[][]", - "name": "values", - "type": "string[][]" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256[]", - "name": "tokenIds", - "type": "uint256[]" - } - ], - "name": "ownerOfForMany", - "outputs": [ - { - "internalType": "address[]", - "name": "owners", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ] diff --git a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsResolver.json b/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsResolver.json deleted file mode 100644 index 114a9a6..0000000 --- a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsResolver.json +++ /dev/null @@ -1,402 +0,0 @@ -[{ - "inputs": [{ - "internalType": "contract Registry", - "name": "registry", - "type": "address" - }, { - "internalType": "contract MintingController", - "name": "mintingController", - "type": "address" - }], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" -}, { - "anonymous": false, - "inputs": [{ - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "indexed": true, - "internalType": "string", - "name": "keyIndex", - "type": "string" - }, { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }], - "name": "NewKey", - "type": "event" -}, { - "anonymous": false, - "inputs": [{ - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "ResetRecords", - "type": "event" -}, { - "anonymous": false, - "inputs": [{ - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "indexed": true, - "internalType": "string", - "name": "keyIndex", - "type": "string" - }, { - "indexed": true, - "internalType": "string", - "name": "valueIndex", - "type": "string" - }, { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }], - "name": "Set", - "type": "event" -}, { - "constant": true, - "inputs": [{ - "internalType": "string", - "name": "key", - "type": "string" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "get", - "outputs": [{ - "internalType": "string", - "name": "", - "type": "string" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "uint256", - "name": "keyHash", - "type": "uint256" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "getByHash", - "outputs": [{ - "internalType": "string", - "name": "key", - "type": "string" - }, { - "internalType": "string", - "name": "value", - "type": "string" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "getMany", - "outputs": [{ - "internalType": "string[]", - "name": "", - "type": "string[]" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "uint256[]", - "name": "keyHashes", - "type": "uint256[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "getManyByHash", - "outputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "uint256", - "name": "keyHash", - "type": "uint256" - }], - "name": "hashToKey", - "outputs": [{ - "internalType": "string", - "name": "", - "type": "string" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "uint256[]", - "name": "hashes", - "type": "uint256[]" - }], - "name": "hashesToKeys", - "outputs": [{ - "internalType": "string[]", - "name": "", - "type": "string[]" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": true, - "inputs": [{ - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "nonceOf", - "outputs": [{ - "internalType": "uint256", - "name": "", - "type": "uint256" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "preconfigure", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "reconfigure", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }], - "name": "reconfigureFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": true, - "inputs": [], - "name": "registry", - "outputs": [{ - "internalType": "address", - "name": "", - "type": "address" - }], - "payable": false, - "stateMutability": "view", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "reset", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }], - "name": "resetFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string", - "name": "key", - "type": "string" - }, { - "internalType": "string", - "name": "value", - "type": "string" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "set", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string", - "name": "key", - "type": "string" - }, { - "internalType": "string", - "name": "value", - "type": "string" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }], - "name": "setFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }], - "name": "setMany", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}, { - "constant": false, - "inputs": [{ - "internalType": "string[]", - "name": "keys", - "type": "string[]" - }, { - "internalType": "string[]", - "name": "values", - "type": "string[]" - }, { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }], - "name": "setManyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" -}] diff --git a/Sources/UnstoppableDomainsResolution/Resources/CNS/network-config.json b/Sources/UnstoppableDomainsResolution/Resources/CNS/network-config.json deleted file mode 100644 index 63d9df4..0000000 --- a/Sources/UnstoppableDomainsResolution/Resources/CNS/network-config.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "version": "1.1.0", - "networks": { - "1": { - "contracts": { - "Registry": { - "address": "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe", - "legacyAddresses": [] - }, - "SignatureController": { - "address": "0x82EF94294C95aD0930055f31e53A34509227c5f7", - "legacyAddresses": [] - }, - "MintingController": { - "address": "0xb0EE56339C3253361730F50c08d3d7817ecD60Ca", - "legacyAddresses": [] - }, - "WhitelistedMinter": { - "address": "0xd3fF3377b0ceade1303dAF9Db04068ef8a650757", - "legacyAddresses": [] - }, - "URIPrefixController": { - "address": "0x09B091492759737C03da9dB7eDF1CD6BCC3A9d91", - "legacyAddresses": [] - }, - "DomainZoneController": { - "address": "0xeA70777e28E00E81f58b8921fC47F78B8a72eFE7", - "legacyAddresses": [] - }, - "Resolver": { - "address": "0xb66DcE2DA6afAAa98F2013446dBCB0f4B0ab2842", - "legacyAddresses": [ - "0xa1cac442be6673c49f8e74ffc7c4fd746f3cbd0d", - "0x878bc2f3f717766ab69c0a5f9a6144931e61aed3" - ] - }, - "ProxyReader": { - "address": "0xa6E7cEf2EDDEA66352Fd68E5915b60BDbb7309f5", - "legacyAddresses": [ - "0x7ea9Ee21077F84339eDa9C80048ec6db678642B1" - ] - }, - "TwitterValidationOperator": { - "address": "0xbb486C6E9cF1faA86a6E3eAAFE2e5665C0507855", - "legacyAddresses": [] - }, - "FreeMinter": { - "address": "0x1fC985cAc641ED5846b631f96F35d9b48Bc3b834", - "legacyAddresses": [] - } - } - }, - "4": { - "contracts": { - "Registry": { - "address": "0xAad76bea7CFEc82927239415BB18D2e93518ecBB", - "legacyAddresses": [] - }, - "SignatureController": { - "address": "0x66a5e3e2C27B4ce4F46BBd975270BE154748D164", - "legacyAddresses": [] - }, - "MintingController": { - "address": "0x51765307AeB3Df2E647014a2C501d5324212467c", - "legacyAddresses": [] - }, - "WhitelistedMinter": { - "address": "0xbcB32f13f90978a9e059E8Cb40FaA9e6619d98e7", - "legacyAddresses": [] - }, - "URIPrefixController": { - "address": "0xe1d2e4B9f0518CA5c803073C3dFa886470627237", - "legacyAddresses": [] - }, - "DomainZoneController": { - "address": "0x6f8F96A566663C1d4fEe70edD37E9b62Fe39dE5D", - "legacyAddresses": [] - }, - "Resolver": { - "address": "0x95AE1515367aa64C462c71e87157771165B1287A", - "legacyAddresses": [] - }, - "ProxyReader": { - "address": "0x3A2e74CF832cbA3d77E72708d55370119E4323a6", - "legacyAddresses": [] - }, - "TwitterValidationOperator": { - "address": "0x1CB337b3b208dc29a6AcE8d11Bb591b66c5Dd83d", - "legacyAddresses": [] - }, - "FreeMinter": { - "address": "0x84214215904cDEbA9044ECf95F3eBF009185AAf4", - "legacyAddresses": [] - } - } - } - } -} diff --git a/Sources/UnstoppableDomainsResolution/Resources/CNS/supported-keys.json b/Sources/UnstoppableDomainsResolution/Resources/CNS/supported-keys.json deleted file mode 100644 index 6dabe6f..0000000 --- a/Sources/UnstoppableDomainsResolution/Resources/CNS/supported-keys.json +++ /dev/null @@ -1,648 +0,0 @@ -{ - "version": "1.1.0", - "keys": { - "crypto.BTC.address": { - "deprecatedKeyName": "BTC" - }, - "crypto.ETH.address": { - "deprecatedKeyName": "ETH" - }, - "crypto.ZIL.address": { - "deprecatedKeyName": "ZIL" - }, - "crypto.LTC.address": { - "deprecatedKeyName": "LTC" - }, - "crypto.ETC.address": { - "deprecatedKeyName": "ETC", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.EQL.address": { - "deprecatedKeyName": "EQL", - "validationRegex": "^bnb[0-9a-z]{39}$" - }, - "crypto.LINK.address": { - "deprecatedKeyName": "LINK", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.USDC.address": { - "deprecatedKeyName": "USDC", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.BAT.address": { - "deprecatedKeyName": "BAT", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.REP.address": { - "deprecatedKeyName": "REP", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.ZRX.address": { - "deprecatedKeyName": "ZRX", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.DAI.address": { - "deprecatedKeyName": "DAI", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.BCH.address": { - "deprecatedKeyName": "BCH", - "validationRegex": "^[13][a-km-zA-HJ-NP-Z1-9]{33}$|^((bitcoincash|bchreg|bchtest):)?(q|p)[a-z0-9]{41}$|^((BITCOINCASH:)?(Q|P)[A-Z0-9]{41})$" - }, - "crypto.XMR.address": { - "deprecatedKeyName": "XMR", - "validationRegex": "^[48]{1}[0-9AB][1-9A-HJ-NP-Za-km-z]{93}$" - }, - "crypto.DASH.address": { - "deprecatedKeyName": "DASH", - "validationRegex": "^X[1-9A-HJ-NP-Za-km-z]{33}$" - }, - "crypto.NEO.address": { - "deprecatedKeyName": "NEO", - "validationRegex": "^A[0-9a-zA-Z]{33}$" - }, - "crypto.SWTH.address": { - "deprecatedKeyName": "SWTH", - "validationRegex": "^A[0-9a-zA-Z]{33}$" - }, - "crypto.DOGE.address": { - "deprecatedKeyName": "DOGE", - "validationRegex": "^D[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}$" - }, - "crypto.XRP.address": { - "deprecatedKeyName": "XRP", - "validationRegex": "^r[1-9a-km-zA-HJ-NP-Z]{24,34}$" - }, - "crypto.ZEC.address": { - "deprecatedKeyName": "ZEC", - "validationRegex": "^z([a-zA-Z0-9]){94}$|^zs([a-zA-Z0-9]){75}$|^t([a-zA-Z0-9]){34}$" - }, - "crypto.ADA.address": { - "deprecatedKeyName": "ADA", - "validationRegex": "^[1-9a-km-zA-HJ-NP-Z]{104}$|^A[1-9A-HJ-NP-Za-km-z]{58}$|^addr[0-9a-zA-Z]{99}$" - }, - "crypto.EOS.address": { - "deprecatedKeyName": "EOS", - "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$" - }, - "crypto.XLM.address": { - "deprecatedKeyName": "XLM", - "validationRegex": "^G[A-Z2-7]{55}$" - }, - "crypto.BNB.address": { - "deprecatedKeyName": "BNB", - "validationRegex": "^bnb[0-9a-z]{39}$" - }, - "crypto.BTG.address": { - "deprecatedKeyName": "BTG", - "validationRegex": "^[GA][a-km-zA-HJ-NP-Z1-9]{33}$" - }, - "crypto.NANO.address": { - "deprecatedKeyName": "NANO", - "validationRegex": "^nano_[1-9a-z]{60}$" - }, - "crypto.WAVES.address": { - "deprecatedKeyName": "WAVES", - "validationRegex": "^3[a-km-zA-HJ-NP-Z1-9]{34}$" - }, - "crypto.KMD.address": { - "deprecatedKeyName": "KMD", - "validationRegex": "^R[a-km-zA-Z1-9]{33}$" - }, - "crypto.AE.address": { - "deprecatedKeyName": "AE", - "validationRegex": "^ak_[a-km-zA-Z1-9]{48,52}$" - }, - "crypto.RSK.address": { - "deprecatedKeyName": "RSK", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.WAN.address": { - "deprecatedKeyName": "WAN", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.STRAT.address": { - "deprecatedKeyName": "STRAT", - "validationRegex": "^S[a-km-zA-HJ-NP-Z1-9]{33}$" - }, - "crypto.UBQ.address": { - "deprecatedKeyName": "UBQ", - "validationRegex": "^0x[a-km-zA-HJ-NP-Z0-9]{40}$" - }, - "crypto.XTZ.address": { - "deprecatedKeyName": "XTZ", - "validationRegex": "^(tz|KT)[a-km-zA-HJ-NP-Z1-9]{34}$" - }, - "crypto.IOTA.address": { - "deprecatedKeyName": "IOTA", - "validationRegex": "^[A-Z0-9]{90}$" - }, - "crypto.VET.address": { - "deprecatedKeyName": "VET", - "validationRegex": "^0x[a-km-zA-HJ-NP-Z0-9]{40}$" - }, - "crypto.QTUM.address": { - "deprecatedKeyName": "QTUM", - "validationRegex": "^Q[a-km-zA-HJ-NP-Z1-9]{33}$" - }, - "crypto.ICX.address": { - "deprecatedKeyName": "ICX", - "validationRegex": "^[a-km-zA-HJ-NP-Z0-9]{42}$" - }, - "crypto.DGB.address": { - "deprecatedKeyName": "DGB", - "validationRegex": "^[a-km-zA-HJ-NP-Z1-9]{34}$|^[a-zA-Z1-9]{42}$" - }, - "crypto.XZC.address": { - "deprecatedKeyName": "XZC", - "validationRegex": "^[a-km-zA-HJ-NP-Z1-9]{34}$" - }, - "crypto.BURST.address": { - "deprecatedKeyName": "BURST", - "validationRegex": "^BURST-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{5}" - }, - "crypto.DCR.address": { - "deprecatedKeyName": "DCR" - }, - "crypto.XEM.address": { - "deprecatedKeyName": "XEM", - "validationRegex": "^N[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]{39}$" - }, - "crypto.LSK.address": { - "deprecatedKeyName": "LSK", - "validationRegex": "^\\d{1,21}[L]$" - }, - "crypto.ATOM.address": { - "deprecatedKeyName": "ATOM", - "validationRegex": "^(cosmos)1([qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$" - }, - "crypto.ONG.address": { - "deprecatedKeyName": "ONG", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.ONT.address": { - "deprecatedKeyName": "ONT", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.SMART.address": { - "deprecatedKeyName": "SMART", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.TPAY.address": { - "deprecatedKeyName": "TPAY", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.GRS.address": { - "deprecatedKeyName": "GRS", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.BSV.address": { - "deprecatedKeyName": "BSV", - "validationRegex": "^bitcoincash:[a-zA-Z0-9]{42}$" - }, - "crypto.GAS.address": { - "deprecatedKeyName": "GAS" - }, - "crypto.TRX.address": { - "deprecatedKeyName": "TRX", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.VTHO.address": { - "deprecatedKeyName": "VTHO", - "validationRegex": "^[a-zA-Z0-9]{42}$" - }, - "crypto.BCD.address": { - "deprecatedKeyName": "BCD", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.BTT.address": { - "deprecatedKeyName": "BTT", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.KIN.address": { - "deprecatedKeyName": "KIN", - "validationRegex": "^[a-zA-Z0-9]{56}$" - }, - "crypto.RVN.address": { - "deprecatedKeyName": "RVN", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.ARK.address": { - "deprecatedKeyName": "ARK", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.XVG.address": { - "deprecatedKeyName": "XVG", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.ALGO.address": { - "deprecatedKeyName": "ALGO", - "validationRegex": "^[a-zA-Z0-9]{58}$" - }, - "crypto.NEBL.address": { - "deprecatedKeyName": "NEBL", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.XPM.address": { - "deprecatedKeyName": "XPM", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.ONE.address": { - "deprecatedKeyName": "ONE", - "validationRegex": "^one[a-zA-Z0-9]{39}$" - }, - "crypto.BNTY.address": { - "deprecatedKeyName": "BNTY", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.CRO.address": { - "deprecatedKeyName": "CRO", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.TWT.address": { - "deprecatedKeyName": "TWT", - "validationRegex": "^bnb[0-9a-z]{39}$" - }, - "crypto.SIERRA.address": { - "deprecatedKeyName": "SIERRA", - "validationRegex": "^[a-zA-Z0-9]{34}$" - }, - "crypto.VSYS.address": { - "deprecatedKeyName": "VSYS", - "validationRegex": "^[a-zA-Z0-9]{35}$" - }, - "crypto.HIVE.address": { - "deprecatedKeyName": "HIVE", - "validationRegex": "^(?!s*$).+" - }, - "crypto.HT.address": { - "deprecatedKeyName": "HT", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.ENJ.address": { - "deprecatedKeyName": "ENJ", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.YFI.address": { - "deprecatedKeyName": "YFI", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.MTA.address": { - "deprecatedKeyName": "MTA", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.COMP.address": { - "deprecatedKeyName": "COMP", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.BAL.address": { - "deprecatedKeyName": "BAL", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.AMPL.address": { - "deprecatedKeyName": "AMPL", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.LEND.address": { - "deprecatedKeyName": "LEND", - "validationRegex": "^0x[a-fA-F0-9]{40}$" - }, - "crypto.TLOS.address": { - "deprecatedKeyName": "TLOS", - "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$" - }, - "crypto.USDT.version.ERC20.address": { - "deprecatedKeyName": "USDT_ERC20" - }, - "crypto.USDT.version.TRON.address": { - "deprecatedKeyName": "USDT_TRON" - }, - "crypto.USDT.version.EOS.address": { - "deprecatedKeyName": "USDT_EOS", - "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$" - }, - "crypto.USDT.version.OMNI.address": { - "deprecatedKeyName": "USDT_OMNI" - }, - "social.payid.name": { - "deprecatedKeyName": "payid", - "validationRegex": "^[0-9a-zA-Z]+\\$[0-9a-zA-Z]+\\.[0-9a-zA-Z]+$" - }, - "whois.email.value": { - "deprecatedKeyName": "email", - "validationRegex": "^[^@]+@[^\\.]+\\..+$" - }, - "whois.for_sale.value": { - "deprecatedKeyName": "for_sale", - "validationRegex": "(true)|(false)" - }, - "ipfs.html.value": { - "deprecatedKeyName": "html", - "validationRegex": ".{0,100}" - }, - "ipfs.redirect_domain.value": { - "deprecatedKeyName": "redirect_domain", - "validationRegex": ".{0,253}" - }, - "gundb.username.value": { - "deprecatedKeyName": "gundb_username" - }, - "gundb.public_key.value": { - "deprecatedKeyName": "gundb_public_key" - }, - "social.image.value": { - "deprecatedKeyName": "image" - }, - "social.twitter.username": { - "deprecatedKeyName": "twitter_username" - }, - "validation.social.twitter.username": { - "deprecatedKeyName": "validation_twitter_username" - }, - "dns.ttl": { - "deprecatedKeyName": "ttl" - }, - "dns.A": { - "deprecatedKeyName": "A" - }, - "dns.A.ttl": { - "deprecatedKeyName": "A_ttl" - }, - "dns.AAAA": { - "deprecatedKeyName": "AAAA" - }, - "dns.AAAA.ttl": { - "deprecatedKeyName": "AAAA_ttl" - }, - "dns.AFSDB": { - "deprecatedKeyName": "AFSDB" - }, - "dns.AFSDB.ttl": { - "deprecatedKeyName": "AFSDB_ttl" - }, - "dns.APL": { - "deprecatedKeyName": "APL" - }, - "dns.APL.ttl": { - "deprecatedKeyName": "APL_ttl" - }, - "dns.CAA": { - "deprecatedKeyName": "CAA" - }, - "dns.CAA.ttl": { - "deprecatedKeyName": "CAA_ttl" - }, - "dns.CDNSKEY": { - "deprecatedKeyName": "CDNSKEY" - }, - "dns.CDNSKEY.ttl": { - "deprecatedKeyName": "CDNSKEY_ttl" - }, - "dns.CDS": { - "deprecatedKeyName": "CDS" - }, - "dns.CDS.ttl": { - "deprecatedKeyName": "CDS_ttl" - }, - "dns.CERT": { - "deprecatedKeyName": "CERT" - }, - "dns.CERT.ttl": { - "deprecatedKeyName": "CERT_ttl" - }, - "dns.CNAME": { - "deprecatedKeyName": "CNAME" - }, - "dns.CNAME.ttl": { - "deprecatedKeyName": "CNAME_ttl" - }, - "dns.CSYNC": { - "deprecatedKeyName": "CSYNC" - }, - "dns.CSYNC.ttl": { - "deprecatedKeyName": "CSYNC_ttl" - }, - "dns.DHCID": { - "deprecatedKeyName": "DHCID" - }, - "dns.DHCID.ttl": { - "deprecatedKeyName": "DHCID_ttl" - }, - "dns.DLV": { - "deprecatedKeyName": "DLV" - }, - "dns.DLV.ttl": { - "deprecatedKeyName": "DLV_ttl" - }, - "dns.DNAME": { - "deprecatedKeyName": "DNAME" - }, - "dns.DNAME.ttl": { - "deprecatedKeyName": "DNAME_ttl" - }, - "dns.DNSKEY": { - "deprecatedKeyName": "DNSKEY" - }, - "dns.DNSKEY.ttl": { - "deprecatedKeyName": "DNSKEY_ttl" - }, - "dns.DS": { - "deprecatedKeyName": "DS" - }, - "dns.DS.ttl": { - "deprecatedKeyName": "DS_ttl" - }, - "dns.EUI48": { - "deprecatedKeyName": "EUI48" - }, - "dns.EUI48.ttl": { - "deprecatedKeyName": "EUI48_ttl" - }, - "dns.EUI64": { - "deprecatedKeyName": "EUI64" - }, - "dns.EUI64.ttl": { - "deprecatedKeyName": "EUI64_ttl" - }, - "dns.HINFO": { - "deprecatedKeyName": "HINFO" - }, - "dns.HINFO.ttl": { - "deprecatedKeyName": "HINFO_ttl" - }, - "dns.HIP": { - "deprecatedKeyName": "HIP" - }, - "dns.HIP.ttl": { - "deprecatedKeyName": "HIP_ttl" - }, - "dns.HTTPS": { - "deprecatedKeyName": "HTTPS" - }, - "dns.HTTPS.ttl": { - "deprecatedKeyName": "HTTPS_ttl" - }, - "dns.IPSECKEY": { - "deprecatedKeyName": "IPSECKEY" - }, - "dns.IPSECKEY.ttl": { - "deprecatedKeyName": "IPSECKEY_ttl" - }, - "dns.KEY": { - "deprecatedKeyName": "KEY" - }, - "dns.KEY.ttl": { - "deprecatedKeyName": "KEY_ttl" - }, - "dns.KX": { - "deprecatedKeyName": "KX" - }, - "dns.KX.ttl": { - "deprecatedKeyName": "KX_ttl" - }, - "dns.LOC": { - "deprecatedKeyName": "LOC" - }, - "dns.LOC.ttl": { - "deprecatedKeyName": "LOC_ttl" - }, - "dns.MX": { - "deprecatedKeyName": "MX" - }, - "dns.MX.ttl": { - "deprecatedKeyName": "MX_ttl" - }, - "dns.NAPTR": { - "deprecatedKeyName": "NAPTR" - }, - "dns.NAPTR.ttl": { - "deprecatedKeyName": "NAPTR_ttl" - }, - "dns.NS": { - "deprecatedKeyName": "NS" - }, - "dns.NS.ttl": { - "deprecatedKeyName": "NS_ttl" - }, - "dns.NSEC": { - "deprecatedKeyName": "NSEC" - }, - "dns.NSEC.ttl": { - "deprecatedKeyName": "NSEC_ttl" - }, - "dns.NSEC3": { - "deprecatedKeyName": "NSEC3" - }, - "dns.NSEC3.ttl": { - "deprecatedKeyName": "NSEC3_ttl" - }, - "dns.NSEC3PARAM": { - "deprecatedKeyName": "NSEC3PARAM" - }, - "dns.NSEC3PARAM.ttl": { - "deprecatedKeyName": "NSEC3PARAM_ttl" - }, - "dns.OPENPGPKEY": { - "deprecatedKeyName": "OPENPGPKEY" - }, - "dns.OPENPGPKEY.ttl": { - "deprecatedKeyName": "OPENPGPKEY_ttl" - }, - "dns.PTR": { - "deprecatedKeyName": "PTR" - }, - "dns.PTR.ttl": { - "deprecatedKeyName": "PTR_ttl" - }, - "dns.RP": { - "deprecatedKeyName": "RP" - }, - "dns.RP.ttl": { - "deprecatedKeyName": "RP_ttl" - }, - "dns.RRSIG": { - "deprecatedKeyName": "RRSIG" - }, - "dns.RRSIG.ttl": { - "deprecatedKeyName": "RRSIG_ttl" - }, - "dns.SIG": { - "deprecatedKeyName": "SIG" - }, - "dns.SIG.ttl": { - "deprecatedKeyName": "SIG_ttl" - }, - "dns.SMIMEA": { - "deprecatedKeyName": "SMIMEA" - }, - "dns.SMIMEA.ttl": { - "deprecatedKeyName": "SMIMEA_ttl" - }, - "dns.SOA": { - "deprecatedKeyName": "SOA" - }, - "dns.SOA.ttl": { - "deprecatedKeyName": "SOA_ttl" - }, - "dns.SRV": { - "deprecatedKeyName": "SRV" - }, - "dns.SRV.ttl": { - "deprecatedKeyName": "SRV_ttl" - }, - "dns.SSHFP": { - "deprecatedKeyName": "SSHFP" - }, - "dns.SSHFP.ttl": { - "deprecatedKeyName": "SSHFP_ttl" - }, - "dns.SVCB": { - "deprecatedKeyName": "SVCB" - }, - "dns.SVCB.ttl": { - "deprecatedKeyName": "SVCB_ttl" - }, - "dns.TA": { - "deprecatedKeyName": "TA" - }, - "dns.TA.ttl": { - "deprecatedKeyName": "TA_ttl" - }, - "dns.TKEY": { - "deprecatedKeyName": "TKEY" - }, - "dns.TKEY.ttl": { - "deprecatedKeyName": "TKEY_ttl" - }, - "dns.TLSA": { - "deprecatedKeyName": "TLSA" - }, - "dns.TLSA.ttl": { - "deprecatedKeyName": "TLSA_ttl" - }, - "dns.TSIG": { - "deprecatedKeyName": "TSIG" - }, - "dns.TSIG.ttl": { - "deprecatedKeyName": "TSIG_ttl" - }, - "dns.TXT": { - "deprecatedKeyName": "TXT" - }, - "dns.TXT.ttl": { - "deprecatedKeyName": "TXT_ttl" - }, - "dns.URI": { - "deprecatedKeyName": "URI" - }, - "dns.URI.ttl": { - "deprecatedKeyName": "URI_ttl" - }, - "dns.ZONEMD": { - "deprecatedKeyName": "ZONEMD" - }, - "dns.ZONEMD.ttl": { - "deprecatedKeyName": "ZONEMD_ttl" - } - } -} diff --git a/Sources/UnstoppableDomainsResolution/Resources/ENS/ensRegistry.json b/Sources/UnstoppableDomainsResolution/Resources/ENS/ensRegistry.json new file mode 100644 index 0000000..14c82dc --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/ENS/ensRegistry.json @@ -0,0 +1,108 @@ +[ + { + "constant": true, + "inputs": [{ "name": "node", "type": "bytes32" }], + "name": "resolver", + "outputs": [{ "name": "", "type": "address" }], + "payable": false, + "type": "function", + }, + { + "constant": true, + "inputs": [{ "name": "node", "type": "bytes32" }], + "name": "owner", + "outputs": [{ "name": "", "type": "address" }], + "payable": false, + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "name": "node", "type": "bytes32" }, + { "name": "label", "type": "bytes32" }, + { "name": "owner", "type": "address" }, + ], + "name": "setSubnodeOwner", + "outputs": [], + "payable": false, + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "name": "node", "type": "bytes32" }, + { "name": "ttl", "type": "uint64" }, + ], + "name": "setTTL", + "outputs": [], + "payable": false, + "type": "function", + }, + { + "constant": true, + "inputs": [{ "name": "node", "type": "bytes32" }], + "name": "ttl", + "outputs": [{ "name": "", "type": "uint64" }], + "payable": false, + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "name": "node", "type": "bytes32" }, + { "name": "resolver", "type": "address" }, + ], + "name": "setResolver", + "outputs": [], + "payable": false, + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "name": "node", "type": "bytes32" }, + { "name": "owner", "type": "address" }, + ], + "name": "setOwner", + "outputs": [], + "payable": false, + "type": "function", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "node", "type": "bytes32" }, + { "indexed": false, "name": "owner", "type": "address" }, + ], + "name": "Transfer", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "node", "type": "bytes32" }, + { "indexed": true, "name": "label", "type": "bytes32" }, + { "indexed": false, "name": "owner", "type": "address" }, + ], + "name": "NewOwner", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "node", "type": "bytes32" }, + { "indexed": false, "name": "resolver", "type": "address" }, + ], + "name": "NewResolver", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "node", "type": "bytes32" }, + { "indexed": false, "name": "ttl", "type": "uint64" }, + ], + "name": "NewTTL", + "type": "event", + }, +] diff --git a/Sources/UnstoppableDomainsResolution/Resources/ENS/ensResolver.json b/Sources/UnstoppableDomainsResolution/Resources/ENS/ensResolver.json new file mode 100644 index 0000000..40d27a1 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/ENS/ensResolver.json @@ -0,0 +1,357 @@ +[ + { + "constant": true, + "inputs": [{ "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "key", "type": "string" }, + { "internalType": "string", "name": "value", "type": "string" }, + ], + "name": "setText", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }, + ], + "name": "interfaceImplementer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "contentTypes", "type": "uint256" }, + ], + "name": "ABI", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "bytes", "name": "", "type": "bytes" }, + ], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "internalType": "bytes32", "name": "y", "type": "bytes32" }, + ], + "name": "setPubkey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes", "name": "hash", "type": "bytes" }, + ], + "name": "setContenthash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bool", "name": "isAuthorised", "type": "bool" }, + ], + "name": "setAuthorisation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "key", "type": "string" }, + ], + "name": "text", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "contentType", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" }, + ], + "name": "setABI", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "name", "type": "string" }, + ], + "name": "setName", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "coinType", "type": "uint256" }, + { "internalType": "bytes", "name": "a", "type": "bytes" }, + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "contenthash", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "pubkey", + "outputs": [ + { "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "internalType": "bytes32", "name": "y", "type": "bytes32" }, + ], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "a", "type": "address" }, + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }, + { "internalType": "address", "name": "implementer", "type": "address" }, + ], + "name": "setInterface", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "coinType", "type": "uint256" }, + ], + "name": "addr", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "", "type": "bytes32" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + ], + "name": "authorisations", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [{ "internalType": "contract ENS", "name": "_ens", "type": "address" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address", + }, + { + "indexed": false, + "internalType": "bool", + "name": "isAuthorised", + "type": "bool", + }, + ], + "name": "AuthorisationChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { + "indexed": false, + "internalType": "string", + "name": "indexedKey", + "type": "string", + }, + { "indexed": false, "internalType": "string", "name": "key", "type": "string" }, + ], + "name": "TextChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes32", "name": "y", "type": "bytes32" }, + ], + "name": "PubkeyChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "string", "name": "name", "type": "string" }, + ], + "name": "NameChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { + "indexed": true, + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4", + }, + { + "indexed": false, + "internalType": "address", + "name": "implementer", + "type": "address", + }, + ], + "name": "InterfaceChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes", "name": "hash", "type": "bytes" }, + ], + "name": "ContenthashChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "address", "name": "a", "type": "address" }, + ], + "name": "AddrChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { + "indexed": false, + "internalType": "uint256", + "name": "coinType", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newAddress", + "type": "bytes", + }, + ], + "name": "AddressChanged", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { + "indexed": true, + "internalType": "uint256", + "name": "contentType", + "type": "uint256", + }, + ], + "name": "ABIChanged", + "type": "event", + }, +] diff --git a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsRegistry.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/cnsRegistry.json similarity index 99% rename from Sources/UnstoppableDomainsResolution/Resources/CNS/cnsRegistry.json rename to Sources/UnstoppableDomainsResolution/Resources/UNS/cnsRegistry.json index ff7aeb5..b6f5788 100644 --- a/Sources/UnstoppableDomainsResolution/Resources/CNS/cnsRegistry.json +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/cnsRegistry.json @@ -1,3 +1,4 @@ + [ { "constant":true, diff --git a/Sources/UnstoppableDomainsResolution/Resources/UNS/supported-keys.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/supported-keys.json new file mode 100644 index 0000000..648aef2 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/supported-keys.json @@ -0,0 +1,2375 @@ +{ + "version": "1.1.1", + "keys": { + "crypto.BTC.address": { + "deprecatedKeyName": "BTC", + "deprecated": false, + "validationRegex": "^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$" + }, + "crypto.ETH.address": { + "deprecatedKeyName": "ETH", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.ZIL.address": { + "deprecatedKeyName": "ZIL", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$|^zil1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38}$" + }, + "crypto.LTC.address": { + "deprecatedKeyName": "LTC", + "deprecated": false, + "validationRegex": "^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$|^ltc1[a-zA-HJ-NP-Z0-9]{25,39}$" + }, + "crypto.ETC.address": { + "deprecatedKeyName": "ETC", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.EQL.address": { + "deprecatedKeyName": "EQL", + "deprecated": false, + "validationRegex": "^bnb[0-9a-z]{39}$" + }, + "crypto.LINK.address": { + "deprecatedKeyName": "LINK", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.USDC.address": { + "deprecatedKeyName": "USDC", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.BAT.address": { + "deprecatedKeyName": "BAT", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.REP.address": { + "deprecatedKeyName": "REP", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.ZRX.address": { + "deprecatedKeyName": "ZRX", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.DAI.address": { + "deprecatedKeyName": "DAI", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.BCH.address": { + "deprecatedKeyName": "BCH", + "deprecated": false, + "validationRegex": "^[13][a-km-zA-HJ-NP-Z1-9]{33}$|^((bitcoincash|bchreg|bchtest):)?(q|p)[a-z0-9]{41}$|^((BITCOINCASH:)?(Q|P)[A-Z0-9]{41})$" + }, + "crypto.XMR.address": { + "deprecatedKeyName": "XMR", + "deprecated": false, + "validationRegex": "^[48]{1}[0-9AB][1-9A-HJ-NP-Za-km-z]{93}$" + }, + "crypto.DASH.address": { + "deprecatedKeyName": "DASH", + "deprecated": false, + "validationRegex": "^X[1-9A-HJ-NP-Za-km-z]{33}$" + }, + "crypto.NEO.address": { + "deprecatedKeyName": "NEO", + "deprecated": false, + "validationRegex": "^A[0-9a-zA-Z]{33}$" + }, + "crypto.SWTH.address": { + "deprecatedKeyName": "SWTH", + "deprecated": false, + "validationRegex": "^A[0-9a-zA-Z]{33}$" + }, + "crypto.DOGE.address": { + "deprecatedKeyName": "DOGE", + "deprecated": false, + "validationRegex": "^D[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}$" + }, + "crypto.XRP.address": { + "deprecatedKeyName": "XRP", + "deprecated": false, + "validationRegex": "^r[1-9a-km-zA-HJ-NP-Z]{24,34}$" + }, + "crypto.ZEC.address": { + "deprecatedKeyName": "ZEC", + "deprecated": false, + "validationRegex": "^z([a-zA-Z0-9]){94}$|^zs([a-zA-Z0-9]){75}$|^t([a-zA-Z0-9]){34}$" + }, + "crypto.ADA.address": { + "deprecatedKeyName": "ADA", + "deprecated": false, + "validationRegex": "^[1-9a-km-zA-HJ-NP-Z]{104}$|^A[1-9A-HJ-NP-Za-km-z]{58}$|^addr[0-9a-zA-Z]{99}$" + }, + "crypto.EOS.address": { + "deprecatedKeyName": "EOS", + "deprecated": false, + "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$" + }, + "crypto.XLM.address": { + "deprecatedKeyName": "XLM", + "deprecated": false, + "validationRegex": "^G[A-Z2-7]{55}$" + }, + "crypto.BNB.address": { + "deprecatedKeyName": "BNB", + "deprecated": false, + "validationRegex": "^bnb[0-9a-z]{39}$" + }, + "crypto.BTG.address": { + "deprecatedKeyName": "BTG", + "deprecated": false, + "validationRegex": "^[GA][a-km-zA-HJ-NP-Z1-9]{33}$" + }, + "crypto.NANO.address": { + "deprecatedKeyName": "NANO", + "deprecated": false, + "validationRegex": "^nano_[1-9a-z]{60}$" + }, + "crypto.WAVES.address": { + "deprecatedKeyName": "WAVES", + "deprecated": false, + "validationRegex": "^3[a-km-zA-HJ-NP-Z1-9]{34}$" + }, + "crypto.KMD.address": { + "deprecatedKeyName": "KMD", + "deprecated": false, + "validationRegex": "^R[a-km-zA-Z1-9]{33}$" + }, + "crypto.AE.address": { + "deprecatedKeyName": "AE", + "deprecated": false, + "validationRegex": "^ak_[a-km-zA-Z1-9]{48,52}$" + }, + "crypto.RSK.address": { + "deprecatedKeyName": "RSK", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.WAN.address": { + "deprecatedKeyName": "WAN", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.STRAT.address": { + "deprecatedKeyName": "STRAT", + "deprecated": false, + "validationRegex": "^S[a-km-zA-HJ-NP-Z1-9]{33}$" + }, + "crypto.UBQ.address": { + "deprecatedKeyName": "UBQ", + "deprecated": false, + "validationRegex": "^0x[a-km-zA-HJ-NP-Z0-9]{40}$" + }, + "crypto.XTZ.address": { + "deprecatedKeyName": "XTZ", + "deprecated": false, + "validationRegex": "^(tz|KT)[a-km-zA-HJ-NP-Z1-9]{34}$" + }, + "crypto.IOTA.address": { + "deprecatedKeyName": "IOTA", + "deprecated": false, + "validationRegex": "^[A-Z0-9]{90}$" + }, + "crypto.VET.address": { + "deprecatedKeyName": "VET", + "deprecated": false, + "validationRegex": "^0x[a-km-zA-HJ-NP-Z0-9]{40}$" + }, + "crypto.QTUM.address": { + "deprecatedKeyName": "QTUM", + "deprecated": false, + "validationRegex": "^Q[a-km-zA-HJ-NP-Z1-9]{33}$" + }, + "crypto.ICX.address": { + "deprecatedKeyName": "ICX", + "deprecated": false, + "validationRegex": "^[a-km-zA-HJ-NP-Z0-9]{42}$" + }, + "crypto.DGB.address": { + "deprecatedKeyName": "DGB", + "deprecated": false, + "validationRegex": "(^[a-km-zA-HJ-NP-Z1-9]{34}$)|(^[a-zA-Z1-9]{42}$)|(^dgb1[a-zA-Z0-9]{39}$)" + }, + "crypto.XZC.address": { + "deprecatedKeyName": "XZC", + "deprecated": false, + "validationRegex": "^[a-km-zA-HJ-NP-Z1-9]{34}$" + }, + "crypto.BURST.address": { + "deprecatedKeyName": "BURST", + "deprecated": false, + "validationRegex": "^BURST-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{5}" + }, + "crypto.DCR.address": { + "deprecatedKeyName": "DCR", + "deprecated": false, + "validationRegex": null + }, + "crypto.XEM.address": { + "deprecatedKeyName": "XEM", + "deprecated": false, + "validationRegex": "^N[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]{39}$" + }, + "crypto.LSK.address": { + "deprecatedKeyName": "LSK", + "deprecated": false, + "validationRegex": "^\\d{1,21}[L]$" + }, + "crypto.ATOM.address": { + "deprecatedKeyName": "ATOM", + "deprecated": false, + "validationRegex": "^(cosmos)1([qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$" + }, + "crypto.ONG.address": { + "deprecatedKeyName": "ONG", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.ONT.address": { + "deprecatedKeyName": "ONT", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.SMART.address": { + "deprecatedKeyName": "SMART", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.TPAY.address": { + "deprecatedKeyName": "TPAY", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.GRS.address": { + "deprecatedKeyName": "GRS", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.BSV.address": { + "deprecatedKeyName": "BSV", + "deprecated": false, + "validationRegex": "^bitcoincash:[a-zA-Z0-9]{42}$" + }, + "crypto.GAS.address": { + "deprecatedKeyName": "GAS", + "deprecated": false, + "validationRegex": null + }, + "crypto.TRX.address": { + "deprecatedKeyName": "TRX", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.VTHO.address": { + "deprecatedKeyName": "VTHO", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{42}$" + }, + "crypto.BCD.address": { + "deprecatedKeyName": "BCD", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.BTT.address": { + "deprecatedKeyName": "BTT", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.KIN.address": { + "deprecatedKeyName": "KIN", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{56}$" + }, + "crypto.RVN.address": { + "deprecatedKeyName": "RVN", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.ARK.address": { + "deprecatedKeyName": "ARK", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.XVG.address": { + "deprecatedKeyName": "XVG", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.ALGO.address": { + "deprecatedKeyName": "ALGO", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{58}$" + }, + "crypto.NEBL.address": { + "deprecatedKeyName": "NEBL", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.XPM.address": { + "deprecatedKeyName": "XPM", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.ONE.address": { + "deprecatedKeyName": "ONE", + "deprecated": false, + "validationRegex": "^one[a-zA-Z0-9]{39}$" + }, + "crypto.BNTY.address": { + "deprecatedKeyName": "BNTY", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.CRO.address": { + "deprecatedKeyName": "CRO", + "deprecated": false, + "validationRegex": "^0x[a-fA-F0-9]{40}$" + }, + "crypto.TWT.address": { + "deprecatedKeyName": "TWT", + "deprecated": false, + "validationRegex": "^bnb[0-9a-z]{39}$" + }, + "crypto.SIERRA.address": { + "deprecatedKeyName": "SIERRA", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{34}$" + }, + "crypto.VSYS.address": { + "deprecatedKeyName": "VSYS", + "deprecated": false, + "validationRegex": "^[a-zA-Z0-9]{35}$" + }, + "crypto.HIVE.address": { + "deprecatedKeyName": "HIVE", + "validationRegex": "^(?!s*$).+", + "deprecated": false + }, + "crypto.HT.address": { + "deprecatedKeyName": "HT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ENJ.address": { + "deprecatedKeyName": "ENJ", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.YFI.address": { + "deprecatedKeyName": "YFI", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MTA.address": { + "deprecatedKeyName": "MTA", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.COMP.address": { + "deprecatedKeyName": "COMP", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BAL.address": { + "deprecatedKeyName": "BAL", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AMPL.address": { + "deprecatedKeyName": "AMPL", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LEND.address": { + "deprecatedKeyName": "LEND", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TLOS.address": { + "deprecatedKeyName": "TLOS", + "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$", + "deprecated": false + }, + "crypto.XDC.address": { + "deprecatedKeyName": "XDC", + "validationRegex": "^xdc[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XST.address": { + "deprecatedKeyName": "XST", + "validationRegex": "(?:RwxQ3jUs2BjKhseNX1em4msn2GyV5XAec[PQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]|RwxQ3jUs2BjKhseNX1em4msn2GyV5XAe[defghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]|RwxQ3jUs2BjKhseNX1em4msn2GyV5XA[fghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{2}|RwxQ3jUs2BjKhseNX1em4msn2GyV5X[BCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3}|RwxQ3jUs2BjKhseNX1em4msn2GyV5[YZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{4}|RwxQ3jUs2BjKhseNX1em4msn2GyV[6789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{5}|RwxQ3jUs2BjKhseNX1em4msn2Gy[WXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{6}|RwxQ3jUs2BjKhseNX1em4msn2G[z][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{7}|RwxQ3jUs2BjKhseNX1em4msn2[HJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{8}|RwxQ3jUs2BjKhseNX1em4msn[3456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{9}|RwxQ3jUs2BjKhseNX1em4ms[opqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{10}|RwxQ3jUs2BjKhseNX1em4m[tuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{11}|RwxQ3jUs2BjKhseNX1em4[nopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{12}|RwxQ3jUs2BjKhseNX1em[56789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{13}|RwxQ3jUs2BjKhseNX1e[nopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{14}|RwxQ3jUs2BjKhseNX1[fghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{15}|RwxQ3jUs2BjKhseNX[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{16}|RwxQ3jUs2BjKhseN[YZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{17}|RwxQ3jUs2BjKhse[PQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{18}|RwxQ3jUs2BjKhs[fghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{19}|RwxQ3jUs2BjKh[tuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{20}|RwxQ3jUs2BjK[ijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21}|RwxQ3jUs2Bj[LMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}|RwxQ3jUs2B[kmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{23}|RwxQ3jUs2[CDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{24}|RwxQ3jUs[3456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{25}|RwxQ3jU[tuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{26}|RwxQ3j[VWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{27}|RwxQ3[kmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{28}|RwxQ[456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}|Rwx[RSTUVWXYZabcdefghijkmnopqrstuvwxyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{30}|Rw[yz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{31}|R[xyz][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{32}|S[123456789ABCDEFGHJKL][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{32}|SM[123456789ABCDEFGH][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{31}|SMJ11[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}|SMJ11[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}|SMJ12[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnop][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{28}|SMJ12q[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkm][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{27}|SMJ12qn[12345678][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{26}|SMJ12qn9[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghi][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{25}|SMJ12qn9j[123456789ABCDEFGHJKLM][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{24}|SMJ12qn9jN[123456789AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{23}|SMJ12qn9jNC[123456789AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}|SMJ12qn9jNCC[123456789ABCDEFGHJKLMNPQRSTUVW][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21}|SMJ12qn9jNCCX[123456789ABCDEFGH][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{20}|SMJ12qn9jNCCXJ[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkm][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{19}|SMJ12qn9jNCCXJn[123456789ABCDEFGHJKLMNPQRS][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{18}|SMJ12qn9jNCCXJnT[123456789ABCDEFGHJKLMNPQRSTUVWX][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{17}|SMJ12qn9jNCCXJnTY[123456789ABCDEFGHJKLMNPQ][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{16}|SMJ12qn9jNCCXJnTYR[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxy][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{15}|SMJ12qn9jNCCXJnTYRz[1234][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{14}|SMJ12qn9jNCCXJnTYRz5[123456789ABCDEFGHJKLMNPQRSTUVWX][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{13}|SMJ12qn9jNCCXJnTYRz5Y[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrst][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{12}|SMJ12qn9jNCCXJnTYRz5Yu[12345678][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{11}|SMJ12qn9jNCCXJnTYRz5Yu9[123456789ABCDEFGHJKLMNPQRSTUVWXY][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{10}|SMJ12qn9jNCCXJnTYRz5Yu9Z[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcd][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{9}|SMJ12qn9jNCCXJnTYRz5Yu9Ze[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkm][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{8}|SMJ12qn9jNCCXJnTYRz5Yu9Zen[123456789ABCD][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{7}|SMJ12qn9jNCCXJnTYRz5Yu9ZenE[123456789ABCDEFGHJKLMNPQ][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{6}|SMJ12qn9jNCCXJnTYRz5Yu9ZenER[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkm][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{5}|SMJ12qn9jNCCXJnTYRz5Yu9ZenERn[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghij][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{4}|SMJ12qn9jNCCXJnTYRz5Yu9ZenERnk[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghij][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3}|SMJ12qn9jNCCXJnTYRz5Yu9ZenERnkk[123456789ABCDEFGHJKLMNPQRST][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{2}|SMJ12qn9jNCCXJnTYRz5Yu9ZenERnkkU[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstu][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]|SMJ12qn9jNCCXJnTYRz5Yu9ZenERnkkUv[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghi])", + "deprecated": false + }, + "crypto.STRAX.address": { + "deprecatedKeyName": "STRAX", + "validationRegex": "^X[a-km-zA-HJ-NP-Z1-9]{33}$", + "deprecated": false + }, + "crypto.USDT.version.ERC20.address": { + "deprecatedKeyName": "USDT_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.USDT.version.TRON.address": { + "deprecatedKeyName": "USDT_TRON", + "validationRegex": "^[T][a-zA-HJ-NP-Z0-9]{33}$", + "deprecated": false + }, + "crypto.USDT.version.EOS.address": { + "deprecatedKeyName": "USDT_EOS", + "validationRegex": "^[a-z][a-z1-5.]{10}[a-z1-5]$", + "deprecated": false + }, + "crypto.USDT.version.OMNI.address": { + "deprecatedKeyName": "USDT_OMNI", + "validationRegex": "^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$", + "deprecated": false + }, + "crypto.FTM.version.ERC20.address": { + "deprecatedKeyName": "FTM_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FTM.version.BEP2.address": { + "deprecatedKeyName": "FTM_BEP2", + "validationRegex": "^(bnb|tbnb)[a-zA-HJ-NP-Z0-9]{39}$", + "deprecated": false + }, + "crypto.FTM.version.OPERA.address": { + "deprecatedKeyName": "FTM_OPERA", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FUSE.version.ERC20.address": { + "deprecatedKeyName": "FUSE_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FUSE.version.FUSE.address": { + "deprecatedKeyName": "FUSE_FUSE", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "social.payid.name": { + "deprecatedKeyName": "payid", + "validationRegex": "^[0-9a-zA-Z]+\\$[0-9a-zA-Z]+\\.[0-9a-zA-Z]+$", + "deprecated": false + }, + "whois.email.value": { + "deprecatedKeyName": "email", + "validationRegex": "^[^@]+@[^\\.]+\\..+$", + "deprecated": false + }, + "whois.for_sale.value": { + "deprecatedKeyName": "for_sale", + "validationRegex": "(true)|(false)", + "deprecated": false + }, + "ipfs.html.value": { + "deprecatedKeyName": "html", + "validationRegex": ".{0,100}", + "deprecated": false + }, + "ipfs.redirect_domain.value": { + "deprecatedKeyName": "redirect_domain", + "validationRegex": ".{0,253}", + "deprecated": false + }, + "dweb.ipfs.hash": { + "deprecatedKeyName": "dweb_hash", + "validationRegex": ".{0,100}", + "deprecated": false + }, + "browser.redirect_url": { + "deprecatedKeyName": "browser_redirect", + "validationRegex": ".{0,253}", + "deprecated": false + }, + "browser.preferred_protocols": { + "deprecatedKeyName": "browser_preferred_protocols", + "validationRegex": null, + "deprecated": false + }, + "gundb.username.value": { + "deprecatedKeyName": "gundb_username", + "validationRegex": null, + "deprecated": false + }, + "gundb.public_key.value": { + "deprecatedKeyName": "gundb_public_key", + "validationRegex": null, + "deprecated": false + }, + "social.image.value": { + "deprecatedKeyName": "image", + "validationRegex": null, + "deprecated": false + }, + "social.twitter.username": { + "deprecatedKeyName": "twitter_username", + "validationRegex": null, + "deprecated": false + }, + "validation.social.twitter.username": { + "deprecatedKeyName": "validation_twitter_username", + "validationRegex": null, + "deprecated": false + }, + "forwarding.url": { + "deprecatedKeyName": "forwarding_url", + "validationRegex": "^(https?)://[^\\s/$.?#].[^\\s]*$", + "deprecated": false + }, + "dns.ttl": { + "deprecatedKeyName": "dns_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.A": { + "deprecatedKeyName": "dns_A", + "validationRegex": null, + "deprecated": false + }, + "dns.A.ttl": { + "deprecatedKeyName": "dns_A_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.AAAA": { + "deprecatedKeyName": "dns_AAAA", + "validationRegex": null, + "deprecated": false + }, + "dns.AAAA.ttl": { + "deprecatedKeyName": "dns_AAAA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.AFSDB": { + "deprecatedKeyName": "dns_AFSDB", + "validationRegex": null, + "deprecated": false + }, + "dns.AFSDB.ttl": { + "deprecatedKeyName": "dns_AFSDB_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.APL": { + "deprecatedKeyName": "dns_APL", + "validationRegex": null, + "deprecated": false + }, + "dns.APL.ttl": { + "deprecatedKeyName": "dns_APL_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CAA": { + "deprecatedKeyName": "dns_CAA", + "validationRegex": null, + "deprecated": false + }, + "dns.CAA.ttl": { + "deprecatedKeyName": "dns_CAA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CDNSKEY": { + "deprecatedKeyName": "dns_CDNSKEY", + "validationRegex": null, + "deprecated": false + }, + "dns.CDNSKEY.ttl": { + "deprecatedKeyName": "dns_CDNSKEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CDS": { + "deprecatedKeyName": "dns_CDS", + "validationRegex": null, + "deprecated": false + }, + "dns.CDS.ttl": { + "deprecatedKeyName": "dns_CDS_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CERT": { + "deprecatedKeyName": "dns_CERT", + "validationRegex": null, + "deprecated": false + }, + "dns.CERT.ttl": { + "deprecatedKeyName": "dns_CERT_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CNAME": { + "deprecatedKeyName": "dns_CNAME", + "validationRegex": null, + "deprecated": false + }, + "dns.CNAME.ttl": { + "deprecatedKeyName": "dns_CNAME_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.CSYNC": { + "deprecatedKeyName": "dns_CSYNC", + "validationRegex": null, + "deprecated": false + }, + "dns.CSYNC.ttl": { + "deprecatedKeyName": "dns_CSYNC_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.DHCID": { + "deprecatedKeyName": "dns_DHCID", + "validationRegex": null, + "deprecated": false + }, + "dns.DHCID.ttl": { + "deprecatedKeyName": "dns_DHCID_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.DLV": { + "deprecatedKeyName": "dns_DLV", + "validationRegex": null, + "deprecated": false + }, + "dns.DLV.ttl": { + "deprecatedKeyName": "dns_DLV_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.DNAME": { + "deprecatedKeyName": "dns_DNAME", + "validationRegex": null, + "deprecated": false + }, + "dns.DNAME.ttl": { + "deprecatedKeyName": "dns_DNAME_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.DNSKEY": { + "deprecatedKeyName": "dns_DNSKEY", + "validationRegex": null, + "deprecated": false + }, + "dns.DNSKEY.ttl": { + "deprecatedKeyName": "dns_DNSKEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.DS": { + "deprecatedKeyName": "dns_DS", + "validationRegex": null, + "deprecated": false + }, + "dns.DS.ttl": { + "deprecatedKeyName": "dns_DS_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.EUI48": { + "deprecatedKeyName": "dns_EUI48", + "validationRegex": null, + "deprecated": false + }, + "dns.EUI48.ttl": { + "deprecatedKeyName": "dns_EUI48_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.EUI64": { + "deprecatedKeyName": "dns_EUI64", + "validationRegex": null, + "deprecated": false + }, + "dns.EUI64.ttl": { + "deprecatedKeyName": "dns_EUI64_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.HINFO": { + "deprecatedKeyName": "dns_HINFO", + "validationRegex": null, + "deprecated": false + }, + "dns.HINFO.ttl": { + "deprecatedKeyName": "dns_HINFO_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.HIP": { + "deprecatedKeyName": "dns_HIP", + "validationRegex": null, + "deprecated": false + }, + "dns.HIP.ttl": { + "deprecatedKeyName": "dns_HIP_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.HTTPS": { + "deprecatedKeyName": "dns_HTTPS", + "validationRegex": null, + "deprecated": false + }, + "dns.HTTPS.ttl": { + "deprecatedKeyName": "dns_HTTPS_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.IPSECKEY": { + "deprecatedKeyName": "dns_IPSECKEY", + "validationRegex": null, + "deprecated": false + }, + "dns.IPSECKEY.ttl": { + "deprecatedKeyName": "dns_IPSECKEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.KEY": { + "deprecatedKeyName": "dns_KEY", + "validationRegex": null, + "deprecated": false + }, + "dns.KEY.ttl": { + "deprecatedKeyName": "dns_KEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.KX": { + "deprecatedKeyName": "dns_KX", + "validationRegex": null, + "deprecated": false + }, + "dns.KX.ttl": { + "deprecatedKeyName": "dns_KX_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.LOC": { + "deprecatedKeyName": "dns_LOC", + "validationRegex": null, + "deprecated": false + }, + "dns.LOC.ttl": { + "deprecatedKeyName": "dns_LOC_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.MX": { + "deprecatedKeyName": "dns_MX", + "validationRegex": null, + "deprecated": false + }, + "dns.MX.ttl": { + "deprecatedKeyName": "dns_MX_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.NAPTR": { + "deprecatedKeyName": "dns_NAPTR", + "validationRegex": null, + "deprecated": false + }, + "dns.NAPTR.ttl": { + "deprecatedKeyName": "dns_NAPTR_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.NS": { + "deprecatedKeyName": "dns_NS", + "validationRegex": null, + "deprecated": false + }, + "dns.NS.ttl": { + "deprecatedKeyName": "dns_NS_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC": { + "deprecatedKeyName": "dns_NSEC", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC.ttl": { + "deprecatedKeyName": "dns_NSEC_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC3": { + "deprecatedKeyName": "dns_NSEC3", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC3.ttl": { + "deprecatedKeyName": "dns_NSEC3_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC3PARAM": { + "deprecatedKeyName": "dns_NSEC3PARAM", + "validationRegex": null, + "deprecated": false + }, + "dns.NSEC3PARAM.ttl": { + "deprecatedKeyName": "dns_NSEC3PARAM_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.OPENPGPKEY": { + "deprecatedKeyName": "dns_OPENPGPKEY", + "validationRegex": null, + "deprecated": false + }, + "dns.OPENPGPKEY.ttl": { + "deprecatedKeyName": "dns_OPENPGPKEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.PTR": { + "deprecatedKeyName": "dns_PTR", + "validationRegex": null, + "deprecated": false + }, + "dns.PTR.ttl": { + "deprecatedKeyName": "dns_PTR_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.RP": { + "deprecatedKeyName": "dns_RP", + "validationRegex": null, + "deprecated": false + }, + "dns.RP.ttl": { + "deprecatedKeyName": "dns_RP_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.RRSIG": { + "deprecatedKeyName": "dns_RRSIG", + "validationRegex": null, + "deprecated": false + }, + "dns.RRSIG.ttl": { + "deprecatedKeyName": "dns_RRSIG_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SIG": { + "deprecatedKeyName": "dns_SIG", + "validationRegex": null, + "deprecated": false + }, + "dns.SIG.ttl": { + "deprecatedKeyName": "dns_SIG_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SMIMEA": { + "deprecatedKeyName": "dns_SMIMEA", + "validationRegex": null, + "deprecated": false + }, + "dns.SMIMEA.ttl": { + "deprecatedKeyName": "dns_SMIMEA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SOA": { + "deprecatedKeyName": "dns_SOA", + "validationRegex": null, + "deprecated": false + }, + "dns.SOA.ttl": { + "deprecatedKeyName": "dns_SOA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SRV": { + "deprecatedKeyName": "dns_SRV", + "validationRegex": null, + "deprecated": false + }, + "dns.SRV.ttl": { + "deprecatedKeyName": "dns_SRV_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SSHFP": { + "deprecatedKeyName": "dns_SSHFP", + "validationRegex": null, + "deprecated": false + }, + "dns.SSHFP.ttl": { + "deprecatedKeyName": "dns_SSHFP_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.SVCB": { + "deprecatedKeyName": "dns_SVCB", + "validationRegex": null, + "deprecated": false + }, + "dns.SVCB.ttl": { + "deprecatedKeyName": "dns_SVCB_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.TA": { + "deprecatedKeyName": "dns_TA", + "validationRegex": null, + "deprecated": false + }, + "dns.TA.ttl": { + "deprecatedKeyName": "dns_TA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.TKEY": { + "deprecatedKeyName": "dns_TKEY", + "validationRegex": null, + "deprecated": false + }, + "dns.TKEY.ttl": { + "deprecatedKeyName": "dns_TKEY_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.TLSA": { + "deprecatedKeyName": "dns_TLSA", + "validationRegex": null, + "deprecated": false + }, + "dns.TLSA.ttl": { + "deprecatedKeyName": "dns_TLSA_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.TSIG": { + "deprecatedKeyName": "dns_TSIG", + "validationRegex": null, + "deprecated": false + }, + "dns.TSIG.ttl": { + "deprecatedKeyName": "dns_TSIG_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.TXT": { + "deprecatedKeyName": "dns_TXT", + "validationRegex": null, + "deprecated": false + }, + "dns.TXT.ttl": { + "deprecatedKeyName": "dns_TXT_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.URI": { + "deprecatedKeyName": "dns_URI", + "validationRegex": null, + "deprecated": false + }, + "dns.URI.ttl": { + "deprecatedKeyName": "dns_URI_ttl", + "validationRegex": null, + "deprecated": false + }, + "dns.ZONEMD": { + "deprecatedKeyName": "dns_ZONEMD", + "validationRegex": null, + "deprecated": false + }, + "dns.ZONEMD.ttl": { + "deprecatedKeyName": "dns_ZONEMD_ttl", + "validationRegex": null, + "deprecated": false + }, + "crypto.DOT.address": { + "deprecatedKeyName": "DOT", + "validationRegex": null, + "deprecated": false + }, + "crypto.UNI.version.ERC20.address": { + "deprecatedKeyName": "UNI_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.UNI.version.BEP20.address": { + "deprecatedKeyName": "UNI_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.UNI.version.HECO.address": { + "deprecatedKeyName": "UNI_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.UNI.version.MATIC.address": { + "deprecatedKeyName": "UNI_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.UNI.version.HRC20.address": { + "deprecatedKeyName": "UNI_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.UNI.version.XDAI.address": { + "deprecatedKeyName": "UNI_XDAI", + "validationRegex": null, + "deprecated": false + }, + "crypto.SOL.address": { + "deprecatedKeyName": "SOL", + "validationRegex": null, + "deprecated": false + }, + "crypto.BUSD.version.ERC20.address": { + "deprecatedKeyName": "BUSD_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BUSD.version.BEP20.address": { + "deprecatedKeyName": "BUSD_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BUSD.version.HRC20.address": { + "deprecatedKeyName": "BUSD_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ICP.address": { + "deprecatedKeyName": "ICP", + "validationRegex": null, + "deprecated": false + }, + "crypto.THETA.address": { + "deprecatedKeyName": "THETA", + "validationRegex": null, + "deprecated": false + }, + "crypto.WBTC.version.ERC20.address": { + "deprecatedKeyName": "WBTC_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.WBTC.version.MATIC.address": { + "deprecatedKeyName": "WBTC_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.WBTC.version.FANTOM.address": { + "deprecatedKeyName": "WBTC_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.WBTC.version.HRC20.address": { + "deprecatedKeyName": "WBTC_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.WBTC.version.XDAI.address": { + "deprecatedKeyName": "WBTC_XDAI", + "validationRegex": null, + "deprecated": false + }, + "crypto.FIL.address": { + "deprecatedKeyName": "FIL", + "validationRegex": null, + "deprecated": false + }, + "crypto.CDAI.address": { + "deprecatedKeyName": "CDAI", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KSM.address": { + "deprecatedKeyName": "KSM", + "validationRegex": null, + "deprecated": false + }, + "crypto.OKB.address": { + "deprecatedKeyName": "OKB", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AAVE.version.ERC20.address": { + "deprecatedKeyName": "AAVE_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AAVE.version.HECO.address": { + "deprecatedKeyName": "AAVE_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.AAVE.version.MATIC.address": { + "deprecatedKeyName": "AAVE_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.AAVE.version.FANTOM.address": { + "deprecatedKeyName": "AAVE_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.AAVE.version.HRC20.address": { + "deprecatedKeyName": "AAVE_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SHIB.version.ERC20.address": { + "deprecatedKeyName": "SHIB_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SHIB.version.MATIC.address": { + "deprecatedKeyName": "SHIB_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.SHIB.version.FANTOM.address": { + "deprecatedKeyName": "SHIB_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.CEL.version.ERC20.address": { + "deprecatedKeyName": "CEL_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CEL.version.MATIC.address": { + "deprecatedKeyName": "CEL_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.CEL.version.FANTOM.address": { + "deprecatedKeyName": "CEL_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.CEL.version.HRC20.address": { + "deprecatedKeyName": "CEL_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CUSDC.address": { + "deprecatedKeyName": "CUSDC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CETH.address": { + "deprecatedKeyName": "CETH", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AMP.address": { + "deprecatedKeyName": "AMP", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CAKE.version.BEP20.address": { + "deprecatedKeyName": "CAKE_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CAKE.version.HRC20.address": { + "deprecatedKeyName": "CAKE_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MIOTA.address": { + "deprecatedKeyName": "MIOTA", + "validationRegex": null, + "deprecated": false + }, + "crypto.FTT.address": { + "deprecatedKeyName": "FTT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MKR.address": { + "deprecatedKeyName": "MKR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TFUEL.address": { + "deprecatedKeyName": "TFUEL", + "validationRegex": null, + "deprecated": false + }, + "crypto.KLAY.address": { + "deprecatedKeyName": "KLAY", + "validationRegex": null, + "deprecated": false + }, + "crypto.LUNA.address": { + "deprecatedKeyName": "LUNA", + "validationRegex": null, + "deprecated": false + }, + "crypto.AVAX.address": { + "deprecatedKeyName": "AVAX", + "validationRegex": null, + "deprecated": false + }, + "crypto.LEO.address": { + "deprecatedKeyName": "LEO", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SAFEMOON.version.BEP20.address": { + "deprecatedKeyName": "SAFEMOON_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SAFEMOON.version.HRC20.address": { + "deprecatedKeyName": "SAFEMOON_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.UST.address": { + "deprecatedKeyName": "UST", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RUNE.address": { + "deprecatedKeyName": "RUNE", + "validationRegex": "^(bnb|tbnb)[a-zA-HJ-NP-Z0-9]{39}$", + "deprecated": false + }, + "crypto.HBAR.address": { + "deprecatedKeyName": "HBAR", + "validationRegex": null, + "deprecated": false + }, + "crypto.TEL.version.ERC20.address": { + "deprecatedKeyName": "TEL_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TEL.version.MATIC.address": { + "deprecatedKeyName": "TEL_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.CHZ.address": { + "deprecatedKeyName": "CHZ", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SUSHI.version.ERC20.address": { + "deprecatedKeyName": "SUSHI_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SUSHI.version.BEP20.address": { + "deprecatedKeyName": "SUSHI_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SUSHI.version.MATIC.address": { + "deprecatedKeyName": "SUSHI_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.SUSHI.version.FANTOM.address": { + "deprecatedKeyName": "SUSHI_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.SUSHI.version.HRC20.address": { + "deprecatedKeyName": "SUSHI_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.EGLD.address": { + "deprecatedKeyName": "EGLD", + "validationRegex": null, + "deprecated": false + }, + "crypto.TUSD.version.ERC20.address": { + "deprecatedKeyName": "TUSD_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TUSD.version.BEP20.address": { + "deprecatedKeyName": "TUSD_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TUSD.version.AVAX.address": { + "deprecatedKeyName": "TUSD_AVAX", + "validationRegex": null, + "deprecated": false + }, + "crypto.TUSD.version.HRC20.address": { + "deprecatedKeyName": "TUSD_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TUSD.version.BEP2.address": { + "deprecatedKeyName": "TUSD_BEP2", + "validationRegex": "^(bnb|tbnb)[a-zA-HJ-NP-Z0-9]{39}$", + "deprecated": false + }, + "crypto.TUSD.version.TRON.address": { + "deprecatedKeyName": "TUSD_TRON", + "validationRegex": "^[T][a-zA-HJ-NP-Z0-9]{33}$", + "deprecated": false + }, + "crypto.HBTC.version.ERC20.address": { + "deprecatedKeyName": "HBTC_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HBTC.version.HECO.address": { + "deprecatedKeyName": "HBTC_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.SNX.version.ERC20.address": { + "deprecatedKeyName": "SNX_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SNX.version.HECO.address": { + "deprecatedKeyName": "SNX_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.SNX.version.MATIC.address": { + "deprecatedKeyName": "SNX_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.SNX.version.FANTOM.address": { + "deprecatedKeyName": "SNX_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.SNX.version.HRC20.address": { + "deprecatedKeyName": "SNX_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HOT.version.ERC20.address": { + "deprecatedKeyName": "HOT_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HOT.version.HRC20.address": { + "deprecatedKeyName": "HOT_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NEAR.address": { + "deprecatedKeyName": "NEAR", + "validationRegex": null, + "deprecated": false + }, + "crypto.HNT.address": { + "deprecatedKeyName": "HNT", + "validationRegex": null, + "deprecated": false + }, + "crypto.STETH.address": { + "deprecatedKeyName": "STETH", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NEXO.version.ERC20.address": { + "deprecatedKeyName": "NEXO_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NEXO.version.FANTOM.address": { + "deprecatedKeyName": "NEXO_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.PAX.address": { + "deprecatedKeyName": "PAX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.STX.address": { + "deprecatedKeyName": "STX", + "validationRegex": null, + "deprecated": false + }, + "crypto.MANA.version.ERC20.address": { + "deprecatedKeyName": "MANA_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MANA.version.MATIC.address": { + "deprecatedKeyName": "MANA_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.MDX.version.HECO.address": { + "deprecatedKeyName": "MDX_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.MDX.version.BEP20.address": { + "deprecatedKeyName": "MDX_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ZEN.address": { + "deprecatedKeyName": "ZEN", + "validationRegex": null, + "deprecated": false + }, + "crypto.ARRR.address": { + "deprecatedKeyName": "ARRR", + "validationRegex": null, + "deprecated": false + }, + "crypto.BNT.address": { + "deprecatedKeyName": "BNT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LUSD.version.ERC20.address": { + "deprecatedKeyName": "LUSD_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LUSD.version.MATIC.address": { + "deprecatedKeyName": "LUSD_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.GRT.version.ERC20.address": { + "deprecatedKeyName": "GRT_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GRT.version.MATIC.address": { + "deprecatedKeyName": "GRT_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.GRT.version.HRC20.address": { + "deprecatedKeyName": "GRT_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SC.address": { + "deprecatedKeyName": "SC", + "validationRegex": null, + "deprecated": false + }, + "crypto.HUSD.version.ERC20.address": { + "deprecatedKeyName": "HUSD_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HUSD.version.HECO.address": { + "deprecatedKeyName": "HUSD_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.CRV.version.ERC20.address": { + "deprecatedKeyName": "CRV_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CRV.version.MATIC.address": { + "deprecatedKeyName": "CRV_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.CRV.version.FANTOM.address": { + "deprecatedKeyName": "CRV_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.UMA.address": { + "deprecatedKeyName": "UMA", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.WRX.version.BEP2.address": { + "deprecatedKeyName": "WRX_BEP2", + "validationRegex": "^(bnb|tbnb)[a-zA-HJ-NP-Z0-9]{39}$", + "deprecated": false + }, + "crypto.WRX.version.MATIC.address": { + "deprecatedKeyName": "WRX_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.AR.address": { + "deprecatedKeyName": "AR", + "validationRegex": null, + "deprecated": false + }, + "crypto.OMG.address": { + "deprecatedKeyName": "OMG", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GT.address": { + "deprecatedKeyName": "GT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.QNT.address": { + "deprecatedKeyName": "QNT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CHSB.address": { + "deprecatedKeyName": "CHSB", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.IOST.address": { + "deprecatedKeyName": "IOST", + "validationRegex": null, + "deprecated": false + }, + "crypto.NXM.address": { + "deprecatedKeyName": "NXM", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KCS.address": { + "deprecatedKeyName": "KCS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LPT.version.ERC20.address": { + "deprecatedKeyName": "LPT_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LPT.version.HRC20.address": { + "deprecatedKeyName": "LPT_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XSUSHI.address": { + "deprecatedKeyName": "XSUSHI", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CUSDT.address": { + "deprecatedKeyName": "CUSDT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FLOW.address": { + "deprecatedKeyName": "FLOW", + "validationRegex": null, + "deprecated": false + }, + "crypto.ANKR.address": { + "deprecatedKeyName": "ANKR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HBC.address": { + "deprecatedKeyName": "HBC", + "validationRegex": null, + "deprecated": false + }, + "crypto.VGX.address": { + "deprecatedKeyName": "VGX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FEI.address": { + "deprecatedKeyName": "FEI", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BAKE.version.BEP20.address": { + "deprecatedKeyName": "BAKE_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BAKE.version.HRC20.address": { + "deprecatedKeyName": "BAKE_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.1INCH.version.ERC20.address": { + "deprecatedKeyName": "1INCH_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.1INCH.version.BEP20.address": { + "deprecatedKeyName": "1INCH_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.1INCH.version.MATIC.address": { + "deprecatedKeyName": "1INCH_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.1INCH.version.HRC20.address": { + "deprecatedKeyName": "1INCH_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CKB.address": { + "deprecatedKeyName": "CKB", + "validationRegex": null, + "deprecated": false + }, + "crypto.WOO.version.ERC20.address": { + "deprecatedKeyName": "WOO_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.WOO.version.HECO.address": { + "deprecatedKeyName": "WOO_HECO", + "validationRegex": null, + "deprecated": false + }, + "crypto.TITAN.address": { + "deprecatedKeyName": "TITAN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.OMI.address": { + "deprecatedKeyName": "OMI", + "validationRegex": null, + "deprecated": false + }, + "crypto.MINA.address": { + "deprecatedKeyName": "MINA", + "validationRegex": null, + "deprecated": false + }, + "crypto.SETH.address": { + "deprecatedKeyName": "SETH", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RSR.address": { + "deprecatedKeyName": "RSR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.OXY.version.SOLANA.address": { + "deprecatedKeyName": "OXY_SOLANA", + "validationRegex": null, + "deprecated": false + }, + "crypto.OXY.version.ERC20.address": { + "deprecatedKeyName": "OXY_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.REN.version.ERC20.address": { + "deprecatedKeyName": "REN_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.REN.version.HRC20.address": { + "deprecatedKeyName": "REN_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XCH.address": { + "deprecatedKeyName": "XCH", + "validationRegex": null, + "deprecated": false + }, + "crypto.RENBTC.version.ERC20.address": { + "deprecatedKeyName": "RENBTC_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RENBTC.version.BEP20.address": { + "deprecatedKeyName": "RENBTC_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RENBTC.version.HRC20.address": { + "deprecatedKeyName": "RENBTC_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.USDN.address": { + "deprecatedKeyName": "USDN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BCHA.address": { + "deprecatedKeyName": "BCHA", + "validationRegex": null, + "deprecated": false + }, + "crypto.LRC.address": { + "deprecatedKeyName": "LRC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.PUNDIX.address": { + "deprecatedKeyName": "PUNDIX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ERG.address": { + "deprecatedKeyName": "ERG", + "validationRegex": null, + "deprecated": false + }, + "crypto.WIN.address": { + "deprecatedKeyName": "WIN", + "validationRegex": "^[T][a-zA-HJ-NP-Z0-9]{33}$", + "deprecated": false + }, + "crypto.NPXS.address": { + "deprecatedKeyName": "NPXS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TRIBE.address": { + "deprecatedKeyName": "TRIBE", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MAID.address": { + "deprecatedKeyName": "MAID", + "validationRegex": "^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$", + "deprecated": false + }, + "crypto.ASD.address": { + "deprecatedKeyName": "ASD", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CUNI.address": { + "deprecatedKeyName": "CUNI", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CELO.address": { + "deprecatedKeyName": "CELO", + "validationRegex": null, + "deprecated": false + }, + "crypto.DENT.address": { + "deprecatedKeyName": "DENT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SNT.address": { + "deprecatedKeyName": "SNT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FEG.version.ERC20.address": { + "deprecatedKeyName": "FEG_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FEG.version.HRC20.address": { + "deprecatedKeyName": "FEG_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SKL.address": { + "deprecatedKeyName": "SKL", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ALUSD.address": { + "deprecatedKeyName": "ALUSD", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MIR.version.ERC20.address": { + "deprecatedKeyName": "MIR_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MIR.version.BEP20.address": { + "deprecatedKeyName": "MIR_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GLM.address": { + "deprecatedKeyName": "GLM", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.PAXG.version.ERC20.address": { + "deprecatedKeyName": "PAXG_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.PAXG.version.HRC20.address": { + "deprecatedKeyName": "PAXG_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CFX.address": { + "deprecatedKeyName": "CFX", + "validationRegex": null, + "deprecated": false + }, + "crypto.UOS.address": { + "deprecatedKeyName": "UOS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SVCS.address": { + "deprecatedKeyName": "SVCS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.REEF.version.ERC20.address": { + "deprecatedKeyName": "REEF_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.REEF.version.BEP20.address": { + "deprecatedKeyName": "REEF_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.REEF.version.HRC20.address": { + "deprecatedKeyName": "REEF_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GNO.address": { + "deprecatedKeyName": "GNO", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.USDP.address": { + "deprecatedKeyName": "USDP", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KAVA.address": { + "deprecatedKeyName": "KAVA", + "validationRegex": null, + "deprecated": false + }, + "crypto.ALCX.address": { + "deprecatedKeyName": "ALCX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.EWT.address": { + "deprecatedKeyName": "EWT", + "validationRegex": null, + "deprecated": false + }, + "crypto.TON.address": { + "deprecatedKeyName": "TON", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RLC.address": { + "deprecatedKeyName": "RLC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AXS.address": { + "deprecatedKeyName": "AXS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AUDIO.address": { + "deprecatedKeyName": "AUDIO", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XVS.address": { + "deprecatedKeyName": "XVS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BAND.version.ERC20.address": { + "deprecatedKeyName": "BAND_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.BAND.version.FANTOM.address": { + "deprecatedKeyName": "BAND_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.NMR.address": { + "deprecatedKeyName": "NMR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.INJ.version.ERC20.address": { + "deprecatedKeyName": "INJ_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.INJ.version.BEP20.address": { + "deprecatedKeyName": "INJ_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.WAXP.address": { + "deprecatedKeyName": "WAXP", + "validationRegex": null, + "deprecated": false + }, + "crypto.UQC.address": { + "deprecatedKeyName": "UQC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.IOTX.address": { + "deprecatedKeyName": "IOTX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FUN.address": { + "deprecatedKeyName": "FUN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.OCEAN.address": { + "deprecatedKeyName": "OCEAN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SAND.version.ERC20.address": { + "deprecatedKeyName": "SAND_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SAND.version.HRC20.address": { + "deprecatedKeyName": "SAND_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CTSI.version.ERC20.address": { + "deprecatedKeyName": "CTSI_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CTSI.version.BEP20.address": { + "deprecatedKeyName": "CTSI_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CTSI.version.MATIC.address": { + "deprecatedKeyName": "CTSI_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.RAY.address": { + "deprecatedKeyName": "RAY", + "validationRegex": null, + "deprecated": false + }, + "crypto.ANC.version.TERRA.address": { + "deprecatedKeyName": "ANC_TERRA", + "validationRegex": null, + "deprecated": false + }, + "crypto.ANC.version.ERC20.address": { + "deprecatedKeyName": "ANC_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.IQ.version.ERC20.address": { + "deprecatedKeyName": "IQ_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.IQ.version.BEP20.address": { + "deprecatedKeyName": "IQ_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.IQ.version.MATIC.address": { + "deprecatedKeyName": "IQ_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.SUSD.version.ERC20.address": { + "deprecatedKeyName": "SUSD_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SUSD.version.FANTOM.address": { + "deprecatedKeyName": "SUSD_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.KLV.address": { + "deprecatedKeyName": "KLV", + "validationRegex": "^[T][a-zA-HJ-NP-Z0-9]{33}$", + "deprecated": false + }, + "crypto.BTCST.address": { + "deprecatedKeyName": "BTCST", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TLM.address": { + "deprecatedKeyName": "TLM", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AKT.address": { + "deprecatedKeyName": "AKT", + "validationRegex": null, + "deprecated": false + }, + "crypto.STMX.address": { + "deprecatedKeyName": "STMX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.PROM.address": { + "deprecatedKeyName": "PROM", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XPRT.address": { + "deprecatedKeyName": "XPRT", + "validationRegex": null, + "deprecated": false + }, + "crypto.SRM.version.ERC20.address": { + "deprecatedKeyName": "SRM_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SRM.version.SOLANA.address": { + "deprecatedKeyName": "SRM_SOLANA", + "validationRegex": null, + "deprecated": false + }, + "crypto.RPL.address": { + "deprecatedKeyName": "RPL", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AGIX.address": { + "deprecatedKeyName": "AGIX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CELR.address": { + "deprecatedKeyName": "CELR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.FET.address": { + "deprecatedKeyName": "FET", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.OXT.address": { + "deprecatedKeyName": "OXT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ARDR.address": { + "deprecatedKeyName": "ARDR", + "validationRegex": null, + "deprecated": false + }, + "crypto.MATH.address": { + "deprecatedKeyName": "MATH", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.10SET.address": { + "deprecatedKeyName": "10SET", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.POLY.address": { + "deprecatedKeyName": "POLY", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GUSD.address": { + "deprecatedKeyName": "GUSD", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NKN.address": { + "deprecatedKeyName": "NKN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CVC.address": { + "deprecatedKeyName": "CVC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.GTC.address": { + "deprecatedKeyName": "GTC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.STEEM.address": { + "deprecatedKeyName": "STEEM", + "validationRegex": null, + "deprecated": false + }, + "crypto.ORN.address": { + "deprecatedKeyName": "ORN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KEEP.version.ERC20.address": { + "deprecatedKeyName": "KEEP_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KEEP.version.HRC20.address": { + "deprecatedKeyName": "KEEP_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HXRO.address": { + "deprecatedKeyName": "HXRO", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ORBS.address": { + "deprecatedKeyName": "ORBS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ALPHA.version.ERC20.address": { + "deprecatedKeyName": "ALPHA_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ALPHA.version.BEP20.address": { + "deprecatedKeyName": "ALPHA_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.DODO.version.ERC20.address": { + "deprecatedKeyName": "DODO_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.DODO.version.BEP20.address": { + "deprecatedKeyName": "DODO_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.OGN.address": { + "deprecatedKeyName": "OGN", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KNCL.version.ERC20.address": { + "deprecatedKeyName": "KNCL_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KNCL.version.FANTOM.address": { + "deprecatedKeyName": "KNCL_FANTOM", + "validationRegex": null, + "deprecated": false + }, + "crypto.KNCL.version.HRC20.address": { + "deprecatedKeyName": "KNCL_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MED.address": { + "deprecatedKeyName": "MED", + "validationRegex": null, + "deprecated": false + }, + "crypto.XAUT.address": { + "deprecatedKeyName": "XAUT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.VLX.address": { + "deprecatedKeyName": "VLX", + "validationRegex": null, + "deprecated": false + }, + "crypto.PHA.address": { + "deprecatedKeyName": "PHA", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.KOBE.address": { + "deprecatedKeyName": "KOBE", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.PERP.address": { + "deprecatedKeyName": "PERP", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.XHV.address": { + "deprecatedKeyName": "XHV", + "validationRegex": null, + "deprecated": false + }, + "crypto.META.address": { + "deprecatedKeyName": "META", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SEUR.address": { + "deprecatedKeyName": "SEUR", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.MONA.address": { + "deprecatedKeyName": "MONA", + "validationRegex": null, + "deprecated": false + }, + "crypto.ANT.address": { + "deprecatedKeyName": "ANT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.HYDRA.address": { + "deprecatedKeyName": "HYDRA", + "validationRegex": null, + "deprecated": false + }, + "crypto.ZKS.address": { + "deprecatedKeyName": "ZKS", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SXP.version.ERC20.address": { + "deprecatedKeyName": "SXP_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SXP.version.BEP20.address": { + "deprecatedKeyName": "SXP_BEP20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.SXP.version.HRC20.address": { + "deprecatedKeyName": "SXP_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.CSPR.address": { + "deprecatedKeyName": "CSPR", + "validationRegex": null, + "deprecated": false + }, + "crypto.MTL.address": { + "deprecatedKeyName": "MTL", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NU.address": { + "deprecatedKeyName": "NU", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ZMT.address": { + "deprecatedKeyName": "ZMT", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.LOC.address": { + "deprecatedKeyName": "LOC", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.TKO.address": { + "deprecatedKeyName": "TKO", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.ETN.address": { + "deprecatedKeyName": "ETN", + "validationRegex": null, + "deprecated": false + }, + "crypto.UBT.version.ERC20.address": { + "deprecatedKeyName": "UBT_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.UBT.version.MATIC.address": { + "deprecatedKeyName": "UBT_MATIC", + "validationRegex": null, + "deprecated": false + }, + "crypto.EXRD.address": { + "deprecatedKeyName": "EXRD", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.NMX.address": { + "deprecatedKeyName": "NMX", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.RIF.address": { + "deprecatedKeyName": "RIF", + "validationRegex": null, + "deprecated": false + }, + "crypto.STORJ.version.ERC20.address": { + "deprecatedKeyName": "STORJ_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.STORJ.version.HRC20.address": { + "deprecatedKeyName": "STORJ_HRC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.AVA.address": { + "deprecatedKeyName": "AVA", + "validationRegex": "^(bnb|tbnb)[a-zA-HJ-NP-Z0-9]{39}$", + "deprecated": false + }, + "crypto.DPI.version.ERC20.address": { + "deprecatedKeyName": "DPI_ERC20", + "validationRegex": "^0x[a-fA-F0-9]{40}$", + "deprecated": false + }, + "crypto.DPI.version.MATIC.address": { + "deprecatedKeyName": "DPI_MATIC", + "validationRegex": null, + "deprecated": false + } + } +} \ No newline at end of file diff --git a/Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json new file mode 100644 index 0000000..72ea3c2 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/uns-config.json @@ -0,0 +1,236 @@ +{ + "version": "0.1.0", + "networks": { + "1": { + "contracts": { + "UNSRegistry": { + "address": "0x049aba7510f45BA5b64ea9E658E342F904DB358D", + "implementation": "0x6d4FaFcD5B4A8b360c80eAca8D91e3Bc814ecc39", + "legacyAddresses": [], + "deploymentBlock": "0xc2fede" + }, + "CNSRegistry": { + "address": "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe", + "legacyAddresses": [], + "deploymentBlock": "0x8a958b" + }, + "MintingManager": { + "address": "0x2a7084870bB724175a3C96Da8FaA55128fa3E19D", + "implementation": "0x2f133a06fe4fc845E41261aCFF6831a727ea9062", + "legacyAddresses": [], + "deploymentBlock": "0xc2fee0" + }, + "ProxyAdmin": { + "address": "0xAA16DA78110D9A9742c760a1a064F28654Ab93de", + "legacyAddresses": [], + "deploymentBlock": "0xc2fedc" + }, + "SignatureController": { + "address": "0x82EF94294C95aD0930055f31e53A34509227c5f7", + "legacyAddresses": [], + "deploymentBlock": "0x8a95a6" + }, + "MintingController": { + "address": "0xb0EE56339C3253361730F50c08d3d7817ecD60Ca", + "legacyAddresses": [], + "deploymentBlock": "0x8a95aa" + }, + "WhitelistedMinter": { + "address": "0xd3fF3377b0ceade1303dAF9Db04068ef8a650757", + "legacyAddresses": [], + "deploymentBlock": "0xa76ad3" + }, + "URIPrefixController": { + "address": "0x09B091492759737C03da9dB7eDF1CD6BCC3A9d91", + "legacyAddresses": [], + "deploymentBlock": "0x8a95ae" + }, + "DomainZoneController": { + "address": "0xeA70777e28E00E81f58b8921fC47F78B8a72eFE7", + "legacyAddresses": [], + "deploymentBlock": "0x98ca20" + }, + "Resolver": { + "address": "0xb66DcE2DA6afAAa98F2013446dBCB0f4B0ab2842", + "legacyAddresses": [ + "0xa1cac442be6673c49f8e74ffc7c4fd746f3cbd0d", + "0x878bc2f3f717766ab69c0a5f9a6144931e61aed3" + ], + "deploymentBlock": "0x960844" + }, + "ProxyReader": { + "address": "0xfEe4D4F0aDFF8D84c12170306507554bC7045878", + "legacyAddresses": [ + "0xa6E7cEf2EDDEA66352Fd68E5915b60BDbb7309f5", + "0x7ea9Ee21077F84339eDa9C80048ec6db678642B1" + ], + "deploymentBlock": "0xc300b4" + }, + "TwitterValidationOperator": { + "address": "0x2F659766E3D08561CA3408FbAba7C0749ab2c402", + "legacyAddresses": [ + "0xbb486C6E9cF1faA86a6E3eAAFE2e5665C0507855" + ], + "deploymentBlock": "0xc300b5" + }, + "FreeMinter": { + "address": "0x1fC985cAc641ED5846b631f96F35d9b48Bc3b834", + "legacyAddresses": [], + "deploymentBlock": "0xacc390" + } + } + }, + "4": { + "contracts": { + "UNSRegistry": { + "address": "0x7fb83000B8eD59D3eAD22f0D584Df3a85fBC0086", + "implementation": "0x0c97caecb791620c61e26c5a9754150a1cae2159", + "legacyAddresses": [], + "deploymentBlock": "0x85e628" + }, + "CNSRegistry": { + "address": "0xAad76bea7CFEc82927239415BB18D2e93518ecBB", + "legacyAddresses": [], + "deploymentBlock": "0x7232bc" + }, + "MintingManager": { + "address": "0xdAAf99A920D31F4f5720e4667b12b24e54A03070", + "implementation": "0xb8efb23b97408147ca63ae0494b2242c5029ffc4", + "legacyAddresses": [], + "deploymentBlock": "0x85e629" + }, + "ProxyReader": { + "address": "0x299974AeD8911bcbd2C61262605b89F591a53E83", + "legacyAddresses": [ + "0x9F19473F6a98a715176291c930558E1954fd3D1e", + "0x3A2e74CF832cbA3d77E72708d55370119E4323a6" + ], + "deploymentBlock": "0x8671b4" + }, + "ProxyAdmin": { + "address": "0xaf9815005A208d1460b6fC60B4f90B9f2185E88c", + "legacyAddresses": [], + "deploymentBlock": "0x85e627" + }, + "SignatureController": { + "address": "0x66a5e3e2C27B4ce4F46BBd975270BE154748D164", + "legacyAddresses": [], + "deploymentBlock": "0x7232be" + }, + "MintingController": { + "address": "0x51765307AeB3Df2E647014a2C501d5324212467c", + "legacyAddresses": [], + "deploymentBlock": "0x7232bf", + "deprecated": true + }, + "WhitelistedMinter": { + "address": "0xbcB32f13f90978a9e059E8Cb40FaA9e6619d98e7", + "legacyAddresses": [], + "deploymentBlock": "0x7232c6", + "deprecated": true + }, + "URIPrefixController": { + "address": "0xe1d2e4B9f0518CA5c803073C3dFa886470627237", + "legacyAddresses": [], + "deploymentBlock": "0x7232c0", + "deprecated": true + }, + "DomainZoneController": { + "address": "0x6f8F96A566663C1d4fEe70edD37E9b62Fe39dE5D", + "legacyAddresses": [], + "deploymentBlock": "0x7232c2", + "deprecated": true + }, + "Resolver": { + "address": "0x95AE1515367aa64C462c71e87157771165B1287A", + "legacyAddresses": [], + "deploymentBlock": "0x7232cf" + }, + "TwitterValidationOperator": { + "address": "0x9ea4A63184ebE9CBA55CD1af473D98075Aa02b4C", + "legacyAddresses": [ + "0x1CB337b3b208dc29a6AcE8d11Bb591b66c5Dd83d" + ], + "deploymentBlock": "0x86935e" + }, + "FreeMinter": { + "address": "0x84214215904cDEbA9044ECf95F3eBF009185AAf4", + "legacyAddresses": [], + "deploymentBlock": "0x740d93", + "deprecated": true + } + } + }, + "1337": { + "contracts": { + "CNSRegistry": { + "address": "0xA310F8e781F8aE80690649be920991AEc9a6595D", + "legacyAddresses": [], + "deploymentBlock": "0x01" + }, + "SignatureController": { + "address": "0xBd8b374200A7D99F15f4e90621dA1BEAEcb705a0", + "legacyAddresses": [], + "deploymentBlock": "0x02" + }, + "MintingController": { + "address": "0x4513073d9B3af7e62be59B57205a2368F76dE9C7", + "legacyAddresses": [], + "deploymentBlock": "0x03" + }, + "URIPrefixController": { + "address": "0xeE1f42382091e260f5B9c152E17639d729Ab829F", + "legacyAddresses": [], + "deploymentBlock": "0x04" + }, + "Resolver": { + "address": "0x76CBBE3B425A7D258B30457785d54de8c8322bfa", + "legacyAddresses": [], + "deploymentBlock": "0x08" + }, + "WhitelistedMinter": { + "address": "0x4d4E78764a6aF57bf628120A38c10560deD2E134", + "legacyAddresses": [], + "deploymentBlock": "0x09" + }, + "DomainZoneController": { + "address": "0x0000000000000000000000000000000000000000", + "legacyAddresses": [], + "deploymentBlock": "0x0" + }, + "TwitterValidationOperator": { + "address": "0x0000000000000000000000000000000000000000", + "legacyAddresses": [], + "deploymentBlock": "0x0" + }, + "FreeMinter": { + "address": "0x0000000000000000000000000000000000000000", + "legacyAddresses": [], + "deploymentBlock": "0x0" + }, + "ProxyAdmin": { + "address": "0x7bB6Cd9be29fab783c0b494A06FED8b2E2596B7a", + "legacyAddresses": [], + "deploymentBlock": "0x0" + }, + "UNSRegistry": { + "address": "0x4a3C194eB88966178bfDD81744ddDafED611B830", + "legacyAddresses": [], + "deploymentBlock": "0x0f", + "implementation": "0xC58206842E4030a3B2CaBC78780Ae7635173C533" + }, + "MintingManager": { + "address": "0x4Be0126fB2885a6D2909166D5801E606470C9aB0", + "legacyAddresses": [], + "deploymentBlock": "0x11", + "implementation": "0x4872CC1be60A9DB9c880A0A437Da7a6AF134F08f" + }, + "ProxyReader": { + "address": "0xAc52F68f31577E44aE0C7E95A42dC9eb574B9383", + "legacyAddresses": [], + "deploymentBlock": "0x15" + } + } + } + } +} diff --git a/Sources/UnstoppableDomainsResolution/Resources/UNS/unsProxyReader.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsProxyReader.json new file mode 100644 index 0000000..8120a62 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsProxyReader.json @@ -0,0 +1,539 @@ +[ + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "unsRegistry", + "type": "address" + }, + { + "internalType": "contract ICryptoRegistry", + "name": "cnsRegistry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "NAME", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "childIdOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "get", + "outputs": [ + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "keyHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getByHash", + "outputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getData", + "outputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getDataByHash", + "outputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "getDataByHashForMany", + "outputs": [ + { + "internalType": "address[]", + "name": "resolvers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "string[][]", + "name": "keys", + "type": "string[][]" + }, + { + "internalType": "string[][]", + "name": "values", + "type": "string[][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "getDataForMany", + "outputs": [ + { + "internalType": "address[]", + "name": "resolvers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "string[][]", + "name": "values", + "type": "string[][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getMany", + "outputs": [ + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getManyByHash", + "outputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "ownerOfForMany", + "outputs": [ + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "registryOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "resolverOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/Sources/UnstoppableDomainsResolution/Resources/UNS/unsRegistry.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsRegistry.json new file mode 100644 index 0000000..7dc3fd7 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsRegistry.json @@ -0,0 +1,981 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "keyIndex", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NewKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "NewURI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "prefix", + "type": "string" + } + ], + "name": "NewURIPrefix", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ResetRecords", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "keyIndex", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "valueIndex", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "Set", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "childIdOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "get", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "keyHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getByHash", + "outputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getMany", + "outputs": [ + { + "internalType": "string[]", + "name": "", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getManyByHash", + "outputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "isApprovedOrOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "name": "mintWithRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "reconfigure", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "resolverOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "name": "safeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "name": "safeMintWithRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeMintWithRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "keyHash", + "type": "uint256" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "setByHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "setMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "setManyByHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "prefix", + "type": "string" + } + ], + "name": "setTokenURIPrefix", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] diff --git a/Sources/UnstoppableDomainsResolution/Resources/UNS/unsResolver.json b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsResolver.json new file mode 100644 index 0000000..49dd76e --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Resources/UNS/unsResolver.json @@ -0,0 +1,265 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "keyIndex", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NewKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ResetRecords", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "keyIndex", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "valueIndex", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "Set", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "get", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "keyHash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getByHash", + "outputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getMany", + "outputs": [ + { + "internalType": "string[]", + "name": "", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "keyHashes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getManyByHash", + "outputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "reconfigure", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "keys", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "values", + "type": "string[]" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "setMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/Sources/UnstoppableDomainsResolution/Support/Base58Swift/Base58.swift b/Sources/UnstoppableDomainsResolution/Support/Base58Swift/Base58.swift new file mode 100644 index 0000000..6139dff --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Support/Base58Swift/Base58.swift @@ -0,0 +1,107 @@ +// Copyright Keefer Taylor, 2019. + +import BigInt +import CommonCrypto +import Foundation + +/// A static utility class which provides Base58 encoding and decoding functionality. +public enum Base58 { + /// Length of checksum appended to Base58Check encoded strings. + private static let checksumLength = 4 + + private static let alphabet = [UInt8]("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".utf8) + private static let zero = BigUInt(0) + private static let radix = BigUInt(alphabet.count) + + /// Encode the given bytes into a Base58Check encoded string. + /// - Parameter bytes: The bytes to encode. + /// - Returns: A base58check encoded string representing the given bytes, or nil if encoding failed. + public static func base58CheckEncode(_ bytes: [UInt8]) -> String { + let checksum = calculateChecksum(bytes) + let checksummedBytes = bytes + checksum + return Base58.base58Encode(checksummedBytes) + } + + /// Decode the given Base58Check encoded string to bytes. + /// - Parameter input: A base58check encoded input string to decode. + /// - Returns: Bytes representing the decoded input, or nil if decoding failed. + public static func base58CheckDecode(_ input: String) -> [UInt8]? { + guard let decodedChecksummedBytes = base58Decode(input) else { + return nil + } + + let decodedChecksum = decodedChecksummedBytes.suffix(checksumLength) + let decodedBytes = decodedChecksummedBytes.prefix(upTo: decodedChecksummedBytes.count - checksumLength) + let calculatedChecksum = calculateChecksum([UInt8](decodedBytes)) + + guard decodedChecksum.elementsEqual(calculatedChecksum, by: { $0 == $1 }) else { + return nil + } + return Array(decodedBytes) + } + + /// Encode the given bytes to a Base58 encoded string. + /// - Parameter bytes: The bytes to encode. + /// - Returns: A base58 encoded string representing the given bytes, or nil if encoding failed. + public static func base58Encode(_ bytes: [UInt8]) -> String { + var answer: [UInt8] = [] + var integerBytes = BigUInt(Data(bytes)) + + while integerBytes > 0 { + let (quotient, remainder) = integerBytes.quotientAndRemainder(dividingBy: radix) + answer.insert(alphabet[Int(remainder)], at: 0) + integerBytes = quotient + } + + let prefix = Array(bytes.prefix { $0 == 0 }).map { _ in alphabet[0] } + answer.insert(contentsOf: prefix, at: 0) + + // swiftlint:disable force_unwrapping + // Force unwrap as the given alphabet will always decode to UTF8. + return String(bytes: answer, encoding: String.Encoding.utf8)! + // swiftlint:enable force_unwrapping + } + + /// Decode the given base58 encoded string to bytes. + /// - Parameter input: The base58 encoded input string to decode. + /// - Returns: Bytes representing the decoded input, or nil if decoding failed. + public static func base58Decode(_ input: String) -> [UInt8]? { + var answer = zero + var i = BigUInt(1) + let byteString = [UInt8](input.utf8) + + for char in byteString.reversed() { + guard let alphabetIndex = alphabet.firstIndex(of: char) else { + return nil + } + answer += (i * BigUInt(alphabetIndex)) + i *= radix + } + + let bytes = answer.serialize() + return Array(byteString.prefix { i in i == alphabet[0] }) + bytes + } + + /// Calculate a checksum for a given input by hashing twice and then taking the first four bytes. + /// - Parameter input: The input bytes. + /// - Returns: A byte array representing the checksum of the input bytes. + private static func calculateChecksum(_ input: [UInt8]) -> [UInt8] { + let hashedData = sha256(input) + let doubleHashedData = sha256(hashedData) + let doubleHashedArray = Array(doubleHashedData) + return Array(doubleHashedArray.prefix(checksumLength)) + } + + /// Create a sha256 hash of the given data. + /// - Parameter data: Input data to hash. + /// - Returns: A sha256 hash of the input data. + private static func sha256(_ data: [UInt8]) -> [UInt8] { + let res = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))! + CC_SHA256( + (Data(data) as NSData).bytes, + CC_LONG(data.count), + res.mutableBytes.assumingMemoryBound(to: UInt8.self) + ) + return [UInt8](res as Data) + } +} diff --git a/Sources/UnstoppableDomainsResolution/Support/Base58Swift/README.md b/Sources/UnstoppableDomainsResolution/Support/Base58Swift/README.md new file mode 100644 index 0000000..1aa2161 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Support/Base58Swift/README.md @@ -0,0 +1,86 @@ +# Base58Swift + +[![Build Status](https://travis-ci.org/keefertaylor/Base58Swift.svg?branch=master)](https://travis-ci.org/keefertaylor/Base58Swift) +[![codecov](https://codecov.io/gh/keefertaylor/Base58Swift/branch/master/graph/badge.svg)](https://codecov.io/gh/keefertaylor/Base58Swift) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Version](https://img.shields.io/cocoapods/v/Base58Swift.svg?style=flat)](http://cocoapods.org/pods/Base58Swift) +[![License](https://img.shields.io/cocoapods/l/Base58Swift.svg?style=flat)](http://cocoapods.org/pods/Base58Swift) + +Base58Swift is a Swift library that implements Base58 / Base58Check encodings for cryptocurrencies. It is based off of [go-base-58](https://github.com/jbenet/go-base58) with some added functions. + +Donations help me find time to work on Base58Swift. If you find the library useful, please consider donating to support ongoing develoment. + +|Currency| Address | +|---------|---| +| __Tezos__ | tz1SNXT8yZCwTss2YcoFi3qbXvTZiCojx833 | +| __Bitcoin__ | 1CdPoF9cvw3YEiuRCHxdsGpvb5tSUYBBo | +| __Bitcoin Cash__ | qqpr9are9gzs5r0q7hy3gdehj3w074pyqsrhpdmxg6 | + + +## Installation +### CocoaPods +Base58Swift supports installation via CocoaPods. You can depend on Base58Swift by adding the following to your Podfile: + +``` +pod "Base58Swift" +``` + +### Carthage + +If you use [Carthage](https://github.com/Carthage/Carthage) to manage your dependencies, simply add +Base58Swift to your `Cartfile`: + + ``` +github "keefertaylor/Base58Swift" +``` + +If you use Carthage to build your dependencies, make sure you have added `BigInt.framework` and `SipHash.framework`, to the "_Linked Frameworks and Libraries_" section of your target, and have included them in your Carthage framework copying build phase. + +### Swift Package Manager + +Add the following to the `dependencies` section of your `Package.swift` file: + +```swift +.package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0") +``` + +## Usage + +Base58Swift provides a static utility class, `Base58`, which provides encoding and decoding functions. + +To encode / decode in Base58: +```swift +let bytes: [UInt8] = [255, 254, 253, 252] + +let encodedString = Base58.encode(bytes)! +let decodedBytes = Base58.decode(encodedString)! + +print(encodedString) // 7YXVWT +print(decodedBytes) // [255, 254, 253, 252] +``` + +To encode / decode in Base58Check: +```swift +let bytes: [UInt8] = [255, 254, 253, 252] + +let encodedString = Base58.base58CheckEncode(bytes)! +let decodedBytes = Base58.base58CheckDecode(encodedString)! + +print(encodedString) // jpUz5f99p1R +print(decodedBytes) // [255, 254, 253, 252] +``` + +## Contributing + +Pull requests are welcome. + +To get set up: +```shell +$ brew install xcodegen # if you don't already have it +$ xcodegen generate # Generate an XCode project from Project.yml +$ open Base58Swift.xcodeproj +``` + +## License + +MIT diff --git a/Sources/UnstoppableDomainsResolution/Support/EthereumAddress/EthereumAddress.swift b/Sources/UnstoppableDomainsResolution/Support/EthereumAddress/EthereumAddress.swift new file mode 100644 index 0000000..168b983 --- /dev/null +++ b/Sources/UnstoppableDomainsResolution/Support/EthereumAddress/EthereumAddress.swift @@ -0,0 +1,139 @@ +// +// EthereumAddress.swift +// EthereumAddress +// +// Created by Alex Vlasov on 25/10/2018. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// +// swiftlint:disable all + +import Foundation +import CryptoSwift + +public struct EthereumAddress: Equatable, ExpressibleByStringLiteral { + public typealias StringLiteralType = String + + public enum AddressType { + case normal + case contractDeployment + } + + public var isValid: Bool { + get { + switch self.type { + case .normal: + return (self.addressData.count == 20) + case .contractDeployment: + return true + } + + } + } + var _address: String + public var type: AddressType = .normal + public static func ==(lhs: EthereumAddress, rhs: EthereumAddress) -> Bool { + return lhs.addressData == rhs.addressData && lhs.type == rhs.type + // return lhs.address.lowercased() == rhs.address.lowercased() && lhs.type == rhs.type + } + + public var addressData: Data { + get { + switch self.type { + case .normal: + guard let dataArray = Data.fromHex(_address) else {return Data()} + return dataArray + // guard let d = dataArray.setLengthLeft(20) else { return Data()} + // return d + case .contractDeployment: + return Data() + } + } + } + public var address: String { + switch self.type { + case .normal: + return EthereumAddress.toChecksumAddress(_address)! + case .contractDeployment: + return "0x" + } + } + + public static func toChecksumAddress(_ addr: String) -> String? { + let address = addr.lowercased().stripHexPrefix() + guard let hash = address.data(using: .ascii)?.sha3(.keccak256).toHexString().stripHexPrefix() else {return nil} + var ret = "0x" + + for (i, char) in address.enumerated() { + let startIdx = hash.index(hash.startIndex, offsetBy: i) + let endIdx = hash.index(hash.startIndex, offsetBy: i+1) + let hashChar = String(hash[startIdx..= 8 { + ret += c.uppercased() + } else { + ret += c + } + } + return ret + } + + public init(stringLiteral value: EthereumAddress.StringLiteralType) { + self.init(value, type: .normal, ignoreChecksum: true)! + } + + public init?(_ addressString: String, type: AddressType = .normal, ignoreChecksum: Bool = false) { + switch type { + case .normal: + guard let data = Data.fromHex(addressString) else {return nil} + guard data.count == 20 else {return nil} + if !addressString.hasHexPrefix() { + return nil + } + if !ignoreChecksum { + // check for checksum + if data.toHexString() == addressString.stripHexPrefix() { + self._address = data.toHexString().addHexPrefix() + self.type = .normal + return + } else if data.toHexString().uppercased() == addressString.stripHexPrefix() { + self._address = data.toHexString().addHexPrefix() + self.type = .normal + return + } else { + let checksummedAddress = EthereumAddress.toChecksumAddress(data.toHexString().addHexPrefix()) + guard checksummedAddress == addressString else {return nil} + self._address = data.toHexString().addHexPrefix() + self.type = .normal + return + } + } else { + self._address = data.toHexString().addHexPrefix() + self.type = .normal + return + } + case .contractDeployment: + self._address = "0x" + self.type = .contractDeployment + } + } + + public init?(_ addressData: Data, type: AddressType = .normal) { + guard addressData.count == 20 else {return nil} + self._address = addressData.toHexString().addHexPrefix() + self.type = type + } + + public static func contractDeploymentAddress() -> EthereumAddress { + return EthereumAddress("0x", type: .contractDeployment)! + } + + // public static func fromIBAN(_ iban: String) -> EthereumAddress { + // + // } + +} + +extension EthereumAddress: Hashable { + +} diff --git a/Tests/ABICoderTests/ABICoderTests.swift b/Tests/ABICoderTests/ABICoderTests.swift new file mode 100644 index 0000000..3822d4f --- /dev/null +++ b/Tests/ABICoderTests/ABICoderTests.swift @@ -0,0 +1,124 @@ +import XCTest + +#if INSIDE_PM +@testable import UnstoppableDomainsResolution +#else +@testable import Resolution +#endif + +var coder: ABICoder! + +class ABICoderTests: XCTestCase { + let abiJsonString: String = "[{\"inputs\": [{ \"indexed\": true, \"internalType\": \"uint256\"," + + "\"name\": \"id\", \"type\": \"uint256\" },{ \"indexed\": false," + + "\"internalType\": \"string\", \"name\": \"value\", \"type\": \"string\" }]," + + "\"name\": \"testEvent\", \"type\": \"event\" },{ \"inputs\": [" + + " { \"internalType\": \"uint256\", \"name\": \"valueId\", \"type\": \"uint256\" } ]," + + "\"name\": \"getValue\", \"outputs\": [" + + " { \"internalType\": \"string\", \"name\": \"value\", \"type\": \"string\" } ]," + + "\"stateMutability\": \"view\", \"payable\": false, \"type\": \"function\" }]" + + override func setUp() { + super.setUp() + do { + let jsonData = abiJsonString.data(using: .utf8) + let abi = try JSONDecoder().decode([ABI.Record].self, from: jsonData!) + let abiNative = try abi.map({ (record) -> ABI.Element in + return try record.parse() + }) + coder = ABICoder(abiNative) + } catch { + XCTFail("Unexpected error during setup") + } + } + + func testFunctionParametersEncoding() throws + { + let data = try coder.encode(method: "getValue", args: ["0000000000000000000000000000000000000000000000000000000000000001"]) + let expected = "0x0ff4c9160000000000000000000000000000000000000000000000000000000000000001" + XCTAssert(data.lowercased() == expected, "failed to encode") + } + + func testFunctionParametersEncodingInvalidMethod() + { + self.checkError(completion: { + _ = try coder.encode(method: "invalid", args: ["0000000000000000000000000000000000000000000000000000000000000001"]) + }, expectedError: .wrongABIInterfaceForMethod(method: "invalid")) + } + + func testFunctionParametersEncodingInvalidArgs() + { + self.checkError(completion: { + _ = try coder.encode(method: "getValue", args: ["invalid"]) + }, expectedError: .couldNotEncode(method: "getValue", args: ["invalid"])) + } + + func testFunctionReturnDecoding() throws + { + let dataString = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000117465737420737472696e672076616c7565000000000000000000000000000000" + let result = try coder.decode(dataString, from: "getValue") + let expected = "test string value" + let dict = result as? Dictionary + XCTAssert(dict != nil, "failed to decode") + let val = dict?["0"] as? String + XCTAssert(val == expected, "failed to decode") + } + + func testFunctionReturnDecodingEmptyString() throws + { + let dataString = "" + let result = try coder.decode(dataString, from: "getValue") + let dict = result as? Dictionary + XCTAssert(dict != nil, "failed to decode") + let val = dict?["0"] as? String + XCTAssert(val == "", "failed to decode") + } + + func testFunctionReturnDecodingInvalidMethod() throws + { + let dataString = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000117465737420737472696e672076616c7565000000000000000000000000000000" + self.checkError(completion: { + _ = try coder.decode(dataString, from: "invalid") + }, expectedError: .wrongABIInterfaceForMethod(method: "invalid")) + } + + func testFunctionReturnDecodingNotFunction() throws + { + let dataString = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000117465737420737472696e672076616c7565000000000000000000000000000000" + self.checkError(completion: { + _ = try coder.decode(dataString, from: "testEvent") + }, expectedError: .wrongABIInterfaceForMethod(method: "testEvent")) + } + + func testFunctionReturnDecodingInvalidData() throws + { + let dataString = "0x01" + self.checkError(completion: { + _ = try coder.decode(dataString, from: "getValue") + }, expectedError: .couldNotDecode(method: "getValue", value: dataString)) + } + + func checkError(completion: @escaping() throws -> Void, expectedError: ABICoderError) { + do { + try completion() + XCTFail("Expected \(expectedError), but got none") + } catch { + if let catched = error as? ABICoderError { + assert(catched == expectedError, "Expected \(expectedError), but got \(catched)") + return + } + XCTFail("Expected ABICoderError, but got different \(error)") + } + } +} + +extension ABICoderError { + static func ==(a: ABICoderError, b: ABICoderError) -> Bool { + switch (a, b) { + case (.wrongABIInterfaceForMethod(let a), .wrongABIInterfaceForMethod(let b)) where a == b: return true + case (.couldNotEncode(let a, _), .couldNotEncode(let b, _)) where a == b: return true + case (.couldNotDecode(let a, let aValue), .couldNotDecode(let b, let bValue)) where a == b && aValue == bValue: return true + default: return false + } + } +} \ No newline at end of file diff --git a/Tests/ABICoderTests/Info.plist b/Tests/ABICoderTests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Tests/ABICoderTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Tests/EthereumABITests/EthereumABITests.swift b/Tests/EthereumABITests/EthereumABITests.swift index 3c42afb..2610571 100644 --- a/Tests/EthereumABITests/EthereumABITests.swift +++ b/Tests/EthereumABITests/EthereumABITests.swift @@ -1,6 +1,5 @@ import XCTest import BigInt -import EthereumAddress #if INSIDE_PM @testable import UnstoppableDomainsResolution diff --git a/Tests/HelpersTests/Info.plist b/Tests/HelpersTests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Tests/HelpersTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Tests/HelpersTests/TokenUriMetadataTests.swift b/Tests/HelpersTests/TokenUriMetadataTests.swift new file mode 100644 index 0000000..e1f287d --- /dev/null +++ b/Tests/HelpersTests/TokenUriMetadataTests.swift @@ -0,0 +1,81 @@ +import XCTest + +#if INSIDE_PM +@testable import UnstoppableDomainsResolution +#else +@testable import Resolution +#endif + +class TokenUriMetadataTests: XCTestCase { + + func testMetadataParsing() { + let jsonString = "{\"name\":\"brad.crypto\",\"description\":\"A .crypto blockchain domain. Use it to resolve your cryptocurrency addresses and decentralized websites.\",\"external_url\":\"https://unstoppabledomains.com/search?searchTerm=brad.crypto\",\"image\":\"https://storage.googleapis.com/dot-crypto-metadata-api/unstoppabledomains_crypto.png\",\"attributes\":[{\"trait_type\":\"domain\",\"value\":\"brad.crypto\"},{\"trait_type\":\"level\",\"value\":2},{\"trait_type\":\"length\",\"value\":4},{\"trait_type\":\"ADA\",\"value\":\"DdzFFzCqrhsuwQKiR3CdQ1FzuPAydtVCBFTRdy9FPKepAHEoXCee2qrio975M4cEbqYwZBsWJTNyrJ8NLJmAReSwAakQEHWBEd2HvSS7\"},{\"trait_type\":\"BTC\",\"value\":\"bc1q359khn0phg58xgezyqsuuaha28zkwx047c0c3y\"},{\"trait_type\":\"ETH\",\"value\":\"0x8aaD44321A86b170879d7A244c1e8d360c99DdA8\"},{\"trait_type\":\"IPFS Content\",\"value\":\"QmdyBw5oTgCtTLQ18PbDvPL8iaLoEPhSyzD91q9XmgmAjb\"},{\"trait_type\":\"type\",\"value\":\"standard\"}],\"image_data\":\"\",\"background_color\":\"4C47F7\"}" + do { + let jsonData = jsonString.data(using: .utf8) + let metadata = try JSONDecoder().decode(TokenUriMetadata.self, from: jsonData!) + assert(metadata.name == "brad.crypto") + assert(metadata.attributes.count == 8) + } catch { + XCTFail() + print(error) + } + } + + func testMetadataAttributeString() { + do { + let attribute = try parseJsonAttribute(jsonString: "{\"trait_type\": \"domain\",\"value\": \"brad.crypto\"}") + assert(attribute.traitType == "domain") + assert(attribute.value.value == "brad.crypto") + } catch { + XCTFail() + print(error) + } + } + + func testMetadataAttributeNumber() { + do { + let attribute = try parseJsonAttribute(jsonString: "{\"trait_type\": \"level\",\"value\": 2}") + assert(attribute.traitType == "level") + assert(attribute.value.value == "2") + } catch { + XCTFail() + print(error) + } + } + + func testMetadataAttributeDouble() { + do { + let attribute = try parseJsonAttribute(jsonString: "{\"trait_type\": \"balance\",\"value\": 1.5}") + assert(attribute.traitType == "balance") + assert(attribute.value.value == "1.5") + } catch { + XCTFail() + print(error) + } + } + + func testMetadataAttributeBoolean() { + do { + let attribute = try parseJsonAttribute(jsonString: "{\"trait_type\": \"enabled\",\"value\": true}") + assert(attribute.traitType == "enabled") + assert(attribute.value.value == "true") + } catch { + XCTFail() + print(error) + } + } + + func testMetadataAttributeIncorrect() { + do { + let attribute = try parseJsonAttribute(jsonString: "{\"trait_type\": \"incorrect\",\"value\": [\"some\", \"values\"]}") + XCTFail("Expected DecodingError, but got none") + } catch { + assert(error is DecodingError, "Expected DecodingError, but got different \(error)") + } + } + + private func parseJsonAttribute(jsonString: String) throws -> TokenUriMetadataAttribute { + let jsonData = jsonString.data(using: .utf8) + return try JSONDecoder().decode(TokenUriMetadataAttribute.self, from: jsonData!) + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 13d2b9a..c43f720 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -5,4 +5,6 @@ import ResolutionTests var tests = [XCTestCaseEntry]() tests += ResolutionTests.allTests() tests += EthereumABITests.allTests() +tests += TokenUriMetadataTests.allTests() +tests += ABICoderTests.allTests() XCTMain(tests) diff --git a/Tests/ResolutionTests/ResolutionTests.swift b/Tests/ResolutionTests/ResolutionTests.swift index 43b4ccd..bf7aad5 100644 --- a/Tests/ResolutionTests/ResolutionTests.swift +++ b/Tests/ResolutionTests/ResolutionTests.swift @@ -17,32 +17,91 @@ var resolution: Resolution! class ResolutionTests: XCTestCase { + static let TEST_DOMAIN: String = "udtestdev-265f8f.crypto" + static let TEST_DOMAIN2: String = "johnnytestdev6357.crypto" + static let TEST_DOMAIN3: String = "brad.crypto" + static let TEST_WALLET_DOMAIN: String = "udtestdev-johnnywallet.wallet" + static let TEST_COIN_DOMAIN: String = "udtestdev-johnnycoin.coin" + static let UNREGISTERED_DOMAIN: String = "unregistered.crypto" + let timeout: TimeInterval = 30 override func setUp() { super.setUp() - resolution = try! Resolution(); + resolution = try! Resolution( + configs: Configurations( + uns: NamingServiceConfig( + providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", + network: "rinkeby"), + zns: NamingServiceConfig( + providerUrl: "https://dev-api.zilliqa.com", + network: "testnet") + ) + ); } - + func testNetworkFromUrl() throws { resolution = try Resolution(configs: Configurations( - cns: NamingServiceConfig(providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817") + uns: NamingServiceConfig(providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817"), + ens: NamingServiceConfig(providerUrl: "https://ropsten.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee") ) ); - let cnsNetwork = try resolution.getNetwork(from: "cns"); + let unsNetwork = try resolution.getNetwork(from: "uns"); let znsNetwork = try resolution.getNetwork(from: "zns"); - assert(cnsNetwork == "rinkeby"); + let ensNetwork = try resolution.getNetwork(from: "ens"); + assert(unsNetwork == "rinkeby"); + assert(ensNetwork == "ropsten"); assert(znsNetwork == "mainnet"); } func testUnsupportedNetwork() throws { self.checkError(completion: { try Resolution(configs: Configurations( - cns: NamingServiceConfig(providerUrl: "https://ropsten.infura.io/v3/3c25f57353234b1b853e9861050f4817") + uns: NamingServiceConfig(providerUrl: "https://ropsten.infura.io/v3/3c25f57353234b1b853e9861050f4817") + )); + }, expectedError: .proxyReaderNonInitialized) + + self.checkError(completion: { + try Resolution(configs: Configurations( + ens: NamingServiceConfig(providerUrl: "https://kovan.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee") )); - }, expectedError: .unsupportedNetwork) + }, expectedError: .registryAddressIsNotProvided) + + self.checkError(completion: { + try Resolution(configs: Configurations( + zns: NamingServiceConfig(providerUrl: "https://kovan.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee") + )); + }, expectedError: .registryAddressIsNotProvided) } + func testCustomNetwork() throws { + let resolution = try Resolution(configs: Configurations( + uns: NamingServiceConfig( + providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", + network: "somethingCustom", + proxyReader: "0x299974AeD8911bcbd2C61262605b89F591a53E83", + registryAddresses: ["0x7fb83000B8eD59D3eAD22f0D584Df3a85fBC0086", "0xAad76bea7CFEc82927239415BB18D2e93518ecBB"] + ), + ens: NamingServiceConfig( + providerUrl: "https://kovan.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee", + network: "customKovan", + registryAddresses: ["0x7fb83000B8eD59D3eAD22f0D584Df3a85fBC0086"] + ), + zns: NamingServiceConfig( + providerUrl: "https://kovan.infura.io/v3/d423cf2499584d7fbe171e33b42cfbee", + network: "customKovanPortZil", + registryAddresses: ["0x7fb83000B8eD59D3eAD22f0D584Df3a85fBC0086"] + ) + )); + let unsNetwork = try resolution.getNetwork(from: "uns") + let ensNetwork = try resolution.getNetwork(from: "ens") + let znsNetwork = try resolution.getNetwork(from: "zns") + assert(unsNetwork == "somethingCustom") + assert(ensNetwork == "customKovan") + assert(znsNetwork == "customKovanPortZil") + } + + func testForUnregisteredDomain() throws { let UnregirestedDomainExpectation = expectation(description: "Domain should not be registered!") var NoRecordResult: Result! @@ -67,7 +126,7 @@ class ResolutionTests: XCTestCase { func testRinkeby() throws { resolution = try Resolution(configs: Configurations( - cns: NamingServiceConfig( + uns: NamingServiceConfig( providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", network: "rinkeby" ) @@ -95,17 +154,10 @@ class ResolutionTests: XCTestCase { } } waitForExpectations(timeout: timeout, handler: nil) - assert(ethAddress == "0x1C8b9B78e3085866521FE206fa4c1a67F49f153A") + Swift.assert(ethAddress == "0x1C8b9B78e3085866521FE206fa4c1a67F49f153A") } func testZilliqaTestNet() throws { - resolution = try Resolution(configs: Configurations( - zns: NamingServiceConfig( - providerUrl: "https://dev-api.zilliqa.com", - network: "testnet" - ) - ) - ); let domainReceived = expectation(description: "Exist domain should be received") var zilOwner = "" resolution.owner(domain: "test-udtesting-654.zil") { (result) in @@ -123,18 +175,73 @@ class ResolutionTests: XCTestCase { func testSupportedDomains() throws { // Given // When // Then - assert(false == resolution.isSupported(domain: "notsupported.crypto1")) - assert(true == resolution.isSupported(domain: "supported.crypto")) - assert(true == resolution.isSupported(domain: "supported.zil")) - assert(false == resolution.isSupported(domain: "notsupported.eth1")) - assert(false == resolution.isSupported(domain: "supported.eth")) - assert(false == resolution.isSupported(domain: "notsupported.xyz1")) - assert(false == resolution.isSupported(domain: "supported.xyz")) - assert(false == resolution.isSupported(domain: "notsupported.luxe1")) - assert(false == resolution.isSupported(domain: "supported.luxe")) - assert(false == resolution.isSupported(domain: "-notsupported.eth")) - assert(false == resolution.isSupported(domain: "supported.kred")) - assert(false == resolution.isSupported(domain: "supported.addr.reverse")) + resolution = try Resolution(configs: Configurations( + uns: NamingServiceConfig( + providerUrl: "https://rinkeby.infura.io/v3/3c25f57353234b1b853e9861050f4817", + network: "rinkeby" + ), + zns: NamingServiceConfig( + providerUrl: "https://dev-api.zilliqa.com", + network: "testnet" + ) + )); + + struct TestCase { + let domain: String + let expectation: XCTestExpectation + var result: Bool? + let expectedResult: Bool + } + + let domains: [String] = [ + "supported.crypto", + "supported.zil", + "supported.nft", + "supported.888", + "supported.coin", + "supported.blockchain", + "supported.dao", + "supported.bitcoin", + "supported.wallet", + "supported.x", + "notsupported.crypto1", + "notsupported.eth1", + "supported.eth", + "notsupported.xyz1", + "supported.xyz", + "notsupported.luxe1", + "-notsupported.eth", + "supported.kred", + "supported.addr.reverse", + "notsupported.definetelynotright" + ] + + var cases = domains.compactMap { + TestCase( + domain: $0, + expectation: expectation(description: "received answer for \($0)"), + result: nil, + expectedResult: $0.components(separatedBy: ".").first! == "supported" + ) + } + + for i in 0..! // When - resolution.multiChainAddress(domain: "brad.crypto", ticker: "usdt", chain: "erc20") { + resolution.multiChainAddress(domain: ResolutionTests.TEST_DOMAIN3, ticker: "usdt", chain: "erc20") { NoRecordResult = $0 NoRecordReceived.fulfill() } @@ -261,17 +415,18 @@ class ResolutionTests: XCTestCase { func testGetOwner() throws { + let CNSDomain = ResolutionTests.TEST_DOMAIN; // Given let domainCryptoReceived = expectation(description: "Exist Crypto domain should be received") - let domainZilReceived = expectation(description: "Exist ziliq domain should be received") + let domainEthReceived = expectation(description: "Exist ETH domain should be received") let unregisteredReceived = expectation(description: "Unregistered domain should be received") var owner = "" - var zilOwner = "" + var ethOwner = "" var unregisteredResult: Result! // When - resolution.owner(domain: "brad.crypto") { (result) in + resolution.owner(domain: CNSDomain) { (result) in switch result { case .success(let returnValue): domainCryptoReceived.fulfill() @@ -281,11 +436,12 @@ class ResolutionTests: XCTestCase { } } - resolution.owner(domain: "brad.zil") { (result) in + + resolution.owner(domain: "matthewgould.eth") { (result) in switch result { case .success(let returnValue): - domainZilReceived.fulfill() - zilOwner = returnValue + domainEthReceived.fulfill() + ethOwner = returnValue case .failure(let error): XCTFail("Expected owner, but got \(error)") } @@ -299,8 +455,8 @@ class ResolutionTests: XCTestCase { waitForExpectations(timeout: timeout, handler: nil) // Then - assert(owner.lowercased() == "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8".lowercased()) - assert(zilOwner.lowercased() == "0x2d418942dce1afa02d0733a2000c71b371a6ac07".lowercased()) + assert(owner.lowercased() == "0xe7474D07fD2FA286e7e0aa23cd107F8379085037".lowercased()) + assert(ethOwner.lowercased() == "0x714ef33943d925731fbb89c99af5780d888bd106".lowercased()) self.checkError(result: unregisteredResult, expectedError: ResolutionError.unregisteredDomain) } @@ -314,7 +470,7 @@ class ResolutionTests: XCTestCase { var partialResult: Result<[String?], ResolutionError>! // When - resolution.batchOwners(domains: ["brad.crypto", "unstoppablecaribou.crypto"]) { (result) in + resolution.batchOwners(domains: [ResolutionTests.TEST_DOMAIN, ResolutionTests.TEST_DOMAIN2]) { (result) in switch result { case .success(let returnValue): owners = returnValue @@ -324,7 +480,7 @@ class ResolutionTests: XCTestCase { } } - resolution.batchOwners(domains: ["brad.crypto", "unregistered.crypto"]) { + resolution.batchOwners(domains: [ResolutionTests.TEST_DOMAIN, ResolutionTests.UNREGISTERED_DOMAIN]) { partialResult = $0 particalResultReceived.fulfill() } @@ -335,7 +491,7 @@ class ResolutionTests: XCTestCase { switch partialResult { case .success(let array): let lowercasedOwners = array.map( {$0?.lowercased()} ) - assert( lowercasedOwners[0] == "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8".lowercased() ) + assert( lowercasedOwners[0] == "0xe7474D07fD2FA286e7e0aa23cd107F8379085037".lowercased() ) assert( lowercasedOwners[1] == nil ) case .failure(let error): @@ -345,20 +501,22 @@ class ResolutionTests: XCTestCase { } let lowercasedOwners = owners.compactMap({$0}).map{$0.lowercased()} - assert( lowercasedOwners[0] == "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8".lowercased() ) - assert( lowercasedOwners[1] == "0x53E238E686BeFF9853b2d8ede1D6B3067A921AAa".lowercased() ) + assert( lowercasedOwners[0] == "0xe7474D07fD2FA286e7e0aa23cd107F8379085037".lowercased() ) + assert( lowercasedOwners[1] == "0xe7474D07fD2FA286e7e0aa23cd107F8379085037".lowercased() ) } func testGetResolver() throws { // Given let domainCryptoReceived = expectation(description: "Exist Crypto domain should be received") + let domainEthReceived = expectation(description: "Exist ETH domain should be received") let unregisteredReceived = expectation(description: "Unregistered domain should be received") var resolverAddress = "" + var ethResolverAddress = "" var unregisteredResult: Result! // When - resolution.resolver(domain: "brad.crypto") { (result) in + resolution.resolver(domain: ResolutionTests.TEST_DOMAIN) { (result) in switch result { case .success(let returnValue): domainCryptoReceived.fulfill() @@ -367,8 +525,18 @@ class ResolutionTests: XCTestCase { XCTFail("Expected resolver Address, but got \(error)") } } + + resolution.resolver(domain: "monkybrain.eth") { (result) in + switch result { + case .success(let returnValue): + domainEthReceived.fulfill() + ethResolverAddress = returnValue + case .failure(let error): + XCTFail("Expected resolver Address, but got \(error)") + } + } - resolution.resolver(domain: "unregistered.crypto") { + resolution.resolver(domain: ResolutionTests.UNREGISTERED_DOMAIN) { unregisteredResult = $0 unregisteredReceived.fulfill() } @@ -376,22 +544,27 @@ class ResolutionTests: XCTestCase { waitForExpectations(timeout: timeout, handler: nil) // Then - assert(resolverAddress.lowercased() == "0xb66DcE2DA6afAAa98F2013446dBCB0f4B0ab2842".lowercased()) + + assert(resolverAddress.lowercased() == "0x95AE1515367aa64C462c71e87157771165B1287A".lowercased()) + assert(ethResolverAddress.lowercased() == "0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41".lowercased()) self.checkError(result: unregisteredResult, expectedError: ResolutionError.unspecifiedResolver) } + //TODO Add zilliqa testnet domain func testAddr() throws { // Given - let domainReceived = expectation(description: "Exist domain should be received") - let domainZilReceived = expectation(description: "Exist ETH domain should be received") + let domainReceived = expectation(description: "Exist UNS domain should be received") + let domainEthReceived = expectation(description: "Exist ENS domain should be received") +// let domainZilReceived = expectation(description: "Exist ZNS domain should be received") let unregisteredReceived = expectation(description: "Unregistered domain should be received") var ethAddress = "" - var zilENSAddress = "" +// var zilENSAddress = "" + var ethENSAddress = "" var unregisteredResult: Result! // When - resolution.addr(domain: "brad.crypto", ticker: "eth") { (result) in + resolution.addr(domain: ResolutionTests.TEST_DOMAIN, ticker: "eth") { (result) in switch result { case .success(let returnValue): ethAddress = returnValue @@ -400,18 +573,29 @@ class ResolutionTests: XCTestCase { XCTFail("Expected Eth Address, but got \(error)") } } - - resolution.addr(domain: "brad.zil", ticker: "eth") { (result) in + + resolution.addr(domain: "monkybrain.eth", ticker: "eth") { (result) in switch result { case .success(let returnValue): - domainZilReceived.fulfill() - zilENSAddress = returnValue + ethENSAddress = returnValue + domainEthReceived.fulfill() case .failure(let error): - XCTFail("Expected owner, but got \(error)") + XCTFail("Expected Eth Address, but got \(error)") } } - resolution.addr(domain: "brad.crypto", ticker: "unknown") { +// Todo replace brad.zil with a testnet domain +// resolution.addr(domain: "brad.zil", ticker: "eth") { (result) in +// switch result { +// case .success(let returnValue): +// domainZilReceived.fulfill() +// zilENSAddress = returnValue +// case .failure(let error): +// XCTFail("Expected owner, but got \(error)") +// } +// } + + resolution.addr(domain: ResolutionTests.TEST_DOMAIN, ticker: "unknown") { unregisteredResult = $0 unregisteredReceived.fulfill() } @@ -420,7 +604,8 @@ class ResolutionTests: XCTestCase { // Then assert(ethAddress == "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8") - assert(zilENSAddress == "0x45b31e01AA6f42F0549aD482BE81635ED3149abb") +// assert(zilENSAddress == "0x45b31e01AA6f42F0549aD482BE81635ED3149abb") + assert(ethENSAddress == "0x842f373409191Cff2988A6F19AB9f605308eE462") self.checkError(result: unregisteredResult, expectedError: ResolutionError.recordNotFound) } @@ -430,7 +615,8 @@ class ResolutionTests: XCTestCase { var chatID = "" // When - resolution.chatId(domain: "brad.crypto") { (result) in + + resolution.chatId(domain: ResolutionTests.TEST_DOMAIN) { (result) in switch result { case .success(let returnValue): chatID = returnValue @@ -441,21 +627,14 @@ class ResolutionTests: XCTestCase { } waitForExpectations(timeout: timeout, handler: nil) - // Then assert(chatID == "0x8912623832e174f2eb1f59cc3b587444d619376ad5bf10070e937e0dc22b9ffb2e3ae059e6ebf729f87746b2f71e5d88ec99c1fb3c7c49b8617e2520d474c48e1c") } func testForTokensOwnedByCns() throws { let tokenReceived = expectation(description: "tokens for 0x8aaD44321A86b170879d7A244c1e8d360c99DdA8 address should be received"); - let resolution = try Resolution(configs: Configurations( - cns: NamingServiceConfig( - providerUrl: "https://mainnet.infura.io/v3/e05c36b6b2134ccc9f2594ddff94c136", - network: "mainnet" - ) - )) var returnedDomains: [String] = []; - resolution.tokensOwnedBy(address: "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", service: "CNS") { (result) in + resolution.tokensOwnedBy(address: "0xe7474D07fD2FA286e7e0aa23cd107F8379085037", service: "uns") { (result) in switch result { case .success(let returnValue): returnedDomains = returnValue.compactMap{ $0 } @@ -466,22 +645,21 @@ class ResolutionTests: XCTestCase { } waitForExpectations(timeout: timeout, handler: nil) - assert(returnedDomains.count >= 4) - assert(returnedDomains.contains("checkoutwithadomain.crypto")) - assert(returnedDomains.contains("brad.crypto")) - assert(returnedDomains.contains("bradley.chat.crypto")) - assert(returnedDomains.contains("kdslkfjadasdfd.crypto")) + assert(returnedDomains.count >= 3) + assert(returnedDomains.contains("johnnytestdev6357.crypto")) + assert(returnedDomains.contains("johnnydevtest6357.crypto")) + assert(returnedDomains.contains("udtestdev-265f8f.crypto")) } func testForTokensOwnedByCnsFromRinkeby() throws { let tetReceived = expectation(description: "This is just for test"); let resolutionB = try Resolution(configs: Configurations( - cns: NamingServiceConfig( + uns: NamingServiceConfig( providerUrl: "https://rinkeby.infura.io/v3/e05c36b6b2134ccc9f2594ddff94c136", network: "rinkeby" ))) var returnedDomains: [String] = []; - resolutionB.tokensOwnedBy(address: "0x6EC0DEeD30605Bcd19342f3c30201DB263291589", service: "CNS") { (result) in + resolutionB.tokensOwnedBy(address: "0x6EC0DEeD30605Bcd19342f3c30201DB263291589", service: "uns") { (result) in switch result { case .success(let returnValue): returnedDomains = returnValue.compactMap{ $0 } @@ -492,8 +670,9 @@ class ResolutionTests: XCTestCase { } waitForExpectations(timeout: timeout, handler: nil) - assert(returnedDomains.count == 4) + assert(returnedDomains.count == 5) assert(returnedDomains.contains("udtestdev-creek.crypto")) + assert(returnedDomains.contains("udtestdev-my-new-tls.wallet")) assert(returnedDomains.contains("reseller-test-udtesting-630444001358.crypto")) assert(returnedDomains.contains("test-test-test-test.crypto")) assert(returnedDomains.contains("reseller-test-udtesting-483809515990.crypto")) @@ -502,13 +681,15 @@ class ResolutionTests: XCTestCase { func testIpfs() throws { // Given let domainReceived = expectation(description: "Exist domain should be received") + let domainEthReceived = expectation(description: "Exist ETH domain should be received") let unregisteredReceived = expectation(description: "Unregistered domain should be received") var hash = "" + var etcHash = "" var unregisteredResult: Result! // When - resolution.ipfsHash(domain: "brad.crypto") { result in + resolution.ipfsHash(domain: ResolutionTests.TEST_DOMAIN) { result in switch result { case .success(let returnValue): hash = returnValue @@ -517,8 +698,18 @@ class ResolutionTests: XCTestCase { XCTFail("Expected ipfsHash, but got \(error)") } } + + resolution.ipfsHash(domain: "monkybrain.eth") { (result) in + switch result { + case .success(let returnValue): + etcHash = returnValue + domainEthReceived.fulfill() + case .failure(let error): + XCTFail("Expected ipfsHash, but got \(error)") + } + } - resolution.ipfsHash(domain: "unregistered.crypto") { result in + resolution.ipfsHash(domain: ResolutionTests.UNREGISTERED_DOMAIN) { result in unregisteredResult = result unregisteredReceived.fulfill() } @@ -527,6 +718,7 @@ class ResolutionTests: XCTestCase { // Then assert(hash == "QmdyBw5oTgCtTLQ18PbDvPL8iaLoEPhSyzD91q9XmgmAjb") + assert(etcHash == "QmXSBLw6VMegqkCHSDBPg7xzfLhUyuRBzTb927KVzKC1vq") self.checkError(result: unregisteredResult, expectedError: ResolutionError.unregisteredDomain) } @@ -535,21 +727,21 @@ class ResolutionTests: XCTestCase { let domainReceived = expectation(description: "Exist domain should be received") let unregisteredReceived = expectation(description: "Unregistered domain should be received") - var ipfshash = "" + var customRecord = "" var unregisteredResult: Result! // When - resolution.record(domain: "brad.crypto", key: "ipfs.html.value") { (result) in + resolution.record(domain: ResolutionTests.TEST_DOMAIN, key: "custom.record") { (result) in switch result { case .success(let returnValue): domainReceived.fulfill() - ipfshash = returnValue + customRecord = returnValue case .failure(let error): - XCTFail("Expected ipfsHash, but got \(error)") + XCTFail("Expected custom record, but got \(error)") } } - resolution.record(domain: "brad.crypto", key: "unknown.value") { + resolution.record(domain: ResolutionTests.TEST_DOMAIN, key: "unknown.value") { unregisteredResult = $0 unregisteredReceived.fulfill() } @@ -557,16 +749,115 @@ class ResolutionTests: XCTestCase { waitForExpectations(timeout: timeout, handler: nil) // Then - assert(ipfshash == "QmdyBw5oTgCtTLQ18PbDvPL8iaLoEPhSyzD91q9XmgmAjb") + assert(customRecord == "custom.value") self.checkError(result: unregisteredResult, expectedError: ResolutionError.recordNotFound) } + func testTokenUri() throws { + // Given + let domainReceived = expectation(description: "Exist domain should be received") + let unregisteredReceived = expectation(description: "Unregistered domain should be received") + + var tokenURI = "" + var unregisteredResult: Result! + + // When + resolution.tokenURI(domain: ResolutionTests.TEST_DOMAIN3) { (result) in + switch result { + case .success(let returnValue): + domainReceived.fulfill() + tokenURI = returnValue + case .failure(let error): + XCTFail("Expected tokenURI, but got \(error)") + } + } + resolution.tokenURI(domain: ResolutionTests.UNREGISTERED_DOMAIN) { + unregisteredResult = $0 + unregisteredReceived.fulfill() + } + waitForExpectations(timeout: timeout, handler: nil) + + // Then + assert(tokenURI == "https://staging-dot-dot-crypto-metadata.appspot.com/metadata/brad.crypto") + self.checkError(result: unregisteredResult, expectedError: ResolutionError.unregisteredDomain) + } + + func testTokenUriMetadata() throws { + // Given + let domainReceived = expectation(description: "Exist domain should be received") + let unregisteredReceived = expectation(description: "Unregistered domain should be received") + + var tokenURIMetadata: TokenUriMetadata? = nil + var unregisteredResult: Result! + + // When + resolution.tokenURIMetadata(domain: ResolutionTests.TEST_DOMAIN3) { (result) in + switch result { + case .success(let returnValue): + domainReceived.fulfill() + tokenURIMetadata = returnValue + case .failure(let error): + XCTFail("Expected tokenURIMetadata, but got \(error)") + } + } + resolution.tokenURIMetadata(domain: "afakedomainthatdoesnotexist-test-20210616.crypto") { + unregisteredResult = $0 + unregisteredReceived.fulfill() + } + waitForExpectations(timeout: timeout, handler: nil) + + // Then + assert(tokenURIMetadata?.name == ResolutionTests.TEST_DOMAIN3) + assert(tokenURIMetadata?.attributes.count == 8) + assert(self.checkAttributeArrayContains(array: tokenURIMetadata?.attributes ?? [], traitType: "ETH", value: "0x8aaD44321A86b170879d7A244c1e8d360c99DdA8")) + + self.checkError(result: unregisteredResult, expectedError: ResolutionError.unregisteredDomain) + } + + func checkAttributeArrayContains(array: [TokenUriMetadataAttribute], traitType: String, value: String) -> Bool { + for attr in array { + if attr.traitType == traitType && attr.value.value == value { + return true + } + } + return false + } + + func testUnhash() throws { + // Given + let domainReceived = expectation(description: "Existing domain should be received") + let unregisteredReceived = expectation(description: "Unregistered domain should be received") + + var domainName: String = "" + var unregisteredResult: Result! + + // When + resolution.unhash(hash: "0x756e4e998dbffd803c21d23b06cd855cdc7a4b57706c95964a37e24b47c10fc9", serviceName: .uns) { (result) in + switch result { + case .success(let returnValue): + domainReceived.fulfill() + domainName = returnValue + case .failure(let error): + XCTFail("Expected domainName, but got \(error)") + } + } + resolution.unhash(hash: "0xdeaddeaddead", serviceName: .uns) { + unregisteredResult = $0 + unregisteredReceived.fulfill() + } + waitForExpectations(timeout: timeout, handler: nil) + + // Then + assert(domainName == ResolutionTests.TEST_DOMAIN3) + self.checkError(result: unregisteredResult, expectedError: ResolutionError.unregisteredDomain) + } + func testGetMany() throws { // Given let domainReceived = expectation(description: "Exist domain should be received") let keys = ["ipfs.html.value", "crypto.BTC.address", "crypto.ETH.address", "someweirdstuf"] - let domain = "brad.crypto" + let domain = ResolutionTests.TEST_DOMAIN3 var values = [String: String]() // When @@ -628,6 +919,16 @@ class ResolutionTests: XCTestCase { return } } + + func checkError(result: Result, expectedError: ResolutionError) { + switch result { + case .success: + XCTFail("Expected \(expectedError), but got none") + case .failure(let error): + assert(error == expectedError, "Expected \(expectedError), but got \(error)") + return + } + } } extension ResolutionError: Equatable { @@ -657,6 +958,8 @@ extension ResolutionError: Equatable { return true case (.unsupportedServiceName, .unsupportedServiceName): return true + case (.registryAddressIsNotProvided, .registryAddressIsNotProvided): + return true case (.unregisteredDomain, _), (.unsupportedDomain, _), @@ -670,7 +973,8 @@ extension ResolutionError: Equatable { (.proxyReaderNonInitialized, _), (.tooManyResponses, _), (.badRequestOrResponse, _), - (.unsupportedServiceName, _): + (.unsupportedServiceName, _), + (.registryAddressIsNotProvided, _): return false // Xcode with Version 12.4 (12D4e) can't compile this without default diff --git a/Tests/ResolutionTests/XCTestManifests.swift b/Tests/ResolutionTests/XCTestManifests.swift index 241a260..30f9a5b 100644 --- a/Tests/ResolutionTests/XCTestManifests.swift +++ b/Tests/ResolutionTests/XCTestManifests.swift @@ -4,7 +4,9 @@ import XCTest public func allTests() -> [XCTestCaseEntry] { return [ testCase(ResolutionTests.allTests), - testCase(EthereumABITests.allTests) + testCase(EthereumABITests.allTests), + testCase(TokenUriMetadataTests.allTests), + testCase(ABICoderTests.allTests) ] } #endif diff --git a/UnstoppableDomainsResolution.podspec b/UnstoppableDomainsResolution.podspec index d8dedc8..e07f78b 100644 --- a/UnstoppableDomainsResolution.podspec +++ b/UnstoppableDomainsResolution.podspec @@ -23,7 +23,6 @@ Pod::Spec.new do |spec| spec.resources = "Sources/UnstoppableDomainsResolution/Resources/**/*.json" - spec.dependency 'EthereumAddress', '~> 1.3' - spec.dependency 'CryptoSwift', '~> 1.0' + spec.dependency 'CryptoSwift', '~> 1.4.1' spec.dependency 'BigInt' end