from __future__ import annotations
from terra_sdk.key.key import Key, SignOptions
from .api.tx import CreateTxOptions, SignerOptions
__all__ = ["Wallet", "AsyncWallet"]
from ...core.tx import SignMode, Tx
class AsyncWallet:
def __init__(self, lcd, key: Key):
self.lcd = lcd
self.key = key
async def account_number(self) -> int:
res = await self.lcd.auth.account_info(self.key.acc_address)
return res.account_number
async def sequence(self) -> int:
res = await self.lcd.auth.account_info(self.key.acc_address)
return res.sequence
async def account_number_and_sequence(self) -> dict:
res = await self.lcd.auth.account_info(self.key.acc_address)
return {"account_number": res.account_number, "sequence": res.sequence}
async def create_tx(self, options: CreateTxOptions) -> Tx:
sigOpt = [
SignerOptions(
address=self.key.acc_address,
sequence=options.sequence,
public_key=self.key.public_key,
)
]
return await self.lcd.tx.create(sigOpt, options)
async def create_and_sign_tx(self, options: CreateTxOptions) -> Tx:
account_number = options.account_number
sequence = options.sequence
if account_number is None or sequence is None:
res = await self.account_number_and_sequence()
if account_number is None:
account_number = res.get("account_number")
if sequence is None:
sequence = res.get("sequence")
options.sequence = sequence
options.account_number = account_number
return self.key.sign_tx(
tx=(await self.create_tx(options)),
options=SignOptions(
account_number=account_number,
sequence=sequence,
chain_id=self.lcd.chain_id,
sign_mode=options.sign_mode
if options.sign_mode
else SignMode.SIGN_MODE_DIRECT,
),
)
[docs]class Wallet:
"""Wraps around a :class:`Key` implementation and provides transaction building and
signing functionality. It is recommended to create this object through
:meth:`LCDClient.wallet()<terra_sdk.client.lcd.LCDClient.wallet>`."""
def __init__(self, lcd, key: Key):
self.lcd = lcd
self.key = key
[docs] def account_number(self) -> int:
"""Fetches account number for the account associated with the Key."""
res = self.lcd.auth.account_info(self.key.acc_address)
return res.account_number
[docs] def sequence(self) -> int:
"""Fetches the sequence number for the account associated with the Key."""
res = self.lcd.auth.account_info(self.key.acc_address)
return res.sequence
[docs] def account_number_and_sequence(self) -> dict:
"""Fetches both account and sequence number associated with the Key."""
res = self.lcd.auth.account_info(self.key.acc_address)
return {"account_number": res.account_number, "sequence": res.sequence}
[docs] def create_tx(self, options: CreateTxOptions) -> Tx:
"""Builds an unsigned transaction object. The ``Wallet`` will first
query the blockchain to fetch the latest ``account`` and ``sequence`` values for the
account corresponding to its Key, unless the they are both provided. If no ``fee``
parameter is set, automatic fee estimation will be used (see `fee_estimation`).
Args:
options (CreateTxOptions): Options to create a tx
Returns:
Tx: unsigned transaction
"""
sigOpt = [
SignerOptions(
address=self.key.acc_address,
sequence=options.sequence,
public_key=self.key.public_key,
)
]
return self.lcd.tx.create(sigOpt, options)
[docs] def create_and_sign_tx(self, options: CreateTxOptions) -> Tx:
"""Creates and signs a :class:`Tx` object in a single step. This is the recommended
method for preparing transaction for immediate signing and broadcastring. The transaction
is generated exactly as :meth:`create_tx`.
Args:
options (CreateTxOptions): Options to create a tx
Returns:
Tx: signed transaction
"""
account_number = options.account_number
sequence = options.sequence
if account_number is None or sequence is None:
res = self.account_number_and_sequence()
if account_number is None:
account_number = res.get("account_number")
if sequence is None:
sequence = res.get("sequence")
options.sequence = sequence
options.account_number = account_number
return self.key.sign_tx(
tx=self.create_tx(options),
options=SignOptions(
account_number=account_number,
sequence=sequence,
chain_id=self.lcd.chain_id,
sign_mode=options.sign_mode
if options.sign_mode
else SignMode.SIGN_MODE_DIRECT,
),
)