2022-07-12 18:23:43 +00:00
|
|
|
import eth/keys
|
2023-07-28 09:18:58 +00:00
|
|
|
import ./basics
|
2022-07-21 00:04:05 +00:00
|
|
|
import ./provider
|
2023-07-04 09:38:48 +00:00
|
|
|
import ./transaction
|
2022-07-12 18:23:43 +00:00
|
|
|
import ./signer
|
2023-07-04 08:40:22 +00:00
|
|
|
import ./wallet/error
|
2023-07-04 09:38:48 +00:00
|
|
|
import ./wallet/signing
|
2022-07-12 18:23:43 +00:00
|
|
|
|
|
|
|
export keys
|
2023-07-04 08:40:22 +00:00
|
|
|
export WalletError
|
2023-10-25 00:36:00 +00:00
|
|
|
export signing
|
2022-07-12 18:23:43 +00:00
|
|
|
|
2022-07-21 00:00:57 +00:00
|
|
|
var rng {.threadvar.}: ref HmacDrbgContext
|
|
|
|
|
|
|
|
proc getRng: ref HmacDrbgContext =
|
2022-07-14 08:22:54 +00:00
|
|
|
if rng.isNil:
|
2022-07-21 00:00:57 +00:00
|
|
|
rng = newRng()
|
2022-07-14 08:22:54 +00:00
|
|
|
rng
|
2022-07-12 18:23:43 +00:00
|
|
|
|
|
|
|
type Wallet* = ref object of Signer
|
|
|
|
privateKey*: PrivateKey
|
|
|
|
publicKey*: PublicKey
|
|
|
|
address*: Address
|
2022-07-21 00:04:05 +00:00
|
|
|
provider*: ?Provider
|
2022-07-12 18:23:43 +00:00
|
|
|
|
2023-07-05 12:55:14 +00:00
|
|
|
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
|
2023-08-29 10:45:49 +00:00
|
|
|
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
|
2022-07-21 00:04:05 +00:00
|
|
|
proc connect*(wallet: Wallet, provider: Provider) =
|
2022-07-12 18:23:43 +00:00
|
|
|
wallet.provider = some provider
|
|
|
|
proc createRandom*(_: type Wallet): Wallet =
|
|
|
|
result = Wallet()
|
2022-07-21 00:00:57 +00:00
|
|
|
result.privateKey = PrivateKey.random(getRng()[])
|
2022-07-12 18:23:43 +00:00
|
|
|
result.publicKey = result.privateKey.toPublicKey()
|
|
|
|
result.address = Address.init(result.publicKey.toCanonicalAddress())
|
2022-07-21 00:04:05 +00:00
|
|
|
proc createRandom*(_: type Wallet, provider: Provider): Wallet =
|
2022-07-12 18:23:43 +00:00
|
|
|
result = Wallet()
|
2022-07-21 00:00:57 +00:00
|
|
|
result.privateKey = PrivateKey.random(getRng()[])
|
2022-07-12 18:23:43 +00:00
|
|
|
result.publicKey = result.privateKey.toPublicKey()
|
|
|
|
result.address = Address.init(result.publicKey.toCanonicalAddress())
|
|
|
|
result.provider = some provider
|
|
|
|
|
2022-07-12 19:13:34 +00:00
|
|
|
method provider*(wallet: Wallet): Provider =
|
2022-07-14 09:24:21 +00:00
|
|
|
without provider =? wallet.provider:
|
2023-07-04 08:40:22 +00:00
|
|
|
raiseWalletError "Wallet has no provider"
|
2022-07-14 09:24:21 +00:00
|
|
|
provider
|
2022-07-12 19:13:34 +00:00
|
|
|
|
2022-07-21 00:00:57 +00:00
|
|
|
method getAddress(wallet: Wallet): Future[Address] {.async.} =
|
|
|
|
return wallet.address
|
2022-07-12 18:23:43 +00:00
|
|
|
|
2023-07-04 09:38:48 +00:00
|
|
|
proc signTransaction*(wallet: Wallet,
|
|
|
|
transaction: Transaction): Future[seq[byte]] {.async.} =
|
|
|
|
if sender =? transaction.sender and sender != wallet.address:
|
2023-07-04 08:40:22 +00:00
|
|
|
raiseWalletError "from address mismatch"
|
2022-07-14 09:24:21 +00:00
|
|
|
|
2023-07-04 09:38:48 +00:00
|
|
|
return wallet.privateKey.sign(transaction)
|
2022-07-12 19:21:35 +00:00
|
|
|
|
2023-07-04 09:38:48 +00:00
|
|
|
method sendTransaction*(wallet: Wallet, transaction: Transaction): Future[TransactionResponse] {.async.} =
|
|
|
|
let signed = await signTransaction(wallet, transaction)
|
|
|
|
return await provider(wallet).sendTransaction(signed)
|