remove raises from async annotation for dynamic dispatch

- removes async: raises from getAddress and signTransaction because derived JsonRpcSigner methods were not being used when dynamically dispatched. Once `raises` was removed from the async annotation, the dynamic dispatch worked again. This is only the case for getAddress and signTransaction.
- add gcsafe annotation to wallet.provider so that it matches the base method
This commit is contained in:
Eric 2024-01-30 17:40:14 +11:00
parent 59a7939e8f
commit 1172b7e56a
No known key found for this signature in database
3 changed files with 27 additions and 17 deletions

View File

@ -304,11 +304,11 @@ template convertSignerError(body) =
except CatchableError as error:
raise newException(JsonRpcSignerError, error.msg)
method provider*(signer: JsonRpcSigner): Provider {.gcsafe.} =
method provider*(signer: JsonRpcSigner): Provider {.gcsafe, raises: [SignerError].} =
signer.provider
method getAddress*(
signer: JsonRpcSigner): Future[Address] {.async: (raises:[SignerError]).} =
signer: JsonRpcSigner): Future[Address] {.async.} =
if address =? signer.address:
return address
@ -331,8 +331,7 @@ method signMessage*(
method sendTransaction*(
signer: JsonRpcSigner,
transaction: Transaction): Future[TransactionResponse]
{.async: (raises:[SignerError]).} =
transaction: Transaction): Future[TransactionResponse] {.async.} =
convertSignerError:
echo "[jsonrpc.sendTransaction]"

View File

@ -1,3 +1,4 @@
import pkg/questionable
import ./basics
import ./provider
@ -39,20 +40,20 @@ method provider*(
doAssert false, "not implemented"
method getAddress*(
signer: Signer): Future[Address] {.base, async: (raises:[SignerError]).} =
signer: Signer): Future[Address] {.base, async.} =
doAssert false, "not implemented"
method signMessage*(
signer: Signer,
message: seq[byte]): Future[seq[byte]] {.base, async: (raises:[SignerError]).} =
message: seq[byte]): Future[seq[byte]] {.base, async: (raises: [SignerError]).} =
doAssert false, "not implemented"
method sendTransaction*(
signer: Signer,
transaction: Transaction): Future[TransactionResponse]
{.base, async: (raises:[SignerError]).} =
{.base, async.} =
doAssert false, "not implemented"
@ -177,7 +178,7 @@ method populateTransaction*(
method cancelTransaction*(
signer: Signer,
tx: Transaction
): Future[TransactionResponse] {.async, base.} =
): Future[TransactionResponse] {.base, async: (raises: [SignerError]).} =
# cancels a transaction by sending with a 0-valued transaction to ourselves
# with the failed tx's nonce
@ -187,5 +188,6 @@ method cancelTransaction*(
raiseSignerError "transaction must have nonce"
var cancelTx = Transaction(to: sender, value: 0.u256, nonce: some nonce)
cancelTx = await signer.populateTransaction(cancelTx)
return await signer.sendTransaction(cancelTx)
convertError:
cancelTx = await signer.populateTransaction(cancelTx)
return await signer.sendTransaction(cancelTx)

View File

@ -10,6 +10,8 @@ export keys
export WalletError
export signing
{.push raises: [].}
var rng {.threadvar.}: ref HmacDrbgContext
proc getRng: ref HmacDrbgContext =
@ -27,26 +29,32 @@ proc new*(_: type Wallet, privateKey: PrivateKey): Wallet =
let publicKey = privateKey.toPublicKey()
let address = Address.init(publicKey.toCanonicalAddress())
Wallet(privateKey: privateKey, publicKey: publicKey, address: address)
proc new*(_: type Wallet, privateKey: PrivateKey, provider: Provider): Wallet =
let wallet = Wallet.new(privateKey)
wallet.provider = some provider
wallet
proc new*(_: type Wallet, privateKey: string): ?!Wallet =
let keyResult = PrivateKey.fromHex(privateKey)
if keyResult.isErr:
return failure newException(WalletError, "invalid key: " & $keyResult.error)
success Wallet.new(keyResult.get())
proc new*(_: type Wallet, privateKey: string, provider: Provider): ?!Wallet =
let wallet = ? Wallet.new(privateKey)
wallet.provider = some provider
success wallet
proc connect*(wallet: Wallet, provider: Provider) =
wallet.provider = some provider
proc createRandom*(_: type Wallet): Wallet =
result = Wallet()
result.privateKey = PrivateKey.random(getRng()[])
result.publicKey = result.privateKey.toPublicKey()
result.address = Address.init(result.publicKey.toCanonicalAddress())
proc createRandom*(_: type Wallet, provider: Provider): Wallet =
result = Wallet()
result.privateKey = PrivateKey.random(getRng()[])
@ -54,12 +62,12 @@ proc createRandom*(_: type Wallet, provider: Provider): Wallet =
result.address = Address.init(result.publicKey.toCanonicalAddress())
result.provider = some provider
method provider*(wallet: Wallet): Provider {.raises: [SignerError].} =
method provider*(wallet: Wallet): Provider {.gcsafe, raises: [SignerError].} =
without provider =? wallet.provider:
raiseWalletError "Wallet has no provider"
provider
method getAddress(wallet: Wallet): Future[Address] {.async: (raises:[ProviderError]).} =
method getAddress*(wallet: Wallet): Future[Address] {.async.} =
return wallet.address
proc signTransaction*(wallet: Wallet,
@ -71,9 +79,10 @@ proc signTransaction*(wallet: Wallet,
method sendTransaction*(
wallet: Wallet,
transaction: Transaction): Future[TransactionResponse] {.async: (raises:[ProviderError]).} =
transaction: Transaction): Future[TransactionResponse] {.async.} =
let signed = await signTransaction(wallet, transaction)
if nonce =? transaction.nonce:
wallet.updateNonce(nonce)
return await provider(wallet).sendTransaction(signed)
convertError:
let signed = await signTransaction(wallet, transaction)
if nonce =? transaction.nonce:
wallet.updateNonce(nonce)
return await provider(wallet).sendTransaction(signed)