mirror of
https://github.com/status-im/nim-ethers.git
synced 2025-01-22 21:41:10 +00:00
241ce6e8f3
Allows it to contain error data. It is not the signing that fails, so it makes sense to use an error type that indicates that the provider failed.
92 lines
2.8 KiB
Nim
92 lines
2.8 KiB
Nim
import eth/keys
|
|
import ../basics
|
|
import ../provider
|
|
import ../transaction
|
|
import ../signer
|
|
import ./wallet/error
|
|
import ./wallet/signing
|
|
|
|
export keys
|
|
export WalletError
|
|
export signing
|
|
|
|
{.push raises: [].}
|
|
|
|
var rng {.threadvar.}: ref HmacDrbgContext
|
|
|
|
proc getRng: ref HmacDrbgContext =
|
|
if rng.isNil:
|
|
rng = newRng()
|
|
rng
|
|
|
|
type Wallet* = ref object of Signer
|
|
privateKey*: PrivateKey
|
|
publicKey*: PublicKey
|
|
address*: Address
|
|
provider*: ?Provider
|
|
|
|
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()[])
|
|
result.publicKey = result.privateKey.toPublicKey()
|
|
result.address = Address.init(result.publicKey.toCanonicalAddress())
|
|
result.provider = some provider
|
|
|
|
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, SignerError]).} =
|
|
|
|
return wallet.address
|
|
|
|
proc signTransaction*(wallet: Wallet,
|
|
transaction: Transaction): Future[seq[byte]] {.async: (raises:[WalletError]).} =
|
|
if sender =? transaction.sender and sender != wallet.address:
|
|
raiseWalletError "from address mismatch"
|
|
|
|
return wallet.privateKey.sign(transaction)
|
|
|
|
method sendTransaction*(
|
|
wallet: Wallet,
|
|
transaction: Transaction): Future[TransactionResponse]
|
|
{.async: (raises:[SignerError, ProviderError]).} =
|
|
|
|
let signed = await signTransaction(wallet, transaction)
|
|
if nonce =? transaction.nonce:
|
|
wallet.updateNonce(nonce)
|
|
return await provider(wallet).sendTransaction(signed)
|