Allow for custom transaction properties

This commit is contained in:
Mark Spanbroek 2022-07-11 15:15:01 +02:00 committed by markspanbroek
parent 440ca6360b
commit a7d1944406
3 changed files with 59 additions and 8 deletions

View File

@ -47,10 +47,14 @@ template raiseContractError(message: string) =
proc createTransaction(contract: Contract, proc createTransaction(contract: Contract,
function: string, function: string,
parameters: tuple): Transaction = parameters: tuple,
overrides = Transaction.default): Transaction =
let selector = selector(function, typeof parameters).toArray let selector = selector(function, typeof parameters).toArray
let data = @selector & AbiEncoder.encode(parameters) let data = @selector & AbiEncoder.encode(parameters)
Transaction(to: contract.address, data: data) var transaction = overrides
transaction.to = contract.address
transaction.data = data
return transaction
proc decodeResponse(T: type, multiple: static bool, bytes: seq[byte]): T = proc decodeResponse(T: type, multiple: static bool, bytes: seq[byte]): T =
when multiple: when multiple:
@ -77,11 +81,13 @@ proc call(contract: Contract,
let response = await contract.provider.call(transaction, blockTag) let response = await contract.provider.call(transaction, blockTag)
return decodeResponse(ReturnType, returnMultiple, response) return decodeResponse(ReturnType, returnMultiple, response)
proc send(contract: Contract, function: string, parameters: tuple): proc send(contract: Contract,
function: string,
parameters: tuple,
overrides = Transaction.default):
Future[?TransactionResponse] {.async.} = Future[?TransactionResponse] {.async.} =
if signer =? contract.signer: if signer =? contract.signer:
let transaction = createTransaction(contract, function, parameters) let transaction = createTransaction(contract, function, parameters, overrides)
let populated = await signer.populateTransaction(transaction) let populated = await signer.populateTransaction(transaction)
let txResp = await signer.sendTransaction(populated) let txResp = await signer.sendTransaction(populated)
return txResp.some return txResp.some
@ -111,6 +117,15 @@ func isMultipleReturn(returnType: NimNode): bool =
(returnType.kind == nnkTupleConstr) or (returnType.kind == nnkTupleConstr) or
(returnType.kind == nnkTupleTy) (returnType.kind == nnkTupleTy)
func addOverrides(procedure: var NimNode) =
procedure[3].add(
newIdentDefs(
ident("overrides"),
newEmptyNode(),
quote do: Transaction.default
)
)
func addContractCall(procedure: var NimNode) = func addContractCall(procedure: var NimNode) =
let contract = procedure[3][1][0] let contract = procedure[3][1][0]
let function = $basename(procedure[0]) let function = $basename(procedure[0])
@ -118,6 +133,8 @@ func addContractCall(procedure: var NimNode) =
let returnType = procedure[3][0] let returnType = procedure[3][0]
let returnMultiple = returnType.isMultipleReturn.newLit let returnMultiple = returnType.isMultipleReturn.newLit
procedure.addOverrides()
func call: NimNode = func call: NimNode =
if returnType.kind == nnkEmpty: if returnType.kind == nnkEmpty:
quote: quote:
@ -130,12 +147,12 @@ func addContractCall(procedure: var NimNode) =
func send: NimNode = func send: NimNode =
if returnType.kind == nnkEmpty: if returnType.kind == nnkEmpty:
quote: quote:
discard await send(`contract`, `function`, `parameters`) discard await send(`contract`, `function`, `parameters`, overrides)
else: else:
quote: quote:
when typeof(result) isnot Confirmable: when typeof(result) isnot Confirmable:
{.error: "unexpected return type, missing {.view.} or {.pure.} ?".} {.error: "unexpected return type, missing {.view.} or {.pure.} ?".}
return await send(`contract`, `function`, `parameters`) return await send(`contract`, `function`, `parameters`, overrides)
procedure[6] = procedure[6] =
if procedure.isConstant: if procedure.isConstant:

20
testmodule/mocks.nim Normal file
View File

@ -0,0 +1,20 @@
import pkg/ethers
type MockSigner* = ref object of Signer
provider: Provider
address*: Address
transactions*: seq[Transaction]
func new*(_: type MockSigner, provider: Provider): MockSigner =
MockSigner(provider: provider)
method provider*(signer: MockSigner): Provider =
signer.provider
method getAddress*(signer: MockSigner): Future[Address] {.async.} =
return signer.address
method sendTransaction*(signer: MockSigner,
transaction: Transaction):
Future[TransactionResponse] {.async.} =
signer.transactions.add(transaction)

View File

@ -5,6 +5,7 @@ import pkg/stint
import pkg/ethers import pkg/ethers
import ./hardhat import ./hardhat
import ./miner import ./miner
import ./mocks
type type
@ -112,6 +113,19 @@ suite "Contracts":
check (await token.connect(provider).balanceOf(accounts[1])) == 25.u256 check (await token.connect(provider).balanceOf(accounts[1])) == 25.u256
check (await token.connect(provider).balanceOf(accounts[2])) == 25.u256 check (await token.connect(provider).balanceOf(accounts[2])) == 25.u256
test "takes custom values for nonce, gasprice and gaslimit":
let overrides = Transaction(
nonce: some 100.u256,
gasPrice: some 200.u256,
gasLimit: some 300.u256
)
let signer = MockSigner.new(provider)
discard await token.connect(signer).mint(accounts[0], 42.u256, overrides)
check signer.transactions.len == 1
check signer.transactions[0].nonce == overrides.nonce
check signer.transactions[0].gasPrice == overrides.gasPrice
check signer.transactions[0].gasLimit == overrides.gasLimit
test "receives events when subscribed": test "receives events when subscribed":
var transfers: seq[Transfer] var transfers: seq[Transfer]