2021-09-08 18:05:39 +00:00
|
|
|
import
|
|
|
|
strutils, options
|
|
|
|
|
|
|
|
import
|
|
|
|
nimcrypto, web3/[encoding, ethtypes]
|
|
|
|
|
|
|
|
import
|
2021-10-01 16:53:38 +00:00
|
|
|
../types/[rpc_response, transaction],
|
|
|
|
../statusgo_backend/coder,
|
|
|
|
../statusgo_backend/eth as eth
|
2021-09-08 18:05:39 +00:00
|
|
|
|
|
|
|
export sendTransaction
|
|
|
|
|
|
|
|
type Method* = object
|
|
|
|
name*: string
|
|
|
|
signature*: string
|
|
|
|
|
|
|
|
proc encodeMethod(self: Method): string =
|
|
|
|
($nimcrypto.keccak256.digest(self.signature))[0..<8].toLower
|
|
|
|
|
|
|
|
proc encodeAbi*(self: Method, obj: object = RootObj()): string =
|
|
|
|
result = "0x" & self.encodeMethod()
|
|
|
|
|
|
|
|
# .fields is an iterator, and there's no way to get a count of an iterator
|
|
|
|
# in nim, so we have to loop and increment a counter
|
|
|
|
var fieldCount = 0
|
|
|
|
for i in obj.fields:
|
|
|
|
fieldCount += 1
|
|
|
|
var
|
|
|
|
offset = 32*fieldCount
|
|
|
|
data = ""
|
|
|
|
|
|
|
|
for field in obj.fields:
|
|
|
|
let encoded = encode(field)
|
|
|
|
if encoded.dynamic:
|
|
|
|
result &= offset.toHex(64).toLower
|
|
|
|
data &= encoded.data
|
|
|
|
offset += encoded.data.len
|
|
|
|
else:
|
|
|
|
result &= encoded.data
|
|
|
|
result &= data
|
|
|
|
|
2021-09-10 17:27:49 +00:00
|
|
|
proc estimateGas*(self: Method, tx: var TransactionData, methodDescriptor: object, success: var bool): string =
|
2021-09-08 18:05:39 +00:00
|
|
|
success = true
|
|
|
|
tx.data = self.encodeAbi(methodDescriptor)
|
|
|
|
try:
|
2021-10-01 16:53:38 +00:00
|
|
|
let response = eth.estimateGas(tx)
|
2021-09-08 18:05:39 +00:00
|
|
|
result = response.result # gas estimate in hex
|
|
|
|
except RpcException as e:
|
|
|
|
success = false
|
|
|
|
result = e.msg
|
|
|
|
|
2021-09-10 17:27:49 +00:00
|
|
|
proc send*(self: Method, tx: var TransactionData, methodDescriptor: object, password: string, success: var bool): string =
|
2021-09-08 18:05:39 +00:00
|
|
|
tx.data = self.encodeAbi(methodDescriptor)
|
|
|
|
result = eth.sendTransaction(tx, password, success)
|
|
|
|
|
2021-09-10 17:27:49 +00:00
|
|
|
proc call*[T](self: Method, tx: var TransactionData, methodDescriptor: object, success: var bool): T =
|
2021-09-08 18:05:39 +00:00
|
|
|
success = true
|
|
|
|
tx.data = self.encodeAbi(methodDescriptor)
|
|
|
|
let response: RpcResponse
|
|
|
|
try:
|
2021-10-01 16:53:38 +00:00
|
|
|
response = eth.call(tx)
|
2021-09-08 18:05:39 +00:00
|
|
|
except RpcException as e:
|
|
|
|
success = false
|
|
|
|
result = e.msg
|
|
|
|
result = coder.decodeContractResponse[T](response.result)
|