Dynamic MPC Wallet SDK for Python — create and manage multi-party computation wallets for EVM and Solana
Project description
Dynamic Wallet SDK for Python
A Python SDK for Dynamic's MPC (Multi-Party Computation) wallet infrastructure. Create, sign with, and manage non-custodial wallets from Python — no browser required.
Guides: ARCHITECTURE.md — internals deep-dive | DEMO_GUIDE.md — build a working demo in minutes
The SDK is split into two layers:
dynamic_wallet_mpc— A native Rust extension (via PyO3) wrapping Dynamic's MPC library. Handles all low-level cryptographic MPC operations: key generation, signing, key refresh, import/export.dynamic_wallet_sdk— Pure Python package providing API client orchestration, key backup encryption (AES-256-GCM), SSE event parsing, and chain-specific logic for EVM and SVM.
Prerequisites
- Python 3.10+
- Rust toolchain (for building the native extension) — install via rustup
- MPC registry access — the native MPC crate is hosted on a private Cargo registry
- Dynamic environment ID + API key — from the Dynamic dashboard
Setup
1. Clone and navigate
cd python/
2. Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate
3. Configure the private Cargo registry
The native extension depends on an internal MPC crate hosted on a private Cargo registry.
.cargo/config.toml (already present in the repo) configures the registry URL.
Add credentials to your global Cargo config:
cat >> ~/.cargo/credentials.toml << 'EOF'
[registries.dynamic-mpc]
token = "Bearer <YOUR_MPC_REGISTRY_TOKEN>"
EOF
The registry token is stored in 1Password. Ask a team member if you don't have access.
4. Install Python dependencies
pip install -e ".[dev]"
This installs:
| Dependency | Purpose |
|---|---|
httpx |
Async HTTP client for Dynamic API + SSE streaming |
cryptography |
AES-256-GCM encryption, PBKDF2 key derivation, RSA-OAEP for delegated signing |
eth-account |
EIP-712 typed data encoding |
eth-hash[pycryptodome] |
Keccak-256 hashing for EVM address derivation and EIP-191 |
base58 |
Solana address encoding |
solders |
Solana primitives |
pytest, pytest-asyncio |
Testing |
respx |
HTTP mocking for tests |
maturin |
Rust-to-Python build tool |
5. Build the native extension
maturin develop
This compiles the Rust code in src/ and installs the resulting dynamic_wallet_mpc native module into your venv. The first build downloads and compiles dependencies, which takes a few minutes. Subsequent builds are incremental (~2-5s).
To verify the build succeeded:
python -c "from dynamic_wallet_mpc import PyEcdsa, PyEd25519; print('Native module loaded')"
Running Tests
pytest
All tests run in ~2 seconds. The test suite covers:
test_encryption.py— AES-256-GCM encrypt/decrypt round-trips, v1/v2 compatibility, wrong-password detectiontest_evm_utils.py— EVM address derivation from public keys, EIP-191 message formatting, EIP-55 checksum encoding, ECDSA signature serializationtest_svm_utils.py— Solana address derivation (base58), hex round-trips, message formattingtest_sse.py— SSE event stream parsing, error events, edge casestest_wallet_client.py— Wallet client initialization, authentication flow (mocked), wallet map operations, address normalization
Tests don't call any live relay or Dynamic API — they exercise the pure Python logic. The native module is imported only for type checks.
Project Structure
python/
├── .cargo/config.toml # Private MPC registry URL
├── Cargo.toml # Rust crate config: MPC library + pyo3 + tokio
├── pyproject.toml # Python package config (maturin build backend)
│
├── src/ # Rust native extension (PyO3)
│ ├── lib.rs # #[pymodule] entry point, tokio runtime init
│ ├── ecdsa.rs # PyEcdsa — ECDSA MPC operations
│ ├── ed25519.rs # PyEd25519 — standard Ed25519 MPC operations
│ ├── exportable_ed25519.rs # PyExportableEd25519 — ExportableEd25519 (used for SVM)
│ ├── types.rs # Python-visible types (PyInitKeygenResult, PyMessageHash, etc.)
│ ├── error.rs # MPCError Python exception
│ └── unsafesend.rs # SendFuture wrapper for !Send FFI futures
│
├── dynamic_wallet_sdk/ # Pure Python SDK
│ ├── __init__.py # Public API re-exports
│ ├── constants.py # URLs, headers, enums (Environment, ChainType, BackupLocation)
│ ├── mpc_config.py # TSS schemes, chain configs, derivation paths
│ ├── exceptions.py # Error hierarchy (DynamicSDKError, AuthenticationError, etc.)
│ │
│ ├── api/
│ │ ├── client.py # BaseClient: dual httpx clients (API + Evervault relay)
│ │ ├── dynamic_api.py # All Dynamic API endpoints (SSE + REST)
│ │ └── sse.py # SSE event stream parser
│ │
│ ├── crypto/
│ │ └── encryption.py # AES-256-GCM + PBKDF2 key share backup encryption
│ │
│ ├── mpc/
│ │ ├── signer.py # get_mpc_signer() factory — returns PyEcdsa or PyExportableEd25519
│ │ └── types.py # ServerKeyShare, WalletProperties dataclasses
│ │
│ ├── wallet_client.py # DynamicWalletClient — orchestrates keygen, sign, refresh, export, import, backup
│ │
│ ├── evm/
│ │ ├── client.py # DynamicEvmWalletClient — EIP-191/712 signing, tx signing
│ │ └── utils.py # EVM address derivation, message formatting, signature serialization
│ │
│ ├── svm/
│ │ ├── client.py # DynamicSvmWalletClient — Solana message/tx signing
│ │ └── utils.py # Solana address derivation, message formatting
│ │
│ └── delegated/
│ ├── client.py # Delegated signing — factory + sign with delegated key shares
│ └── decrypt.py # RSA-OAEP + AES-GCM webhook decryption
│
└── tests/
├── conftest.py # Shared fixtures
├── test_encryption.py
├── test_evm_utils.py
├── test_svm_utils.py
├── test_sse.py
└── test_wallet_client.py
Architecture
Native Extension (dynamic_wallet_mpc)
The Rust layer exposes these classes to Python:
| Class | Description |
|---|---|
PyEcdsa |
ECDSA MPC operations (EVM, BTC segwit) |
PyEd25519 |
Ed25519 MPC operations |
PyExportableEd25519 |
ExportableEd25519 MPC operations (Solana) |
PyInitKeygenResult |
Returned by init_keygen() — contains keygen_id (str) and keygen_secret (bytes) |
PyEcdsaKeygenResult |
ECDSA keygen output — pubkey_uncompressed, pubkey_compressed, secret_share |
PyEd25519KeygenResult |
Ed25519 keygen output — pubkey (32 bytes), secret_share |
PyEcdsaSignature |
ECDSA signature — r, s, v, der |
PyMessageHash |
32-byte message hash with sha256(), keccak256() static constructors |
Key API details:
init_keygen(),derive_pubkey(), andexport_id()are synchronouskeygen(),sign(),refresh(),export_full_private_key(),import_*,reshare_*are async (return Python awaitables)- All async operations share a single tokio runtime initialized at module load
- The
SendFuturewrapper inunsafesend.rsmakes the MPC library's FFI futures compatible withpyo3_async_runtimes::tokio::future_into_py
Python SDK (dynamic_wallet_sdk)
The Python layer handles everything above the MPC primitives:
- Authentication — Exchange API tokens for JWTs via Dynamic's API
- Keygen orchestration —
init_keygen()→ SSE call to Dynamic API → MPCkeygen()→ derive address - Sign orchestration — SSE call for signing room → MPC
sign()→ format chain-specific signature - Key backup — Encrypt key shares with AES-256-GCM (PBKDF2, 1M iterations) and store via Evervault relay
- Key recovery — Retrieve and decrypt backed-up key shares
- Key export/import — Full private key export via MPC, or import existing keys into MPC
- Delegated signing — Sign using server-held delegated key shares, decrypt webhook payloads
Chain Support
| Chain | Algorithm | Client Class | Derivation Path |
|---|---|---|---|
| EVM | ECDSA | DynamicEvmWalletClient |
m/44'/60'/0'/0/0 |
| SVM (Solana) | Ed25519 | DynamicSvmWalletClient |
m/44'/501'/0'/0/0 |
| Cosmos | Ed25519 | — | m/44'/118'/0'/0/0 |
| Sui | Ed25519 | — | m/44'/784'/0'/0/0 |
| TON | Ed25519 | — | m/44'/607'/0'/0/0 |
| Stellar | Ed25519 | — | m/44'/148'/0'/0/0 |
| BTC (taproot) | BIP340 | — | m/86'/0'/0'/0/0 |
| BTC (segwit) | ECDSA | — | m/84'/0'/0'/0/0 |
EVM and SVM have full client implementations. Other chains have config entries but need client classes.
Usage
EVM Wallet
import asyncio
from dynamic_wallet_sdk.evm.client import DynamicEvmWalletClient
async def main():
async with DynamicEvmWalletClient("your-environment-id") as client:
# Authenticate
await client.authenticate_api_token("your-api-token")
# Create wallet (keygen)
address = await client.create_wallet_account(password="backup-password")
print(f"Created EVM wallet: {address}")
# Sign a message (EIP-191)
signature = await client.sign_message(
message="Hello, Dynamic!",
address=address,
password="backup-password",
)
print(f"Signature: {signature}")
# Sign EIP-712 typed data
typed_data = {
"types": {...},
"primaryType": "...",
"domain": {...},
"message": {...},
}
sig = await client.sign_typed_data(address, typed_data, password="backup-password")
asyncio.run(main())
SVM (Solana) Wallet
import asyncio
from dynamic_wallet_sdk.svm.client import DynamicSvmWalletClient
async def main():
async with DynamicSvmWalletClient("your-environment-id") as client:
await client.authenticate_api_token("your-api-token")
address = await client.create_wallet_account(password="backup-password")
print(f"Created Solana wallet: {address}")
# Sign a message
signature = await client.sign_message(
message="Hello from Solana!",
address=address,
password="backup-password",
)
print(f"Signature (base58): {signature}")
asyncio.run(main())
Delegated Signing
For server-side signing where key shares are held by the customer's server:
from dynamic_wallet_sdk.delegated.client import (
create_delegated_evm_client,
delegated_sign_message,
)
from dynamic_wallet_sdk.delegated.decrypt import decrypt_delegated_webhook_data
# 1. Decrypt the webhook data you received
decrypted = decrypt_delegated_webhook_data(
private_key_pem=rsa_private_key,
encrypted_delegated_key_share=webhook["encryptedDelegatedShare"],
encrypted_wallet_api_key=webhook["encryptedWalletApiKey"],
)
# 2. Create a client and sign
client = await create_delegated_evm_client("env-id", "api-key")
sig = await delegated_sign_message(
client,
wallet_id="wallet-id",
wallet_api_key=decrypted.decrypted_wallet_api_key,
key_share=decrypted.decrypted_delegated_share["secretShare"],
message="0x...",
chain_name="EVM",
is_formatted=True,
)
Using the Native Module Directly
If you want to use the MPC primitives without the SDK orchestration:
from dynamic_wallet_mpc import PyEcdsa, PyEd25519, PyMessageHash
# ECDSA
ecdsa = PyEcdsa("https://relay.dynamicauth.com")
init = ecdsa.init_keygen() # synchronous
print(init.keygen_id, len(init.keygen_secret)) # str, 32 bytes
# Ed25519
ed = PyEd25519("https://relay.dynamicauth.com")
init = ed.init_keygen()
# Hashing
h = PyMessageHash.keccak256(b"hello world")
print(h.to_hex())
h2 = PyMessageHash.sha256(b"hello world")
h3 = PyMessageHash("ab" * 32) # from 64-char hex string
Key Concepts
Threshold Signature Schemes
The SDK supports three TSS configurations:
| Scheme | Parties | Threshold | Client Shares | Server Shares |
|---|---|---|---|---|
TWO_OF_TWO |
2 | 2 | 1 | 1 |
TWO_OF_THREE |
3 | 2 | 2 | 1 |
THREE_OF_FIVE |
5 | 3 | 3 | 2 |
Wallet Map
The DynamicWalletClient maintains an in-memory _wallet_map keyed by normalized address. Always use the accessor methods:
wp = client.get_wallet_from_map(address) # raises WalletNotFoundError if missing
client.update_wallet_in_map(address, wallet_id="new-id")
EVM addresses are normalized to lowercase. Solana addresses are stored as-is.
Key Share Backup
Key shares are encrypted with AES-256-GCM using a password-derived key (PBKDF2, SHA-256, 1M iterations). Two versions exist:
- v1 — 100K PBKDF2 iterations (legacy)
- v2 — 1M PBKDF2 iterations (current default)
Decryption auto-detects the version. Encrypted backups are stored through the Evervault keyshares relay.
SSE Communication
Most mutating API calls (create wallet, sign, refresh, export, import) use Server-Sent Events:
- Client POSTs to the API endpoint with
Accept: text/event-stream - Server creates an MPC room and streams events
- Client waits for a success event (
keygen_completeorroom_created) - Client uses the room ID to perform the MPC operation via the Dynamic relay
Timeout is 30 seconds by default. See api/sse.py.
Build Commands
| Command | Description |
|---|---|
maturin develop |
Build native extension in dev mode and install into venv |
maturin develop --release |
Build with optimizations |
maturin build --release |
Build a distributable wheel in target/wheels/ |
pytest |
Run all tests |
pytest -v |
Run tests with verbose output |
pytest tests/test_encryption.py |
Run a specific test file |
Troubleshooting
cargo not found
Install the Rust toolchain:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
Registry authentication failure
If you see authenticated registries require a credential-provider to be available:
- Verify
~/.cargo/credentials.tomlhas the[registries.dynamic-mpc]section with your registry token - Verify
.cargo/config.tomlhasglobal-credential-providers = ["cargo:token"]
maturin develop fails with compilation errors
Make sure you're using a compatible Rust version (1.75+). Update with:
rustup update stable
ImportError for dynamic_wallet_mpc
The native module wasn't built or the venv isn't activated. Run:
source .venv/bin/activate
maturin develop
Slow encryption tests
PBKDF2 with 1M iterations takes ~1-2 seconds per encrypt/decrypt. This is by design.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dynamic_wallet_sdk-0.1.1.tar.gz.
File metadata
- Download URL: dynamic_wallet_sdk-0.1.1.tar.gz
- Upload date:
- Size: 87.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6cc12a42f505cd8f0c4ee50ec34b750e963fae4106add3e39a48b5c767a9b5d
|
|
| MD5 |
261a1cad2433f42c32038a1c2f21ffb6
|
|
| BLAKE2b-256 |
91005b1fe6a62bbff0f91810dca65e1b6e09eead56038207b00f451d8ae8970f
|
Provenance
The following attestation bundles were made for dynamic_wallet_sdk-0.1.1.tar.gz:
Publisher:
python-publish.yml on dynamic-labs/dynamic-waas-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dynamic_wallet_sdk-0.1.1.tar.gz -
Subject digest:
c6cc12a42f505cd8f0c4ee50ec34b750e963fae4106add3e39a48b5c767a9b5d - Sigstore transparency entry: 1217810011
- Sigstore integration time:
-
Permalink:
dynamic-labs/dynamic-waas-sdk@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dynamic-labs
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.11+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd88f99b3b1e2196c8f48d341e3d378bd4a6d213d6ab84bb706d795554ed1dbd
|
|
| MD5 |
06d94dd242525290935fbed1c9600875
|
|
| BLAKE2b-256 |
7e265cd28caf118b62dffbec192e3f4963f4afba16a7451328f7ef6e87d48b34
|
Provenance
The following attestation bundles were made for dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl:
Publisher:
python-publish.yml on dynamic-labs/dynamic-waas-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
fd88f99b3b1e2196c8f48d341e3d378bd4a6d213d6ab84bb706d795554ed1dbd - Sigstore transparency entry: 1217810044
- Sigstore integration time:
-
Permalink:
dynamic-labs/dynamic-waas-sdk@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dynamic-labs
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 4.6 MB
- Tags: CPython 3.11+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e09b5d88a9a36d1b472b98c981ec74366533ad0f1111f3e248a1b5f208b21d78
|
|
| MD5 |
c20cf8cc60aed4f03ac26cff2b955127
|
|
| BLAKE2b-256 |
79fb8e49c191c5ebe9468cac4a8d53000296caf0af780d9a5cc6a27d837dbeba
|
Provenance
The following attestation bundles were made for dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl:
Publisher:
python-publish.yml on dynamic-labs/dynamic-waas-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dynamic_wallet_sdk-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
e09b5d88a9a36d1b472b98c981ec74366533ad0f1111f3e248a1b5f208b21d78 - Sigstore transparency entry: 1217810038
- Sigstore integration time:
-
Permalink:
dynamic-labs/dynamic-waas-sdk@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dynamic-labs
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.8 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85a65530ef86822edaa8208279a74a56a00ca71eeaaeaeaa5604410dd2cfb974
|
|
| MD5 |
e81028ebe12b8ba32cec32228c0b9dcf
|
|
| BLAKE2b-256 |
626fac406a8caf624a53b69a8719d4bf11d9273e36eb5ce297c2a0ae2fec5f16
|
Provenance
The following attestation bundles were made for dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_11_0_arm64.whl:
Publisher:
python-publish.yml on dynamic-labs/dynamic-waas-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_11_0_arm64.whl -
Subject digest:
85a65530ef86822edaa8208279a74a56a00ca71eeaaeaeaa5604410dd2cfb974 - Sigstore transparency entry: 1217810026
- Sigstore integration time:
-
Permalink:
dynamic-labs/dynamic-waas-sdk@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dynamic-labs
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 5.0 MB
- Tags: CPython 3.11+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26f6ee8f74c90500ef870c7dd5f113e4a08d412b040031e495b7849bb3bee538
|
|
| MD5 |
7109fa34a36fd9bddd44338d2436b2cb
|
|
| BLAKE2b-256 |
b5946c0629e5c7a55c7b7a5ddea32ddcc20a4778bac8958724211ad3659664ef
|
Provenance
The following attestation bundles were made for dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl:
Publisher:
python-publish.yml on dynamic-labs/dynamic-waas-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dynamic_wallet_sdk-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl -
Subject digest:
26f6ee8f74c90500ef870c7dd5f113e4a08d412b040031e495b7849bb3bee538 - Sigstore transparency entry: 1217810018
- Sigstore integration time:
-
Permalink:
dynamic-labs/dynamic-waas-sdk@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dynamic-labs
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5900d6d89ab6d159cf7cd08626313b97c3c46e13 -
Trigger Event:
workflow_dispatch
-
Statement type: