Integrate Web3Auth with the Ethereum Blockchain in Android
While using the Web3Auth Android SDK, you get the private key and sessionId within the user scope.
This private key can interact with Ethereum to make any blockchain calls,
like getting the user's account
, fetching balance
, sign transaction
, send transaction
,
read
from and write
to the smart contract, etc. We have highlighted a few here to get you
started quickly on that.
Installation
To interact with the Ethereum blockchain in Android, you can use any EIP1193
compatible package available
for Android. Here we're using web3j to demonstrate how to make blockchain calls using it with Web3Auth.
In your app-level build.gradle
's dependencies section, add the following:
dependencies {
// ...
implementation 'org.web3j:core:4.8.7-android'
}
Chain Details for Ethereum
- Mainnet
- Testnet
- Chain ID: 0x1
- Public RPC URL: https://rpc.ankr.com/eth (Avoid using public rpcTarget in production, use services like Infura, Quicknode etc)
- Display Name: Ethereum Mainnet
- Block Explorer Link: https://etherscan.io
- Ticker: ETH
- Ticker Name: Ethereum
- Chain ID: 0xaa36a7
- Public RPC URL: https://rpc.ankr.com/eth_sepolia (Avoid using public rpcTarget in production, use services like Infura, Quicknode etc)
- Display Name: Ethereum Sepolia Testnet
- Block Explorer Link: https://sepolia.etherscan.io
- Ticker: ETH
- Ticker Name: Sepolia
Initialize
class MainActivity : AppCompatActivity() {
private lateinit var web3Auth: Web3Auth
private lateinit var web3: Web3j
private lateinit var credentials: Credentials
private val rpcUrl = "" // RPC URL of EVM Chain
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
web3Auth = Web3Auth(
Web3AuthOptions(context = this,
clientId = getString(R.string.web3auth_project_id),
network = Network.MAINNET,
redirectUrl = Uri.parse("{YOUR_APP_PACKAGE_NAME}://auth")
)
)
// Handle user signing in when app is not alive
web3Auth.setResultUrl(intent?.data)
// Call initialize() in onCreate() to check for any existing session.
val sessionResponse: CompletableFuture<Void> = web3Auth.initialize()
sessionResponse.whenComplete { _, error ->
if (error == null) {
reRender()
println("PrivKey: " + web3Auth.getPrivkey())
println("ed25519PrivKey: " + web3Auth.getEd25519PrivKey())
println("Web3Auth UserInfo" + web3Auth.getUserInfo())
credentials = Credentials.create(web3Auth.getPrivkey())
web3 = Web3j.build(HttpService(rpcUrl))
} else {
Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
// Ideally, you should initiate the login function here.
}
}
// Setup UI and event handlers
val signInButton = findViewById<Button>(R.id.signInButton)
signInButton.setOnClickListener { signIn() }
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Handle user signing in when app is active
web3Auth.setResultUrl(intent?.data)
}
private fun signIn() {
val selectedLoginProvider = Provider.GOOGLE // Can be GOOGLE, FACEBOOK, TWITCH etc.
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> =
web3Auth.login(LoginParams(selectedLoginProvider))
loginCompletableFuture.whenComplete { loginResponse, error ->
if (error == null) {
// render logged in UI
println(loginResponse)
// Set the sessionId from Web3Auth in App State
credentials = Credentials.create(web3Auth.getPrivkey())
web3 = Web3j.build(HttpService(rpcUrl))
} else {
// render error UI
}
}
}
//...
}
Get User Info
You get the user information after a successful login returned from the login
method. The
userInfo
object contains the user information, whereas the privKey
object contains the private
key that can be used to make blockchain calls.
private fun signIn() {
val selectedLoginProvider = Provider.GOOGLE // Can be GOOGLE, FACEBOOK, TWITCH etc.
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> =
web3Auth.login(LoginParams(selectedLoginProvider))
loginCompletableFuture.whenComplete { _, error ->
if (error == null) {
// render logged in UI with User's Info
credentials = Credentials.create(web3Auth.getPrivkey())
web3 = Web3j.build(HttpService(rpcUrl))
} else {
// render error UI
}
}
}
Get Account
private fun getAddress(): String {
println("Address:, ${credentials.address}")
return credentials.address
}
// Setup UI and event handlers
val getAccountButton = findViewById<Button>(R.id.getAccountButton)
getAccountButton.setOnClickListener { getAddress() }
Get Balance
private fun getBalance(): BigInteger? {
val publicAddress = credentials.address
val ethBalance: EthGetBalance = web3.ethGetBalance(publicAddress, DefaultBlockParameterName.LATEST).sendAsync().get()
println("Balance: ${ethBalance.balance}")
return ethBalance.balance
}
// Setup UI and event handlers
val getBalanceButton = findViewById<Button>(R.id.getBalanceButton)
getBalanceButton.setOnClickListener { getBalance() }
Send Transaction
private fun sendTransaction(amount: Double, recipientAddress: String): String? {
val ethGetTransactionCount: EthGetTransactionCount = web3.ethGetTransactionCount(credentials.address, DefaultBlockParameterName.LATEST).sendAsync().get()
val nonce: BigInteger = ethGetTransactionCount.transactionCount
val value: BigInteger = Convert.toWei(amount.toString(), Convert.Unit.ETHER).toBigInteger()
val gasLimit: BigInteger = BigInteger.valueOf(21000)
val chainId: EthChainId = web3.ethChainId().sendAsync().get()
// Raw Transaction
val rawTransaction: RawTransaction = RawTransaction.createTransaction(
chainId.chainId.toLong(),
nonce,
gasLimit,
recipientAddress,
value,
"",
BigInteger.valueOf(5000000000),
BigInteger.valueOf(6000000000000)
)
val signedMessage: ByteArray = TransactionEncoder.signMessage(rawTransaction, credentials)
val hexValue: String = Numeric.toHexString(signedMessage)
val ethSendTransaction: EthSendTransaction = web3.ethSendRawTransaction(hexValue).sendAsync().get()
return if(ethSendTransaction.error != null) {
println("Tx Error: ${ethSendTransaction.error.message}")
ethSendTransaction.error.message
} else {
println("Tx Hash: ${ethSendTransaction.transactionHash}")
ethSendTransaction.transactionHash
}
}
// Setup UI and event handlers
val sendTransactionButton = findViewById<Button>(R.id.sendTransactionButton)
sendTransactionButton.setOnClickListener { sendTransaction() }
Sign a message
private fun signMessage(message: String): String {
val hashedData = Hash.sha3(message.toByteArray(StandardCharsets.UTF_8))
val signature = Sign.signMessage(hashedData, credentials.ecKeyPair)
val r = Numeric.toHexString(signature.r)
val s = Numeric.toHexString(signature.s).substring(2)
val v = Numeric.toHexString(signature.v).substring(2)
val signHash = StringBuilder(r).append(s).append(v).toString()
println("Signed Hash: $signHash")
return signHash
}
// Setup UI and event handlers
val signMessageButton = findViewById<Button>(R.id.signMessageButton)
signMessageButton.setOnClickListener { signMessage() }