Cleanup
This commit is contained in:
parent
e4224a1241
commit
fec6bdc581
|
@ -15,6 +15,16 @@ type
|
||||||
address: Address
|
address: Address
|
||||||
ContractError* = object of EthersError
|
ContractError* = object of EthersError
|
||||||
|
|
||||||
|
func new*(ContractType: type Contract,
|
||||||
|
address: Address,
|
||||||
|
provider: Provider): ContractType =
|
||||||
|
ContractType(provider: provider, address: address)
|
||||||
|
|
||||||
|
func new*(ContractType: type Contract,
|
||||||
|
address: Address,
|
||||||
|
signer: Signer): ContractType =
|
||||||
|
ContractType(signer: some signer, provider: signer.provider, address: address)
|
||||||
|
|
||||||
func provider*(contract: Contract): Provider =
|
func provider*(contract: Contract): Provider =
|
||||||
contract.provider
|
contract.provider
|
||||||
|
|
||||||
|
@ -27,48 +37,39 @@ func address*(contract: Contract): Address =
|
||||||
template raiseContractError(message: string) =
|
template raiseContractError(message: string) =
|
||||||
raise newException(ContractError, message)
|
raise newException(ContractError, message)
|
||||||
|
|
||||||
proc createTxData(function: string, parameters: tuple): seq[byte] =
|
proc createTransaction(contract: Contract,
|
||||||
let selector = selector(function, typeof parameters).toArray
|
|
||||||
return @selector & AbiEncoder.encode(parameters)
|
|
||||||
|
|
||||||
proc createTx(contract: Contract,
|
|
||||||
function: string,
|
function: string,
|
||||||
parameters: tuple): Transaction =
|
parameters: tuple): Transaction =
|
||||||
Transaction(to: contract.address, data: createTxData(function, parameters))
|
let selector = selector(function, typeof parameters).toArray
|
||||||
|
let data = @selector & AbiEncoder.encode(parameters)
|
||||||
|
Transaction(to: contract.address, data: data)
|
||||||
|
|
||||||
proc decodeResponse(T: type, bytes: seq[byte]): T =
|
proc decodeResponse(T: type, bytes: seq[byte]): T =
|
||||||
without decoded =? AbiDecoder.decode(bytes, T):
|
without decoded =? AbiDecoder.decode(bytes, T):
|
||||||
raiseContractError "unable to decode return value as " & $T
|
raiseContractError "unable to decode return value as " & $T
|
||||||
return decoded
|
return decoded
|
||||||
|
|
||||||
proc call[ContractType: Contract, ReturnType](
|
proc call(contract: Contract, function: string, parameters: tuple) {.async.} =
|
||||||
contract: ContractType,
|
let transaction = createTransaction(contract, function, parameters)
|
||||||
|
discard await contract.provider.call(transaction)
|
||||||
|
|
||||||
|
proc call(contract: Contract,
|
||||||
function: string,
|
function: string,
|
||||||
parameters: tuple): Future[ReturnType] {.async.} =
|
parameters: tuple,
|
||||||
let transaction = createTx(contract, function, parameters)
|
ReturnType: type): Future[ReturnType] {.async.} =
|
||||||
|
let transaction = createTransaction(contract, function, parameters)
|
||||||
let response = await contract.provider.call(transaction)
|
let response = await contract.provider.call(transaction)
|
||||||
return decodeResponse(ReturnType, response)
|
return decodeResponse(ReturnType, response)
|
||||||
|
|
||||||
proc callNoResult[ContractType: Contract](
|
proc send(contract: Contract, function: string, parameters: tuple) {.async.} =
|
||||||
contract: ContractType,
|
if signer =? contract.signer:
|
||||||
function: string,
|
let transaction = createTransaction(contract, function, parameters)
|
||||||
parameters: tuple) {.async.} =
|
|
||||||
let transaction = createTx(contract, function, parameters)
|
|
||||||
discard await contract.provider.call(transaction)
|
|
||||||
|
|
||||||
proc send[ContractType: Contract](
|
|
||||||
contract: ContractType,
|
|
||||||
function: string,
|
|
||||||
parameters: tuple) {.async.} =
|
|
||||||
|
|
||||||
without signer =? contract.signer:
|
|
||||||
raiseContractError "trying to send transaction without a signer"
|
|
||||||
|
|
||||||
let transaction = createTx(contract, function, parameters)
|
|
||||||
let populated = await signer.populateTransaction(transaction)
|
let populated = await signer.populateTransaction(transaction)
|
||||||
await signer.sendTransaction(populated)
|
await signer.sendTransaction(populated)
|
||||||
|
else:
|
||||||
|
await call(contract, function, parameters)
|
||||||
|
|
||||||
func getParameterTuple(procedure: var NimNode): NimNode =
|
func getParameterTuple(procedure: NimNode): NimNode =
|
||||||
let parameters = procedure[3]
|
let parameters = procedure[3]
|
||||||
var tupl = newNimNode(nnkTupleConstr, parameters)
|
var tupl = newNimNode(nnkTupleConstr, parameters)
|
||||||
for parameter in parameters[2..^1]:
|
for parameter in parameters[2..^1]:
|
||||||
|
@ -88,35 +89,26 @@ func isConstant(procedure: NimNode): bool =
|
||||||
false
|
false
|
||||||
|
|
||||||
func addContractCall(procedure: var NimNode) =
|
func addContractCall(procedure: var NimNode) =
|
||||||
let name = procedure[0]
|
let contract = procedure[3][1][0]
|
||||||
let function = if name.kind == nnkPostfix: $name[1] else: $name
|
let function = $basename(procedure[0])
|
||||||
let parameters = procedure[3]
|
let parameters = getParameterTuple(procedure)
|
||||||
let contract = parameters[1][0]
|
let returntype = procedure[3][0]
|
||||||
let contracttype = parameters[1][1]
|
procedure[6] =
|
||||||
let returntype = parameters[0]
|
|
||||||
let tupl = getParameterTuple(procedure)
|
|
||||||
if procedure.isConstant:
|
if procedure.isConstant:
|
||||||
if returntype.kind == nnkEmpty:
|
if returntype.kind == nnkEmpty:
|
||||||
procedure[6] = quote do:
|
quote:
|
||||||
await callNoResult[`contracttype`](
|
await call(`contract`, `function`, `parameters`)
|
||||||
`contract`, `function`, `tupl`
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
procedure[6] = quote do:
|
quote:
|
||||||
return await call[`contracttype`,`returntype`](
|
return await call(`contract`, `function`, `parameters`, `returntype`)
|
||||||
`contract`, `function`, `tupl`
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
procedure[6] = quote do:
|
quote:
|
||||||
if `contract`.signer.isSome:
|
await send(`contract`, `function`, `parameters`)
|
||||||
await send[`contracttype`](`contract`, `function`, `tupl`)
|
|
||||||
else:
|
|
||||||
await callNoResult[`contracttype`](`contract`, `function`, `tupl`)
|
|
||||||
|
|
||||||
func addFuture(procedure: var NimNode) =
|
func addFuture(procedure: var NimNode) =
|
||||||
let returntype = procedure[3][0]
|
let returntype = procedure[3][0]
|
||||||
if returntype.kind != nnkEmpty:
|
if returntype.kind != nnkEmpty:
|
||||||
procedure[3][0] = quote do: Future[`returntype`]
|
procedure[3][0] = quote: Future[`returntype`]
|
||||||
|
|
||||||
func addAsyncPragma(procedure: var NimNode) =
|
func addAsyncPragma(procedure: var NimNode) =
|
||||||
let pragmas = procedure[4]
|
let pragmas = procedure[4]
|
||||||
|
@ -124,23 +116,8 @@ func addAsyncPragma(procedure: var NimNode) =
|
||||||
procedure[4] = newNimNode(nnkPragma)
|
procedure[4] = newNimNode(nnkPragma)
|
||||||
procedure[4].add ident("async")
|
procedure[4].add ident("async")
|
||||||
|
|
||||||
func new*(ContractType: type Contract,
|
|
||||||
address: Address,
|
|
||||||
provider: Provider): ContractType =
|
|
||||||
ContractType(provider: provider, address: address)
|
|
||||||
|
|
||||||
func new*(ContractType: type Contract,
|
|
||||||
address: Address,
|
|
||||||
signer: Signer): ContractType =
|
|
||||||
ContractType(signer: some signer, provider: signer.provider, address: address)
|
|
||||||
|
|
||||||
template view* {.pragma.}
|
|
||||||
template pure* {.pragma.}
|
|
||||||
template constant* {.pragma.}
|
|
||||||
|
|
||||||
func checkReturnType(procedure: NimNode) =
|
func checkReturnType(procedure: NimNode) =
|
||||||
let parameters = procedure[3]
|
let returntype = procedure[3][0]
|
||||||
let returntype = parameters[0]
|
|
||||||
if returntype.kind != nnkEmpty and not procedure.isConstant:
|
if returntype.kind != nnkEmpty and not procedure.isConstant:
|
||||||
const message =
|
const message =
|
||||||
"only contract functions with {.constant.}, {.pure.} or {.view.} " &
|
"only contract functions with {.constant.}, {.pure.} or {.view.} " &
|
||||||
|
@ -148,13 +125,20 @@ func checkReturnType(procedure: NimNode) =
|
||||||
error(message, returntype)
|
error(message, returntype)
|
||||||
|
|
||||||
macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped =
|
macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped =
|
||||||
|
|
||||||
let parameters = procedure[3]
|
let parameters = procedure[3]
|
||||||
let body = procedure[6]
|
let body = procedure[6]
|
||||||
parameters.expectMinLen(2)
|
|
||||||
|
parameters.expectMinLen(2) # at least return type and contract instance
|
||||||
body.expectKind(nnkEmpty)
|
body.expectKind(nnkEmpty)
|
||||||
procedure.checkReturnType()
|
procedure.checkReturnType()
|
||||||
|
|
||||||
var contractcall = copyNimTree(procedure)
|
var contractcall = copyNimTree(procedure)
|
||||||
contractcall.addContractCall()
|
contractcall.addContractCall()
|
||||||
contractcall.addFuture()
|
contractcall.addFuture()
|
||||||
contractcall.addAsyncPragma()
|
contractcall.addAsyncPragma()
|
||||||
contractcall
|
contractcall
|
||||||
|
|
||||||
|
template view* {.pragma.}
|
||||||
|
template pure* {.pragma.}
|
||||||
|
template constant* {.pragma.}
|
||||||
|
|
Loading…
Reference in New Issue