Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FOR REVIEW ONLY: py-algorand-sdk v2.2.0 #474

Merged
merged 12 commits into from
May 8, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/pr-type-category.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ jobs:
labels: "New Feature, Enhancement, Bug-Fix, Not-Yet-Enabled, Skip-Release-Notes"

- name: "Checking for PR Category in PR title. Should be like '<category>: <pr title>'."
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ ! "${{ github.event.pull_request.title }}" =~ ^.{2,}\:.{2,} ]]; then
if [[ ! "$PR_TITLE" =~ ^.{2,}\:.{2,} ]]; then
echo "## PR Category is missing from PR title. Please add it like '<category>: <pr title>'." >> GITHUB_STEP_SUMMARY
exit 1
fi
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

# v2.2.0
## What's Changed
Supports new devmode block timestamp offset endpoints.
### Bugfixes
* Fix: improve SignedTransaction type signature for dryrun and send_transaction by @barnjamin in https://github.com/algorand/py-algorand-sdk/pull/457
* Fix: add auth addr for multisig sign when the msig has been rekeyed by @barnjamin in https://github.com/algorand/py-algorand-sdk/pull/460
### New Features
* Simulation: Lift log limits option in SimulateRequest by @ahangsu in https://github.com/algorand/py-algorand-sdk/pull/469
### Enhancements
* Docs: Examples by @barnjamin in https://github.com/algorand/py-algorand-sdk/pull/454
* BugFix: ATC error message improvement by @barnjamin in https://github.com/algorand/py-algorand-sdk/pull/463
* API: Support updated simulate endpoint by @jasonpaulos in https://github.com/algorand/py-algorand-sdk/pull/466
* algod: Add endpoints for devmode timestamps, sync, and ready by @algochoi in https://github.com/algorand/py-algorand-sdk/pull/468
* DevOps: Add CODEOWNERS to restrict workflow editing by @onetechnical in https://github.com/algorand/py-algorand-sdk/pull/473


**Full Changelog**: https://github.com/algorand/py-algorand-sdk/compare/v2.1.2...v2.2.0

# v2.1.2

## What's Changed
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.github/ @algorand/dev
.circleci/ @algorand/dev
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ RUN pip install . -q \
&& pip install -r requirements.txt -q

# Run integration tests
CMD ["/bin/bash", "-c", "python --version && make unit && make integration"]
CMD ["/bin/bash", "-c", "python --version && make unit && make integration && make smoke-test-examples"]
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ docker-pysdk-run:
docker ps -a
docker run -it --network host py-sdk-testing:latest

# todo replace with ports from harness .env file
smoke-test-examples:
cd examples && bash smoke_test.sh && cd -


docker-test: harness docker-pysdk-build docker-pysdk-run
55 changes: 0 additions & 55 deletions _examples/indexer.py

This file was deleted.

92 changes: 0 additions & 92 deletions _examples/utils.py

This file was deleted.

80 changes: 65 additions & 15 deletions algosdk/atomic_transaction_composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from algosdk import abi, error, transaction
from algosdk.transaction import GenericSignedTransaction
from algosdk.abi.address_type import AddressType
from algosdk.v2client import algod
from algosdk.v2client import algod, models


# The first four bytes of an ABI method call return must have this hash
ABI_RETURN_HASH = b"\x15\x1f\x7c\x75"
Expand Down Expand Up @@ -255,35 +256,67 @@ def __init__(
decode_error: Optional[Exception],
tx_info: dict,
method: abi.Method,
missing_signature: bool,
) -> None:
self.tx_id = tx_id
self.raw_value = raw_value
self.return_value = return_value
self.decode_error = decode_error
self.tx_info = tx_info
self.method = method
self.missing_signature = missing_signature


class SimulateEvalOverrides:
def __init__(
self,
*,
max_log_calls: Optional[int] = None,
max_log_size: Optional[int] = None,
allow_empty_signatures: Optional[bool] = None,
) -> None:
self.max_log_calls = max_log_calls
self.max_log_size = max_log_size
self.allow_empty_signatures = allow_empty_signatures

@staticmethod
def from_simulation_result(
simulation_result: Dict[str, Any]
) -> Optional["SimulateEvalOverrides"]:
if "eval-overrides" not in simulation_result:
return None

eval_override_dict = simulation_result.get("eval-overrides", dict())
eval_override = SimulateEvalOverrides()

if "max-log-calls" in eval_override_dict:
eval_override.max_log_calls = eval_override_dict["max-log-calls"]
if "max-log-size" in eval_override_dict:
eval_override.max_log_size = eval_override_dict["max-log-size"]
if "allow-empty-signatures" in eval_override_dict:
eval_override.allow_empty_signatures = eval_override_dict[
"allow-empty-signatures"
]

return eval_override


class SimulateAtomicTransactionResponse:
def __init__(
self,
version: int,
would_succeed: bool,
failure_message: str,
failed_at: Optional[List[int]],
simulate_response: Dict[str, Any],
tx_ids: List[str],
results: List[SimulateABIResult],
eval_overrides: Optional[SimulateEvalOverrides] = None,
) -> None:
self.version = version
self.would_succeed = would_succeed
self.failure_message = failure_message
self.failed_at = failed_at
self.simulate_response = simulate_response
self.tx_ids = tx_ids
self.abi_results = results
self.eval_overrides = eval_overrides


class AtomicTransactionComposer:
Expand Down Expand Up @@ -495,15 +528,18 @@ def add_method_call(
# or encode a ABI value.
for i, arg in enumerate(method.args):
if abi.is_abi_transaction_type(arg.type):
if not isinstance(
method_args[i], TransactionWithSigner
) or not abi.check_abi_transaction_type(
if not isinstance(method_args[i], TransactionWithSigner):
raise error.AtomicTransactionComposerError(
"expected TransactionWithSigner as method argument, "
f"but received: {method_args[i]}"
)

if not abi.check_abi_transaction_type(
arg.type, method_args[i].txn
):
raise error.AtomicTransactionComposerError(
"expected TransactionWithSigner as method argument, but received: {}".format(
method_args[i]
)
f"expected Transaction type {arg.type} as method argument, "
f"but received: {method_args[i].txn.type}"
)
txn_list.append(method_args[i])
else:
Expand Down Expand Up @@ -683,7 +719,9 @@ def submit(self, client: algod.AlgodClient) -> List[str]:
return self.tx_ids

def simulate(
self, client: algod.AlgodClient
self,
client: algod.AlgodClient,
request: Optional[models.SimulateRequest] = None,
) -> SimulateAtomicTransactionResponse:
"""
Send the transaction group to the `simulate` endpoint and wait for results.
Expand All @@ -693,6 +731,8 @@ def simulate(

Args:
client (AlgodClient): Algod V2 client
request (models.SimulateRequest): SimulateRequest with options in simulation.
The request's transaction group will be overrwritten by the composer's group, only simulation related options will be used.

Returns:
SimulateAtomicTransactionResponse: Object with simulation results for this
Expand All @@ -710,9 +750,18 @@ def simulate(
"lower to simulate a group"
)

current_simulation_request = (
request if request else models.SimulateRequest(txn_groups=list())
)
current_simulation_request.txn_groups = [
models.SimulateRequestTransactionGroup(txns=self.signed_txns)
]

simulation_result = cast(
Dict[str, Any], client.simulate_transactions(self.signed_txns)
Dict[str, Any],
client.simulate_transactions(current_simulation_request),
)

# Only take the first group in the simulate response
txn_group: Dict[str, Any] = simulation_result["txn-groups"][0]

Expand Down Expand Up @@ -751,18 +800,19 @@ def simulate(
decode_error=result.decode_error,
tx_info=result.tx_info,
method=result.method,
missing_signature=sim_txn.get("missing-signature", False),
)
)

return SimulateAtomicTransactionResponse(
version=simulation_result.get("version", 0),
would_succeed=simulation_result.get("would-succeed", False),
failure_message=txn_group.get("failure-message", ""),
failed_at=txn_group.get("failed-at"),
simulate_response=simulation_result,
tx_ids=self.tx_ids,
results=sim_results,
eval_overrides=SimulateEvalOverrides.from_simulation_result(
simulation_result
),
)

def execute(
Expand Down
2 changes: 1 addition & 1 deletion algosdk/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"""str: header key for algod requests"""
INDEXER_AUTH_HEADER = "X-Indexer-API-Token"
"""str: header key for indexer requests"""
UNVERSIONED_PATHS = ["/health", "/versions", "/metrics", "/genesis"]
UNVERSIONED_PATHS = ["/health", "/versions", "/metrics", "/genesis", "/ready"]
"""str[]: paths that don't use the version path prefix"""
NO_AUTH: List[str] = []
"""str[]: requests that don't require authentication"""
Expand Down
5 changes: 5 additions & 0 deletions algosdk/kmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,11 @@ def sign_multisig_transaction(self, handle, password, public_key, mtx):
"public_key": public_key,
"partial_multisig": partial,
}

if hasattr(mtx, "auth_addr") and mtx.auth_addr is not None:
signer = base64.b64encode(encoding.decode_address(mtx.auth_addr))
query["signer"] = signer.decode()

result = self.kmd_request("POST", req, data=query)["multisig"]
msig = encoding.msgpack_decode(result)
mtx.multisig = msig
Expand Down
Loading