Skip to content
Kristenlike1234 edited this page Oct 6, 2022 · 44 revisions

Question #1: Why does “Use of unresolved identifier” error occurs only for Device Archive Builds?

I've been working with CocoaPods using several dependencies, and I have tested my project and it works perfectly using the simulator, but I'm unable to build my project for a real device with the error: "Use of unresolved identifier". The Pod that's causing the problem is web3swift and there are a number of Classes that the compiler can't find when I try to build for a device, ie.

let contract = web3.contract(contractABI, at EthereumAdress(Rinkeby.address))  

Error: Use of unresolved identifier " EthereumAdress" I have no idea why this problem occurs exclusively when I try to build/archive for a real device. I'm hopeless about this issue as it goes beyond my knowledge, I'd really appreciate your help (the solutions from StackOverflow that I've tried did not work for me)

ANSWER:

This issue has been resolved for the latest versions of web3_swift, since this issue is quite old now

[TODO - Answer @ José Estrella Campaña] source:https://stackoverflow.com/questions/48939394/why-does-use-of-unresolved-identifier-error-occurs-only-for-device-archive-bui

Question #2: Sign any message with the user’s private key and verify the signature on Ethereum

I'm trying to explore Ethereum and creating a app which let user sign message and validate the message. I'm using web3swift framework for this and what I have tried so far is as follows -

let web3Rinkeby = Web3.InfuraRinkebyWeb3()
    let msgStr = "This is my first Ethereum App";
    let data = msgStr.data(using: .utf8)
    let signMsg = web3Rinkeby.wallet.signPersonalMessage(data!, account: address);

    print(signMsg);

but I'm not sure if this is right and how to validate any message as well. Please help.

ANSWER:

let web3Rinkeby = Web3.InfuraRinkebyWeb3()
/// 
    let keystore = try! EthereumKeystoreV3(password: "")
    let keystoreManager = KeystoreManager([keystore!])
    web3Rinkeby.addKeystoreManager(keystoreManager)
    let address = keystoreManager.addresses![0]
///
let msgStr = "This is my first Ethereum App";
let data = msgStr.data(using: .utf8)
let signMsg = web3Rinkeby.wallet.signPersonalMessage(data!, account: address);
print(signMsg);

Here is an example, how to sign transactions in the tests of the project: [TODO - Answer @skywinder] source: https://stackoverflow.com/questions/52455188/sign-any-message-with-the-user-s-private-key-and-verify-the-signature-on-ethereu/52600931#52600931

Question #3 Interacting with custom smart contract using web3swift

I am using the web3swift library and I managed to do some transactions, mostly gets (balanceOf, owner etc). I read the whole readme(documentation), but I am not quite sure, can we use this library to call functions from our custom smart contracts? For example I have store smart contract and I want to call the buy function from it? I saw that we can transfer eth and ERC20 tokens but that is not enough for me. Any help on this?

ANSWER:

Yes, you can call any function on your custom smart contract. Here is an example.

let infura = Web3.InfuraMainnetWeb3()
        // 1
        let contract = infura.contract(someABI, at: ethContractAddress, abiVersion: 2)
        // 2
        var options = TransactionOptions.defaultOptions
        options.from = address
        // 3 
        let transactionIntermediate = contract?.method("accountExists", parameters:[address] as [AnyObject], options: options)
        // 4
        let result = transactionIntermediate!.call(options: options)
        switch result {
        // 5    
        case .success(let res):
            let ans = res["0"] as! Bool
            DispatchQueue.main.async {
                completion(Result.Success(ans))
            }
        case .failure(let error):
            DispatchQueue.main.async {
                completion(Result.Error(error))
            }
        }
    }  
  1. Setting up the contract and ABI. You need contract address for this in Data or String format. let ethContractAddress = EthereumAddress("0xfa28eC7198028438514b49a3CF353BcA5541ce1d")! You can get the ABI of your contract directly from Remix IDE.
  2. Set up all the options you want.
  3. Probably one of the main parts of the answer - here you create the transaction with contract method name and put into it all the parameters this method needs. 4.Here you can either call or send the transaction. call method is for methods with view identifier in solidity, so you won't pay for it and method send() is for the methods of smart contract that should be paid with gas for execution.
  4. Here you just parse the result, returned by the method. You should know data types of the variables you want to obtain from the concrete method in order to parse them correctly.

[TODO - Answer @ Georgy Fesenko]

source: https://stackoverflow.com/questions/51307215/interacting-with-custom-smart-contract-using-web3swift/51965276#51965276

Question #4 How to sign personal message with the personal extension of web3?

I'm making a Dapp with web3swift by matter inc. One method I come across is one of the web3.Personal extension:

public func signPersonalMessage(message: Data, from: 
    web3swift.EthereumAddress, password: String = default) -> 
    Result.Result<Data, web3swift.Web3Error>

I was trying like this:

let web3 = Web3.InfuraMainnetWeb3()
let res = web3.personal.signPersonalMessage(message: msgHash!, 
    from: self.keystore.getAddress()!, password: password)

but what I got was always a Web3ConnectionError. There must not be in the right way I guess. So, any tip to get a usable instance of web3.Personal, and to call the signPersonalMessage method? Thanks :)

By the way, Web3.Utils.signPersonalMessage method is not what I am looking for.

ANSWER:

Please do check that you have a keystore attached to the web3 object. If there is no local keystore than the message is sent to the remote node for signing, but Infura nodes do not contain any private keys.

If a problem persists please open an issue on gitHub repo.

[TODO - Answer @skywinder] source:https://stackoverflow.com/questions/50794445/how-to-sign-personal-message-with-the-personal-extension-of-web3/51115496#51115496

Question #5 How to create raw transaction using web3swift?

I'm working on a project related to blockchain and need to figure out how raw transaction can be possible. I got no reference for this as of now.

I have tried matterinc/web3swift but unable to get exact thing.

ANSWER:

    var options = TransactionOptions.defaultOptions

    options.gasLimit = BigUInt(21000)

    options.from = self.bip32keystore?.addresses?.first!

    let amountDouble = Int((Double(amount) ?? 0.0)*pow(10, 18))

    let am = BigUInt.init(amountDouble)

    options.value = am

    let estimatedGasResult =   self.web3Rinkeby?.contract(Web3.Utils.coldWalletABI, at: toaddress)!.method(options: options)!.estimateGas(options: nil)

    guard case .success(let estimatedGas)? = estimatedGasResult else {return}

    options.gasLimit = estimatedGas

    var intermediateSend = self.web3Rinkeby?.contract(Web3.Utils.coldWalletABI, at: toaddress, abiVersion: 2)!.method(options: options)!

    intermediateSend = self.web3Rinkeby?.contract(Web3.Utils.coldWalletABI, at: toaddress, abiVersion: 2)!.method(options: options)!

    let sendResult = intermediateSend?.send(password: pass)

    switch sendResult {

        case .success(let r)?:

        print("Sucess",r)

      case .failure(let err)?:

      print("Eroor",err)

     case .none:

     print("sendResultBip32",sendResult)

     }     

[TODO - Answer @anton] source: https://stackoverflow.com/questions/48877073/how-to-create-raw-transaction-using-web3swift

Question #6 Compile error when trying to import web3swift

I am trying to import web3swift into one of my Swift files, but get the compiler !Error - No such module 'web3swift'".

The import statements look like this:

import Geth
import web3swift

In my pod file, I have:

pod 'web3swift', :git => 'https://github.com/MercuryProtocol/web3.swift.git'

I have also tried the following fix which hasn't worked:

  • Go to swift Build Settings
  • Search swift Framework Search Paths (case sensitive)
  • Double click on swift <Multiple values>
  • Click the swift +
  • swift Add $(SRCROOT) and set it to recursive

ANSWER:

According to your question - probably you are using another repo. Please, kindly check actual version 0.7.0

Installation web3swift is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'web3swift', git: 'https://github.com/matterinc/web3swift'

Run swift pod install from the command line

It should work fine after that. If you still have problems, feel free to open issue

[TODO - Answer @skywinder] source: https://stackoverflow.com/questions/49859007/compile-error-when-trying-to-import-web3swift/50613486#50613486

Question #7 Sign any message with the user’s private key and verify the signature on Ethereum

I'm trying to explore Ethereum and creating a app which let user sign message and validate the message. I'm using web3swift framework for this and what I have tried so far is as follows

    let web3Rinkeby = Web3.InfuraRinkebyWeb3()
    let msgStr = "This is my first Ethereum App";
    let data = msgStr.data(using: .utf8)
    let signMsg = web3Rinkeby.wallet.signPersonalMessage(data!, account: address);

    print(signMsg);

but I'm not sure if this is right and how to validate any message as well. Please help.

Answer:

Seems, that you didn't specify exact address. Here is an example:

let web3Rinkeby = Web3.InfuraRinkebyWeb3()

/// 
    let keystore = try! EthereumKeystoreV3(password: "")
    let keystoreManager = KeystoreManager([keystore!])
    web3Rinkeby.addKeystoreManager(keystoreManager)
    let address = keystoreManager.addresses![0]
///

let msgStr = "This is my first Ethereum App";
let data = msgStr.data(using: .utf8)
let signMsg = web3Rinkeby.wallet.signPersonalMessage(data!, account: address);

print(signMsg);

Here is an example, how to sign transactions in the tests of the project: https://github.com/matterinc/web3swift/blob/develop/web3swiftTests/web3swift_rinkeby_personalSignature_Tests.swift#L20

Question #8 How to use custom json contract with web3swift

How can I use a JSON contract local, for example something like this:

let jsonString = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]"

ANSWER:

You can use swift it in let contract = Web3.InfuraMainnetWeb3().contract(<abiString: String>, at: <EthereumAddress?>, abiVersion: <Int>)

Also you should call its needed method: swift let transaction = contract.method(<method: String>, parameters: <[AnyObject]>, extraData: <Data>, options: <Web3Options?>)

Example of preparing transaction function:

func prepareTransaction(parameters: Data, gasLimit: BigUInt = 27500, completion: @escaping (Result<TransactionIntermediate>) -> Void) {
    DispatchQueue.global().async {
        guard let addressFrom: String = <YOURS WALLET ADDRESS> else {return}
        guard let ethAddressFrom = EthereumAddress(addressFrom) else {return}

        let yourContractAddress = "<YOUR CONTRACT ETH ADDRESS>"
        guard let ethContractAddress = EthereumAddress(contractAddress) else {return}

        let web3 = Web3.InfuraMainnetWeb3() //or any test network
        web3.addKeystoreManager(KeystoreManager.defaultManager)

        var options = TransactionOptions.defaultOptions
        options.from = ethAddressFrom
        options.value = 0 // or any other value you want to send

        guard let contract = web3.contract(yourContractJsonABI, at: ethContractAddress, abiVersion: 2) else {return}

        guard let gasPrice = web3.eth.getGasPrice().value else {return}
        options.gasPrice = gasPrice
        options.gasLimit = gasLimit

        guard let transaction = contract.method("<METHOD OF CONTRACT YOU WANT TO CALL>", parameters: [parameters] as [AnyObject], options: options) else {return}
        guard case .success(let estimate) = transaction.estimateGas(options: options) else {return} //here is estimated gas - something like confirming that you made a transaction correctly
        print("estimated cost: \(estimate)")

        DispatchQueue.main.async {
            completion(Result.Success(transaction))
        }
    }
}

[TODO - Answer @Anton Grigorev] source: https://stackoverflow.com/questions/50761595/how-to-use-custom-json-contract-with-web3swift

Question #9 Export mnemonics function in web3swift library

I have a problem interacting with web3swift. I need to show mnemonics to my users when they want it. Is there a way to do it? I did a little research and found out that in trust wallet this could be done just with code:

String(data: decryptedPK, encoding: .utf8)

However, in web3swift even the length in bytes of decryptedPK is different(82 in web3swift, 73 in Trust).

ANSWER:

In web3swift there is no backward conversion from PK to the mnemonic. Also it is theoretically impossible to recover a phrase from a PK.

When the user is creating his keystore you should ask him if he wants to save a passphrase. After seed phrase is converted to some initial entropy the “master key is derived” and the initial entropy is discarded.

The simplest solution is to encrypt the phrase using users pincode and save it in some keystore.

Hope I've answered your question!

[TODO - Answer @ Anton Grigorev] source:https://stackoverflow.com/questions/51963782/export-mnemonics-function-in-web3swift-library

Question #10 Generating 12-word mnemonic from private key

Hey all, I would like to get a mnemonic representation of a private key. Right now, I am getting 24 words by doing the following:

    private func generateKey() -> String {
        let userDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        var ks: EthereumKeystoreV3?
        ks = try! EthereumKeystoreV3(password: "PASSWORD")
        let keydata = try! JSONEncoder().encode(ks!.keystoreParams)
        FileManager.default.createFile(atPath: userDir + "/keystore"+"/key.json", contents: keydata, attributes: nil)
        var mnemonic: String = ""
        do {
            if let pk = try ks?.UNSAFE_getPrivateKeyData(password: "PASSWORD", account: (ks?.addresses?.first)!) {
                print("pk to hex: \(pk.toHexString())")
                let entropy = Data(hex: pk.toHexString())
                mnemonic = Mnemonic.create(entropy: entropy)
                print("pk hex to menmonic: \(mnemonic)")
            }
        } catch {print("Error with getting private key: \(error)")}
        return mnemonic
    }

I am using the Mnemonic helper class found here: https://github.com/essentiaone/HDWallet/blob/develop/HDWalletKit/Mnemonic/Mnemonic.swift

This is the Mnemonic.create function:

    public static func create(entropy: Data, language: WordList = .english) -> String {
        let entropybits = String(entropy.flatMap { ("00000000" + String($0, radix: 2)).suffix(8) })
        let hashBits = String(entropy.sha256().flatMap { ("00000000" + String($0, radix: 2)).suffix(8) })
        let checkSum = String(hashBits.prefix((entropy.count * 8) / 32))
        
        let words = language.words
        let concatenatedBits = entropybits + checkSum
        
        var mnemonic: [String] = []
        for index in 0..<(concatenatedBits.count / 11) {
            let startIndex = concatenatedBits.index(concatenatedBits.startIndex, offsetBy: index * 11)
            let endIndex = concatenatedBits.index(startIndex, offsetBy: 11)
            let wordIndex = Int(strtoul(String(concatenatedBits[startIndex..<endIndex]), nil, 2))
            mnemonic.append(String(words[wordIndex]))
        }
        
        return mnemonic.joined(separator: " ")
    }

A couple questions:

Would the user still be able to derive their private key from this mnemonic? Also, instead of generating a 24-word mnemonic, is it possible to generate a 12-word mnemonic?

ANSWER:

I was able to generate a 12-word mnemonic by changing the following:

        for index in 0..<(concatenatedBits.count / 11) {
            ...

Changed to:

        for index in 0..<(concatenatedBits.count / 22) {
            ...

swift concatenatedBits.count is equal to 264. By dividing by 22, the for loop index now runs from 0 to 11. [TODO - Answer @barrasso ] source: https://github.com/matterinc/web3swift/issues/79

Question #11 please support Carthage

I know it wont be easy because its dependencies do not support Cartharge :( but any change?

ANSWER:

I'll have a look what is the simplest way to make it work. Worst case I'll have to provide a custom repository for libsodium.

[TODO - Answer @shamatar] source: https://github.com/matterinc/web3swift/issues/44

Question #12: How to get all the tokenids I own in a contract address?

ANSWER:

You should use external service for that or ask that for every block in chain.

[TODO - Answer @sunxxg] source: https://github.com/skywinder/web3swift/issues/567

Question #13: How to get my wallet's transaction history list, gas price and token 's detail?

Hi all, I m working on a wallet project, and found some problem that I can't handle with web3swift doc. I can get transID after each transaction, but how to get my wallet's transaction history list? Almost every dapp will show gasprice with high, average and slow speed when prepare to send a transaction. Where can I get the gas price? How to get unit price, symbol name and icon for a token? Btw, where do you guys get monetary exchange rate?I 've read all functions in Web3+Eth.swift, looks like there 's no function that satisfied my needs. And I also confused with :* let block = try! web3.eth.getBlockByNumber(blockNumber, fullTransactions: false) ``let transactionInBlockArr : [TransactionInBlock] = block.transactions let transactionInBlock : TransactionInBlock = transactionInBlockArr.first! *What exactly mean for block.transactions? Is it transaction records for the block?

ANSWER:

You have to cycle through all transactions. Get list of tx hash's. For each Gas price is web3.eth.gasPrice I believe. Exchange rate is your choice, I use kucoin api and update my own database. Token details are called through call transactions.

[TODO - Answer @JJBFC] source: https://github.com/skywinder/web3swift/issues/377

Question #14: How can I get tx hashs with my address and the token address, still not found it.

For web3.eth.gasPrice only return one price, so how can I calculate the high speed price and slow speed price? For token details, I need to show the token unit price before transactions even in my homepage, what should I do. If you can show me the code that would be great! I can get tx hash after finishing a transaction. So how can I get tx's hash list when I import a wallet without doing transations which almost every dapp can do?

ANSWER:

I do the transaction sync on the server. I use filters and cycle through the blocks. I think there is even a GitHub repo if you search. I went the long way though. Here is the docs for web3 python. Learn More Gas Price is just an estimate. Its an arbitrary number. In the beginning there was no high or slow. It was one number and we started just "estimating". There are some calculators out there. You could use python web3 I know they return the prices. Or there's likely another api. And I use the kucoin api for prices. Learn More

[TODO - Answer @JJBFC] source: https://github.com/skywinder/web3swift/issues/377

Question #15: I tried some api from Infura. eth_getTransactionCount should return the count that my wallet made, but only the count. eth_getTransactionByHash should return the whole detail for one tx. I tried to combine this two method to get my history list but still not found how to get every hash for my tx. The getLogs *api looks like can show the whole logs with my wallet address, but I don't really know how to set the "fromBlock" and "toBlock".

ANSWER:

Please see #576 issue. Spoiler: you're too use some external services for both tasks.

[TODO - Answer @JJBFC] source: https://github.com/skywinder/web3swift/issues/377

Question #16: How can I get the hash value in TransactionInBlock?

TransactionInBlock to hash data or string. How can I convert it? That is I have get the transaction block number ,can I get transaction details by using transaction block?

ANSWER:

If the transaction is completed for same blockl

let blockNumber = BigUInt("yourBlockNumber")
let ethAdd = EthereumAddress(yourAddress)
let fullTx = try? wInstance.eth.getBlockByNumber(ethAdd, fullTransactions: true)
print(fullTx, "is transaction detail with Block number if you are the creator of block")
or you can Directly pass your block Number as it is BigUInt

The response You will get :

Optional(web3swift.Block(number: 8329255, hash: 32 bytes, parentHash: 32 bytes, nonce: Optional(8 bytes), sha3Uncles: 32 bytes, logsBloom: Optional(web3swift.EthereumBloomFilter(bytes: 256 bytes)), transactionsRoot: 32 bytes, stateRoot: 32 bytes, receiptsRoot: 32 bytes, miner: Optional(0x0000000000000000000000000000000000000000), difficulty: 54, totalDifficulty: 240834883, extraData: 97 bytes, size: 791, gasLimit: 84000000, gasUsed: 21000, timestamp: 2020-12-23 06:56:29 +0000, transactions: [web3swift.TransactionInBlock.transaction(Transaction Nonce: 12 Gas price: 250000000 Gas limit: 51993 To: 0x30f0bc2b30A36814C1C96aff8Ac221762c739E43 Value: 99987001750000000 Data: v: 28 r: 88414629294957954135223318033644220767680734761987916978592294065679295027734 s: 34433966693919024161425876030718683640418465163901476606695063733879920573501 Intrinsic chainID: nil Infered chainID: nil sender: Optional("0x77c95e25b937b83135e0E5b91fF9E1f957Ffcf01") hash: Optional(32 bytes))], uncles: [])) is transaction detail with Block number if you are the creator of block

it has most of the details

You can get these detail from transactions:

Transaction Nonce: 12
Value: 99987001750000000
To: 0x30f0bc2b30A36814C1C96aff8Ac221762c739E43
sender: Optional("0x77c95e25b937b83135e0E5b91fF9E1f957Ffcf01")
Gas price: 250000000 Gas limit: 51993

[TODO - Answer @jesuasir007] source: https://github.com/skywinder/web3swift/issues/370

Question #17: BEP20 Contract

How to interact with smart contract method for BEP20 token. When I try to access contract for https://api-testnet.bscscan.com/api?`module=contract&action=getabi&address=0xc6E070BCb7823E483164bB41D2297DCd8b1FAb25&apikey=`

guard let contract = web3.contract(contractAbi, at: EthereumAddress("0xc6E070BCb7823E483164bB41D2297DCd8b1FAb25"), abiVersion: 2) else {
return
}

ANSWER:

You have to set a custom endpoint (Networks.Custom(networkID: BigUInt(networkID) and provide a BSC settings there.

P.S. If you are interested in grants: You can make a PR with default parameters for BSC since there is lack of documentation for this method: write documentation on how to do this. |I'll make a bounty for this.

[TODO - Answer @RajKumar7777] source: https:github.com/skywinder/web3swift/issues/361

Question #18: BEP20 Contract

I have done this (Networks.Custom(networkID: BigUInt(networkID)it works as expected. I can able to send the transaction for BSC and BEP20 Tokens successfully. But Interacting with smart contract method is not working for BEP20 Tokens..It supports only ERC Token. Please check on this.

ANSWER:

I'd be more than happy to merge a PR adding this feature, it seems like it would be useful for sure.

[TODO - Answer @RajKumar7777] source: https:github.com/skywinder/web3swift/issues/361

Question #19: Can we use this for Tron (Trx) chain? Suggest one.

ANSWER:

There is no such feature yet. If it's EVM compatible, you can add it as custom network.

[TODO - Answer @akhilccrb] source: https:github.com/skywinder/web3swift/issues/350

Question #20: BEP20

This library work with BEP20 contract?

ANSWER:

Looks like it's the same as Ethereum. You just have to change RPC there is no support binance chain. P.S. Feel free to add missing functionality to the library and I will issue a bounty for this improvement.

[TODO - Answer @DorenBoust] source: https://github.com/skywinder/web3swift/issues/343

Question #21: Dapp Browser

Am integrating a Dapp browser into my ETH wallet following your documentation. I just downloaded your example project web3swiftBrowser and tried to work with.Only https://app.compound.finance this link is connecting and working. I want to connect my wallet to https://uniswap.org. When I open "https://app.compound.finance", demo can auto connect wallet. But when I open "https://app.uniswap.org/#/swap", demo cannot auto connect wallet. Check with alpha wallet app when you open "https://app.uniswap.org/#/swap" it will auto connect wallet.

ANSWER:

This is low level library. This question is not related to this functionality.

[TODO - Answer @RajKumar7777] source: https://github.com/skywinder/web3swift/issues/303

Question #22: Dapps metamask Issue

Hi am integrating Dapp browser to my app following the example provided by you. Am trying to load the link: https://portal.openalexa.io/auth in webview. When I try to connect it shows the error as please provide connection permission window.ethereum.enable is not a function. Please check the attached image.

ANSWER:

Can you check log messages in console please?

[TODO - Answer @RajKumar7777] source: https://github.com/skywinder/web3swift/issues/302

Question #23: How to use Web3.Utils.formatToEthereumUnits() to parse a BigUint?

If I get a token's decimal, and a BigUInt balance, how to format it to a string?

ANSWER:

You can use your own unit using web3Units:

Create Your Unit let myUnit = Web3Units(rawValue: your deciamal Unit)

Fetch balance with web3 instance and your address let balance = try? wInstance.eth.getBalance(address: yourEthAddress)

Convert balance in to string let balanceString = Web3.Utils.formatToEthereumUnits(balance ?? "0", toUnits: myUnit, decimals: 4)

[TODO - Answer @AlleniCode] source: https://github.com/skywinder/web3swift/issues/294

Question #24: Failed to fetch gas estimate

My code:

let keystore = try! EthereumKeystoreV3(privateKey: "MyPrivateKey", password: "MyPassword")!
let name = "New Wallet"
let keyData = try! JSONEncoder().encode(keystore.keystoreParams)
let address = keystore.addresses!.first!.address
let wallet = Wallet(address: address, data: keyData, name: name, isHD: false)

let web3 = Web3.InfuraMainnetWeb3(accessToken: "fdde8c95e4704489aac3c8b014871980")
let contractAdddress = EthereumAddress("0x7a9E457991352F8feFB90AB1ce7488DF7cDa6ed5")
let keystoreManager = KeystoreManager([EthereumKeystoreV3(wallet.data)!])
web3.addKeystoreManager(keystoreManager)

let amount = "1.0"
var options = TransactionOptions.defaultOptions
options.value = Web3.Utils.parseToBigUInt(amount, units: .eth)
options.from = EthereumAddress(wallet.address)
options.gasPrice = . automatic
options.gasLimit = .automatic

let contract = web3.contract("MyABI", at: contractAdddress, abiVersion: 2)
let parameters = [EthereumAddress("0x000000000000000000000000000000000000000E"), Web3.Utils.parseToBigUInt(amount, units: .eth)] as [AnyObject]
let transaction = contract?.write("deposit",
                                               parameters: parameters,
                                               extraData: Data(),
                                               transactionOptions: options)

let result  = try transaction?.send(password: "MyPassword", transactionOptions: options)

In 'Web3+MutatingTransaction.swift' file, line 102, printing description of results: expression produced error: error: /var/folders/z0/89zqhrn56hn16zv5y_h4vhlr0000gn/T/expr5-4bebed..swift:1:102: error: 'BigUInt' is not a member type of 'BigInt' Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Swift.Array<PromiseKit.Result<BigInt.BigUInt>>>(bitPattern: 0x110307d20)!.pointee)

ANSWER:

This is typically an issue with your "parameters". If "0x000000000000000000000000000000000000000E" is an address it needs to be EthereumAddress(whateverAddress). You're putting the value of the transaction and the value of the parameters as the same. Most likely you want one or the other? Or you wrote a bad sc. You can always get the msg.value in the contract, so why are you passing the value in?

[TODO - Answer @AlleniCode] source: https://github.com/skywinder/web3swift/issues/292

Question #25: Set ChainID?

So when I call the chainID in python I get 1111 however, when I call chain ID in swift I get 32414... Can I set the chainID? or am I doing something wrong? I'm running a private chain.

ANSWER:

I got it to work by setting the chainID after building the transaction but before sending.

[TODO - Answer @dangell7] source: https://github.com/skywinder/web3swift/issues/280

Question #26: Still Maintained?

I wanted to gather some info on the repo. I use it in a few POCs that are likely making their way to funding. Is this repo maintained? Will this repo continue into 2.0? Do you need help?

ANSWER:

Yes, this repo is supported, although it is not a priority for our team. We would be very grateful for your help in maintaining it. If you're willing to help, we can even reward GitCoin for features and updates to web3swift. You can found more information about this here: https://gitcoin.co/grants/358/web3swift

[TODO - Answer @dangell7] source: https://github.com/skywinder/web3swift/issues/271

Question #27: How to add eth_getLogs?

How to add eth_getLogs?

ANSWER:

Please have a look at this example: https://github.com/matter-labs/web3swift/blob/e36e767eb2de26decb0c157aeef2d023a1175076/Sources/web3swift/Web3/Web3%2BEventParser.swift#L254 If it doesn't help, please provide more details about your case.

[TODO - Answer @PeterCore] source: https://github.com/skywinder/web3swift/issues/270

Question #28: encodeFunctionCall

I'm trying to replicate some code made on Ionic, which uses web3.js. At a certain point, it calls web3.eth.abi.encodeFunctionCall but as far as I've looked throught the library it doesn't contain any similar feature. Here's the snippet I'm trying to mirror:

const transaction = Object.assign({}, config_1.config.basicTransaction);
    transaction.gasLimit = 600000;
    const publicKeyCallData = web3.eth.abi.encodeFunctionCall(config_1.config.contractsAbi.registry.addKey, [publicKey]);
    transaction.data = web3.eth.abi.encodeFunctionCall(config_1.config.contractsAbi.manager.identity, [publicKeyCallData]);
    transaction.to = config_1.config.manager;
    return transaction;

So far I have this, trying to replicate the first encodeFunctionCall:

 let walletAddress = EthereumAddress(walletAddress)! // Your wallet address
        let contractMethod = "addKey" // Contract method you want to write
        let contractABI = """
<JSON with ABI>
"""
        let contractAddress = EthereumAddress("<Address>")!
        let abiVersion = 2 // Contract ABI version
        let parameters : [AnyObject] = [publicKey.toHexString() as AnyObject] // Parameters for contract method
        let extraData: Data = Data() // Extra data for contract method
        let contract = w3.contract(contractABI, at: contractAddress, abiVersion: abiVersion)!
        var options = TransactionOptions.defaultOptions
        options.from = walletAddress
        options.gasPrice = .manual(BigUInt(0))
        options.gasLimit = .manual(BigUInt(600000))
        let tx = contract.method(contractMethod, parameters: parameters, extraData: extraData, transactionOptions: options)
        
if let ethTransaction = try? tx?.assemble(), let hashSignature = ethTransaction.encode(forSignature: true, chainID: nil)?.toHexString(){
            print(hashSignature)
            return hashSignature
        }else {
            throw Error.pubKeyData
        }

I've tried to use assemble and encode the transaction trying to replicate encodeFunctionCall, which then I need to add as parameter to the second method, but this fails with "Failed to fetch gas estimate" and I'm clueless wether this is an issue with how I coded that function or with the Ionic - Swift translation I'm developing. Can you elaborate on how to use web3.eth.abi.encodeFunctionCall on this library or if it's not supported at all?

ANSWER:

Hello. Now you can use this function: https://github.com/matter-labs/web3swift/blob/e36e767eb2de26decb0c157aeef2d023a1175076/Sources/web3swift/EthereumABI/ABIEncoding.swift#L136

[TODO - Answer @rextremotabaresDtt] source: https://github.com/skywinder/web3swift/issues/269

Question #29: Send ETH to contract address

I need to send ETH to contract address..But am getting issue as failed to fetch gas estimate.

My code: let walletAddress = keystoreManager.addresses![0]

let contractABI = Web3Utils.erc20ABI // Contract ABI
let contractAddressVal = EthereumAddress(contractAddress)!
let abiVersion = 2 // Contract ABI version
let contract = web3Main.contract(contractABI, at: contractAddressVal, abiVersion: abiVersion)!
let amount = Web3.Utils.parseToBigUInt(value, units: .eth)
var options = TransactionOptions.defaultOptions
options.value = amount
options.from = walletAddress
options.gasPrice = .manual(BigUInt("10000000000"))
options.gasLimit = .manual(BigUInt("70000"))

let tx = contract.write()!
  
do {
    let transaction = try tx.send(password: "", transactionOptions: options)
    print("output", transaction)
} catch(let err) {
  print("err", err)
}

ANSWER:

Hi Please check below code

Convert receiver address into Ethereum string

            `let toaddress = EthereumAddress(self.receiverAddressString ?? "")`

Create web3 options

            `var sendTransactionIntermediateOptions = Web3Options.defaultOptions()`

Convert amount into BIGINT

            `let amountDouble = BigInt((Double(sendigTokenCount) ?? 1.0)*pow(10, 18))`
            `print("Total amount in double value : ", amountDouble)`

Convert amount in BigUInt

            `let amount = BigUInt.init(amountDouble)`

get gas price let estimateGasPrice = try wInstance.eth.getGasPrice() guard let contractString = self.contractAddressString else { print("Unable to get contract address") return }

Create your contract address as EthereumAddress

           `let contractAddress = EthereumAddress(contractString)
            guard let eGasReult = self.estimatedGasResult else {
                print("Unable to find gas")
                return
            }`

Get nonce

            print("estimated gas : ", eGasReult)
            let fee = estimateGasPrice * eGasReult
            print("Is the Transaction fees ", fee)
             adding
             - sender address
             - Gas Result
             - Gas price
             - amount
             

            `sendTransactionIntermediateOptions.from = senderEthAddress`
            `sendTransactionIntermediateOptions.gasLimit = eGasReult`
            `sendTransactionIntermediateOptions.gasPrice = estimateGasPrice`

Strat your Transaction with contract

            `var tokenTransactionIntermediate: TransactionIntermediate!`

tokenTransactionIntermediate = try wInstance.contract(Web3.Utils.yourABIString, at: contractAddress).method("transfer", args: toaddress, amount, options: sendTransactionIntermediateOptions)

[TODO - Answer @rachkumar] source: https://github.com/skywinder/web3swift/issues/259

Question #30: Please tell me where the password is obtained?

Please tell me where the password is obtained? Send Transaction Write

let password = "web3swift"
let result = try! transaction.send(password: password)

ANSWER:

It's a hard coded value.

[TODO - Answer @suusofttruongnv] source: https://github.com/skywinder/web3swift/issues/255

Question #31: Send ERC-20 Token error

let value: String = amountStr
let walletAddress = EthereumAddress(wallet.address)! // Your wallet address
let toAddress = EthereumAddress(toAddressStr)!
let erc20ContractAddress = EthereumAddress("0xaB8Ad2d7f39A54960Be8b71e01276a9E897833eE", ignoreChecksum:true)!
let contract = self.web3.contract(Web3.Utils.erc20ABI, at: erc20ContractAddress, abiVersion: 2)!
let amount = Web3.Utils.parseToBigUInt(value, units: .eth)
var options = TransactionOptions.defaultOptions
options.value = amount
options.from = walletAddress
options.gasPrice = .automatic
options.gasLimit = .automatic
let method = "transfer"
let tx = contract.write(
method,
parameters: [toAddress, amount] as [AnyObject],
extraData: Data(),
transactionOptions: options)!
let res = try tx.send(password: password, transactionOptions: options)
            print(res.hash)
back:
processingError(desc: "Failed to fetch gas estimate")

I also get an error when I try to send the token to a different address

let web3 = getWeb3()
    let walletAddress = EthereumAddress(wallet_token.address)! // Your wallet address
    let toAddress = EthereumAddress(toAddressString)!
    let erc20ContractAddress = EthereumAddress(token.address)!
    let contract = web3.contract( Web3.Utils.erc20ABI, at: erc20ContractAddress, abiVersion: 2)! 
    let amount = Web3.Utils.parseToBigUInt(value, decimals: token.decimals)
    var options = TransactionOptions.defaultOptions
    options.value = amount
    options.from = walletAddress
    options.gasPrice = .automatic
    options.gasLimit = .automatic
    let method = "transfer"
    let tx = contract.write(
        method,
        parameters: [toAddress, amount] as [AnyObject],
        extraData: Data(),
        transactionOptions: options)!
    
    do {
        let result = try tx.send(password: "web3swift")
        print("\(TAG) result")
        return result
    } catch let error {
        print("\(TAG) error" + error.localizedDescription)
        throw error
    }

It appears an error like this:

PromiseKit: warning: wait() called on main thread! error The operation couldn’t be completed. (web3swift.Web3Error error 2.)

Please help me, what do I have to do to fix it, and send my ERC token smoothly?

ANSWER:

Change: options.value = Web3.Utils.parseToBigUInt("0", decimals: token.decimals)

[TODO - Answer @CYC666] source: https://github.com/skywinder/web3swift/issues/251

Question #32: How to get public key After generating a wallet?

How to get public key After generating a wallet?

ANSWER:

If you saved your data in KeystoreManager, try this

let privateKey = try! keystoreManager.UNSAFE_getPrivateKeyData(password: password, account: ethereumAddress)
let publicKey = Web3.Utils.privateToPublic(privateKey, compressed: false)!

[TODO - Answer @amirhossein7] source: https://github.com/skywinder/web3swift/issues/233

Question #33: How to know when another person send eth for me?

I try to send ETH in Ropsten. I connect to WebSockets follow document and I don't know how to get amount ETH another person send for me? Can you help me? I need example.

ANSWER:

Please, have a look at documentation in this section: https://github.com/matter-labs/web3swift/blob/master/Documentation/Usage.md#create-a-new-subscription-over-particular-events

And here is test, where you can see example in action: https://github.com/matter-labs/web3swift/blob/develop/Tests/web3swiftTests/web3swift_Websockets_Tests.swift#L72-L94

[TODO - Answer @tuanYasuo] source: https://github.com/skywinder/web3swift/issues/215

Question #34: Encrypt Decrypt using generated EC Key Pair

Is there any function here to encrypt and decrypt using the generated key pair using this library?

ANSWER:

Please, have a look for tests for examples: https://github.com/matter-labs/web3swift/blob/df45360ac4c9741cf43a0828bdbb296d374acf0f/Carthage/Checkouts/CryptoSwift/Tests/CryptoSwiftTests/ExtensionsTest.swift#L74

[TODO - Answer @tentenponce] source: https://github.com/skywinder/web3swift/issues/211

Question #35: Where is "web3swiftExample"?

I want to run "example" app, but I faild to move "web3swiftExample" described in "https://github.com/matter-labs/web3swift#example-project" If it is not possible, can I get any simple example of web3swift.

ANSWER:

You can run it from Exmaple folder.

[TODO - Answer @surida] source: https://github.com/skywinder/web3swift/issues/194

Question #36: Is there any function to calculate minimum amount needed to perform ethereum transaction?

I wanted to know is there any function in web3swift to validate minimum amount required to make transaction?

ANSWER:

Think you need estimateGas function. It estimates a minimal amount of gas required to run a transaction. To do it the Ethereum node tries to run it and counts how much gas it consumes for computations. Setting the transaction gas limit lower than the estimate will most likely result in a failing transaction. Usage example:

let web3 = Web3.InfuraMainnetWeb3()
let sendToAddress = EthereumAddress("recepient_address")
let keystore = try! EthereumKeystoreV3(password: "")
let keystoreManager = KeystoreManager([tempKeystore!])
web3.addKeystoreManager(keystoreManager)
let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)
guard let writeTX = contract?.write("fallback") else {return} // you can use any other tx method
writeTX.transactionOptions.from = tempKeystore!.addresses?.first // its your address
writeTX.transactionOptions.value = BigUInt("1.0", .eth) // value in eth
let estimate = try writeTX.estimateGasPromise().wait()
print(estimate) // here you'll get gas estimation

[TODO - Answer @DiwakarThapa] source: https://github.com/skywinder/web3swift/issues/134

Question #37: Generating 12-word mnemonic from private key

I would like to get a mnemonic representation of a private key. Right now, I am getting 24 words by doing the following:

 private func generateKey() -> String {
        let userDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        var ks: EthereumKeystoreV3?
        ks = try! EthereumKeystoreV3(password: "PASSWORD")
        let keydata = try! JSONEncoder().encode(ks!.keystoreParams)
        FileManager.default.createFile(atPath: userDir + "/keystore"+"/key.json", contents: keydata, attributes: nil)
        var mnemonic: String = ""
        do {
            if let pk = try ks?.UNSAFE_getPrivateKeyData(password: "PASSWORD", account: (ks?.addresses?.first)!) {
                print("pk to hex: \(pk.toHexString())")
                let entropy = Data(hex: pk.toHexString())
                mnemonic = Mnemonic.create(entropy: entropy)
                print("pk hex to menmonic: \(mnemonic)")
            }
        } catch {print("Error with getting private key: \(error)")}
        return mnemonic
    }

I am using the Mnemonic helper class found here: https://github.com/essentiaone/HDWallet/blob/develop/HDWalletKit/Mnemonic/Mnemonic.swift

This is the Mnemonic.create function: public static func create(entropy: Data, language: WordList = .english) -> String { let entropybits = String(entropy.flatMap { ("00000000" + String(, radix: 2)).suffix(8) }) let hashBits = String(entropy.sha256().flatMap { ("00000000" + String(, radix: 2)).suffix(8) }) let checkSum = String(hashBits.prefix((entropy.count * 8) / 32))

    let words = language.words
    let concatenatedBits = entropybits + checkSum
    
    var mnemonic: [String] = []
    for index in 0..<(concatenatedBits.count / 11) {
        let startIndex = concatenatedBits.index(concatenatedBits.startIndex, offsetBy: index * 11)
        let endIndex = concatenatedBits.index(startIndex, offsetBy: 11)
        let wordIndex = Int(strtoul(String(concatenatedBits[startIndex..<endIndex]), nil, 2))
        mnemonic.append(String(words[wordIndex]))
    }
    
    return mnemonic.joined(separator: " ")
}

A couple questions:

Would the user still be able to derive their private key from this mnemonic? Also, instead of generating a 24-word mnemonic, is it possible to generate a 12-word mnemonic?

ANSWER:

I was able to generate a 12-word mnemonic by changing the following: ```

for index in 0..<(concatenatedBits.count / 11) {
            ...

Changed to:

 for index in 0..<(concatenatedBits.count / 22) {
            ...

[TODO - Answer @barrasso] source: https://github.com/skywinder/web3swift/issues/79

Question #38: How to signed Transaction

Facing problem how to sign Transaction and get token then sent to server.

ANSWER:

// transactionSign func transactionSign(nonce :String,gasPrice :String,gasLimit :String,toAddress :String,value :String,privateKeyData :Data,chainID :String,templateData :Data) -> Data {

var transaction = EthereumTransaction(nonce: BigUInt(nonce)!,
                                          gasPrice: BigUInt(gasPrice)!,
                                          gasLimit: BigUInt(gasLimit)!,
                                          to: EthereumAddress(toAddress)!,
                                          value: BigUInt(value)!,
                                          data: templateData,
                                          v: BigUInt(0),
                                          r: BigUInt(0),
                                          s: BigUInt(0))
    transaction.UNSAFE_setChainID(BigUInt(chainID)!)
    print(transaction)
    try! Web3Signer.EIP155Signer.sign(transaction: &transaction, privateKey: privateKeyData, useExtraEntropy: false)
    print(transaction)
    let encoded:Data? = transaction.encode()
    return encoded!
}

[TODO - Answer @kirti301290] source: https://github.com/skywinder/web3swift/issues/61

Question #39: How to custom nonce?

Create two transaction in a short time,will cause replacement error due to same nonce,so how to create custom nonce transcation?

ANSWER:

Right now you have to assemble a transactions manually or by help of transaction intermediate and then set the nonce.

 guard case .success(let tx) = transactionIntermediate.assemble(options: someOptions, onBlock: "pending") // may fail, that would mean that gas estimation failed, for example
  var txCopy = tx
  txCopy.nonce = BigUInt(1337)
  let result = web3.eth.sendTransaction(txCopy, options: someOptions, password: "web3swift")

[TODO - Answer @cctanfujun] source: https://github.com/skywinder/web3swift/issues/37

Question #40: New account

Can have an example of creating a new account?

ANSWER:

Here is "How to create account" example in readme: https://github.com/matterinc/web3swift#create-account

Here's an example for a password protected keystore called EthereumKeystoreV3 ... you'll need to sort out the optionals and preferably remove the fatalError calls.

//First you need a `KeystoreManager` instance:
guard let userDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first,
    let keystoreManager = KeystoreManager.managerForPath(userDirectory + "/keystore")
else {
    fatalError("Couldn't create a KeystoreManager.")
}

//Next you create the a new Keystore:

let newKeystore = try? EthereumKeystoreV3(password: "YOUR_PASSWORD")

// Then you save the created keystore to the file system:

let newKeystoreJSON = try? JSONEncoder().encode(newKeystore.keystoreParams)
FileManager.default.createFile(atPath: "\(keystoreManager.path)/keystore.json", contents: newKeystoreJSON, attributes: nil)

// Later you can retreive it:

if let address = keystoreManager.addresses?.first,
let retrievedKeystore = keystoreManager.walletForAddress(address) as? EthereumKeystoreV3 {
    return retrievedKeystore
}

[TODO - Answer @soulCorw] source: https://github.com/skywinder/web3swift/issues/29

Question #41: Is there any functions to get pending transactions list?

I want to check the transactions is in pending,is there any functions to get pending transactions list likes python supportted https://web3py.readthedocs.io/en/stable/web3.txpool.html or is there any way to check the tx_hash is in pending?

ANSWER:

Monitoring of transaction satus could be useful feature. Probably we can do a convenience method like:

enum TxStatus {
  case Completed
  case Rejected
  case Pending
}
func checkTransacion(timeout : Int , repeat_interval :Int) -> (TxStatus) {
    ...
}

[TODO - Answer @tiantianyuan] source: https://github.com/skywinder/web3swift/issues/28

Question #42: PromiseKit example

Could you please provide an example of how to use the async functions. For example web3.eth.getGasPricePromise().then { ???? }

Whatever I do with what comes from autocomplete gives a build-time error.

ANSWER:

There is a good example in code

self.assemblePromise(options: options, onBlock: onBlock).then(on: queue) { transaction throws -> Promise<TransactionSendingResult> in
            guard let mergedOptions = Web3Options.merge(self.options, with: options) else {
                throw Web3Error.inputError(desc: "Provided options are invalid")
            }
            var cleanedOptions = Web3Options()
            cleanedOptions.from = mergedOptions.from
            cleanedOptions.to = mergedOptions.to
            return self.web3.eth.sendTransactionPromise(transaction, options: cleanedOptions, password: password)
        }

If you call then - your internal closure should return a Promise If you call map - you can return a normal value that will be wrapped into the Promise for further chaining

[TODO - Answer @matijakregar] source: https://github.com/skywinder/web3swift/issues/23

Question #43: When can I use ERC721?

When can I use ERC721?

ANSWER:

ERC20 support is already implemented. we are currently working on support of erc721 as well.

[TODO - Answer @coderybxuu] source: https://github.com/skywinder/web3swift/issues/20

Question #44: How to listen the contract event?

I don't know where the event listener.

ANSWER:

Me(@skywinder) and Alex (@shamatar) as main maintainers are moving our development to the new repo ➡️ https://github.com/matterinc/web3swift

[TODO - Answer @BlueFlicker] source: https://github.com/skywinder/web3swift/issues/18

Question #45: How to import wallet by keystore and password?

I want to import wallet by keystore and password. what should I do?

ANSWER:

If you want to export the private key - just use the public func UNSAFE_getPrivateKeyData(password: String, account: EthereumAddress) throws -> Data Otherwise if you follow the normal workflow for sending ETH, tokens or interacting with a smart-contract you can use an encrypted keystore and only supply a password to decrypt it when sending a transaction.

[TODO - Answer @chenshuai0710] source: https://github.com/skywinder/web3swift/issues/9

Question #46: Calling a payable function with parameters

I'm struggling to find an example to use a payable function with parameters.

let's say i've an function in my Smart Contract:

 function doSomething(address[] _adresses, address[] _groups, uint[] _percentages)
        public
        payable
        returns(address) {

How do i call this SC and send ethers to it & pass parameters and get the return value?

ANSWER:

Please, check our new documentation, here is well explained how to use library: https://github.com/matterinc/web3swift/blob/develop/Documentation/Usage.md

[TODO - Answer @ungaro] source: https://github.com/skywinder/web3swift/issues/8

Question #47: How to decode input data from transaction?

I have fetched transactions list from etherscan.io API. I need to decode input data to get the value and the token receiver address for ERC20Token transaction.

for example, the following input data 0xa9059cbb000000000000000000000000066a46470fd976e89303f501b704f73016da101e0000000000000000000000000000000000000000000000000de0b6b3a7640000

ANSWER:

Please refer to the web3swift_contractV2_Tests in the source code, it has two examples of how to decode the input data. Those examples are for ERC20 input data actually.

[TODO - Answer @runryan] source: https://github.com/skywinder/web3swift/issues/6

Question #48: Calling a payable function with parameters?

I'm struggling to find an example to use a payable function with parameters.

let's say i've an function in my Smart Contract:

 function doSomething(address[] _adresses, address[] _groups, uint[] _percentages)
        public
        payable
        returns(address) {

How do i call this SC and send ethers to it & pass parameters and get the return value?

ANSWER:

First of all you should understand that if the function is mutating (like one above) you are not guaranteed that a return value will in fact be the same when you check for it and when transaction executes.

how to get a return value: encode the parameters into the “TransactionIntermediate”. Please check the various examples in tests use the “call” method on this intermediate and supply required options (Web3Options struct) into the call. One of the field in options is “value” - it’s an amount of Wei (1 ETH = 10^18 wei) attached to the transaction upon execution you will get returned parameters to send a transaction make an intermediate use the “send” method and supply the options I recommend you to go through the tests of web3swift to check the examples.

[TODO - Answer @ungaro] source: https://github.com/skywinder/web3swift/issues/2

Question #49: Create a EIP712 TypedData signature?

I need to do a EIP712 signature in my app. I saw that web3swift allowed EIP712 but when I saw the test file https://github.com/skywinder/web3swift/blob/e733e077a613cba3a68ec7b480f1f7ef1a22d316/Tests/web3swiftTests/localTests/EIP712Tests.swift I saw that it uses a predetermined Gnosis SafeTX. I would like to know how to change the parameters of the safetx to be able to create a correct signature.

ANSWER:

Looks like Web3Signer.signEIP712 must accept any EIP712Hashable object and not just SafeTx. That's a mistake on the side of the library. I've just updated locally the type of the first input argument of that function, ran tests and can confirm that it will fix the issue. We will fix that in the upcoming release.

Temporarily you can use the implementation from Web3Signer.signEIP712 in a place where you need to construct a signature or you can create a copy of that function temporarily if you need that in multiple places:

public func signEIP712(_ eip712HashableMessage: EIP712Hashable, keystore: BIP32Keystore, verifyingContract: EthereumAddress, account: EthereumAddress, password: String? = nil, chainId: BigUInt? = nil) throws -> Data {

`let domainSeparator: EIP712DomainHashable = EIP712Domain(chainId: chainId, verifyingContract: verifyingContract)`

`let password = password ?? ""`
`let hash = try eip712encode(domainSeparator: domainSeparator, message: eip712HashableMessage)`

`guard let signature = try Web3Signer.signPersonalMessage(hash, keystore: keystore, account: account, password: password) else {`
    `throw Web3Error.dataError`
`}`

`return signature`

}

You can even copy-paste this function outside of any class/struct to make it accessible globally. I'll post updates here as PR will be opened and merged.

Looks like you'll have to wait until this fix is released as eip712encode function is not public.

[TODO - Answer @OnChainArt] source: https://github.com/skywinder/web3swift/issues/617

Question #50: How can we deploy smart contract using webe3swift?

In web3java, i can deploy a smart contract by following the methods

Create .bin and .abi files from solidity file using solcjs library. Create java file using .abi and .bin files. Java file contains deploy() method to deploy a smart contract on Ethereum network. Now in web3swift i don't see any method to deploy smart contract. I know there will be any other way of deploying but i don't know. can anyone please help in this regard?

ANSWER:

You can try using one of the following options. There is definitely an improvement for that API coming but I cannot tell when exactly that will be done.

Options:

  1. Create the whole transaction // Some smart contract instance let contract = web3Instance.contract(...)

// A transaction ready to be signed and executed let writeTransaction = contract.prepareDeploy(bytecode: yourScBytecode) ...

  1. Create only encoded data - how a transaction object will be created is up to you. // It throws only if you give two functions with exactly the same name and input but different output. // That's an invalid overloading of a function. We're safe here thus using try!. let contract = try! EthereumContract(abi: [])

// There is also an option to pass constructor and input arguments let encodedData = contract.deploy(smartContractBytecode) ...

[TODO - Answer @ShoaibKakal] source: https://github.com/skywinder/web3swift/issues/612

Question #51: SPM Package Not Working With 3.0.0 Version

I created a project from scratch and tried to use SPM 3.0.0 version. I just tried a simple implementation: let walletAddress = try? BIP32Keystore(mnemonics: "" , prefixPath: "") I am getting this error: Cannot find 'BIP32Keystore' in scope

I can't access anything inside the library.

ANSWER:

You have to add import Core alongside to import Web3Swift to your sources to make it works.

[TODO - Answer @rocxteady] source: https://github.com/skywinder/web3swift/issues/629

Question #52: Error while installing from develop branch

Hi! I tried to install the develop branch to get the EIP712 fix but I get an web3core error while installing it with cacaopods.

_[!] CocoaPods could not find compatible versions for pod "Web3Core": In Podfile: web3swift (from https://github.com/OnChainArt/web3swift.git) was resolved to 3.0.0, which depends on Web3Core (~> 3.0.0)

None of your spec sources contain a spec satisfying the dependency: Web3Core (~> 3.0.0).

You have either:

out-of-date source repos which you can update with pod repo update or with pod install --repo-update. mistyped the name or version. not added the source repo that hosts the Podspec to your Podfile._

ANSWER:

Yep, due to package split to two modules and cocoapods dependency issue it's not released on cocoapods yet. We're working on it, but it could take up to few more weeks.

[TODO - Answer @OnChainArt] source: https://github.com/skywinder/web3swift/issues/626

Question #53: Will web3 and eth have circle reference issues?

class web3{

    var ethInstance: web3.Eth?
    ....
   
    public class Eth: TransactionOptionsInheritable {
        ...
        public init(provider prov: Web3Provider, web3 web3instance: web3) {
            provider = prov
            web3 = web3instance
        }
    }

I didn't see the release of web3 in 'debug memory graph'.

ANSWER:

Please try new major update, is this issue is still represents there?

[TODO - Answer @vincentiss] source: https://github.com/skywinder/web3swift/issues/601

Question #54: How to read internal transaction?

I write a transaction with a smart contract,but the result what I want to retrieve is inside Internal Transactions. so How can I get the internal transactions? If I can use ‘eth_call’ method to get a tx information? And how can I make it in this repo? Thanks for answering.

ANSWER:

As long as you have the TransactionHash you can use web3.eth.getTransactionDetails() to retrieve the transaction itself. getTransactionDetails returns a structure with a meber called .transaction which is the decoded transaction. From there you have access to all the parameters and data that was encoded within the transaction. Note that if the transaction was a contract call, you will need to do some further decoding of the data field to get at that data, as that will be contract specific.

[TODO - Answer @KittenYang] source: https://github.com/skywinder/web3swift/issues/597

Question #55: Transaction option is not applied to send translation

There is a problem that the trasactionOptions cannot be used properly because of merge. In the Web3+ MutatingTransaction class, it is replaced by cleanedOptions. I want to know the reason. 2.6.5 library version. Estimategas for EIP1559 is excellent. However, transaction option is not applied to send translation.

var options = writeTransaction.transactionOptions options.nonce = .latest options.callOnBlock = .latest options.type = .eip1559 options.maxFeePerGas = .manual(maxFee) options.maxPriorityFeePerGas = .manual(maxTip)

If you run sendTransactionPromise with the above options, maxFeePerGas and maxPriorityFeePerGas are ignored. There seems to be some problem when merge.

public func sendPromise(password: String = "web3swift", transactionOptions: TransactionOptions? = nil) -> Promise<TransactionSendingResult>{ let queue = self.web3.requestDispatcher.queue return self.assemblePromise(transactionOptions: transactionOptions).then(on: queue) { transaction throws -> Promise<TransactionSendingResult> in let mergedOptions = self.transactionOptions.merge(transactionOptions) var cleanedOptions = TransactionOptions () cleanedOptions.to = mergedOptions.to return self.web3.eth.sendTransactionPromise(transaction, transactionOptions: cleanedOptions, password: password) } } image

maxFeePerGas , maxPriorityFeePerGas, type, nonce all nil. Only from, to exists.

/// create a JSCON RPC Request object for the given transaction /// - Parameters: /// - method: RPC request method /// - transaction: the thansaction to encode/send /// - trasactionOptions: additional options for the transaction /// - Returns: a JSCONRPCrequest object static func createRequest(method: JSONRPCmethod, transaction: EthereumTransaction, transactionOptions: TransactionOptions?) -> JSONRPCrequest? { let onBlock = transactionOptions?.callOnBlock?.stringValue var request = JSONRPCrequest ()

request.method = method let from = transactionOptions?.from quard var txParams = transaction.encodeAsDictionary(from: from) else { return nil } if method == .estimateGas || transactionOptions?.gasLimit == nil { txParams.gas = nil } var params = [txParams] as [Encodable] if method.requiredNumOfParameters == 2&& onBlock != nil { params.append( onBlock as Encodable ) } let pars = JSONRPCparams(params: params) request.params = pars if !request.isValid { return nil } return request }

ANSWER:

Here is even more proof that your transaction options will actually get into JSON RPC request's parameters. I've set maxFeePerGas to .manual(1) and maxPriorityFeePerGas to .manual(2) which are 0x1 and 0x2 in HEX respectively.

▿ TransactionParameters
  ▿ type : Optional<String>
    - some : "0x2"
  ▿ chainID : Optional<String>
    - some : "0x181d7807ea5"
  ▿ data : Optional<String>
    - some : "0xd93c982100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000011536f6d6520696e70757420737472696e67000000000000000000000000000000"
  ▿ from : Optional<String>
    - some : "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae"
  ▿ gas : Optional<String>
    - some : "0xf1140"
  - gasPrice : nil
  ▿ maxFeePerGas : Optional<String>
    - some : "0x1"
  ▿ maxPriorityFeePerGas : Optional<String>
    - some : "0x2"
  ▿ accessList : Optional<Array<AccessListEntry>>
    - some : 0 elements
  ▿ to : Optional<String>
    - some : "0xbb9bc244d798123fde783fcc1c72d3bb8c189413"
  ▿ value : Optional<String>
    - some : "0x759"

[TODO - Answer @Kristenlike1234] source: https://github.com/skywinder/web3swift/issues/586

Question #55: Deprecated description for Send ERC-20 Token

https://github.com/skywinder/web3swift#send-erc-20-token

When send ERC-20 Token not needed line - "options.value = amount" because method "transfer" in erc20ABI is not "payable"

ANSWER:

Generally speaking ALL transactions need a value, even if not payable. So if the transaction has no value, set value to 0. The requirement for it to be set in options is there because value is a required field for a transaction on the chain.

[TODO - Answer @6od9i] source: https://github.com/skywinder/web3swift/issues/568

Question #56: Import the keystore file when error

when I import the Keystore file into the metamask, the error as : Private key does not satisfy the curve requirements (ie. it is invalid) where is the error, who can help me?

ANSWER:

I think you should search on a web for common solutions to recover your assets as there is nothing special we have here for you to help.

[TODO - Answer @Crypjoe1] source: https://github.com/skywinder/web3swift/issues/564

Question #57: Best way to test smart contracts using this library

I'm new in ethereum development and I found out that there is only one way to effectively test smart contracts is using 'truffle'. Truffle requires javascript knowledge and I don't really want to learn javascript.

Can I use this library to interact with truffle (somehow) or directly with 'ganache' to effectively test smart contracts and work with them in production not using javascript? I need to know should I really learn javascript to become professional smart contract developer or not.

Thanks!

ANSWER:

While you can test contracts using web3Swift, you'll likely find it easier and more efficient to use something like Remix for the contract development side, then transition to something like Web3Swift when you get to the application side of things.

[TODO - Answer @xbladesub] source: https://github.com/skywinder/web3swift/issues/538

Question #58: Creating a new wallet is too slow

macos Version :12.3 xcode Version : 13.3 cocospod Version:1.11.3 Installing BigInt (5.2.0) Installing CryptoSwift (1.4.3) Installing PromiseKit (6.15.3) Installing Starscream (4.0.4) Installing secp256k1.c (0.1.2) Installing web3swift (2.6.0) image Creating a new wallet is too slow, 5 seconds to print information image

image

Get private key is too slow,5 seconds to print information The speed of creating wallet in web3swift version 2.3.0 is normal

ANSWER:

I can confirm that the issue lies between debug and release builds. I created a simple test app to create a private key.

Debug Build/Run: 7.790989995002747 Release Build/Run: 0.10214793682098389

The issue is also exclusively when building via SPM, as SPM builds everything from source, using the app's build settings. XCode projects include the libraries as frameworks, which are built separately in release mode, so even a debug app, does not see the same performance hit.

This not really an issue as it affects debugging only, and there is nothing we can really do about it. This is a known issue with CryptoSwift, you can follow the link posted in https://github.com/skywinder/web3swift/issues/535 if you want to know more.

This issue should probably be closed at this point.

[TODO - Answer @xhzth70911] source: https://github.com/skywinder/web3swift/issues/538

Question #59: Send ERC-20 Token

macos 版本:12.3 xcode 版本:13.3 cocospod 版本:1.11.3 web3swift (2.6.0) and web3swift (2.3.0) I send erc-20 token without option.Value can succeed, but I fill in option.Value will report an error in the future. How to deal with it

Error reporting information: web3swift.Web3Error.processingError(desc: "Failed to fetch gas estimate")

code: @IBAction func Ethe(_ sender: Any) { SendERC(value: "1.0", toAddressString: "0xd914c8b0BD935C4F5709Bd9F1ed2A5a01ADdFE1a") }

func SendERC(value:String,toAddressString:String){
    
    let walletAddress = EthereumAddress(address)!
    let toAddress = EthereumAddress(toAddressString)!
    let erc721ContractAddress = EthereumAddress("0x3aae468ffaa298147c7249ed10e03610bc932e26", ignoreChecksum: true)!
    let contract = web3.contract(Web3.Utils.erc721ABI, at: erc721ContractAddress, abiVersion: 2)!
    let tokenID = BigUInt(0)
    let originalOwner = EthereumAddress(address)!
   //print("tokenId :\(tokenID)")
    let amount = Web3.Utils.parseToBigUInt(value, units: .eth)
    var option = TransactionOptions.defaultOptions
    option.from = walletAddress

// option.value = amount // option.gasLimit = .automatic // option.gasPrice = .automatic option.gasLimit = .manual(BigUInt(60000)) do { let gasPriceResult = try web3.eth.getGasPrice() option.gasPrice = .manual(gasPriceResult) let method = "transferFrom" let tx = contract.write(method, parameters: [originalOwner, toAddress, tokenID] as [AnyObject], extraData: Data(), transactionOptions: option)!

  let result =  try! tx.send(password:password)
        print("scu:\(result)")
    } catch let e {
       print("err:\(e)")
    }
}

I send erc-20 token without option Value can succeed, but I fill in option Value will report an error in the future Success: image

ANSWER:

Can you please provide the exact code for when it is failing? The error you show is for gasLimit estimation, and I can see no reason as to why, or how, you can get that error by simply setting value for the transaction.

[TODO - Answer @xhzth70911] source: https://github.com/skywinder/web3swift/issues/539

Clone this wiki locally