From fec6bdc581d301311ad66d1f09bd25b69c37a083 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 26 Jan 2022 10:31:54 +0100 Subject: [PATCH] Cleanup --- ethers/contract.nim | 126 +++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 71 deletions(-) diff --git a/ethers/contract.nim b/ethers/contract.nim index 382f6d4..5d2df64 100644 --- a/ethers/contract.nim +++ b/ethers/contract.nim @@ -15,6 +15,16 @@ type address: Address 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 = contract.provider @@ -27,48 +37,39 @@ func address*(contract: Contract): Address = template raiseContractError(message: string) = raise newException(ContractError, message) -proc createTxData(function: string, parameters: tuple): seq[byte] = +proc createTransaction(contract: Contract, + function: string, + parameters: tuple): Transaction = let selector = selector(function, typeof parameters).toArray - return @selector & AbiEncoder.encode(parameters) - -proc createTx(contract: Contract, - function: string, - parameters: tuple): Transaction = - Transaction(to: contract.address, data: createTxData(function, parameters)) + let data = @selector & AbiEncoder.encode(parameters) + Transaction(to: contract.address, data: data) proc decodeResponse(T: type, bytes: seq[byte]): T = without decoded =? AbiDecoder.decode(bytes, T): raiseContractError "unable to decode return value as " & $T return decoded -proc call[ContractType: Contract, ReturnType]( - contract: ContractType, +proc call(contract: Contract, function: string, parameters: tuple) {.async.} = + let transaction = createTransaction(contract, function, parameters) + discard await contract.provider.call(transaction) + +proc call(contract: Contract, function: string, - parameters: tuple): Future[ReturnType] {.async.} = - let transaction = createTx(contract, function, parameters) + parameters: tuple, + ReturnType: type): Future[ReturnType] {.async.} = + let transaction = createTransaction(contract, function, parameters) let response = await contract.provider.call(transaction) return decodeResponse(ReturnType, response) -proc callNoResult[ContractType: Contract]( - contract: ContractType, - function: string, - parameters: tuple) {.async.} = - let transaction = createTx(contract, function, parameters) - discard await contract.provider.call(transaction) +proc send(contract: Contract, function: string, parameters: tuple) {.async.} = + if signer =? contract.signer: + let transaction = createTransaction(contract, function, parameters) + let populated = await signer.populateTransaction(transaction) + await signer.sendTransaction(populated) + else: + await call(contract, function, parameters) -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) - await signer.sendTransaction(populated) - -func getParameterTuple(procedure: var NimNode): NimNode = +func getParameterTuple(procedure: NimNode): NimNode = let parameters = procedure[3] var tupl = newNimNode(nnkTupleConstr, parameters) for parameter in parameters[2..^1]: @@ -88,35 +89,26 @@ func isConstant(procedure: NimNode): bool = false func addContractCall(procedure: var NimNode) = - let name = procedure[0] - let function = if name.kind == nnkPostfix: $name[1] else: $name - let parameters = procedure[3] - let contract = parameters[1][0] - let contracttype = parameters[1][1] - let returntype = parameters[0] - let tupl = getParameterTuple(procedure) - if procedure.isConstant: - if returntype.kind == nnkEmpty: - procedure[6] = quote do: - await callNoResult[`contracttype`]( - `contract`, `function`, `tupl` - ) - else: - procedure[6] = quote do: - return await call[`contracttype`,`returntype`]( - `contract`, `function`, `tupl` - ) - else: - procedure[6] = quote do: - if `contract`.signer.isSome: - await send[`contracttype`](`contract`, `function`, `tupl`) + let contract = procedure[3][1][0] + let function = $basename(procedure[0]) + let parameters = getParameterTuple(procedure) + let returntype = procedure[3][0] + procedure[6] = + if procedure.isConstant: + if returntype.kind == nnkEmpty: + quote: + await call(`contract`, `function`, `parameters`) else: - await callNoResult[`contracttype`](`contract`, `function`, `tupl`) + quote: + return await call(`contract`, `function`, `parameters`, `returntype`) + else: + quote: + await send(`contract`, `function`, `parameters`) func addFuture(procedure: var NimNode) = let returntype = procedure[3][0] if returntype.kind != nnkEmpty: - procedure[3][0] = quote do: Future[`returntype`] + procedure[3][0] = quote: Future[`returntype`] func addAsyncPragma(procedure: var NimNode) = let pragmas = procedure[4] @@ -124,23 +116,8 @@ func addAsyncPragma(procedure: var NimNode) = procedure[4] = newNimNode(nnkPragma) 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) = - let parameters = procedure[3] - let returntype = parameters[0] + let returntype = procedure[3][0] if returntype.kind != nnkEmpty and not procedure.isConstant: const message = "only contract functions with {.constant.}, {.pure.} or {.view.} " & @@ -148,13 +125,20 @@ func checkReturnType(procedure: NimNode) = error(message, returntype) macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped = + let parameters = procedure[3] let body = procedure[6] - parameters.expectMinLen(2) + + parameters.expectMinLen(2) # at least return type and contract instance body.expectKind(nnkEmpty) procedure.checkReturnType() + var contractcall = copyNimTree(procedure) contractcall.addContractCall() contractcall.addFuture() contractcall.addAsyncPragma() contractcall + +template view* {.pragma.} +template pure* {.pragma.} +template constant* {.pragma.}