diff --git a/Package.resolved b/Package.resolved index 72bdcdb7..08ffadef 100644 --- a/Package.resolved +++ b/Package.resolved @@ -12,11 +12,11 @@ }, { "package": "GenericJSON", - "repositoryURL": "https://github.com/zoul/generic-json-swift", + "repositoryURL": "https://github.com/iwill/generic-json-swift", "state": { "branch": null, - "revision": "a137894b2a217abe489cdf1ea287e6f7819b1051", - "version": "2.0.1" + "revision": "0a06575f4038b504e78ac330913d920f1630f510", + "version": "2.0.2" } }, { diff --git a/Package.swift b/Package.swift index 0b329e53..c276c2e4 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ let package = Package( ], dependencies: [ .package(name: "BigInt", url: "https://github.com/attaswift/BigInt", from: "5.0.0"), - .package(name: "GenericJSON", url: "https://github.com/zoul/generic-json-swift", from: "2.0.0"), + .package(name: "GenericJSON", url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.0")), .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMajor(from: "0.6.0")), .package(url: "https://github.com/vapor/websocket-kit.git", from: "2.0.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0") @@ -56,7 +56,9 @@ let package = Package( path: "web3sTests", resources: [ .copy("Resources/rlptests.json"), - .copy("Account/cryptofights_712.json") + .copy("Account/cryptofights_712.json"), + .copy("Account/ethermail_signTypedDataV4.json"), + .copy("Account/real_word_opensea_signTypedDataV4.json"), ] ) ] diff --git a/README.md b/README.md index 6e147068..b85ca9ef 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,14 @@ $ pod install ### Getting Started -Create an instance of `EthereumAccount` with a `EthereumKeyStorage` provider. This provides a wrapper around your key for web3.swift to use. **NOTE** We recommend you implement your own KeyStorage provider, instead of relying on the provided `EthereumKeyLocalStorage` class. This is provided as an example for conformity to the `EthereumKeyStorageProtocol`. +Create an instance of `EthereumAccount` with a `EthereumKeyStorage` provider. This provides a wrapper around your key for web3.swift to use. **NOTE We recommend you implement your own KeyStorage provider, instead of relying on the provided `EthereumKeyLocalStorage` class. This is provided as an example for conformity to the `EthereumSingleKeyStorageProtocol`.** ```swift import web3 - +// This is just an example. EthereumKeyLocalStorage should not be used in production code let keyStorage = EthereumKeyLocalStorage() -let account = try? EthereumAccount.create(keyStorage: keyStorage, keystorePassword: "MY_PASSWORD") +let account = try? EthereumAccount.create(replacing: keyStorage, keystorePassword: "MY_PASSWORD") ``` Create an instance of `EthereumHttpClient` or `EthereumWebSocketClient`. This will then provide you access to a set of functions for interacting with the Blockchain. @@ -50,7 +50,7 @@ OR `EthereumWebSocketClient` ```swift -guard let clientUrl = URL(string: "wss://ropsten.infura.io/ws/v3//123") else { return } +guard let clientUrl = URL(string: "wss://goerli.infura.io/ws/v3//123") else { return } let client = EthereumWebSocketClient(url: clientUrl) ``` @@ -159,7 +159,7 @@ We support querying ERC721 token data via the `ERC721` struct. Including: ### Running Tests -The tests will all pass when running against Ropsten. You will need to provide a URL for the blockchain proxy (e.g. on Infura), and a key-pair in `TestConfig.swift`. Some of the account signing tests will fail, given the signature assertions are against a specific (unprovided) key. +The tests will all pass when running against Goerli. You will need to provide a URL for the blockchain proxy (e.g. on Infura), and a key-pair in `TestConfig.swift`. Some of the account signing tests will fail, given the signature assertions are against a specific (unprovided) key. ## Dependencies diff --git a/web3.swift.podspec b/web3.swift.podspec index 199ce5cf..367924e9 100644 --- a/web3.swift.podspec +++ b/web3.swift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'web3.swift' - s.version = '1.3.0' + s.version = '1.4.0' s.license = 'MIT' s.summary = 'Ethereum API for Swift' s.homepage = 'https://github.com/argentlabs/web3.swift' diff --git a/web3sTests/Account/EthereumAccount+SignTypedTests.swift b/web3sTests/Account/EthereumAccount+SignTypedTests.swift index 18c8c42b..12c006f8 100644 --- a/web3sTests/Account/EthereumAccount+SignTypedTests.swift +++ b/web3sTests/Account/EthereumAccount+SignTypedTests.swift @@ -231,6 +231,18 @@ class EthereumAccount_SignTypedTests: XCTestCase { let typedData = try! decoder.decode(TypedData.self, from: data) XCTAssertEqual(try! typedData.signableHash().web3.hexString, "0xdb12328a6d193965801548e1174936c3aa7adbe1b54b3535a3c905bd4966467c") } + + func test_GivenCustomTypeArray_V4_ItHashesCorrectly() { + let simpleUrl = Bundle.module.url(forResource: "ethermail_signTypedDataV4", withExtension: "json")! + let simpleData = try! Data(contentsOf: simpleUrl) + let simpleTypedData = try! decoder.decode(TypedData.self, from: simpleData) + XCTAssertEqual(try! simpleTypedData.signableHash().web3.hexString, "0x8a2c45f690057d91a9738b313da3f65916327e1d5b9a1348b9fc1cff0dc4091e") + + let realWorldUrl = Bundle.module.url(forResource: "real_word_opensea_signTypedDataV4", withExtension: "json")! + let realWorldData = try! Data(contentsOf: realWorldUrl) + let realWorldTypedData = try! decoder.decode(TypedData.self, from: realWorldData) + XCTAssertEqual(try! realWorldTypedData.signableHash().web3.hexString, "0x76a61293096587b582305a07a60785f92b99ae6c8647c4bcf46d6651db0bd778") + } func test_givenExampleWithDynamicData_ItHashesCorrectly() { let typedData = try! decoder.decode(TypedData.self, from: example4) diff --git a/web3sTests/Account/EthereumAccountTests.swift b/web3sTests/Account/EthereumAccountTests.swift index ffb6144c..699af655 100644 --- a/web3sTests/Account/EthereumAccountTests.swift +++ b/web3sTests/Account/EthereumAccountTests.swift @@ -27,41 +27,41 @@ class EthereumAccountTests: XCTestCase { } func testCreateAccount() { - let storage = EthereumKeyLocalStorage() as EthereumKeyStorageProtocol - let account = try? EthereumAccount.create(keyStorage: storage, keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try? EthereumAccount.create(replacing: storage, keystorePassword: "PASSWORD") XCTAssertNotNil(account, "Failed to create account. Ensure key is valid in TestConfig.swift") } func testCreateAccountMultiple() { - let storage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol - let account = try? EthereumAccount.create(keyStorage: storage, keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try? EthereumAccount.create(addingTo: storage, keystorePassword: "PASSWORD") XCTAssertNotNil(account, "Failed to create account. Ensure key is valid in TestConfig.swift") } func testImportAccount() { - let storage = EthereumKeyLocalStorage() as EthereumKeyStorageProtocol - let account = try! EthereumAccount.importAccount(keyStorage: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try! EthereumAccount.importAccount(replacing: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") XCTAssertEqual(account.address.value, "0x675f5810feb3b09528e5cd175061b4eb8de69075") } func testImportAccountMultiple() { - let storage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol - let account = try! EthereumAccount.importAccount(keyStorage: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try! EthereumAccount.importAccount(addingTo: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") XCTAssertEqual(account.address.value, "0x675f5810feb3b09528e5cd175061b4eb8de69075") } func testFetchAccounts() { - let storage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol - let account = try! EthereumAccount.importAccount(keyStorage: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try! EthereumAccount.importAccount(addingTo: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") let accounts = try! storage.fetchAccounts() XCTAssertTrue(accounts.contains(account.address)) } func testDeleteAccount() { - let storage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol - let account = try! EthereumAccount.importAccount(keyStorage: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") + let storage = EthereumKeyLocalStorage() + let account = try! EthereumAccount.importAccount(addingTo: storage, privateKey: "0x2639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde7173", keystorePassword: "PASSWORD") let ethereumAddress = EthereumAddress("0x675f5810feb3b09528e5cd175061b4eb8de69075") try! storage.deletePrivateKey(for: ethereumAddress) let accounts = try! storage.fetchAccounts() diff --git a/web3sTests/Account/EthereumKeyStorageTests.swift b/web3sTests/Account/EthereumKeyStorageTests.swift index e63f4cc4..92b5f824 100644 --- a/web3sTests/Account/EthereumKeyStorageTests.swift +++ b/web3sTests/Account/EthereumKeyStorageTests.swift @@ -43,7 +43,7 @@ class EthereumKeyStorageTests: XCTestCase { func testEncryptAndStorePrivateKey() { let randomData = Data.randomOfLength(256)! - let keyStorage = EthereumKeyLocalStorage() as EthereumKeyStorageProtocol + let keyStorage = EthereumKeyLocalStorage() as EthereumSingleKeyStorageProtocol let password = "myP4ssw0rD" do { @@ -73,11 +73,11 @@ class EthereumKeyStorageTests: XCTestCase { } func testDeleteAllPrivateKeys() { - let keyStorage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol + let keyStorage = EthereumKeyLocalStorage() do { - _ = try EthereumAccount.create(keyStorage: keyStorage, keystorePassword: "PASSWORD") - _ = try EthereumAccount.create(keyStorage: keyStorage, keystorePassword: "PASSWORD") - _ = try EthereumAccount.create(keyStorage: keyStorage, keystorePassword: "PASSWORD") + _ = try EthereumAccount.create(addingTo: keyStorage, keystorePassword: "PASSWORD") + _ = try EthereumAccount.create(addingTo: keyStorage, keystorePassword: "PASSWORD") + _ = try EthereumAccount.create(addingTo: keyStorage, keystorePassword: "PASSWORD") try keyStorage.deleteAllKeys() let countAfterDeleting = try keyStorage.fetchAccounts() XCTAssertEqual(countAfterDeleting.count, 0) diff --git a/web3sTests/Account/ethermail_signTypedDataV4.json b/web3sTests/Account/ethermail_signTypedDataV4.json new file mode 100644 index 00000000..38b79c4d --- /dev/null +++ b/web3sTests/Account/ethermail_signTypedDataV4.json @@ -0,0 +1,70 @@ +{ + "domain": { + "chainId": "137", + "name": "Etaher Mail", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "version": "1" + }, + "message": { + "contents": "Hello, Bob!", + "from": { + "name": "Cow", + "wallets": [ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" + ] + }, + "to": [{ + "name": "Cow", + "wallets": [ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" + ] + }] + }, + "primaryType": "Mail", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Mail": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Person[]" + }, + { + "name": "contents", + "type": "string" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallets", + "type": "address[]" + } + ] + } +} diff --git a/web3sTests/Account/real_word_opensea_signTypedDataV4.json b/web3sTests/Account/real_word_opensea_signTypedDataV4.json new file mode 100644 index 00000000..32e49df3 --- /dev/null +++ b/web3sTests/Account/real_word_opensea_signTypedDataV4.json @@ -0,0 +1,190 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "OfferItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + } + ], + "ConsiderationItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + }, + { + "name": "recipient", + "type": "address" + } + ], + "OrderComponents": [ + { + "name": "offerer", + "type": "address" + }, + { + "name": "zone", + "type": "address" + }, + { + "name": "offer", + "type": "OfferItem[]" + }, + { + "name": "consideration", + "type": "ConsiderationItem[]" + }, + { + "name": "offertest", + "type": "OfferItem[]" + }, + { + "name": "orderType", + "type": "uint8" + }, + { + "name": "startTime", + "type": "uint256" + }, + { + "name": "endTime", + "type": "uint256" + }, + { + "name": "zoneHash", + "type": "bytes32" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "conduitKey", + "type": "bytes32" + }, + { + "name": "counter", + "type": "uint256" + } + ], + + }, + "primaryType": "OrderComponents", + "domain": { + "name": "Seaport", + "version": "1.1", + "chainId": "137", + "verifyingContract": "0x00000000006c3852cbEf3e08E8dF289169EdE581" + }, + "message": { + "offerer": "0x1fB4b0D6EB80142a6d4893D20d541b235c314f0A", + "offer": [ + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "900000000000000", + "endAmount": "900000000000000" + }, + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "900000000000000", + "endAmount": "900000000000000" + } + ], + "offertest": [ + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "900000000000000", + "endAmount": "900000000000000" + }, + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "900000000000000", + "endAmount": "900000000000000" + } + ], + "consideration": [ + { + "itemType": "2", + "token": "0xa9a6A3626993D487d2Dbda3173cf58cA1a9D9e9f", + "identifierOrCriteria": "59091204723763704856388986543321552591754523831551465717007213448841304074849", + "startAmount": "1", + "endAmount": "1", + "recipient": "0x1fB4b0D6EB80142a6d4893D20d541b235c314f0A" + }, + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "22500000000000", + "endAmount": "22500000000000", + "recipient": "0x0000a26b00c1F0DF003000390027140000fAa719" + } + ], + "startTime": "1668033203", + "endTime": "1668292398", + "orderType": "0", + "zone": "0x0000000000000000000000000000000000000000", + "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "24446860302761739304752683030156737591518664810215442929813510023260621276899", + "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000", + "totalOriginalConsiderationItems": "2", + "counter": "0" + } +} diff --git a/web3sTests/Client/EthereumClientTests.swift b/web3sTests/Client/EthereumClientTests.swift index f857e5a4..0f86b27b 100644 --- a/web3sTests/Client/EthereumClientTests.swift +++ b/web3sTests/Client/EthereumClientTests.swift @@ -81,7 +81,7 @@ class EthereumClientTests: XCTestCase { func testNetVersion() async { do { let network = try await client?.net_version() - XCTAssertEqual(network, EthereumNetwork.ropsten, "Network incorrect") + XCTAssertEqual(network, EthereumNetwork.goerli, "Network incorrect") } catch { XCTFail("Expected network but failed \(error).") } @@ -116,7 +116,7 @@ class EthereumClientTests: XCTestCase { func testEthSendRawTransaction() async { do { - let tx = EthereumTransaction(from: nil, to: "0x3c1bd6b420448cf16a389c8b0115ccb3660bb854", value: BigUInt(1600000), data: nil, nonce: 2, gasPrice: BigUInt(4000000), gasLimit: BigUInt(500000), chainId: EthereumNetwork.ropsten.intValue) + let tx = EthereumTransaction(from: nil, to: "0x3c1bd6b420448cf16a389c8b0115ccb3660bb854", value: BigUInt(1600000), data: nil, nonce: 2, gasPrice: BigUInt(4000000), gasLimit: BigUInt(500000), chainId: EthereumNetwork.goerli.intValue) let txHash = try await client?.eth_sendRawTransaction(tx, withAccount: account!) XCTAssertNotNil(txHash, "No tx hash, ensure key is valid in TestConfig.swift") @@ -127,7 +127,7 @@ class EthereumClientTests: XCTestCase { func testEthGetTransactionReceipt() async { do { - let txHash = "0xc51002441dc669ad03697fd500a7096c054b1eb2ce094821e68831a3666fc878" + let txHash = "0x706bbe6f2593235942b8e76c2f37af3824d47a64caf65f7ae5e0c5ee1e886132" let receipt = try await client?.eth_getTransactionReceipt(txHash: txHash) XCTAssertNotNil(receipt, "Transaction receipt not available") } catch { @@ -137,7 +137,7 @@ class EthereumClientTests: XCTestCase { func testEthCall() async { do { - let tx = EthereumTransaction(from: nil, to: "0x3c1bd6b420448cf16a389c8b0115ccb3660bb854", value: BigUInt(1800000), data: nil, nonce: 2, gasPrice: BigUInt(400000), gasLimit: BigUInt(50000), chainId: EthereumNetwork.ropsten.intValue) + let tx = EthereumTransaction(from: nil, to: "0x3c1bd6b420448cf16a389c8b0115ccb3660bb854", value: BigUInt(1800000), data: nil, nonce: 2, gasPrice: BigUInt(400000), gasLimit: BigUInt(50000), chainId: EthereumNetwork.goerli.intValue) let txHash = try await client?.eth_call(tx, block: .Latest) XCTAssertNotNil(txHash, "Transaction hash not available") } catch { @@ -156,8 +156,8 @@ class EthereumClientTests: XCTestCase { func testOrTopicsEthGetLogs() async { do { - let logs = try await client?.eth_getLogs(addresses: nil, orTopics: [["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", "0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65"], ["0x000000000000000000000000655ef694b98e55977a93259cb3b708560869a8f3"]], fromBlock: .Number(6540313), toBlock: .Number(6540397)) - XCTAssertEqual(logs?.count, 2) + let logs = try await client?.eth_getLogs(addresses: nil, orTopics: [["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"], ["0x000000000000000000000000377f56d089c7e0b7e18865e6e3f0c14feb55bf36"]], fromBlock: .Number(8012709), toBlock: .Number(8012709)) + XCTAssertEqual(logs?.count, 15) XCTAssertNotNil(logs, "Logs not available") } catch { XCTFail("Expected logs but failed \(error).") @@ -167,7 +167,7 @@ class EthereumClientTests: XCTestCase { func testGivenGenesisBlock_ThenReturnsByNumber() async { do { let block = try await client?.eth_getBlockByNumber(.Number(0)) - XCTAssertEqual(block?.timestamp.timeIntervalSince1970, 0) + XCTAssertEqual(block?.timestamp.timeIntervalSince1970, 1548854791) XCTAssertEqual(block?.transactions.count, 0) XCTAssertEqual(block?.number, .Number(0)) } catch { @@ -186,11 +186,11 @@ class EthereumClientTests: XCTestCase { func testGivenExistingBlock_ThenGetsBlockByNumber() async { do { - let block = try await client?.eth_getBlockByNumber(.Number(3415757)) - XCTAssertEqual(block?.number, .Number(3415757)) - XCTAssertEqual(block?.timestamp.timeIntervalSince1970, 1528711895) - XCTAssertEqual(block?.transactions.count, 40) - XCTAssertEqual(block?.transactions.first, "0x387867d052b3f89fb87937572891118aa704c1ba604c157bbd9c5a07f3a7e5cd") + let block = try await client?.eth_getBlockByNumber(.Number(8006312)) + XCTAssertEqual(block?.number, .Number(8006312)) + XCTAssertEqual(block?.timestamp.timeIntervalSince1970, 1669224864) + XCTAssertEqual(block?.transactions.count, 53) + XCTAssertEqual(block?.transactions.first, "0xd6b8256322a91ea138afa16181c61040381ca713c56ca7046dcbbd832ed71386") } catch { XCTFail("Expected block but failed \(error).") } @@ -207,15 +207,15 @@ class EthereumClientTests: XCTestCase { func testGivenMinedTransactionHash_ThenGetsTransactionByHash() async { do { - let transaction = try await client?.eth_getTransaction(byHash: "0x014726c783ab2fd6828a9ca556850bccfc66f70926f411274eaf886385c704af") - XCTAssertEqual(transaction?.from?.value, "0xbbf5029fd710d227630c8b7d338051b8e76d50b3") - XCTAssertEqual(transaction?.to.value, "0x37f13b5ffcc285d2452c0556724afb22e58b6bbe") - XCTAssertEqual(transaction?.gas, "30400") - XCTAssertEqual(transaction?.gasPrice, BigUInt(hex: "0x9184e72a000")) - XCTAssertEqual(transaction?.nonce, 973253) - XCTAssertEqual(transaction?.value, BigUInt(hex: "0x56bc75e2d63100000")) - XCTAssertEqual(transaction?.blockNumber, EthereumBlock.Number(3439303)) - XCTAssertEqual(transaction?.hash?.web3.hexString, "0x014726c783ab2fd6828a9ca556850bccfc66f70926f411274eaf886385c704af") + let transaction = try await client?.eth_getTransaction(byHash: "0x706bbe6f2593235942b8e76c2f37af3824d47a64caf65f7ae5e0c5ee1e886132") + XCTAssertEqual(transaction?.from?.value, "0x64d0ea4fc60f27e74f1a70aa6f39d403bbe56793") + XCTAssertEqual(transaction?.to.value, "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984") + XCTAssertEqual(transaction?.gas, "85773") + XCTAssertEqual(transaction?.gasPrice, BigUInt(14300000000)) + XCTAssertEqual(transaction?.nonce, 23) + XCTAssertEqual(transaction?.value, 0) + XCTAssertEqual(transaction?.blockNumber, EthereumBlock.Number(8006312)) + XCTAssertEqual(transaction?.hash?.web3.hexString, "0x706bbe6f2593235942b8e76c2f37af3824d47a64caf65f7ae5e0c5ee1e886132") } catch { XCTFail("Expected transaction but failed \(error).") } @@ -234,15 +234,15 @@ class EthereumClientTests: XCTestCase { func testGivenNoFilters_WhenMatchingSingleTransferEvents_AllEventsReturned() async { do { - let to = try! ABIEncoder.encode(EthereumAddress("0x3C1Bd6B420448Cf16A389C8b0115CCB3660bB854")) + let to = try! ABIEncoder.encode(EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41")) let eventsResult = try await client?.getEvents(addresses: nil, topics: [try! ERC20Events.Transfer.signature(), nil, to.hexString, nil], fromBlock: .Earliest, toBlock: .Latest, eventTypes: [ERC20Events.Transfer.self]) - XCTAssertEqual(eventsResult?.events.count, 2) - XCTAssertEqual(eventsResult?.logs.count, 0) + XCTAssertEqual(eventsResult?.events.count, 3) + XCTAssertEqual(eventsResult?.logs.count, 4) } catch { XCTFail("Expected events but failed \(error).") } @@ -250,15 +250,15 @@ class EthereumClientTests: XCTestCase { func testGivenNoFilters_WhenMatchingMultipleTransferEvents_BothEventsReturned() async { do { - let to = try! ABIEncoder.encode(EthereumAddress("0x3C1Bd6B420448Cf16A389C8b0115CCB3660bB854")) + let to = try! ABIEncoder.encode(EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41")) let eventsResult = try await client?.getEvents(addresses: nil, topics: [try! ERC20Events.Transfer.signature(), nil, to.hexString, nil], fromBlock: .Earliest, toBlock: .Latest, eventTypes: [ERC20Events.Transfer.self, TransferMatchingSignatureEvent.self]) - XCTAssertEqual(eventsResult?.events.count, 4) - XCTAssertEqual(eventsResult?.logs.count, 0) + XCTAssertEqual(eventsResult?.events.count, 6) + XCTAssertEqual(eventsResult?.logs.count, 8) } catch { XCTFail("Expected events but failed \(error).") } @@ -266,9 +266,9 @@ class EthereumClientTests: XCTestCase { func testGivenContractFilter_WhenMatchingSingleTransferEvents_OnlyMatchingSourceEventReturned() async { do { - let to = try! ABIEncoder.encodeRaw("0x3C1Bd6B420448Cf16A389C8b0115CCB3660bB854", forType: ABIRawType.FixedAddress) + let to = try! ABIEncoder.encodeRaw("0x162142f0508F557C02bEB7C473682D7C91Bcef41", forType: ABIRawType.FixedAddress) let filters = [ - EventFilter(type: ERC20Events.Transfer.self, allowedSenders: ["0xdb0040451f373949a4be60dcd7b6b8d6e42658b6"]) + EventFilter(type: ERC20Events.Transfer.self, allowedSenders: ["0x0C45dd4A3DEcb146F3ae0d82b1151AdEEEfA73cD"]) ] let eventsResult = try await client?.getEvents(addresses: nil, @@ -277,7 +277,7 @@ class EthereumClientTests: XCTestCase { toBlock: .Latest, matching: filters) XCTAssertEqual(eventsResult?.events.count, 1) - XCTAssertEqual(eventsResult?.logs.count, 1) + XCTAssertEqual(eventsResult?.logs.count, 6) } catch { XCTFail("Expected events but failed \(error).") } @@ -285,10 +285,10 @@ class EthereumClientTests: XCTestCase { func testGivenContractFilter_WhenMatchingMultipleTransferEvents_OnlyMatchingSourceEventsReturned() async { do { - let to = try! ABIEncoder.encode(EthereumAddress("0x3C1Bd6B420448Cf16A389C8b0115CCB3660bB854")) + let to = try! ABIEncoder.encode(EthereumAddress("0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56793")) let filters = [ - EventFilter(type: ERC20Events.Transfer.self, allowedSenders: ["0xdb0040451f373949a4be60dcd7b6b8d6e42658b6"]), - EventFilter(type: TransferMatchingSignatureEvent.self, allowedSenders: ["0xdb0040451f373949a4be60dcd7b6b8d6e42658b6"]) + EventFilter(type: ERC20Events.Transfer.self, allowedSenders: ["0x0C45dd4A3DEcb146F3ae0d82b1151AdEEEfA73cD"]), + EventFilter(type: TransferMatchingSignatureEvent.self, allowedSenders: ["0x162142f0508F557C02bEB7C473682D7C91Bcef41"]) ] let eventsResult = try await client?.getEvents(addresses: nil, @@ -296,8 +296,8 @@ class EthereumClientTests: XCTestCase { fromBlock: .Earliest, toBlock: .Latest, matching: filters) - XCTAssertEqual(eventsResult?.events.count, 2) - XCTAssertEqual(eventsResult?.logs.count, 2) + XCTAssertEqual(eventsResult?.events.count, 1) + XCTAssertEqual(eventsResult?.logs.count, 27) } catch { XCTFail("Expected events but failed \(error).") } @@ -305,10 +305,10 @@ class EthereumClientTests: XCTestCase { func test_GivenDynamicArrayResponse_ThenCallReceivesData() async { do { - let function = GetGuardians(wallet: "0x2A6295C34b4136F2C3c1445c6A0338D784fe0ddd") + let function = GetDynamicArray() - let response = try await function.call(withClient: client!, responseType: GetGuardians.Response.self) - XCTAssertEqual(response.guardians, ["0x44fe11c90d2bcbc8267a0e56d55235ddc2b96c4f"]) + let response = try await function.call(withClient: client!, responseType: GetDynamicArray.Response.self) + XCTAssertEqual(response.addresses, ["0x83f7338d17A85B0a0A8A1AE7Edead4dA571566E0"]) } catch { XCTFail("Expected response but failed \(error).") } @@ -350,8 +350,8 @@ class EthereumClientTests: XCTestCase { func test_ValueWithLeadingZero_EstimatesGas() async { do { - let tx = EthereumTransaction(from: EthereumAddress("0xD18dE36e6FB4a5A069f673723Fab71cc00C6CE5F"), - to: EthereumAddress("0x2A6295C34b4136F2C3c1445c6A0338D784fe0ddd"), + let tx = EthereumTransaction(from: EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41"), + to: EthereumAddress("0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56793"), value: BigUInt(5000000000), data: Data(), gasPrice: BigUInt(0), @@ -364,28 +364,24 @@ class EthereumClientTests: XCTestCase { } } -struct GetGuardians: ABIFunction { - static let name = "getGuardians" - let contract: EthereumAddress = "0x25BD64224b7534f7B9e3E16dd10b6dED1A412b90" - let from: EthereumAddress? = "0x25BD64224b7534f7B9e3E16dd10b6dED1A412b90" +struct GetDynamicArray: ABIFunction { + static let name = "getDynamicArray" + let contract: EthereumAddress = "0xD5017917007D588dD5f9Dd5d260a0d72E7C3Ee25" + let from: EthereumAddress? = "0xD5017917007D588dD5f9Dd5d260a0d72E7C3Ee25" let gasPrice: BigUInt? = nil let gasLimit: BigUInt? = nil struct Response: ABIResponse { static var types: [ABIType.Type] = [ABIArray.self] - let guardians: [EthereumAddress] + let addresses: [EthereumAddress] init?(values: [ABIDecoder.DecodedValue]) throws { - self.guardians = try values[0].decodedArray() + self.addresses = try values[0].decodedArray() } } - let wallet: EthereumAddress - func encode(to encoder: ABIFunctionEncoder) throws { - try encoder.encode(wallet) - } } @@ -414,30 +410,8 @@ struct TransferToken: ABIFunction { struct InvalidMethodA: ABIFunction { static let name = "invalidMethodCallBoolResponse" - let contract: EthereumAddress = "0xed0439eacf4c4965ae4613d77a5c2efe10e5f183" - let from: EthereumAddress? = "0xed0439eacf4c4965ae4613d77a5c2efe10e5f183" - let gasPrice: BigUInt? = nil - let gasLimit: BigUInt? = nil - - let param: EthereumAddress - - struct BoolResponse: ABIResponse { - static var types: [ABIType.Type] = [Bool.self] - let value: Bool - - init?(values: [ABIDecoder.DecodedValue]) throws { - self.value = try values[0].decoded() - } - } - - func encode(to encoder: ABIFunctionEncoder) throws { - } -} - -struct InvalidMethodB: ABIFunction { - static let name = "invalidMethodCallBoolResponse" - let contract: EthereumAddress = "0xC011A72400E58ecD99Ee497CF89E3775d4bd732F" - let from: EthereumAddress? = "0xC011A72400E58ecD99Ee497CF89E3775d4bd732F" + let contract: EthereumAddress = "0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca" + let from: EthereumAddress? = "0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca" let gasPrice: BigUInt? = nil let gasLimit: BigUInt? = nil diff --git a/web3sTests/Contract/ABIEventTests.swift b/web3sTests/Contract/ABIEventTests.swift index c0cc10ad..826d2972 100644 --- a/web3sTests/Contract/ABIEventTests.swift +++ b/web3sTests/Contract/ABIEventTests.swift @@ -14,24 +14,24 @@ class ABIEventTests: XCTestCase { super.setUp() client = EthereumHttpClient(url: URL(string: TestConfig.clientUrl)!) } - + func test_givenEventWithData4_ItParsesCorrectly() async { do { - let encodedAddress = (try? ABIEncoder.encode(EthereumAddress("0x3B6Def16666a23905DD29071d13E7a9db08240E2")).bytes) ?? [] + let encodedAddress = (try? ABIEncoder.encode(EthereumAddress("0x787411394Ccb38483a6F303FDee075f3EA67D65F")).bytes) ?? [] let eventsResult = try await client.getEvents(addresses: nil, - topics: [try? EnabledStaticCall.signature(), String(hexFromBytes: encodedAddress), nil], - fromBlock: .Number(8386245), - toBlock: .Number(8386245), - eventTypes: [EnabledStaticCall.self]) - - let eventFirst = eventsResult.events.first as? EnabledStaticCall - XCTAssertEqual(eventFirst?.module, EthereumAddress("0x3b6def16666a23905dd29071d13e7a9db08240e2")) - XCTAssertEqual(eventFirst?.method, Data(hex: "0x20c13b0b")!) - - let eventLast = eventsResult.events.last as? EnabledStaticCall - XCTAssertEqual(eventLast?.module, EthereumAddress("0x3b6def16666a23905dd29071d13e7a9db08240e2")) - XCTAssertEqual(eventLast?.method, Data(hex: "0x1626ba7e")!) + topics: [try? AddressAndData4Event.signature(), String(hexFromBytes: encodedAddress), nil], + fromBlock: .Number(8017312 ), + toBlock: .Number(8017312 ), + eventTypes: [AddressAndData4Event.self]) + + let eventFirst = eventsResult.events.first as? AddressAndData4Event + XCTAssertEqual(eventFirst?.address, EthereumAddress("0x787411394Ccb38483a6F303FDee075f3EA67D65F")) + XCTAssertEqual(eventFirst?.data, Data(hex: "0x05f50234")!) + + let eventLast = eventsResult.events.last as? AddressAndData4Event + XCTAssertEqual(eventLast?.address, EthereumAddress("0x787411394Ccb38483a6F303FDee075f3EA67D65F")) + XCTAssertEqual(eventLast?.data, Data(hex: "0xdeadbeef")!) } catch { XCTFail("Expected events but failed \(error).") } @@ -40,17 +40,17 @@ class ABIEventTests: XCTestCase { func test_givenEventWithData32_ItParsesCorrectly() async { do { let eventsResult = try await client.getEvents(addresses: nil, - topics: [try? UpgraderRegistered.signature()], + topics: [try? AddressAndData32Event.signature()], fromBlock: .Number( - 8110676 ), + 8017318 ), toBlock: .Number( - 8110676 ), - eventTypes: [UpgraderRegistered.self]) + 8017318 ), + eventTypes: [AddressAndData32Event.self]) XCTAssertEqual(eventsResult.events.count, 1) - let event = eventsResult.events.first as? UpgraderRegistered - XCTAssertEqual(event?.upgrader, EthereumAddress("0x17b11d842ae09eddedf5592f8271a7d07f6931e7")) - XCTAssertEqual(event?.name, Data(hex: "0x307864323664616666635f307833373731376663310000000000000000000000")!) + let event = eventsResult.events.first as? AddressAndData32Event + XCTAssertEqual(event?.address, EthereumAddress("0x787411394Ccb38483a6F303FDee075f3EA67D65F")) + XCTAssertEqual(event?.data, Data(hex: "05f5023424311e0f21827eba3fbe0dc4c3810a9d49fae3a16bf2b9d12c33d576")!) } catch { XCTFail("Expected events but failed \(error).") } @@ -64,39 +64,39 @@ class ABIEventWebSocketTests: ABIEventTests { } } -struct EnabledStaticCall: ABIEvent { - static let name = "EnabledStaticCall" +struct AddressAndData4Event: ABIEvent { + static let name = "AddressAndData4Event" static let types: [ABIType.Type] = [EthereumAddress.self, Data4.self] static let typesIndexed = [true, true] let log: EthereumLog - let module: EthereumAddress - let method: Data + let address: EthereumAddress + let data: Data init?(topics: [ABIDecoder.DecodedValue], data: [ABIDecoder.DecodedValue], log: EthereumLog) throws { - try EnabledStaticCall.checkParameters(topics, data) + try AddressAndData4Event.checkParameters(topics, data) self.log = log - self.module = try topics[0].decoded() - self.method = try topics[1].decoded() + self.address = try topics[0].decoded() + self.data = try topics[1].decoded() } } -struct UpgraderRegistered: ABIEvent { - static let name = "UpgraderRegistered" +struct AddressAndData32Event: ABIEvent { + static let name = "AddressAndData32Event" static let types: [ABIType.Type] = [EthereumAddress.self, Data32.self] static let typesIndexed = [true, false] let log: EthereumLog - let upgrader: EthereumAddress - let name: Data + let address: EthereumAddress + let data: Data init?(topics: [ABIDecoder.DecodedValue], data: [ABIDecoder.DecodedValue], log: EthereumLog) throws { - try UpgraderRegistered.checkParameters(topics, data) + try AddressAndData32Event.checkParameters(topics, data) self.log = log - self.upgrader = try topics[0].decoded() - self.name = try data[0].decoded() + self.address = try topics[0].decoded() + self.data = try data[0].decoded() } } diff --git a/web3sTests/ENS/ENSOffchainTests.swift b/web3sTests/ENS/ENSOffchainTests.swift index b0a67b09..0f1e1ada 100644 --- a/web3sTests/ENS/ENSOffchainTests.swift +++ b/web3sTests/ENS/ENSOffchainTests.swift @@ -27,7 +27,7 @@ class ENSOffchainTests: XCTestCase { } - func testGivenRopstenRegistry_WhenResolvingOffchainENS_ResolvesCorrectly() async { + func testGivenRegistry_WhenResolvingOffchainENS_ResolvesCorrectly() async { do { let nameService = EthereumNameService(client: client!) let ens = try await nameService.resolve( @@ -40,7 +40,7 @@ class ENSOffchainTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenResolvingOffchainENSAndDisabled_ThenFails() async { + func testGivenRegistry_WhenResolvingOffchainENSAndDisabled_ThenFails() async { do { let nameService = EthereumNameService(client: client!) _ = try await nameService.resolve( @@ -53,20 +53,20 @@ class ENSOffchainTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenResolvingNonOffchainENS_ThenResolves() async { + func testGivenRegistry_WhenResolvingNonOffchainENS_ThenResolves() async { do { let nameService = EthereumNameService(client: client!) let ens = try await nameService.resolve( ens: "resolver.eth", mode: .allowOffchainLookup ) - XCTAssertEqual(EthereumAddress("0x42d63ae25990889e35f215bc95884039ba354115"), ens) + XCTAssertEqual(EthereumAddress("0xe264d5bb84ba3b8061adc38d3d76e6674ab91852"), ens) } catch { XCTFail("Expected ens but failed \(error).") } } - func testGivenRopstenRegistry_WhenWildcardSupported_AndAddressHasSubdomain_ThenResolvesCorrectly() async { + func testGivenRegistry_WhenWildcardSupported_AndAddressHasSubdomain_ThenResolvesCorrectly() async { do { let nameService = EthereumNameService(client: client!) @@ -81,7 +81,7 @@ class ENSOffchainTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenWildcardNOTSupported_AndAddressHasSubdomain_ThenFailsResolving() async { + func testGivenRegistry_WhenWildcardNOTSupported_AndAddressHasSubdomain_ThenFailsResolving() async { do { let nameService = EthereumNameService(client: client!) @@ -96,7 +96,7 @@ class ENSOffchainTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenTwoRequestsWithAndWithoutSubdomain_ThenBothResolveCorrectly() async { + func testGivenRegistry_WhenTwoRequestsWithAndWithoutSubdomain_ThenBothResolveCorrectly() async { let nameService = EthereumNameService(client: client!) do { @@ -104,7 +104,7 @@ class ENSOffchainTests: XCTestCase { ens: "resolver.eth", mode: .allowOffchainLookup ) - XCTAssertEqual(EthereumAddress("0x42d63ae25990889e35f215bc95884039ba354115"), ens) + XCTAssertEqual(EthereumAddress("0xe264d5bb84ba3b8061adc38d3d76e6674ab91852"), ens) } catch { XCTFail("Expected ens but failed \(error).") } @@ -120,7 +120,7 @@ class ENSOffchainTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenTwoRequestsWithoutAndWithSubdomain_ThenBothResolveCorrectly() async { + func testGivenRegistry_WhenTwoRequestsWithoutAndWithSubdomain_ThenBothResolveCorrectly() async { let nameService = EthereumNameService(client: client!) do { @@ -139,7 +139,7 @@ class ENSOffchainTests: XCTestCase { ens: "resolver.eth", mode: .allowOffchainLookup ) - XCTAssertEqual(EthereumAddress("0x42d63ae25990889e35f215bc95884039ba354115"), ens) + XCTAssertEqual(EthereumAddress("0xe264d5bb84ba3b8061adc38d3d76e6674ab91852"), ens) } catch { XCTFail("Expected ens but failed \(error).") } diff --git a/web3sTests/ENS/ENSTests.swift b/web3sTests/ENS/ENSTests.swift index 31ac6efc..85acf5f1 100644 --- a/web3sTests/ENS/ENSTests.swift +++ b/web3sTests/ENS/ENSTests.swift @@ -21,9 +21,9 @@ class ENSTests: XCTestCase { XCTAssertEqual(nameHash, "0x3e58ef7a2e196baf0b9d36a65cc590ac9edafb3395b7cdeb8f39206049b4534c") } - func testGivenRopstenRegistry_WhenExistingDomainName_ResolvesOwnerAddressCorrectly() async { + func testGivenRegistry_WhenExistingDomainName_ResolvesOwnerAddressCorrectly() async { do { - let function = ENSContracts.ENSRegistryFunctions.owner(contract: ENSContracts.RegistryAddress, _node: EthereumNameService.nameHash(name: "test").web3.hexData ?? Data()) + let function = ENSContracts.ENSRegistryFunctions.owner(contract: ENSContracts.RegistryAddress, _node: EthereumNameService.nameHash(name: "eth").web3.hexData ?? Data()) let tx = try function.transaction() @@ -34,69 +34,69 @@ class ENSTests: XCTestCase { } let owner = String(dataStr[dataStr.index(dataStr.endIndex, offsetBy: -40)...]) - XCTAssertEqual(owner.web3.noHexPrefix, "09b5bd82f3351a4c8437fc6d7772a9e6cd5d25a1") + XCTAssertEqual(owner.web3.noHexPrefix, "57f1887a8bf19b14fc0df6fd9b2acc9af147ea85") } catch { XCTFail("Expected dataStr but failed \(error).") } } - func testGivenRopstenRegistry_WhenExistingAddress_ThenResolvesCorrectly() async { + func testGivenRegistry_WhenExistingAddress_ThenResolvesCorrectly() async { do { let nameService = EthereumNameService(client: client!) let ens = try await nameService.resolve( - address: "0xb0b874220ff95d62a676f58d186c832b3e6529c8", + address: "0x162142f0508F557C02bEB7C473682D7C91Bcef41", mode: .onchain ) - XCTAssertEqual("julien.argent.test", ens) + XCTAssertEqual("darhmike.eth", ens) } catch { XCTFail("Expected ens but failed \(error).") } } - func testGivenRopstenRegistry_WhenNotExistingAddress_ThenFailsCorrectly() async { + func testGivenRegistry_WhenExistingAddressHasSubdomain_ThenResolvesCorrectly() async { do { let nameService = EthereumNameService(client: client!) - _ = try await nameService.resolve( - address: "0xb0b874220ff95d62a676f58d186c832b3e6529c9", + let ens = try await nameService.resolve( + address: "0xB1037eB3268f942715c999EA6697ce33Febd70A7", mode: .onchain ) - XCTFail("Expected to throw while awaiting, but succeeded") + XCTAssertEqual("subdomain.darhmike.eth", ens) } catch { - XCTAssertEqual(error as? EthereumNameServiceError, .ensUnknown) + XCTFail("Expected ens but failed \(error).") } } - func testGivenCustomRegistry_WhenNotExistingAddress_ThenResolvesFailsCorrectly() async { + func testGivenRegistry_WhenAddressHasSubdomain_AndReverseRecordNotSet_ThenDoesNotResolveCorrectly() async { do { - let nameService = EthereumNameService(client: client!, registryAddress: "0x7D7C04B7A05539a92541105806e0971E45969F85") - _ = try await nameService.resolve( - address: "0xb0b874220ff95d62a676f58d186c832b3e6529c9", + let nameService = EthereumNameService(client: client!) + let ens = try await nameService.resolve( + address: "0x787411394Ccb38483a6F303FDee075f3EA67D65F", mode: .onchain ) - XCTFail("Expected to throw while awaiting, but succeeded") + XCTFail("Resolved but expected failure") } catch { XCTAssertEqual(error as? EthereumNameServiceError, .ensUnknown) } } - func testGivenRopstenRegistry_WhenExistingENS_ThenResolvesAddressCorrectly() async { + func testGivenRegistry_WhenAddressHasSubdomain_AndReverseRecordNotSet_ThenResolvesENS() async { do { let nameService = EthereumNameService(client: client!) - let ens = try await nameService.resolve( - ens: "julien.argent.test", + let address = try await nameService.resolve( + ens: "another.darhmike.eth", mode: .onchain ) - XCTAssertEqual(EthereumAddress("0xb0b874220ff95d62a676f58d186c832b3e6529c8"), ens) + XCTAssertEqual(address, "0x787411394Ccb38483a6F303FDee075f3EA67D65F") } catch { - XCTFail("Expected ens but failed \(error).") + XCTAssertEqual(error as? EthereumNameServiceError, .ensUnknown) } } - func testGivenRopstenRegistry_WhenInvalidENS_ThenErrorsRequest() async { + func testGivenRegistry_WhenNotExistingAddress_ThenFailsCorrectly() async { do { let nameService = EthereumNameService(client: client!) _ = try await nameService.resolve( - ens: "**somegarbage)_!!", + address: "0xb0b874220ff95d62a676f58d186c832b3e6529c9", mode: .onchain ) XCTFail("Expected to throw while awaiting, but succeeded") @@ -105,9 +105,22 @@ class ENSTests: XCTestCase { } } - func testGivenCustomRegistry_WhenInvalidENS_ThenErrorsRequest() async { + func testGivenRegistry_WhenExistingENS_ThenResolvesAddressCorrectly() async { do { - let nameService = EthereumNameService(client: client!, registryAddress: "0x7D7C04B7A05539a92541105806e0971E45969F85") + let nameService = EthereumNameService(client: client!) + let ens = try await nameService.resolve( + ens: "darhmike.eth", + mode: .onchain + ) + XCTAssertEqual(EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41"), ens) + } catch { + XCTFail("Expected ens but failed \(error).") + } + } + + func testGivenRegistry_WhenInvalidENS_ThenErrorsRequest() async { + do { + let nameService = EthereumNameService(client: client!) _ = try await nameService.resolve( ens: "**somegarbage)_!!", mode: .onchain @@ -118,16 +131,16 @@ class ENSTests: XCTestCase { } } - func testGivenRopstenRegistry_ThenResolvesMultipleAddressesInOneCall() async { + func testGivenRegistry_ThenResolvesMultipleAddressesWithMultiCall() async { do { let nameService = EthereumNameService(client: client!) var results: [EthereumNameService.ResolveOutput]? let resolutions = try await nameService.resolve(addresses: [ - "0xb0b874220ff95d62a676f58d186c832b3e6529c8", + "0x162142f0508F557C02bEB7C473682D7C91Bcef41", "0x09b5bd82f3351a4c8437fc6d7772a9e6cd5d25a1", - "0x7e691d7ffb007abe91d8a24d7f22fc74307dab06" + "0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56793" ]) results = resolutions.map { $0.output } @@ -135,24 +148,107 @@ class ENSTests: XCTestCase { XCTAssertEqual( results, [ - .resolved("julien.argent.test"), + .resolved("darhmike.eth"), .couldNotBeResolved(.ensUnknown), - .resolved("davidtests.argent.xyz") + .resolved("darthmike.eth") + ] + ) } catch { + XCTFail("Expected resolutions but failed \(error).") + } + } + + func testGivenRegistry_ThenResolvesSingleAddressWithMultiCall() async { + do { + let nameService = EthereumNameService(client: client!) + + var results: [EthereumNameService.ResolveOutput]? + + let resolutions = try await nameService.resolve(addresses: [ + "0x162142f0508F557C02bEB7C473682D7C91Bcef41" + ]) + + results = resolutions.map { $0.output } + + XCTAssertEqual( + results, + [ + .resolved("darhmike.eth") + ] + ) } catch { + XCTFail("Expected resolutions but failed \(error).") + } + } + + func testGivenRegistry_WhenAddressHasSubdomain_ThenResolvesSingleAddressWithMultiCall() async { + do { + let nameService = EthereumNameService(client: client!) + + var results: [EthereumNameService.ResolveOutput]? + + let resolutions = try await nameService.resolve(addresses: [ + "0xB1037eB3268f942715c999EA6697ce33Febd70A7" + ]) + + results = resolutions.map { $0.output } + + XCTAssertEqual( + results, + [ + .resolved("subdomain.darhmike.eth") ] ) } catch { XCTFail("Expected resolutions but failed \(error).") } } - func testGivenRopstenRegistry_ThenResolvesMultipleNamesInOneCall() async { + func testGivenRegistry_WhenAddressHasSubdomain_AndReverseRecordNotSet_ThenDoesNotResolveSingleAddressWithMultiCall() async { + do { + let nameService = EthereumNameService(client: client!) + + var results: [EthereumNameService.ResolveOutput]? + + let resolutions = try await nameService.resolve(addresses: [ + "0x787411394Ccb38483a6F303FDee075f3EA67D65F" + ]) + + results = resolutions.map { $0.output } + + XCTAssertEqual( + results, + [ + .couldNotBeResolved(.ensUnknown) + ] + ) } catch { + XCTFail("Expected resolutions but failed \(error).") + } + } + + func testGivenRegistry_WhenAddressHasSubdomain_AndReverseRecordNotSet_ThenResolvesENSWithMultiCall() async { + do { + let nameService = EthereumNameService(client: client!) + let results = try await nameService.resolve( + names: ["another.darhmike.eth"] + ) + XCTAssertEqual( + results.map(\.output), + [ + .resolved("0x787411394Ccb38483a6F303FDee075f3EA67D65F") + ] + ) + } catch { + XCTAssertEqual(error as? EthereumNameServiceError, .ensUnknown) + } + } + + func testGivenRegistry_ThenResolvesMultipleNamesWithMultiCall() async { do { let nameService = EthereumNameService(client: client!) var results: [EthereumNameService.ResolveOutput]? let resolutions = try await nameService.resolve(names: [ - "julien.argent.test", - "davidtests.argent.xyz", + "darhmike.eth", + "darthmike.eth", "somefakeens.argent.xyz" ]) @@ -161,8 +257,8 @@ class ENSTests: XCTestCase { XCTAssertEqual( results, [ - .resolved("0xb0b874220ff95d62a676f58d186c832b3e6529c8"), - .resolved("0x7e691d7ffb007abe91d8a24d7f22fc74307dab06"), + .resolved("0x162142f0508F557C02bEB7C473682D7C91Bcef41"), + .resolved("0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56793"), .couldNotBeResolved(.ensUnknown) ] ) @@ -171,7 +267,7 @@ class ENSTests: XCTestCase { } } - func testGivenRopstenRegistry_WhenWildcardSupported_AndAddressHasSubdomain_ThenResolvesExampleCorrectly() async { + func testGivenRegistry_WhenWildcardSupported_AndAddressHasSubdomain_ThenResolvesExampleCorrectly() async { do { let nameService = EthereumNameService(client: client!) @@ -180,13 +276,13 @@ class ENSTests: XCTestCase { mode: .onchain ) - XCTAssertEqual(address, EthereumAddress("0x4FaBE0A3a4DDd9968A7b4565184Ad0eFA7BE5411")) + XCTAssertEqual(address, EthereumAddress("0x4b711a377b1b3534749fbe5e59bcf7f94d92ea98")) } catch { XCTFail("Expected ens but failed \(error).") } } - func testGivenRopstenRegistry_WhenWildcardNOTSupported_AndAddressHasSubdomain_ThenFailsResolving() async { + func testGivenRegistry_WhenWildcardNOTSupported_AndAddressHasSubdomain_ThenFailsResolving() async { do { let nameService = EthereumNameService(client: client!) diff --git a/web3sTests/ERC1271/ERC1271Tests.swift b/web3sTests/ERC1271/ERC1271Tests.swift index 9595c04e..a9969ca0 100644 --- a/web3sTests/ERC1271/ERC1271Tests.swift +++ b/web3sTests/ERC1271/ERC1271Tests.swift @@ -25,9 +25,9 @@ class ERC1271Tests: XCTestCase { func testSuccesfulVerificationWithMagicNumberContract() async { do { let isValid = try await erc1271.isValidSignature( - contract: EthereumAddress("0x2bD85c85666a29bD453918B20b9E5ef7603d9007"), - messageHash: "0xb7755e72da7aca68df7d5ed5a832d027b624d56dab707d2b5257bbfc1bc5d4fd".web3.hexData!, - signature: "0x468732fa8210c6f8481a288a668bd6f40745e67c9640f82f7415b44e7ba280e13b6fce01acaaa4ab2fe8620a179ca99960620a014fdf74d9cf828912811c1b821b".web3.hexData! + contract: EthereumAddress("0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca"), + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0x44632b4bebf8a8817899aa90036285c884aa197c72da6ac11612a2ca59f1fcd76aa41ac92b961a4693b213513f5fdf1f509b7f52d439d1c09422af7eaa69f0d11c".web3.hexData! ) XCTAssertTrue(isValid) } catch { @@ -38,9 +38,9 @@ class ERC1271Tests: XCTestCase { func testSuccessfulVerificationWithBooleanContract() async { do { let isValid = try await erc1271.isValidSignature( - contract: EthereumAddress("0x2505E4d4A76EC941591828311159552A832681D5"), - messageHash: "0xb7755e72da7aca68df7d5ed5a832d027b624d56dab707d2b5257bbfc1bc5d4fd".web3.hexData!, - signature: "0x468732fa8210c6f8481a288a668bd6f40745e67c9640f82f7415b44e7ba280e13b6fce01acaaa4ab2fe8620a179ca99960620a014fdf74d9cf828912811c1b821b".web3.hexData! + contract: EthereumAddress("0xA05758Bb454c08f6cD7CECd81eFBAf5f0879B7d8"), + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0x44632b4bebf8a8817899aa90036285c884aa197c72da6ac11612a2ca59f1fcd76aa41ac92b961a4693b213513f5fdf1f509b7f52d439d1c09422af7eaa69f0d11c".web3.hexData! ) XCTAssertTrue(isValid) } catch { @@ -52,9 +52,9 @@ class ERC1271Tests: XCTestCase { do { // Here the signature and the hash matches, but the contract will say is invalid cause the signer is not the owner of the contract let isValid = try await erc1271.isValidSignature( - contract: EthereumAddress("0x2bD85c85666a29bD453918B20b9E5ef7603d9007"), - messageHash: "0x09bf2f6417d2bc487040194b78cbdd6b04f72ea12cf0014f83f4f228bed95ee4".web3.hexData!, - signature: "0xf85b9506180b11dc472278ff1e5fbb1e4b50baa3cadaec26b4b8179a55623f652a794c09b49227231f1144a62221453c854f09a986c1de1e19cdfff451e751b21c".web3.hexData! + contract: EthereumAddress("0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca"), + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0x8e2ba38942cd698e4a47fc5227c61b94c9458f9093daa051bb87f57ebfd929280181f9f375d28864d4d9c1d24a29e0a2142d721669f737731d738c02b3ab89981b".web3.hexData! ) XCTAssertFalse(isValid) } catch { @@ -64,9 +64,9 @@ class ERC1271Tests: XCTestCase { do { // Here the signature and the hash don't match let isValid = try await erc1271.isValidSignature( - contract: EthereumAddress("0x2bD85c85666a29bD453918B20b9E5ef7603d9007"), - messageHash: "0xb7755e72da7aca68df7d5ed5a832d027b624d56dab707d2b5257bbfc1bc5d4fd".web3.hexData!, - signature: "0xf85b9506180b11dc472278ff1e5fbb1e4b50baa3cadaec26b4b8179a55623f652a794c09b49227231f1144a62221453c854f09a986c1de1e19cdfff451e751b21c".web3.hexData! + contract: EthereumAddress("0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca"), + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0xe0c97bb5b8bc876636598132f0b4a250b94bb0d0b95dde49edbbacd1835c62ae301cc27f7117bf362973c64e100edee9c1c4a2ae52503c1a4cb621ec58e7f4521b".web3.hexData! ) XCTAssertFalse(isValid) } catch { @@ -79,8 +79,8 @@ class ERC1271Tests: XCTestCase { // Here the signature and the hash matches, but the contract will say is invalid cause the signer is not the owner of the contract let isValid = try await erc1271.isValidSignature( contract: EthereumAddress("0x2505E4d4A76EC941591828311159552A832681D5"), - messageHash: "0x09bf2f6417d2bc487040194b78cbdd6b04f72ea12cf0014f83f4f228bed95ee4".web3.hexData!, - signature: "0xf85b9506180b11dc472278ff1e5fbb1e4b50baa3cadaec26b4b8179a55623f652a794c09b49227231f1144a62221453c854f09a986c1de1e19cdfff451e751b21c".web3.hexData! + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0x8e2ba38942cd698e4a47fc5227c61b94c9458f9093daa051bb87f57ebfd929280181f9f375d28864d4d9c1d24a29e0a2142d721669f737731d738c02b3ab89981b".web3.hexData! ) XCTAssertFalse(isValid) } catch { @@ -91,8 +91,8 @@ class ERC1271Tests: XCTestCase { // Here the signature and the hash don't match let isValid = try await erc1271.isValidSignature( contract: EthereumAddress("0x2505E4d4A76EC941591828311159552A832681D5"), - messageHash: "0xb7755e72da7aca68df7d5ed5a832d027b624d56dab707d2b5257bbfc1bc5d4fd".web3.hexData!, - signature: "0xf85b9506180b11dc472278ff1e5fbb1e4b50baa3cadaec26b4b8179a55623f652a794c09b49227231f1144a62221453c854f09a986c1de1e19cdfff451e751b21c".web3.hexData! + messageHash: "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750".web3.hexData!, + signature: "0xe0c97bb5b8bc876636598132f0b4a250b94bb0d0b95dde49edbbacd1835c62ae301cc27f7117bf362973c64e100edee9c1c4a2ae52503c1a4cb621ec58e7f4521b".web3.hexData! ) XCTAssertFalse(isValid) } catch { diff --git a/web3sTests/ERC20/ERC20Tests.swift b/web3sTests/ERC20/ERC20Tests.swift index adfc50e3..66f800c9 100644 --- a/web3sTests/ERC20/ERC20Tests.swift +++ b/web3sTests/ERC20/ERC20Tests.swift @@ -25,7 +25,7 @@ class ERC20Tests: XCTestCase { func testName() async { do { let name = try await erc20?.name(tokenContract: testContractAddress) - XCTAssertEqual(name, "BokkyPooBah Test Token") + XCTAssertEqual(name, "Uniswap") } catch { XCTFail("Expected name but failed \(error).") } @@ -52,7 +52,7 @@ class ERC20Tests: XCTestCase { func testSymbol() async { do { let symbol = try await erc20?.symbol(tokenContract: testContractAddress) - XCTAssertEqual(symbol, "BOKKY") + XCTAssertEqual(symbol, "UNI") } catch { XCTFail("Expected symbol but failed \(error).") } @@ -60,7 +60,7 @@ class ERC20Tests: XCTestCase { func testTransferRawEvent() async { do { - let result = try! ABIEncoder.encode(EthereumAddress("0x72e3b687805ef66bf2a1e6d9f03faf8b33f0267a")) + let result = try! ABIEncoder.encode(EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41")) let sig = try! ERC20Events.Transfer.signature() let topics = [ sig, result.hexString] @@ -73,7 +73,7 @@ class ERC20Tests: XCTestCase { func testGivenAddressWithInTransfers_ThenGetsTheTransferEvents() async { do { - let events = try await erc20?.transferEventsTo(recipient: "0x72e3b687805ef66bf2a1e6d9f03faf8b33f0267a", fromBlock: .Earliest, toBlock: .Latest) + let events = try await erc20?.transferEventsTo(recipient: "0x162142f0508F557C02bEB7C473682D7C91Bcef41", fromBlock: .Earliest, toBlock: .Latest) XCTAssert(events!.count > 0) } catch { XCTFail("Expected events but failed \(error).") @@ -91,11 +91,11 @@ class ERC20Tests: XCTestCase { func testGivenAddressWithOutgoingEvents_ThenGetsTheTransferEvents() async { do { - let events = try await erc20?.transferEventsFrom(sender: "0x2FB78FA9842f20bfD515A41C3196C4b368bDbC48", fromBlock: .Earliest, toBlock: .Latest) - XCTAssertEqual(events?.first?.log.transactionHash, "0xfb6e0d7fdf8f9b97fe9b634cb5abc7041ee47a396191f23425955f9fda008efe") - XCTAssertEqual(events?.first?.to, EthereumAddress("0xFe325C1E3396b2285d517B0CE2E3ffA472260Bce")) - XCTAssertEqual(events?.first?.value, BigUInt(10).power(18)) - XCTAssertEqual(events?.first?.log.address, EthereumAddress("0xdb0040451f373949a4be60dcd7b6b8d6e42658b6")) + let events = try await erc20?.transferEventsFrom(sender: "0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56793", fromBlock: .Earliest, toBlock: .Latest) + XCTAssertEqual(events?.first?.log.transactionHash, "0x706bbe6f2593235942b8e76c2f37af3824d47a64caf65f7ae5e0c5ee1e886132") + XCTAssertEqual(events?.first?.to, EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41")) + XCTAssertEqual(events?.first?.value, 20000000000000000) + XCTAssertEqual(events?.first?.log.address, EthereumAddress(TestConfig.erc20Contract)) } catch { XCTFail("Expected events but failed \(error).") } diff --git a/web3sTests/ERC721/ERC721Tests.swift b/web3sTests/ERC721/ERC721Tests.swift index 61c226ac..3fc157c3 100644 --- a/web3sTests/ERC721/ERC721Tests.swift +++ b/web3sTests/ERC721/ERC721Tests.swift @@ -11,11 +11,11 @@ import XCTest import FoundationNetworking #endif -let tokenOwner = EthereumAddress("0x69F84b91E7107206E841748C2B52294A1176D45e") +let tokenOwner = EthereumAddress("0x162142f0508F557C02bEB7C473682D7C91Bcef41") let previousOwner = EthereumAddress("0x64d0ea4fc60f27e74f1a70aa6f39d403bbe56793") let nonOwner = EthereumAddress("0x64d0eA4FC60f27E74f1a70Aa6f39D403bBe56792") -let nftImageURL = URL(string: "https://ipfs.io/ipfs/QmUDJMmiJEsueLbr6jxh7vhSSFAvjfYTLC64hgkQm1vH2C/graph.svg")! -let nftURL = URL(string: "https://ipfs.io/ipfs/QmUtKP7LnZnL2pWw2ERvNDndP9v5EPoJH7g566XNdgoRfE")! +let nftImageURL = URL(string: "https://camo.githubusercontent.com/337987fd840686af3ccd336ecb6f76c8d9682539086a5b77f565cb71e6ad167c/68747470733a2f2f7261772e6769746875622e636f6d2f617267656e746c6162732f776562332e73776966742f6d61737465722f7765623373776966742e706e67")! +let nftURL = URL(string: "https://raw.githubusercontent.com/argentlabs/web3.swift/tech/migrate-goerli/web3sTests/Resources/ERC721Metadata.json")! class ERC721Tests: XCTestCase { var client: EthereumClientProtocol! @@ -48,7 +48,7 @@ class ERC721Tests: XCTestCase { func test_GivenAccountWithNFT_ThenOwnerOfNFTIsAccount() async { do { - let balance = try await erc721.ownerOf(contract: address, tokenId: 23) + let balance = try await erc721.ownerOf(contract: address, tokenId: 1) XCTAssertEqual(balance, tokenOwner) } catch { XCTFail("Expected OwnerOf but failed \(error).") @@ -57,7 +57,7 @@ class ERC721Tests: XCTestCase { func test_GivenAccountWithNFT_ThenOwnerOfAnotherNFTIsNotAccount() async { do { - let balance = try await erc721.ownerOf(contract: address, tokenId: 22) + let balance = try await erc721.ownerOf(contract: address, tokenId: 3) XCTAssertNotEqual(balance, tokenOwner) } catch { XCTFail("Expected OwnerOf but failed \(error).") @@ -68,12 +68,12 @@ class ERC721Tests: XCTestCase { do { let events = try await erc721.transferEventsTo(recipient: tokenOwner, fromBlock: .Number( - 6948276), + 8011670 ), toBlock: .Number( - 6948276)) + 8011670 )) XCTAssertEqual(events.first?.from, previousOwner) XCTAssertEqual(events.first?.to, tokenOwner) - XCTAssertEqual(events.first?.tokenId, 23) + XCTAssertEqual(events.first?.tokenId, 2) } catch { XCTFail("Expected Events but failed \(error).") } @@ -83,12 +83,12 @@ class ERC721Tests: XCTestCase { do { let events = try await erc721.transferEventsFrom(sender: previousOwner, fromBlock: .Number( - 6948276), + 8011670), toBlock: .Number( - 6948276)) + 8011670)) XCTAssertEqual(events.first?.to, tokenOwner) XCTAssertEqual(events.first?.from, previousOwner) - XCTAssertEqual(events.first?.tokenId, 23) + XCTAssertEqual(events.first?.tokenId, 2) } catch { XCTFail("Expected Events but failed \(error).") } @@ -99,11 +99,15 @@ class ERC721MetadataTests: XCTestCase { var client: EthereumClientProtocol! var erc721: ERC721Metadata! let address = EthereumAddress(TestConfig.erc721Contract) - let nftDetails = ERC721Metadata.Token(title: "Asset Metadata", - type: "object", - properties: ERC721Metadata.Token.Properties(name: ERC721Metadata.Token.Property(description: "Random Graph Token"), - description: ERC721Metadata.Token.Property(description: "NFT to represent Random Graph"), - image: ERC721Metadata.Token.Property(description: nftImageURL))) + let nftDetails = ERC721Metadata.Token( + title: "Test token metadata", + type: "object", + properties: ERC721Metadata.Token.Properties( + name: ERC721Metadata.Token.Property(description: "Unnamed"), + description: ERC721Metadata.Token.Property(description: "Test ERC721 token"), + image: ERC721Metadata.Token.Property(description: nftImageURL) + ) + ) override func setUp() { super.setUp() @@ -118,7 +122,7 @@ class ERC721MetadataTests: XCTestCase { func test_ReturnsName() async { do { let name = try await erc721.name(contract: address) - XCTAssertEqual(name, "Graph Art Token") + XCTAssertEqual(name, "web3.swift token") } catch { XCTFail("Expected name but failed \(error).") } @@ -127,7 +131,7 @@ class ERC721MetadataTests: XCTestCase { func test_ReturnsSymbol() async { do { let symbol = try await erc721.symbol(contract: address) - XCTAssertEqual(symbol, "GAT") + XCTAssertEqual(symbol, "WEB3T") } catch { XCTFail("Expected symbol but failed \(error).") } @@ -170,7 +174,7 @@ class ERC721EnumerableTests: XCTestCase { func test_returnsTotalSupply() async { do { let supply = try await erc721.totalSupply(contract: address) - XCTAssertGreaterThan(supply, 22) + XCTAssertGreaterThan(supply, 1) } catch { XCTFail("Expected totalSupply but failed \(error).") } @@ -178,8 +182,8 @@ class ERC721EnumerableTests: XCTestCase { func test_returnsTokenByIndex() async { do { - let index = try await erc721.tokenByIndex(contract: address, index: 22) - XCTAssertEqual(index, 23) + let index = try await erc721.tokenByIndex(contract: address, index: 2) + XCTAssertEqual(index, 2) } catch { XCTFail("Expected tokenByIndex but failed \(error).") } @@ -188,7 +192,7 @@ class ERC721EnumerableTests: XCTestCase { func test_GivenAddressWithNFT_returnsTokenOfOwnerByIndex() async { do { let tokenID = try await erc721.tokenOfOwnerByIndex(contract: address, owner: tokenOwner, index: 2) - XCTAssertEqual(tokenID, 23) + XCTAssertEqual(tokenID, 2) } catch { XCTFail("Expected tokenByIndex but failed \(error).") } diff --git a/web3sTests/Mocks/TestEthereumKeyStorage.swift b/web3sTests/Mocks/TestEthereumKeyStorage.swift index fc229742..542bd6e4 100644 --- a/web3sTests/Mocks/TestEthereumKeyStorage.swift +++ b/web3sTests/Mocks/TestEthereumKeyStorage.swift @@ -6,7 +6,7 @@ import Foundation @testable import web3 -class TestEthereumKeyStorage: EthereumKeyStorageProtocol { +class TestEthereumKeyStorage: EthereumSingleKeyStorageProtocol { private var privateKey: String diff --git a/web3sTests/Multicall/MulticallTests.swift b/web3sTests/Multicall/MulticallTests.swift index 7014dad8..938a6d43 100644 --- a/web3sTests/Multicall/MulticallTests.swift +++ b/web3sTests/Multicall/MulticallTests.swift @@ -39,13 +39,13 @@ class MulticallTests: XCTestCase { do { let response = try await multicall.aggregate(calls: aggregator.calls) let symbol = try ERC20Responses.symbolResponse(data: try response.outputs[2].get())?.value - XCTAssertEqual(symbol, "BOKKY") + XCTAssertEqual(symbol, "UNI") } catch { XCTFail("Unexpected failure while handling output") } XCTAssertEqual(decimals, 18) - XCTAssertEqual(name, "BokkyPooBah Test Token") + XCTAssertEqual(name, "Uniswap") } } diff --git a/web3sTests/OffchainLookup/OffchainLookupTests.swift b/web3sTests/OffchainLookup/OffchainLookupTests.swift index 1683805f..8c909b9b 100644 --- a/web3sTests/OffchainLookup/OffchainLookupTests.swift +++ b/web3sTests/OffchainLookup/OffchainLookupTests.swift @@ -12,7 +12,7 @@ struct DummyOffchainENSResolve: ABIFunction { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0x7A876E79a89b9B6dF935F2C1e832E15930FEf3f6" + var contract: EthereumAddress = "0x5d3B57647E36a95AFb3d6F04c2587571B4cfF3cc" var from: EthereumAddress? var node: Data @@ -22,13 +22,14 @@ struct DummyOffchainENSResolve: ABIFunction { } } +// https://github.com/ethers-io/ethers.js/blob/master/packages/tests/src.ts/test-providers.ts enum EthersTestContract { struct TestGet: ABIFunction { static var name: String = "testGet" var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -43,7 +44,7 @@ enum EthersTestContract { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -58,7 +59,7 @@ enum EthersTestContract { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -73,7 +74,7 @@ enum EthersTestContract { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -88,7 +89,7 @@ enum EthersTestContract { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -103,7 +104,7 @@ enum EthersTestContract { var gasPrice: BigUInt? var gasLimit: BigUInt? - var contract: EthereumAddress = "0xAe375B05A08204C809b3cA67C680765661998886" + var contract: EthereumAddress = "0x6C5ed35574a9b4d163f75bBf0595F7540D8FCc2d" var from: EthereumAddress? var data: Data @@ -164,7 +165,7 @@ class OffchainLookupTests: XCTestCase { let decoded = try? error?.decode(error: offchainLookup) XCTAssertEqual(error?.code, JSONRPCErrorCode.contractExecution) - XCTAssertEqual(try? decoded?[0].decoded(), EthereumAddress("0x7a876e79a89b9b6df935f2c1e832e15930fef3f6")) + XCTAssertEqual(try? decoded?[0].decoded(), EthereumAddress("0x5d3b57647e36a95afb3d6f04c2587571b4cff3cc")) XCTAssertEqual(try? decoded?[1].decodedArray(), ["https://argent.xyz"]) XCTAssertEqual(try? decoded?[2].decoded(), Data(hex: "0x35b8485202b076a4e2d0173bf3d7e69546db3eb92389469473b2680c3cdb4427cafbcf2a")!) XCTAssertEqual(try? decoded?[3].decoded(), Data(hex: "0xd2479f3e")!) diff --git a/web3sTests/Resources/ABITests.sol b/web3sTests/Resources/ABITests.sol new file mode 100644 index 00000000..df222032 --- /dev/null +++ b/web3sTests/Resources/ABITests.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +contract ABITests { + + event AddressAndData4Event(address indexed from, bytes4 indexed data); + event AddressAndData32Event(address indexed from, bytes32 data); + + address[] private addresses; + constructor() { + addresses = [0x83f7338d17A85B0a0A8A1AE7Edead4dA571566E0]; + } + function getDynamicArray() public view returns (address[] memory) { + return addresses; + } + + function callEventData4(address from) public { + bytes32 hash = keccak256(abi.encodePacked(from)); + emit AddressAndData4Event(from, bytes4(hash)); + emit AddressAndData4Event(from, bytes4(0xdeadbeef)); + } + + function callEventData32(address from) public { + bytes32 hash = keccak256(abi.encodePacked(from)); + emit AddressAndData32Event(from, hash); + } +} diff --git a/web3sTests/Resources/DummyOffchainResolver.sol b/web3sTests/Resources/DummyOffchainResolver.sol new file mode 100644 index 00000000..b1dfb5dd --- /dev/null +++ b/web3sTests/Resources/DummyOffchainResolver.sol @@ -0,0 +1,41 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.4; + +interface Gateway { + function resolveL2Address(bytes32 node) external view returns(address); +} + +error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData); + +contract DummyOffchainResolver { + + string[] public _urls; + + /** + * @dev Constructor that gives msg.sender all of existing tokens. + */ + constructor( + string[] memory urls + ) { + _urls = urls; + } + + function setUrls(string[] memory urls_) external { + _urls = urls_; + } + + function validateENS(bytes calldata result, bytes calldata) external pure returns(address) { + address resolved = abi.decode(result, (address)); + return resolved; + } + + function resolver(bytes32 node) public view returns (address) { + revert OffchainLookup( + address(this), + _urls, + abi.encodeWithSelector(Gateway.resolveL2Address.selector, node), + DummyOffchainResolver.validateENS.selector, + "" + ); + } +} diff --git a/web3sTests/Resources/ERC1271Checker.sol b/web3sTests/Resources/ERC1271Checker.sol new file mode 100644 index 00000000..0c27c30e --- /dev/null +++ b/web3sTests/Resources/ERC1271Checker.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; +import "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract ERC1271Checker is IERC1271, Ownable { + // bytes4(keccak256("isValidSignature(bytes32,bytes)") + bytes4 constant internal MAGICVALUE = 0x1626ba7e; + + function isValidSignature( + bytes32 _hash, + bytes calldata _signature + ) external override view returns (bytes4) { + (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(_hash, _signature); + require(error == ECDSA.RecoverError.NoError, "Invalid signature"); + if (recovered == owner()) { + return MAGICVALUE; + } else { + return 0xffffffff; + } + } +} diff --git a/web3sTests/Resources/ERC1271CheckerBool.sol b/web3sTests/Resources/ERC1271CheckerBool.sol new file mode 100644 index 00000000..6940a328 --- /dev/null +++ b/web3sTests/Resources/ERC1271CheckerBool.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract ERC1271CheckerBool is Ownable { + + function isValidSignature( + bytes32 _hash, + bytes calldata _signature + ) external view returns (bool) { + (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(_hash, _signature); + require(error == ECDSA.RecoverError.NoError, "Invalid signature"); + if (recovered == owner()) { + return true; + } else { + return false; + } + } +} diff --git a/web3sTests/Resources/ERC721Metadata.json b/web3sTests/Resources/ERC721Metadata.json new file mode 100644 index 00000000..d79f847b --- /dev/null +++ b/web3sTests/Resources/ERC721Metadata.json @@ -0,0 +1,7 @@ +{ + "title": "Test token metadata", + "type": "object", + "name": "Unnamed", + "description": "Test ERC721 token", + "image": "https://camo.githubusercontent.com/337987fd840686af3ccd336ecb6f76c8d9682539086a5b77f565cb71e6ad167c/68747470733a2f2f7261772e6769746875622e636f6d2f617267656e746c6162732f776562332e73776966742f6d61737465722f7765623373776966742e706e67" +} diff --git a/web3sTests/Resources/TestERC721.sol b/web3sTests/Resources/TestERC721.sol new file mode 100644 index 00000000..bea7e709 --- /dev/null +++ b/web3sTests/Resources/TestERC721.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "@openzeppelin/contracts@4.8.0/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts@4.8.0/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts@4.8.0/access/Ownable.sol"; +import "@openzeppelin/contracts@4.8.0/utils/Counters.sol"; + +contract MyToken is ERC721, ERC721Enumerable, Ownable { + using Counters for Counters.Counter; + + Counters.Counter private _tokenIdCounter; + + constructor() ERC721("web3.swift token", "WEB3T") {} + + function safeMint(address to) public onlyOwner { + uint256 tokenId = _tokenIdCounter.current(); + _tokenIdCounter.increment(); + _safeMint(to, tokenId); + } + + // The following functions are overrides required by Solidity. + + function tokenURI(uint256) public view virtual override returns (string memory) { + return "https://raw.githubusercontent.com/argentlabs/web3.swift/tech/migrate-goerli/web3sTests/Resources/ERC721Metadata.json"; + } + + function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) + internal + override(ERC721, ERC721Enumerable) + { + super._beforeTokenTransfer(from, to, tokenId, batchSize); + } + + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC721, ERC721Enumerable) + returns (bool) + { + return super.supportsInterface(interfaceId); + } +} + diff --git a/web3sTests/SIWE/SIWETests.swift b/web3sTests/SIWE/SIWETests.swift index 1c183efa..60eea08d 100644 --- a/web3sTests/SIWE/SIWETests.swift +++ b/web3sTests/SIWE/SIWETests.swift @@ -30,7 +30,7 @@ class SIWETests: XCTestCase { URI: https://login.xyz/demo#login Version: 1 - Chain ID: 3 + Chain ID: 5 Nonce: qwerty123456 Issued At: \(SiweMessage.dateFormatter.string(from: Date())) Expiration Time: \(SiweMessage.dateFormatter.string(from: Date(timeInterval: 60, since: Date()))) diff --git a/web3sTests/SIWE/SiweVerifierTests.swift b/web3sTests/SIWE/SiweVerifierTests.swift index 094e059e..5dfb50b7 100644 --- a/web3sTests/SIWE/SiweVerifierTests.swift +++ b/web3sTests/SIWE/SiweVerifierTests.swift @@ -13,7 +13,7 @@ class SiweVerifierTests: XCTestCase { override func setUp() { super.setUp() if self.client == nil { - self.client = EthereumHttpClient(url: URL(string: TestConfig.clientUrl)!) + self.client = EthereumHttpClient(url: URL(string: TestConfig.clientUrl)!, network: .goerli) } } @@ -55,7 +55,7 @@ class SiweVerifierTests: XCTestCase { statement: "You abide to our T&C", uri: URL(string: "https://login.xyz/demo#login")!, version: "1", - chainId: 3, + chainId: 5, nonce: "qwerty123456", issuedAt: Date(timeIntervalSince1970: 1_655_082_630.023), expirationTime: Date(timeIntervalSince1970: 1_657_674_629.0), @@ -85,7 +85,7 @@ class SiweVerifierTests: XCTestCase { statement: "You abide to our T&C", uri: URL(string: "https://login.xyz/demo#login")!, version: "1", - chainId: 3, + chainId: 5, nonce: "qwerty123456", issuedAt: Date(timeIntervalSince1970: 1_655_082_630.023), expirationTime: Date(timeIntervalSince1970: 1_657_674_629.0), @@ -113,13 +113,13 @@ class SiweVerifierTests: XCTestCase { let isVerified = try await verifier.verify( """ login.xyz wants you to sign in with your Ethereum account: - 0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F + 0x719561fee351F7aC6560D0302aE415FfBEEc0B51 Please sign this 🙏 URI: https://login.xyz/demo#login Version: 1 - Chain ID: 3 + Chain ID: 5 Nonce: qwerty123456 Issued At: 2022-06-16T12:09:07.937Z Request ID: some-request-id @@ -127,7 +127,7 @@ class SiweVerifierTests: XCTestCase { - https://docs.login.xyz - https://login.xyz """, - against: "0x14ff8392ce953be96f3e57d8519d94f4b19f98cf42d0dca8961c3fa70a12c9857e95f4732839d39e883d26abf0fcdd4602f50acde7721274ea4c31f26981e4b41b" + against: "0x22694f51b1eda4559b117ac0bdbf40f774b17bbb76f763b1c30e1adaab42ce1a406a02c38158c6b500f4f5d803774907d231020867d376e05f3a6eea7041aff31b" ) XCTAssertTrue(isVerified) } catch { @@ -147,7 +147,7 @@ class SiweVerifierTests: XCTestCase { URI: https://login.xyz/demo#login Version: 1 - Chain ID: 3 + Chain ID: 5 Nonce: qwerty123456 Issued At: 2022-06-16T12:09:07.937Z Request ID: some-request-id @@ -170,13 +170,13 @@ class SiweVerifierTests: XCTestCase { let isVerified = try await verifier.verify( """ login.xyz wants you to sign in with your Ethereum account: - 0x2bD85c85666a29bD453918B20b9E5ef7603d9007 + 0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca Please sign this 🙏 URI: https://login.xyz/demo#login Version: 1 - Chain ID: 3 + Chain ID: 5 Nonce: qwerty123456 Issued At: 2022-06-16T12:09:07.937Z Request ID: some-request-id @@ -184,7 +184,7 @@ class SiweVerifierTests: XCTestCase { - https://docs.login.xyz - https://login.xyz """, - against: "0x0217550201eb35af7048e32dbf05201de1440eb079e1046f16cce27463fb5bf56f8c9c33a93845b1e891afdcf60608255433b18435c9cdabca6625fb1bcc41841b" + against: "0x4f49c1a24513ad1b677546c2dfc3be361d861c9d595d47ebf97aac57497f7971184e31f997f67466690becacd5aac5d3716db457329ba392c81ba5836a26449c1b" ) XCTAssertTrue(isVerified) } catch { @@ -199,13 +199,13 @@ class SiweVerifierTests: XCTestCase { let isVerified = try await verifier.verify( """ login.xyz wants you to sign in with your Ethereum account: - 0x2bD85c85666a29bD453918B20b9E5ef7603d9007 + 0x72602FE1F2CaBAbCfFB51eb84741AFaE04AF10ca Please sign this 🙏 URI: https://login.xyz/demo#login Version: 1 - Chain ID: 3 + Chain ID: 5 Nonce: qwerty123456 Issued At: 2022-06-16T12:09:07.937Z Request ID: some-request-id diff --git a/web3sTests/TestConfig.swift b/web3sTests/TestConfig.swift index 414aa5e9..f81ce600 100644 --- a/web3sTests/TestConfig.swift +++ b/web3sTests/TestConfig.swift @@ -7,11 +7,11 @@ import Foundation import web3 struct TestConfig { - // This is the proxy URL for connecting to the Blockchain. For testing we usually use the Ropsten network on Infura. Using free tier, so might hit rate limits - static let clientUrl = "https://ropsten.infura.io/v3/b2f4b3f635d8425c96854c3d28ba6bb0" + // This is the proxy URL for connecting to the Blockchain. For testing we usually use the Goerli network on Infura. Using free tier, so might hit rate limits + static let clientUrl = "https://goerli.infura.io/v3/b2f4b3f635d8425c96854c3d28ba6bb0" - // This is the proxy wss URL for connecting to the Blockchain. For testing we usually use the Ropsten network on Infura. Using free tier, so might hit rate limits - static let wssUrl = "wss://ropsten.infura.io/ws/v3/467b3cd9ab2a4cbda33f14e608362e32" + // This is the proxy wss URL for connecting to the Blockchain. For testing we usually use the Goerli network on Infura. Using free tier, so might hit rate limits + static let wssUrl = "wss://goerli.infura.io/ws/v3/b2f4b3f635d8425c96854c3d28ba6bb0" // An EOA with some Ether, so that we can test sending transactions (pay for gas) static let privateKey = "0xef4e182ae2cf32192d2a62c1159c8c4f7f2d658c303d0dfca5791a205456a132" @@ -19,14 +19,14 @@ struct TestConfig { // This is the expected public key (address) from the above private key static let publicKey = "0x719561fee351F7aC6560D0302aE415FfBEEc0B51" - // A test ERC20 token contract (BOKKY) - static let erc20Contract = "0x583cbBb8a8443B38aBcC0c956beCe47340ea1367" + // A test ERC20 token contract (UNI) + static let erc20Contract = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984" - // A test ERC721 token contract (GAT) - static let erc721Contract = "0x6F2443D87F0F6Cb6aa47b0C6a310468163871E94" + // A test ERC721 token contract (W3ST) + static let erc721Contract = "0xb34354a70d2b985b031Ca443b87C92F7DaE5DA02" // ERC165 compliant contract - static let erc165Contract = "0x5c007a1d8051dfda60b3692008b9e10731b67fde" + static let erc165Contract = "0xA2618a1c426a1684E00cA85b5C736164AC391d35" static let webSocketConfig = WebSocketConfiguration(maxFrameSize: 1_000_000) } diff --git a/web3sTests/Transaction/TransactionTests.swift b/web3sTests/Transaction/TransactionTests.swift index 0207c1a5..d5a8c467 100644 --- a/web3sTests/Transaction/TransactionTests.swift +++ b/web3sTests/Transaction/TransactionTests.swift @@ -40,9 +40,9 @@ class TransactionTests: XCTestCase { nonce: 1, gasPrice: 10, gasLimit: 400000, - chainId: 3) + chainId: 5) - XCTAssertEqual(transaction.hash?.web3.hexString, "0xec010a83061a80a01639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde71748080038080") + XCTAssertEqual(transaction.hash?.web3.hexString, "0xec010a83061a80a01639f727ded571d584643895d43d02a7a190f8249748a2c32200cfc12dde71748080058080") } func test_GivenLocalTransaction_WhenTransactionWithoutChainID_HashIsNil() { diff --git a/web3swift/src/Account/EthereumAccount.swift b/web3swift/src/Account/EthereumAccount.swift index 46065ba0..c219a02e 100644 --- a/web3swift/src/Account/EthereumAccount.swift +++ b/web3swift/src/Account/EthereumAccount.swift @@ -37,7 +37,7 @@ public class EthereumAccount: EthereumAccountProtocol { return KeyUtil.generateAddress(from: self.publicKeyData) }() - required public init(keyStorage: EthereumKeyStorageProtocol, keystorePassword password: String, logger: Logger? = nil) throws { + required public init(keyStorage: EthereumSingleKeyStorageProtocol, keystorePassword password: String, logger: Logger? = nil) throws { self.logger = logger ?? Logger(label: "web3.swift.eth-account") do { let decodedKey = try keyStorage.loadAndDecryptPrivateKey(keystorePassword: password) @@ -49,7 +49,7 @@ public class EthereumAccount: EthereumAccountProtocol { } } - required public init(keyStorage: EthereumKeyStorageProtocol, logger: Logger? = nil) throws { + required public init(keyStorage: EthereumSingleKeyStorageProtocol, logger: Logger? = nil) throws { self.logger = logger ?? Logger(label: "web3.swift.eth-account") do { let data = try keyStorage.loadPrivateKey() @@ -85,7 +85,7 @@ public class EthereumAccount: EthereumAccountProtocol { } } - public static func create(keyStorage: EthereumMultipleKeyStorageProtocol, keystorePassword password: String) throws -> EthereumAccount { + public static func create(addingTo keyStorage: EthereumMultipleKeyStorageProtocol, keystorePassword password: String) throws -> EthereumAccount { guard let privateKey = KeyUtil.generatePrivateKeyData() else { throw EthereumAccountError.createAccountError } @@ -100,7 +100,7 @@ public class EthereumAccount: EthereumAccountProtocol { } } - public static func create(keyStorage: EthereumKeyStorageProtocol, keystorePassword password: String) throws -> EthereumAccount { + public static func create(replacing keyStorage: EthereumSingleKeyStorageProtocol, keystorePassword password: String) throws -> EthereumAccount { guard let privateKey = KeyUtil.generatePrivateKeyData() else { throw EthereumAccountError.createAccountError } @@ -113,7 +113,7 @@ public class EthereumAccount: EthereumAccountProtocol { } } - public static func importAccount(keyStorage: EthereumMultipleKeyStorageProtocol, privateKey: String, keystorePassword password: String) throws -> EthereumAccount { + public static func importAccount(addingTo keyStorage: EthereumMultipleKeyStorageProtocol, privateKey: String, keystorePassword password: String) throws -> EthereumAccount { guard let privateKey = privateKey.web3.hexData else { throw EthereumAccountError.importAccountError } @@ -127,7 +127,7 @@ public class EthereumAccount: EthereumAccountProtocol { } } - public static func importAccount(keyStorage: EthereumKeyStorageProtocol, privateKey: String, keystorePassword password: String) throws -> EthereumAccount { + public static func importAccount(replacing keyStorage: EthereumSingleKeyStorageProtocol, privateKey: String, keystorePassword password: String) throws -> EthereumAccount { guard let privateKey = privateKey.web3.hexData else { throw EthereumAccountError.importAccountError } diff --git a/web3swift/src/Account/EthereumKeyStorage+Password.swift b/web3swift/src/Account/EthereumKeyStorage+Password.swift index 61579fb9..5c085b24 100644 --- a/web3swift/src/Account/EthereumKeyStorage+Password.swift +++ b/web3swift/src/Account/EthereumKeyStorage+Password.swift @@ -5,7 +5,7 @@ import Foundation -public extension EthereumKeyStorageProtocol { +public extension EthereumSingleKeyStorageProtocol { func encryptAndStorePrivateKey(key: Data, keystorePassword: String) throws { let encodedKey = try KeystoreUtil.encode(privateKey: key, password: keystorePassword) try storePrivateKey(key: encodedKey) diff --git a/web3swift/src/Account/EthereumKeyStorage.swift b/web3swift/src/Account/EthereumKeyStorage.swift index 6d47bd77..c9fff6e7 100644 --- a/web3swift/src/Account/EthereumKeyStorage.swift +++ b/web3swift/src/Account/EthereumKeyStorage.swift @@ -5,7 +5,7 @@ import Foundation -public protocol EthereumKeyStorageProtocol { +public protocol EthereumSingleKeyStorageProtocol { func storePrivateKey(key: Data) throws func loadPrivateKey() throws -> Data } @@ -25,7 +25,7 @@ public enum EthereumKeyStorageError: Error { case failedToDelete } -public class EthereumKeyLocalStorage: EthereumKeyStorageProtocol { +public class EthereumKeyLocalStorage: EthereumSingleKeyStorageProtocol { public init() {} diff --git a/web3swift/src/Account/TypedData.swift b/web3swift/src/Account/TypedData.swift index 0de5870f..4a908b82 100644 --- a/web3swift/src/Account/TypedData.swift +++ b/web3swift/src/Account/TypedData.swift @@ -71,6 +71,7 @@ extension TypedData { let param = types[type]!.map { "\($0.type) \($0.name)" }.joined(separator: ",") return "\(type)(\(param))" }.joined() + return encoded.data(using: .utf8) ?? Data() } @@ -83,10 +84,32 @@ extension TypedData { } let recursiveEncoded: [UInt8] = try valueTypes.flatMap { variable -> [UInt8] in - if types[variable.type] != nil { + + // Decomposit the type if it is array type + let components = variable.type.components(separatedBy: CharacterSet(charactersIn: "[]")) + let parsedType = components[0] + + // Check the type is a custom type + if types[parsedType] != nil { guard let json = data[variable.name] else { throw ABIError.invalidValue } + + // If is custom type array, recursively encode the array + if components.count == 3 && components[1].isEmpty { + let encoded = try json.arrayValue!.flatMap { try encodeData(data: $0, type: parsedType).web3.keccak256.web3.bytes } + + return Data(encoded).web3.keccak256.web3.bytes + } else if components.count == 3 && !components[1].isEmpty { + let num = String(components[1].filter { "0"..."9" ~= $0 }) + guard let int = Int(num), int == json.arrayValue?.count ?? 0 else { + throw ABIError.invalidValue + } + + let encoded = try json.arrayValue!.flatMap { try encodeData(data: $0, type: parsedType) } + return Data(encoded).web3.keccak256.web3.bytes + } + return try encodeData(data: json, type: variable.type).web3.keccak256.web3.bytes } else if let json = data[variable.name] { return try parseAtomicType(json, type: variable.type) @@ -94,19 +117,30 @@ extension TypedData { return [] } } - + encoded.append(contentsOf: recursiveEncoded) return Data(encoded) } + private func getParsedType(primaryType: String) -> String { + // Decomposit the type if it is an array type + let components = primaryType.components(separatedBy: CharacterSet(charactersIn: "[]")) + let parsedType = components[0] + + return parsedType + } + private func findDependencies(primaryType: String, dependencies: Set = Set()) -> Set { var found = dependencies - guard !found.contains(primaryType), - let primaryTypes = types[primaryType] else { + + let parsedType = getParsedType(primaryType: primaryType) + + guard !found.contains(parsedType), + let primaryTypes = types[parsedType] else { return found } - found.insert(primaryType) + found.insert(parsedType) for type in primaryTypes { findDependencies(primaryType: type.type, dependencies: found) .forEach { found.insert($0) } @@ -155,6 +189,7 @@ extension TypedData { } let encoded = try value.flatMap { try parseAtomicType($0, type: nested.rawValue) } + return Data(encoded).web3.keccak256.web3.bytes case .FixedArray(let nested, let count): guard let value = data.arrayValue else { diff --git a/web3swift/src/Client/Models/EthereumNetwork.swift b/web3swift/src/Client/Models/EthereumNetwork.swift index dd85373b..2d78ccbb 100644 --- a/web3swift/src/Client/Models/EthereumNetwork.swift +++ b/web3swift/src/Client/Models/EthereumNetwork.swift @@ -7,8 +7,6 @@ import Foundation public enum EthereumNetwork: Equatable, Decodable { case mainnet - case ropsten - case rinkeby case kovan case goerli case sepolia @@ -17,10 +15,6 @@ public enum EthereumNetwork: Equatable, Decodable { switch networkId { case "1": return .mainnet - case "3": - return .ropsten - case "4": - return .rinkeby case "5": return .goerli case "42": @@ -36,10 +30,6 @@ public enum EthereumNetwork: Equatable, Decodable { switch self { case .mainnet: return "1" - case .ropsten: - return "3" - case .rinkeby: - return "4" case .goerli: return "5" case .kovan: @@ -55,10 +45,6 @@ public enum EthereumNetwork: Equatable, Decodable { switch self { case .mainnet: return 1 - case .ropsten: - return 3 - case .rinkeby: - return 4 case .goerli: return 5 case .kovan: diff --git a/web3swift/src/ENS/ENSContracts.swift b/web3swift/src/ENS/ENSContracts.swift index 31f060b8..6c3073ff 100644 --- a/web3swift/src/ENS/ENSContracts.swift +++ b/web3swift/src/ENS/ENSContracts.swift @@ -13,8 +13,6 @@ public enum ENSContracts { public static func registryAddress(for network: EthereumNetwork) -> EthereumAddress? { switch network { - case .ropsten: - return ENSContracts.RegistryAddress case .mainnet: return ENSContracts.RegistryAddress case .goerli: diff --git a/web3swift/src/Multicall/MulticallContract.swift b/web3swift/src/Multicall/MulticallContract.swift index 159a87b0..1633661e 100644 --- a/web3swift/src/Multicall/MulticallContract.swift +++ b/web3swift/src/Multicall/MulticallContract.swift @@ -10,16 +10,10 @@ extension Multicall { public enum Contract { static let goerliAddress: EthereumAddress = "0x77dCa2C955b15e9dE4dbBCf1246B4B85b651e50e" - static let ropstenAddress: EthereumAddress = "0x604D19Ba889A223693B0E78bC1269760B291b9Df" - static let rinkebyAddress: EthereumAddress = "0xF20A5837Eb2D9F1F7cdf9D635f3Bc68C47B8B8fF" static let mainnetAddress: EthereumAddress = "0xF34D2Cb31175a51B23fb6e08cA06d7208FaD379F" public static func registryAddress(for network: EthereumNetwork) -> EthereumAddress? { switch network { - case .ropsten: - return Self.ropstenAddress - case .rinkeby: - return Self.rinkebyAddress case .mainnet: return Self.mainnetAddress case .goerli: