import org.web3j.crypto.Credentials
import org.web3j.crypto.Sign
import org.web3j.protocol.Web3j
import org.web3j.protocol.core.DefaultBlockParameterName
import org.web3j.protocol.http.HttpService
import org.web3j.tx.RawTransactionManager
import org.web3j.utils.Numeric
class Web3jDelegate(
private val credentials: Credentials,
private val web3j: Web3j
) : WalletDelegate {
override fun getAddress(): String = credentials.address
override fun getChainId(): ULong {
return web3j.ethChainId().send().chainId.toLong().toULong()
}
override fun signMessage(message: String): String {
val messageBytes = message.toByteArray()
val prefix = "\u0019Ethereum Signed Message:\n${messageBytes.size}"
val prefixedMessage = (prefix + message).toByteArray()
val signature = Sign.signPrefixedMessage(prefixedMessage, credentials.ecKeyPair)
val r = Numeric.toHexStringNoPrefix(signature.r)
val s = Numeric.toHexStringNoPrefix(signature.s)
val v = Numeric.toHexStringNoPrefix(byteArrayOf(signature.v[0]))
return "0x$r$s$v"
}
override fun signTypedData(typedDataJson: String): String {
// Parse and sign EIP-712 typed data
val typedData = parseTypedData(typedDataJson)
val structHash = hashTypedData(typedData)
val signature = Sign.signMessage(structHash, credentials.ecKeyPair, false)
val r = Numeric.toHexStringNoPrefix(signature.r)
val s = Numeric.toHexStringNoPrefix(signature.s)
val v = Numeric.toHexStringNoPrefix(byteArrayOf(signature.v[0]))
return "0x$r$s$v"
}
override fun sendTransaction(toAddress: String, value: String, data: String): String {
val nonce = web3j.ethGetTransactionCount(
credentials.address,
DefaultBlockParameterName.LATEST
).send().transactionCount
val gasPrice = web3j.ethGasPrice().send().gasPrice
val gasLimit = estimateGas(toAddress, value, data)
val txManager = RawTransactionManager(web3j, credentials, getChainId().toLong())
val txHash = txManager.sendTransaction(
gasPrice,
gasLimit,
toAddress,
data,
value.toBigInteger()
).transactionHash
return txHash
}
private fun estimateGas(to: String, value: String, data: String): java.math.BigInteger {
val estimate = web3j.ethEstimateGas(
org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
credentials.address,
null,
null,
null,
to,
value.toBigInteger(),
data
)
).send()
return estimate.amountUsed.multiply(java.math.BigInteger.valueOf(120)).divide(java.math.BigInteger.valueOf(100))
}
private fun parseTypedData(json: String): TypedData {
// Implementation depends on your JSON parsing library
TODO("Parse EIP-712 typed data")
}
private fun hashTypedData(typedData: TypedData): ByteArray {
// Implementation of EIP-712 hashing
TODO("Hash typed data")
}
}