Argument decoding and initial deploy contract testing
This commit is contained in:
parent
332b0ccfc8
commit
aff05ca240
|
@ -9,7 +9,7 @@ contract(TestContract):
|
|||
proc ChainStart(deposit_root: bytes32, time: bytes) {.event.}
|
||||
proc deposit(deposit_input: bytes) {.payable.}
|
||||
proc get_deposit_root(): bytes32 {.view.}
|
||||
#proc get_branch(leaf: uint256): bytes32[32] {.pure.}
|
||||
proc get_branch(leaf: uint256): bytes32[32] {.view.}
|
||||
|
||||
#var
|
||||
# x2 = TestContract(address:
|
||||
|
@ -21,13 +21,15 @@ contract(TestContract):
|
|||
|
||||
var
|
||||
x = TestContract(address:
|
||||
"4e7f73f0bbee44db86fbf8b957cf7c8bf330c2fe".toAddress,
|
||||
"630170976aBc526b1408Cc2Dd7b7B5599862c02f".toAddress,
|
||||
client: newRpcHttpClient()
|
||||
)
|
||||
sender = x.initSender("127.0.0.1", 8545,
|
||||
"45b6fc37a833d2f20dc25917f0a632f351be474b".toAddress)
|
||||
receiver = x.initReceiver("127.0.0.1", 8545)
|
||||
eventListener = receiver.initEventListener()
|
||||
"c9f03520257dd207a159164c534c2b2664d8fd22".toAddress)
|
||||
#receiver = x.initReceiver("127.0.0.1", 8545)
|
||||
#eventListener = receiver.initEventListener()
|
||||
|
||||
echo waitFor sender.getDepositRoot()
|
||||
|
||||
#x.callbacks.Transfer.add proc (fromAddr, toAddr: Address, value: Uint256) =
|
||||
# echo $value, " coins were transferred from ", fromAddr.toHex, " to ", toAddr.toHex
|
||||
|
@ -52,4 +54,4 @@ var
|
|||
# 10.to(Stuint[256])
|
||||
#))
|
||||
|
||||
waitFor eventListener.listen()
|
||||
#waitFor eventListener.listen()
|
||||
|
|
|
@ -27,7 +27,7 @@ proc eth_getCode(data: array[20, byte], quantityTag: string): seq[byte]
|
|||
proc eth_sign(data: array[20, byte], message: seq[byte]): seq[byte]
|
||||
proc eth_sendTransaction(obj: EthSend): UInt256
|
||||
proc eth_sendRawTransaction(data: string, quantityTag: int): UInt256
|
||||
proc eth_call(call: EthCall, quantityTag: string): seq[byte]#UInt256
|
||||
proc eth_call(call: EthCall, quantityTag: string): string #UInt256
|
||||
proc eth_estimateGas(call: EthCall, quantityTag: string): UInt256
|
||||
proc eth_getBlockByHash(data: array[32, byte], fullTransactions: bool): BlockObject
|
||||
proc eth_getBlockByNumber(quantityTag: string, fullTransactions: bool): BlockObject
|
||||
|
|
|
@ -8,11 +8,6 @@ contract(TestContract):
|
|||
proc sendCoin(receiver: Address, amount: Uint): Bool
|
||||
proc getBalance(address: Address): Uint {.view.}
|
||||
proc Transfer(fromAddr: indexed[Address], toAddr: indexed[Address], value: Uint256) {.event.}
|
||||
proc Deposit(previous_deposit_root: Bytes32, data: Byte[2064], merkle_tree_index: bytes[8]) {.event.}
|
||||
proc ChainStart(deposit_root: bytes32, time: byte[8])
|
||||
proc deposit(deposit_input: byte[2048]) {.payable.}
|
||||
proc get_deposit_root(): bytes32 {.pure.}
|
||||
proc get_branch(leaf: uint256): bytes32 {.pure.}
|
||||
|
||||
#var
|
||||
# x2 = TestContract(address:
|
||||
|
|
84
src/web3.nim
84
src/web3.nim
|
@ -37,12 +37,12 @@ type
|
|||
# result = new Web3
|
||||
# result.eth = client
|
||||
|
||||
func encode[bits: static[int]](x: Stuint[bits]): EncodeResult =
|
||||
func encode*[bits: static[int]](x: Stuint[bits]): EncodeResult =
|
||||
## Encodes a `Stuint` to a textual representation for use in the JsonRPC
|
||||
## `sendTransaction` call.
|
||||
(dynamic: false, data: '0'.repeat((256 - bits) div 4) & x.dumpHex)
|
||||
|
||||
func encode[bits: static[int]](x: Stint[bits]): EncodeResult =
|
||||
func encode*[bits: static[int]](x: Stint[bits]): EncodeResult =
|
||||
## Encodes a `Stint` to a textual representation for use in the JsonRPC
|
||||
## `sendTransaction` call.
|
||||
(dynamic: false,
|
||||
|
@ -53,6 +53,13 @@ func encode[bits: static[int]](x: Stint[bits]): EncodeResult =
|
|||
'0'.repeat((256 - bits) div 4) & x.dumpHex
|
||||
)
|
||||
|
||||
func decode*[bits: static[int]](input: string, to: type Stuint[bits]): Stuint[bits] =
|
||||
fromHex(to, input)
|
||||
|
||||
func decode*[bits: static[int]](input: string, to: type Stint[bits]): Stint[bits] =
|
||||
cast[Stint[bits]](fromHex(Stuint[bits], input))
|
||||
|
||||
|
||||
macro makeTypeEnum(): untyped =
|
||||
## This macro creates all the various types of Solidity contracts and maps
|
||||
## them to the type used for their encoding. It also creates an enum to
|
||||
|
@ -85,6 +92,7 @@ macro makeTypeEnum(): untyped =
|
|||
`identInt`* = Int256
|
||||
`identBool`* = distinct Int256
|
||||
func encode*(x: `identBool`): EncodeResult = encode(Int256(x))
|
||||
func decode*(input: string, x: `identBool`): `identBool` = `identBool`(decode(input, Stint[256]))
|
||||
fields.add [
|
||||
identAddress,
|
||||
identUint,
|
||||
|
@ -117,6 +125,12 @@ macro makeTypeEnum(): untyped =
|
|||
func encode*[N: static[int]](x: `identUfixed`[N]): EncodeResult =
|
||||
encode(`identUint`(x) * (10 ^ N).to(`identUint`))
|
||||
|
||||
func decode*[N: static[int]](input: string, to: `identFixed`[N]): `identFixed`[N] =
|
||||
decode(input, `identInt`) div / (10 ^ N).to(`identInt`)
|
||||
|
||||
func decode*[N: static[int]](input: string, to: `identUfixed`[N]): `identFixed`[N] =
|
||||
decode(input, `identUint`) div / (10 ^ N).to(`identUint`)
|
||||
|
||||
fields.add ident("Fixed" & $m)
|
||||
fields.add ident("Ufixed" & $m)
|
||||
let
|
||||
|
@ -145,6 +159,8 @@ macro makeTypeEnum(): untyped =
|
|||
func fromHex*(x: type `identBytes`, s: string): `identBytes` =
|
||||
for i in 0..(`i`-1):
|
||||
`identResult`[i] = parseHexInt(s[i*2..i*2+1]).uint8
|
||||
func decode*(input: string, to: type `identBytes`): `identBytes` =
|
||||
fromHex(to, input)
|
||||
|
||||
fields.add [
|
||||
ident("Function"),
|
||||
|
@ -165,6 +181,8 @@ macro makeTypeEnum(): untyped =
|
|||
`identResult`.data &= "00".repeat(32 - (x.len mod 32))
|
||||
func fromHex*(x: type `identBytes`, s: string): `identBytes` =
|
||||
fromHex(s)
|
||||
func decode*(input: string, to: type `identBytes`): `identBytes` =
|
||||
fromHex(to, input)
|
||||
|
||||
result.add newEnum(ident "FieldKind", fields, public = true, pure = true)
|
||||
echo result.repr
|
||||
|
@ -175,7 +193,7 @@ type
|
|||
Encodable = concept x
|
||||
encode(x) is EncodeResult
|
||||
|
||||
func encode(x: seq[Encodable]): EncodeResult =
|
||||
func encode*(x: seq[Encodable]): EncodeResult =
|
||||
result.dynamic = true
|
||||
result.data = x.len.toHex(64).toLower
|
||||
var
|
||||
|
@ -191,7 +209,13 @@ func encode(x: seq[Encodable]): EncodeResult =
|
|||
offset += encoded.data.len
|
||||
result.data &= data
|
||||
|
||||
func encode(x: openArray[Encodable]): EncodeResult =
|
||||
func decode*[T](input: string, to: seq[T]): seq[T] =
|
||||
var count = input[0..64].decode(Stuint)
|
||||
result = newSeq[T](count)
|
||||
for i in 0..count:
|
||||
result[i] = input[i*64 .. (i+1)*64].decode(T)
|
||||
|
||||
func encode*(x: openArray[Encodable]): EncodeResult =
|
||||
result.dynamic = false
|
||||
result.data = ""
|
||||
var
|
||||
|
@ -206,6 +230,11 @@ func encode(x: openArray[Encodable]): EncodeResult =
|
|||
result.data &= encoded.data
|
||||
offset += encoded.data.len
|
||||
|
||||
func decode*[T; I: static int](input: string, to: array[0..I, T]): array[0..I, T] =
|
||||
for i in 0..I:
|
||||
result[i] = input[i*64 .. (i+1)*64].decode(T)
|
||||
|
||||
|
||||
type
|
||||
InterfaceObjectKind = enum
|
||||
function, constructor, event
|
||||
|
@ -282,11 +311,31 @@ proc getEventSignature(event: EventObject): string =
|
|||
|
||||
proc parseContract(body: NimNode): seq[InterfaceObject] =
|
||||
proc parseOutputs(outputNode: NimNode): seq[FunctionInputOutput] =
|
||||
if outputNode.kind == nnkIdent:
|
||||
#if outputNode.kind == nnkIdent:
|
||||
# result.add FunctionInputOutput(
|
||||
# name: "",
|
||||
# kind: parseEnum[FieldKind]($outputNode.ident)
|
||||
# )
|
||||
case outputNode.kind:
|
||||
of nnkBracketExpr:
|
||||
result.add FunctionInputOutput(
|
||||
name: "",
|
||||
kind: parseEnum[FieldKind]($outputNode.ident)
|
||||
kind: parseEnum[FieldKind]($outputNode[0].ident),
|
||||
sequenceKind: if outputNode.len == 1:
|
||||
dynamic
|
||||
else:
|
||||
fixed
|
||||
)
|
||||
if outputNode.len == 2:
|
||||
result[^1].count = outputNode[1].intVal.int
|
||||
of nnkIdent:
|
||||
result.add FunctionInputOutput(
|
||||
name: "",
|
||||
kind: parseEnum[FieldKind]($outputNode.ident),
|
||||
sequenceKind: single
|
||||
)
|
||||
else:
|
||||
discard
|
||||
proc parseInputs(inputNodes: NimNode): seq[FunctionInputOutput] =
|
||||
for i in 1..<inputNodes.len:
|
||||
let input = inputNodes[i]
|
||||
|
@ -436,7 +485,7 @@ macro contract*(cname: untyped, body: untyped): untyped =
|
|||
ident "Address"
|
||||
else:
|
||||
if obj.functionObject.outputs.len != 1:
|
||||
newEmptyNode()
|
||||
ident "void"#newEmptyNode()
|
||||
else:
|
||||
ident $obj.functionObject.outputs[0].kind
|
||||
var
|
||||
|
@ -499,16 +548,23 @@ macro contract*(cname: untyped, body: untyped): untyped =
|
|||
)
|
||||
case obj.functionObject.stateMutability:
|
||||
of view:
|
||||
let cc = ident "cc"
|
||||
procDef[6].add quote do:
|
||||
var cc: EthCall
|
||||
cc.source = some(`senderName`.address)
|
||||
var `cc`: EthCall
|
||||
`cc`.source = some(`senderName`.address)
|
||||
#cc.to = `senderName`.contract.Contract.address
|
||||
cc.to = `senderName`.contract.address
|
||||
`cc`.to = `senderName`.contract.address
|
||||
`encoder`
|
||||
cc.data = some("0x" & ($keccak_256.digest(`signature`))[0..<8].toLower & `encodedParams`)
|
||||
echo cc.data
|
||||
let response = await `senderName`.contract.`client`.eth_call(cc, "latest")
|
||||
return response
|
||||
`cc`.data = some("0x" & ($keccak_256.digest(`signature`))[0..<8].toLower & `encodedParams`)
|
||||
echo `cc`.data
|
||||
if output != ident "void":
|
||||
procDef[6].add quote do:
|
||||
let response = await `senderName`.contract.`client`.eth_call(`cc`, "latest")
|
||||
echo response
|
||||
return response[2..^1].decode(`output`)
|
||||
else:
|
||||
procDef[6].add quote do:
|
||||
await `senderName`.contract.`client`.eth_call(`cc`, "latest")
|
||||
else:
|
||||
procDef[6].add quote do:
|
||||
var cc: EthSend
|
||||
|
|
Loading…
Reference in New Issue