├── .coveragerc
├── .flake8
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dependabot.yml
├── donate_addr.png
├── logo.png
└── workflows
│ ├── main.yml
│ └── publish.yml
├── .gitignore
├── .readthedocs.yaml
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── docs
├── Makefile
├── make.bat
├── requirements.txt
└── source
│ ├── api
│ ├── pycardano.address.rst
│ ├── pycardano.backend.base.rst
│ ├── pycardano.certificate.rst
│ ├── pycardano.cip.rst
│ ├── pycardano.coinselection.rst
│ ├── pycardano.crypto.rst
│ ├── pycardano.exception.rst
│ ├── pycardano.governance.rst
│ ├── pycardano.hash.rst
│ ├── pycardano.key.rst
│ ├── pycardano.metadata.rst
│ ├── pycardano.nativescript.rst
│ ├── pycardano.network.rst
│ ├── pycardano.plutus.rst
│ ├── pycardano.poolparams.rst
│ ├── pycardano.serialization.rst
│ ├── pycardano.transaction.rst
│ ├── pycardano.utils.rst
│ └── pycardano.witness.rst
│ ├── conf.py
│ ├── guides
│ ├── address.rst
│ ├── instance_creation.rst
│ ├── plutus.rst
│ ├── serialization.rst
│ └── transaction.rst
│ ├── index.rst
│ └── tutorial.rst
├── ensure_pure_cbor2.sh
├── examples
├── delegator_loyalty_rewards.py
├── full_stack
│ ├── README.md
│ ├── demo.gif
│ ├── poetry.lock
│ ├── pyproject.toml
│ ├── sequence_diagram.svg
│ ├── sequence_diagram.txt
│ ├── server.py
│ ├── static
│ │ ├── App.js
│ │ └── style.css
│ └── templates
│ │ └── index.html
├── more_examples
│ ├── .env-example
│ ├── .gitignore
│ ├── 01_address.py
│ ├── 02_query_address.py
│ ├── 03_distribute.py
│ ├── 04_consolidate.py
│ ├── 05_mint_asset.py
│ ├── 06_query_receive_address.py
│ ├── 07_mint_nfts.py
│ ├── 08_burn_nfts.py
│ ├── 09_sign_document_data.py
│ ├── 10_verify_document.py
│ ├── 11_verify_fake_document.py
│ ├── 12_transaction_chaining.py
│ ├── README.md
│ └── keys
│ │ └── .gitkeep
├── native_token.py
├── plutus
│ └── forty_two
│ │ ├── README.md
│ │ ├── forty_two.py
│ │ ├── fortytwo.plutus
│ │ └── fortytwoV2.plutus
├── raw_multi_asset_transaction.py
├── raw_transaction.py
├── tx_builder.py
└── tx_builder_with_metadata.py
├── integration-test
├── README.md
├── __init__.py
├── bootstrap.sh
├── configs
│ ├── local-alonzo
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── byron
│ │ │ ├── delegate.cert
│ │ │ └── delegate.key
│ │ ├── config.json
│ │ ├── conway-genesis.json
│ │ ├── shelley-genesis.json
│ │ ├── shelley
│ │ │ ├── kes.skey
│ │ │ ├── kes.vkey
│ │ │ ├── node.cert
│ │ │ ├── operator.counter
│ │ │ ├── operator.skey
│ │ │ ├── operator.vkey
│ │ │ ├── utxo-keys
│ │ │ │ ├── payment.addr
│ │ │ │ ├── utxo1.skey
│ │ │ │ └── utxo1.vkey
│ │ │ ├── vrf.skey
│ │ │ └── vrf.vkey
│ │ └── topology.json
│ ├── local-chang
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── byron
│ │ │ ├── delegate.cert
│ │ │ └── delegate.key
│ │ ├── config.json
│ │ ├── conway-genesis.json
│ │ ├── shelley-genesis.json
│ │ ├── shelley
│ │ │ ├── kes.skey
│ │ │ ├── kes.vkey
│ │ │ ├── node.cert
│ │ │ ├── operator.counter
│ │ │ ├── operator.skey
│ │ │ ├── operator.vkey
│ │ │ ├── utxo-keys
│ │ │ │ ├── payment.addr
│ │ │ │ ├── utxo1.skey
│ │ │ │ └── utxo1.vkey
│ │ │ ├── vrf.skey
│ │ │ └── vrf.vkey
│ │ └── topology.json
│ ├── local-vasil
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── byron
│ │ │ ├── delegate.cert
│ │ │ └── delegate.key
│ │ ├── config.json
│ │ ├── conway-genesis.json
│ │ ├── shelley-genesis.json
│ │ ├── shelley
│ │ │ ├── kes.skey
│ │ │ ├── kes.vkey
│ │ │ ├── node.cert
│ │ │ ├── operator.counter
│ │ │ ├── operator.skey
│ │ │ ├── operator.vkey
│ │ │ ├── utxo-keys
│ │ │ │ ├── payment.addr
│ │ │ │ ├── utxo1.skey
│ │ │ │ └── utxo1.vkey
│ │ │ ├── vrf.skey
│ │ │ └── vrf.vkey
│ │ └── topology.json
│ ├── mainnet
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── config.json
│ │ ├── shelley-genesis.json
│ │ └── topology.json
│ └── testnet
│ │ ├── alonzo-genesis.json
│ │ ├── byron-genesis.json
│ │ ├── config.json
│ │ ├── shelley-genesis.json
│ │ └── topology.json
├── docker-compose-chang.yml
├── docker-compose.yml
├── keys
│ ├── extended.skey
│ └── pool
│ │ ├── cold.counter
│ │ ├── cold.skey
│ │ ├── cold.vkey
│ │ ├── delegation.cert
│ │ ├── full.addr
│ │ ├── kes.skey
│ │ ├── kes.vkey
│ │ ├── node.cert
│ │ ├── payment.addr
│ │ ├── payment.skey
│ │ ├── payment.vkey
│ │ ├── pool-registration.cert
│ │ ├── pool.id
│ │ ├── pool_registration_tx.signed
│ │ ├── stake.addr
│ │ ├── stake.cert
│ │ ├── stake.skey
│ │ ├── stake.vkey
│ │ ├── topology.json
│ │ ├── vrf.skey
│ │ └── vrf.vkey
├── plutus_scripts
│ ├── always_succeeds.plutus
│ ├── fortytwo.plutus
│ ├── fortytwoV2.plutus
│ ├── helloworldV3.plutus
│ ├── pass_certifying_and_rewarding.plutus
│ └── unroll.plutus
├── run_node.sh
├── run_pool.sh
├── run_tests.sh
└── test
│ ├── __init__.py
│ ├── base.py
│ ├── test_cardano_cli.py
│ ├── test_certificate.py
│ ├── test_certificate_script.py
│ ├── test_governance.py
│ ├── test_min_utxo.py
│ ├── test_mint.py
│ ├── test_ogmios.py
│ ├── test_plutus.py
│ └── test_zero_empty_asset.py
├── poetry.lock
├── pycardano
├── __init__.py
├── address.py
├── backend
│ ├── __init__.py
│ ├── base.py
│ ├── blockfrost.py
│ ├── cardano_cli.py
│ ├── kupo.py
│ ├── ogmios_v5.py
│ └── ogmios_v6.py
├── certificate.py
├── cip
│ ├── __init__.py
│ ├── cip14.py
│ └── cip8.py
├── coinselection.py
├── crypto
│ ├── __init__.py
│ ├── bech32.py
│ └── bip32.py
├── exception.py
├── governance.py
├── hash.py
├── key.py
├── logging.py
├── metadata.py
├── nativescript.py
├── network.py
├── plutus.py
├── pool_params.py
├── serialization.py
├── transaction.py
├── txbuilder.py
├── types.py
├── utils.py
└── witness.py
├── pyproject.toml
└── test
├── __init__.py
├── conftest.py
├── pycardano
├── __init__.py
├── backend
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_blockfrost.py
│ ├── test_cardano_cli.py
│ └── test_ogmios_v5.py
├── crypto
│ ├── __init__.py
│ └── test_bip32.py
├── test_address.py
├── test_certificate.py
├── test_cip14.py
├── test_cip8.py
├── test_coinselection.py
├── test_governance.py
├── test_key.py
├── test_metadata.py
├── test_nativescript.py
├── test_network.py
├── test_plutus.py
├── test_pool_params.py
├── test_serialization.py
├── test_transaction.py
├── test_txbuilder.py
├── test_types.py
├── test_util.py
└── util.py
└── resources
├── haskell
└── PlutusData
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── cabal.project
│ ├── hie.yaml
│ ├── plutus-data.cabal
│ ├── plutus-data.cbor
│ ├── plutus-data.json
│ └── src
│ └── PlutusData.hs
└── keys
├── cold.skey
├── cold.vkey
├── payment.skey
├── payment.vkey
├── staking.skey
└── staking.vkey
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | branch = True
3 | omit =
4 | pycardano/crypto/bech32.py
5 |
6 | [report]
7 | # Regexes for lines to exclude from consideration
8 | exclude_lines =
9 | # Have to re-enable the standard pragma
10 | pragma: no cover
11 |
12 | # Don't complain about missing debug-only code:
13 | def __repr__
14 | if self\.debug
15 |
16 | # Don't complain if tests don't hit defensive assertion code:
17 | raise AssertionError
18 | raise NotImplementedError
19 |
20 | # Don't complain if non-runnable code isn't run:
21 | if 0:
22 | if __name__ == .__main__.:
23 |
24 | ignore_errors = True
25 |
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore = D203, E126, W503, E203
3 | exclude =
4 | .git,
5 | __pycache__,
6 | docs/source/conf.py,
7 | build,
8 |
9 | max-line-length = 120
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [cffls]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior. e.g. A python script.
15 |
16 | **Logs**
17 | If applicable, add logs to help explain your problem.
18 |
19 | **Expected behavior**
20 | A clear and concise description of what you expected to happen.
21 |
22 | **Environment and software version (please complete the following information):**
23 | - OS: [e.g. Ubuntu 20.04.3 LTS, Mac OS 12.1]
24 | - PyCardano Version [e.g. 0.1.1]
25 |
26 |
27 | **Additional context**
28 | Add any other context about the problem here.
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "pip" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 | open-pull-requests-limit: 0
--------------------------------------------------------------------------------
/.github/donate_addr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/.github/donate_addr.png
--------------------------------------------------------------------------------
/.github/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/.github/logo.png
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: "**"
6 | pull_request:
7 | branches: ["main", "chang"]
8 | types: [opened, reopened, edited, synchronize]
9 |
10 | jobs:
11 | build:
12 |
13 | runs-on: ${{ matrix.os }}
14 | strategy:
15 | matrix:
16 | os: [ubuntu-latest, macos-latest]
17 | python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | - name: Install poetry
22 | run: pipx install poetry
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v5
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 | cache: 'poetry'
28 | - name: Install dependencies
29 | run: |
30 | poetry install
31 | - name: Ensure pure cbor2 is installed
32 | run: |
33 | make ensure-pure-cbor2
34 | - name: Run unit tests
35 | run: |
36 | poetry run pytest --doctest-modules --ignore=examples --cov=pycardano --cov-config=.coveragerc --cov-report=xml
37 | - name: "Upload coverage to Codecov"
38 | if: ${{ matrix.python-version == '3.11' }}
39 | uses: codecov/codecov-action@v4
40 | with:
41 | fail_ci_if_error: false
42 | token: ${{ secrets.CODECOV_TOKEN || '' }}
43 | - name: Run static analyses
44 | if: ${{ matrix.python-version == '3.11' }}
45 | run: |
46 | make qa
47 |
48 | continuous-integration:
49 | runs-on: ${{ matrix.os }}
50 | strategy:
51 | matrix:
52 | os: [ubuntu-latest]
53 | python-version: ['3.11']
54 |
55 | steps:
56 | - uses: actions/checkout@v4
57 | - name: Install poetry
58 | run: pipx install poetry
59 | - name: Set up Python ${{ matrix.python-version }}
60 | uses: actions/setup-python@v5
61 | with:
62 | python-version: ${{ matrix.python-version }}
63 | cache: 'poetry'
64 |
65 | - name: Setup docker-compose
66 | uses: KengoTODA/actions-setup-docker-compose@v1.2.2
67 | with:
68 | version: '2.14.2'
69 |
70 | - name: Run integration tests
71 | run: |
72 | cd integration-test && ./run_tests.sh
73 |
74 | - name: "Upload coverage to Codecov"
75 | if: ${{ matrix.python-version == '3.11' }}
76 | uses: codecov/codecov-action@v4
77 | with:
78 | fail_ci_if_error: false
79 | token: ${{ secrets.CODECOV_TOKEN || '' }}
80 |
81 | - name: Dump docker logs
82 | if: failure()
83 | run: |
84 | cd integration-test && docker compose logs --no-color > integration-test.log
85 |
86 | - name: Upload integration-test.log
87 | if: failure()
88 | uses: actions/upload-artifact@v4
89 | with:
90 | name: integration-test.log
91 | path: integration-test/integration-test.log
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: publish
2 | on:
3 | push:
4 | tags:
5 | - "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching *, i.e. 1.0, 20.15.10
6 |
7 | jobs:
8 | publish:
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | python-version: ['3.13']
13 | os: [ubuntu-latest]
14 | runs-on: ${{ matrix.os }}
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Install poetry
18 | run: pipx install poetry
19 | - name: Set up Python ${{ matrix.python-version }}
20 | uses: actions/setup-python@v5
21 | with:
22 | python-version: ${{ matrix.python-version }}
23 | cache: 'poetry'
24 | - name: Install dependencies
25 | run: |
26 | poetry install
27 | - name: Ensure pure cbor2 is installed
28 | run: |
29 | make ensure-pure-cbor2
30 | - name: Lint with flake8
31 | run: |
32 | poetry run flake8 pycardano
33 | - name: Run unit tests
34 | run: |
35 | poetry run pytest --doctest-modules --ignore=examples --cov=pycardano --cov-config=.coveragerc --cov-report=xml
36 | - name: poetry-check
37 | run: |
38 | poetry check
39 | - name: poetry-publish
40 | run: |
41 | poetry publish --build --username __token__ --password ${{ secrets.PYPI_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | .coverage
3 | cov_html
4 | docs/build
5 | dist
6 | .mypy_cache
7 | coverage.xml
8 | .cbor2_version
9 |
10 | # IDE
11 | .idea
12 | .code
13 | /integration-test/.env
14 | /integration-test/tmp_configs/*
15 | /integration-test/.coverage*
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yaml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Set the version of Python and other tools you might need
9 | build:
10 | os: ubuntu-20.04
11 | tools:
12 | python: "3.9"
13 | # You can also specify other tool versions:
14 | # nodejs: "16"
15 | # rust: "1.55"
16 | # golang: "1.17"
17 |
18 | # Build documentation in the docs/ directory with Sphinx
19 | sphinx:
20 | configuration: docs/source/conf.py
21 |
22 | # If using Sphinx, optionally build your docs in additional formats such as PDF
23 | # formats:
24 | # - pdf
25 |
26 | # Optionally declare the Python requirements required to build your docs
27 | python:
28 | install:
29 | - requirements: docs/requirements.txt
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 cffls
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: cov cov-html clean clean-test clean-pyc clean-build qa format test test-single help docs
2 | .DEFAULT_GOAL := help
3 |
4 | define BROWSER_PYSCRIPT
5 | import os, webbrowser, sys
6 |
7 | from urllib.request import pathname2url
8 |
9 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
10 | endef
11 | export BROWSER_PYSCRIPT
12 |
13 | define PRINT_HELP_PYSCRIPT
14 | import re, sys
15 |
16 | for line in sys.stdin:
17 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
18 | if match:
19 | target, help = match.groups()
20 | print("%-20s %s" % (target, help))
21 | endef
22 | export PRINT_HELP_PYSCRIPT
23 |
24 | BROWSER := poetry run python -c "$$BROWSER_PYSCRIPT"
25 |
26 | ensure-pure-cbor2: ## ensures cbor2 is installed with pure Python implementation
27 | @poetry run python -c "from importlib.metadata import version; \
28 | print(version('cbor2'))" > .cbor2_version
29 | @poetry run python -c "import cbor2, inspect; \
30 | print('Checking cbor2 implementation...'); \
31 | decoder_path = inspect.getfile(cbor2.CBORDecoder); \
32 | using_c_ext = decoder_path.endswith('.so'); \
33 | print(f'Implementation path: {decoder_path}'); \
34 | print(f'Using C extension: {using_c_ext}'); \
35 | exit(1 if using_c_ext else 0)" || \
36 | (echo "Reinstalling cbor2 with pure Python implementation..." && \
37 | poetry run pip uninstall -y cbor2 && \
38 | CBOR2_BUILD_C_EXTENSION=0 poetry run pip install --no-binary cbor2 "cbor2==$$(cat .cbor2_version)" --force-reinstall && \
39 | rm .cbor2_version)
40 |
41 | help:
42 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
43 |
44 | cov: ensure-pure-cbor2 ## check code coverage
45 | poetry run pytest -n 4 --cov pycardano
46 |
47 | cov-html: cov ## check code coverage and generate an html report
48 | poetry run coverage html -d cov_html
49 | $(BROWSER) cov_html/index.html
50 |
51 |
52 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
53 |
54 | clean-build: ## remove build artifacts
55 | rm -fr build/
56 | rm -fr dist/
57 | rm -fr .eggs/
58 | find . -name '*.egg-info' -exec rm -fr {} +
59 | find . -name '*.egg' -exec rm -f {} +
60 |
61 | clean-pyc: ## remove Python file artifacts
62 | find . -name '*.pyc' -exec rm -f {} +
63 | find . -name '*.pyo' -exec rm -f {} +
64 | find . -name '*~' -exec rm -f {} +
65 | find . -name '__pycache__' -exec rm -fr {} +
66 |
67 | clean-test: ## remove test and coverage artifacts
68 | rm -f .coverage
69 | rm -fr cov_html/
70 | rm -fr .pytest_cache
71 |
72 | test: ensure-pure-cbor2 ## runs tests
73 | poetry run pytest -vv -n 4
74 |
75 | test-integration: ## runs integration tests
76 | cd integration-test && ./run_tests.sh
77 |
78 | test-single: ## runs tests with "single" markers
79 | poetry run pytest -s -vv -m single
80 |
81 | qa: ensure-pure-cbor2 ## runs static analyses
82 | poetry run flake8 pycardano
83 | poetry run mypy --install-types --non-interactive pycardano
84 | poetry run black --check .
85 |
86 | format: ## runs code style and formatter
87 | poetry run isort .
88 | poetry run black .
89 |
90 | docs: ## build the documentation
91 | poetry export --dev --without-hashes > docs/requirements.txt
92 | rm -r -f docs/build
93 | poetry run sphinx-build docs/source docs/build/html
94 | $(BROWSER) docs/build/html/index.html
95 |
96 | release: clean qa test format ensure-pure-cbor2 ## build dist version and release to pypi
97 | poetry build
98 | poetry publish
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.https://www.sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.address.rst:
--------------------------------------------------------------------------------
1 | Address
2 | ========================
3 |
4 | .. automodule:: pycardano.address
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.backend.base.rst:
--------------------------------------------------------------------------------
1 | Backend
2 | =============================
3 |
4 | .. automodule:: pycardano.backend.base
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | .. automodule:: pycardano.backend.blockfrost
10 | :members:
11 | :undoc-members:
12 | :show-inheritance:
13 |
14 | .. automodule:: pycardano.backend.ogmios_v6
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 | .. automodule:: pycardano.backend.ogmios_v5
20 | :members:
21 | :undoc-members:
22 | :show-inheritance:
23 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.certificate.rst:
--------------------------------------------------------------------------------
1 | Certificate
2 | ==============================
3 |
4 | .. automodule:: pycardano.certificate
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.cip.rst:
--------------------------------------------------------------------------------
1 | CIP
2 | =====================
3 |
4 | Implementation of Cardano Improvement Proposals (CIPs)
5 |
6 | .. automodule:: pycardano.cip.cip8
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
10 |
11 | .. automodule:: pycardano.cip.cip14
12 | :members:
13 | :undoc-members:
14 | :show-inheritance:
15 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.coinselection.rst:
--------------------------------------------------------------------------------
1 | Coin selection
2 | ==============================
3 |
4 | .. automodule:: pycardano.coinselection
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.crypto.rst:
--------------------------------------------------------------------------------
1 | Crypto
2 | =============================
3 | A module that contains cryptographic functions.
4 |
5 | .. automodule:: pycardano.crypto.bip32
6 | :members:
7 | :undoc-members:
8 | :show-inheritance:
9 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.exception.rst:
--------------------------------------------------------------------------------
1 | Exception
2 | ==========================
3 |
4 | .. automodule:: pycardano.exception
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.governance.rst:
--------------------------------------------------------------------------------
1 | Governance
2 | ==============================
3 |
4 | .. automodule:: pycardano.governance
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.hash.rst:
--------------------------------------------------------------------------------
1 | Hash
2 | =====================
3 |
4 | .. automodule:: pycardano.hash
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.key.rst:
--------------------------------------------------------------------------------
1 | Key
2 | ====================
3 |
4 | .. automodule:: pycardano.key
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.metadata.rst:
--------------------------------------------------------------------------------
1 | Metadata
2 | ====================
3 |
4 | .. automodule:: pycardano.metadata
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.nativescript.rst:
--------------------------------------------------------------------------------
1 | Native Script
2 | ====================
3 |
4 | .. automodule:: pycardano.nativescript
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.network.rst:
--------------------------------------------------------------------------------
1 | Network
2 | ========================
3 |
4 | .. automodule:: pycardano.network
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.plutus.rst:
--------------------------------------------------------------------------------
1 | Plutus
2 | ========================
3 |
4 | .. automodule:: pycardano.plutus
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.poolparams.rst:
--------------------------------------------------------------------------------
1 | Pool parameters
2 | ========================
3 |
4 | .. automodule:: pycardano.pool_params
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.serialization.rst:
--------------------------------------------------------------------------------
1 | Serialization
2 | ==============================
3 |
4 | .. automodule:: pycardano.serialization
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.transaction.rst:
--------------------------------------------------------------------------------
1 | Transaction
2 | ============================
3 |
4 | .. automodule:: pycardano.transaction
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | .. automodule:: pycardano.txbuilder
10 | :members:
11 | :undoc-members:
12 | :show-inheritance:
13 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.utils.rst:
--------------------------------------------------------------------------------
1 | Utils
2 | ======================
3 |
4 | .. automodule:: pycardano.utils
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/api/pycardano.witness.rst:
--------------------------------------------------------------------------------
1 | Witness
2 | ========================
3 |
4 | .. automodule:: pycardano.witness
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 |
16 | sys.path.insert(0, os.path.abspath("../"))
17 | # For readthedocs whose working dir is at docs/source
18 | sys.path.insert(0, os.path.abspath("../../"))
19 |
20 |
21 | # -- Project information -----------------------------------------------------
22 |
23 | project = "PyCardano"
24 | copyright = "2023, Jerry"
25 | author = "Jerry"
26 |
27 |
28 | # -- General configuration ---------------------------------------------------
29 |
30 | # Add any Sphinx extension module names here, as strings. They can be
31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32 | # ones.
33 | extensions = [
34 | "sphinx.ext.autodoc",
35 | "sphinx.ext.autosectionlabel",
36 | "sphinx.ext.napoleon",
37 | "sphinx_rtd_theme",
38 | "sphinx_copybutton",
39 | ]
40 |
41 | master_doc = "index"
42 |
43 | napoleon_google_docstring = True
44 | napoleon_include_init_with_doc = False
45 |
46 | copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
47 | copybutton_prompt_is_regexp = True
48 |
49 | autodoc_member_order = "bysource"
50 |
51 | # Add any paths that contain templates here, relative to this directory.
52 | templates_path = ["_templates"]
53 |
54 | # List of patterns, relative to source directory, that match files and
55 | # directories to ignore when looking for source files.
56 | # This pattern also affects html_static_path and html_extra_path.
57 | exclude_patterns = []
58 |
59 | pygments_style = "sphinx"
60 | highlight_language = "python"
61 | todo_include_todos = False
62 |
63 |
64 | # -- Options for HTML output -------------------------------------------------
65 |
66 | # The theme to use for HTML and HTML Help pages. See the documentation for
67 | # a list of builtin themes.
68 | #
69 | html_theme = "sphinx_rtd_theme"
70 |
71 | # Add any paths that contain custom static files (such as style sheets) here,
72 | # relative to this directory. They are copied after the builtin static files,
73 | # so a file named "default.css" will overwrite the builtin "default.css".
74 | html_static_path = ["_static"]
75 |
--------------------------------------------------------------------------------
/docs/source/guides/serialization.rst:
--------------------------------------------------------------------------------
1 | =============
2 | Serialization
3 | =============
4 |
5 |
6 | Cardano uses Concise Binary Object Representation (`CBOR `_) to
7 | store on-chain data. Reading and writing data from/to blockchain requires serialization and deserialization of CBOR
8 | binaries.
9 |
10 | A core feature PyCardano provides is serialization. It can serialize Python objects into CBOR bytes and deserialize
11 | CBOR bytes back to Python objects. Most Classes in PyCardano are child class of
12 | `CBORSerializable <../api/pycardano.serialization.html#pycardano.serialization.CBORSerializable>`_, which provides two
13 | CBOR-related methods. `to_cbor <../api/pycardano.serialization.html#pycardano.serialization.CBORSerializable.to_cbor>`_
14 | generates CBOR bytes from an instance, and
15 | `from_cbor <../api/pycardano.serialization.html#pycardano.serialization.CBORSerializable.from_cbor>`_ restore an instance.
16 |
17 | Examples::
18 |
19 | >>> from pycardano import (TransactionBody,
20 | ... TransactionInput,
21 | ... TransactionId,
22 | ... TransactionOutput)
23 | >>>
24 | >>> tx_id_hex = "732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e5"
25 | >>> tx_in = TransactionInput(TransactionId(bytes.fromhex(tx_id_hex)), 0)
26 | >>> addr = Address.decode(
27 | ... "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
28 | ... )
29 | >>> output1 = TransactionOutput(addr, 100000000000)
30 | >>> output2 = TransactionOutput(addr, 799999834103)
31 | >>> fee = 165897
32 | >>> tx_body = TransactionBody(
33 | ... inputs=[tx_in],
34 | ... outputs=[output1, output2],
35 | ... fee=fee
36 | ... )
37 | >>> cbor_hex = tx_body.to_cbor_hex()
38 | a50081825820732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e500018282581d60f6532850e1bccee9c72a9113ad98bcc5dbb30d2ac960262444f6e5f41b000000174876e80082581d60f6532850e1bccee9c72a9113ad98bcc5dbb30d2ac960262444f6e5f41b000000ba43b4b7f7021a000288090d800e80
39 |
40 | >>> restored_tx_body = TransactionBody.from_cbor(cbor_hex)
41 | >>> assert tx_body == restored_tx_body
42 |
43 | >>> restored_tx_body
44 | {'auxiliary_data_hash': None,
45 | 'certificates': None,
46 | 'collateral': [],
47 | 'fee': 165897,
48 | 'inputs': [{'index': 0,
49 | 'transaction_id': TransactionId(hex='732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e5')}],
50 | 'mint': None,
51 | 'network_id': None,
52 | 'outputs': [{'address': addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x,
53 | 'amount': 100000000000,
54 | 'datum_hash': None},
55 | {'address': addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x,
56 | 'amount': 799999834103,
57 | 'datum_hash': None}],
58 | 'required_signers': [],
59 | 'script_data_hash': None,
60 | 'ttl': None,
61 | 'update': None,
62 | 'validity_start': None,
63 | 'withdraws': None}
64 |
65 | ----------
66 | Plutus Data
67 | ----------
68 |
69 | Note that Plutus datums, passed to `smart contracts <./plutus.html>`_ follow slightly specific rules to `from_cbor`, outlined in the `plutus documentation <./plutus.html#...>`_.
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. PyCardano documentation master file, created by
2 | sphinx-quickstart on Wed Dec 29 20:36:02 2021.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | PyCardano
7 | =====================================
8 |
9 | PyCardano is a standalone Cardano client written in Python. The library is able to create and sign transactions
10 | without depending on third-party Cardano serialization tools, such as cardano-cli and cardano-serialization-lib,
11 | making it a light-weight library that is easy and fast to set up in all kinds of environments.
12 |
13 | .. toctree::
14 | :maxdepth: 1
15 | :caption: Get Started
16 |
17 | tutorial
18 |
19 | .. toctree::
20 | :maxdepth: 1
21 | :caption: Usage Guides
22 |
23 | guides/address
24 | guides/serialization
25 | guides/instance_creation
26 | guides/transaction
27 | guides/plutus
28 |
29 |
30 | .. toctree::
31 | :maxdepth: 1
32 | :caption: API Reference
33 |
34 | api/pycardano.address
35 | api/pycardano.backend.base
36 | api/pycardano.certificate
37 | api/pycardano.cip
38 | api/pycardano.crypto
39 | api/pycardano.coinselection
40 | api/pycardano.exception
41 | api/pycardano.governance
42 | api/pycardano.hash
43 | api/pycardano.key
44 | api/pycardano.metadata
45 | api/pycardano.nativescript
46 | api/pycardano.network
47 | api/pycardano.plutus
48 | api/pycardano.poolparams
49 | api/pycardano.serialization
50 | api/pycardano.transaction
51 | api/pycardano.utils
52 | api/pycardano.witness
53 |
54 |
55 | Links
56 | ==================
57 |
58 | * :ref:`genindex`
59 | * :ref:`modindex`
60 | * :ref:`search`
61 | * `Github Home Page `_
62 | * `More usage examples on Github `_
63 |
64 |
--------------------------------------------------------------------------------
/docs/source/tutorial.rst:
--------------------------------------------------------------------------------
1 | ==========
2 | Quickstart
3 | ==========
4 |
5 | ------------
6 | Installation
7 | ------------
8 |
9 | PyCardano could be installed using ``pip`` as follows:
10 |
11 | .. code-block:: shell
12 |
13 | $ pip install pycardano
14 |
15 |
16 | ---------------
17 | Using PyCardano
18 | ---------------
19 |
20 | Create a payment key and a payment address::
21 |
22 | >>> from pycardano import Address, Network, PaymentSigningKey, PaymentVerificationKey
23 |
24 | >>> payment_signing_key = PaymentSigningKey.generate()
25 | >>> payment_signing_key.save("payment.skey")
26 | >>> payment_verification_key = PaymentVerificationKey.from_signing_key(payment_signing_key)
27 | >>> payment_verification_key.save("payment.vkey")
28 |
29 | >>> network = Network.TESTNET
30 | >>> address = Address(payment_part=payment_verification_key.hash(), network=network)
31 | >>> address
32 | 'addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7'
33 |
34 |
35 | .. warning::
36 |
37 | Your address generated by the python code above will be different from the one shown.
38 | Please use the address you generated. Anything sent to the address above will be lost.
39 |
40 |
41 | Fund the address with some tADA (test ADA) through the
42 | `faucet `_ here.
43 |
44 | With the address and key created above, you can now create and sign transactions, and submit the
45 | transaction to Cardano network. `Transaction usage guide `_ provides detailed steps about
46 | transaction creation and signing.
--------------------------------------------------------------------------------
/ensure_pure_cbor2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Script to ensure cbor2 is installed with pure Python implementation
3 |
4 | set -e
5 |
6 | # Check if poetry is available, otherwise use python directly
7 | if command -v poetry &> /dev/null; then
8 | PYTHON="poetry run python"
9 | else
10 | PYTHON="python"
11 | fi
12 |
13 | echo "Checking cbor2 version..."
14 | $PYTHON -c "from importlib.metadata import version; print(version('cbor2'))" > .cbor2_version
15 | CBOR2_VERSION=$(cat .cbor2_version)
16 | echo "Found cbor2 version: $CBOR2_VERSION"
17 |
18 | echo "Checking cbor2 implementation..."
19 | $PYTHON -c "
20 | import cbor2, inspect, sys
21 | decoder_path = inspect.getfile(cbor2.CBORDecoder)
22 | using_c_ext = decoder_path.endswith('.so')
23 | print(f'Implementation path: {decoder_path}')
24 | print(f'Using C extension: {using_c_ext}')
25 | sys.exit(1 if using_c_ext else 0)
26 | "
27 |
28 | if [ $? -ne 0 ]; then
29 | echo "Reinstalling cbor2 with pure Python implementation..."
30 | $PYTHON -m pip uninstall -y cbor2
31 | CBOR2_BUILD_C_EXTENSION=0 $PYTHON -m pip install --no-binary cbor2 "cbor2==$CBOR2_VERSION" --force-reinstall
32 | echo "Successfully reinstalled cbor2 with pure Python implementation"
33 | else
34 | echo "Already using pure Python implementation of cbor2"
35 | fi
36 |
37 | # Clean up
38 | rm -f .cbor2_version
--------------------------------------------------------------------------------
/examples/delegator_loyalty_rewards.py:
--------------------------------------------------------------------------------
1 | """A script that sends loyalty rewards (based on certain rules) to a pool's delegators in one transaction
2 | An example transaction generated by this script on mainnet:
3 | https://cardanoscan.io/transaction/c1b58dd4f2f4ee8656cc7962eefa8552877c4aa23d0699c02b885363d592a961
4 | """
5 |
6 | from blockfrost import ApiUrls, BlockFrostApi
7 |
8 | from pycardano import *
9 |
10 | # ======= Modify variables below ========
11 |
12 | network = Network.MAINNET
13 |
14 | BLOCK_FROST_PROJECT_ID = "your_project_id"
15 |
16 | POOL_ID = "your_pool_id"
17 |
18 | POOL_TICKER = "your_pool_ticker"
19 |
20 | # An address where any changes will be returned to
21 | CHANGE_ADDRESS = "your_change_address"
22 |
23 | # If you want to exclude any address (e.g. your own address), include those in the variable below
24 | EXCLUDE_ADDRESSES = []
25 |
26 | # The payment key used to generate sender address
27 | PAYMENT_KEY_PATH = "payment.skey"
28 |
29 | # ======= Modify variables above ========
30 |
31 |
32 | # Read keys to memory
33 | # Assume there is a payment.skey file sitting in current directory
34 | psk = PaymentSigningKey.load(PAYMENT_KEY_PATH)
35 | pvk = PaymentVerificationKey.from_signing_key(psk)
36 |
37 | # Derive an address from payment verification key
38 | input_address = Address(pvk.hash(), network=network)
39 | print(
40 | f"ADA will be distributed from this address: {input_address}, make sure there are enough ADA in it."
41 | )
42 |
43 | # Create a BlockFrost chain context
44 | context = BlockFrostChainContext(BLOCK_FROST_PROJECT_ID, base_url=ApiUrls.mainnet.value)
45 |
46 | api = BlockFrostApi(BLOCK_FROST_PROJECT_ID, ApiUrls.mainnet.value)
47 |
48 | delegators = api.pool_delegators(POOL_ID, gather_pages=True)
49 |
50 | to_send_50 = []
51 | to_send_10 = []
52 |
53 | for delegator in delegators:
54 | if delegator.address not in EXCLUDE_ADDRESSES:
55 | if int(delegator.live_stake) >= 100000000000:
56 | to_send_50.append(delegator)
57 | elif int(delegator.live_stake) >= 10000000000:
58 | to_send_10.append(delegator)
59 |
60 | builder = TransactionBuilder(context)
61 |
62 | builder.add_input_address(input_address)
63 |
64 | # ======= Business logic starts ========
65 |
66 | # Send 50 ADA to delegators with 100K+ ADA
67 | for d in to_send_50:
68 | to_send_addr = api.account_addresses(d.address)[0].address
69 | builder.add_output(TransactionOutput.from_primitive([to_send_addr, 50000000]))
70 |
71 | # Send 10 ADA to delegators with 10K+ ADA
72 | for d in to_send_10:
73 | to_send_addr = api.account_addresses(d.address)[0].address
74 | builder.add_output(TransactionOutput.from_primitive([to_send_addr, 10000000]))
75 |
76 | # ======= Business logic ends ========
77 |
78 | auxiliary_data = AuxiliaryData(
79 | AlonzoMetadata(
80 | metadata=Metadata(
81 | {
82 | 674: {
83 | "Title": f"Loyalty rewards for stake pool [{POOL_TICKER}] delegators",
84 | "Rules": {"100K+": "50 ADA", "10K+": "10 ADA"},
85 | "Notes": "Created with https://github.com/Python-Cardano/pycardano.",
86 | }
87 | }
88 | )
89 | )
90 | )
91 |
92 | builder.auxiliary_data = auxiliary_data
93 |
94 | # Create final signed transaction
95 | signed_tx = builder.build_and_sign(
96 | [psk], change_address=Address.from_primitive(CHANGE_ADDRESS)
97 | )
98 |
99 | # Submit signed transaction to the network
100 | print(signed_tx)
101 |
102 | print("#### Transaction id ####")
103 | print(signed_tx.id)
104 | context.submit_tx(signed_tx)
105 | print("Transaction successfully submitted!")
106 |
--------------------------------------------------------------------------------
/examples/full_stack/README.md:
--------------------------------------------------------------------------------
1 | ## Full stack demo
2 |
3 | This is a full stack demo on transaction creation with PyCardano and transaction signing with
4 | [Nami](https://namiwallet.io/) wallet.
5 |
6 | The backend is hosted by a simple [flask](https://flask.palletsprojects.com/en/2.0.x/) application.
7 | The frontend is rendered using [React](https://reactjs.org/).
8 |
9 | This webapp allows users to send ADA to multiple addresses, which is currently not possible with only Nami wallet.
10 |
11 | #### Note
12 | This is a simple demo built in a few hours. It is not fully tested and some designs could be inefficient.
13 |
14 | The DApp (on testnet) is now hosted on replit: https://pycardano.cffls.repl.co/
15 |
16 | ### Steps
17 |
18 | 1. Install dependencies
19 |
20 | ```shell
21 | $ poetry install
22 | ```
23 |
24 | 2. Modify BlockFrost project ID in `server.py`
25 |
26 | 3. Start flask app
27 |
28 | ```shell
29 | $ export BLOCKFROST_ID="your_blockfrost_project_id"
30 | $ export FLASK_APP=server
31 | $ poetry run flask run
32 | ```
33 |
34 | 4. Open a browser that has Nami wallet extension installed, go to
35 |
36 | ```http://127.0.0.1:5000/```
37 |
38 |
39 | 5. Connect the wallet by clicking "Connect wallet" button.
40 |
41 | 6. Paste multiple Cardano addresses and specify the amount of ADA to send for each one.
42 |
43 | 7. When you are done with adding addresses, click "Submit Tx" button, and Nami will prompt a signing window.
44 |
45 | 8. Sign the transaction and you are all set. You should be able to see the transaction soon in the blockchain explorer.
46 |
47 |
48 | ### Demo
49 |
50 | 
51 |
52 | The transaction submitted in the demo could be found
53 | [here](https://explorer.cardano-testnet.iohkdev.io/en/transaction?id=79476c8b257f36cf6f560d4e43b40bf853ee5c2a87e8fd6f09ab722675efcb6e).
54 |
55 | ### Sequence Diagram
56 |
57 | 
--------------------------------------------------------------------------------
/examples/full_stack/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/examples/full_stack/demo.gif
--------------------------------------------------------------------------------
/examples/full_stack/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "backend"
3 | version = "0.1.0"
4 | description = ""
5 | authors = ["Your Name "]
6 |
7 | [tool.poetry.dependencies]
8 | python = "^3.8.1"
9 | Flask = "^2.0.3"
10 | pycardano = "^0.12.0"
11 |
12 | [tool.poetry.dev-dependencies]
13 |
14 | [build-system]
15 | requires = ["poetry-core>=1.0.0"]
16 | build-backend = "poetry.core.masonry.api"
17 |
--------------------------------------------------------------------------------
/examples/full_stack/sequence_diagram.txt:
--------------------------------------------------------------------------------
1 | title Sequence Diagram
2 |
3 | participant User
4 |
5 | participant WebApp
6 |
7 | participant Nami
8 |
9 | participant PyCardano
10 |
11 | participant BlockFrost
12 |
13 |
14 | User->WebApp: Type in output addresses and amount to send
15 | note over User, WebApp: User click "**Submit Tx**" button
16 | WebApp->Nami: getUsedAddresses() getChangeAddress()
17 | Nami-->>WebApp: Return sender addresses and change address
18 | WebApp->PyCardano: build_tx(senderAddress, changeAddress)
19 | PyCardano-->>WebApp: unsignedTx
20 | WebApp->Nami: signTx(unsignedTx)
21 | note over User, Nami: Nami pops tx signing window; user signs tx
22 | Nami-->>WebApp: witness
23 | WebApp->PyCardano: submit_tx(unsignedTx, witnesses)
24 | note over PyCardano: Compose a signed Tx using unsignedTx and witnesses
25 | PyCardano->BlockFrost: submitTx(signedTx)
26 | BlockFrost-->>PyCardano: OK 200
27 | PyCardano-->>WebApp: Tx ID
28 | WebApp-->>User: Notify user with Tx ID
--------------------------------------------------------------------------------
/examples/full_stack/server.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from flask import Flask, render_template, request
4 |
5 | from pycardano import (
6 | Address,
7 | Asset,
8 | BlockFrostChainContext,
9 | MultiAsset,
10 | Network,
11 | Transaction,
12 | TransactionBuilder,
13 | TransactionOutput,
14 | TransactionWitnessSet,
15 | Value,
16 | )
17 |
18 | app = Flask(__name__)
19 |
20 | block_forst_project_id = os.environ.get("BLOCKFROST_ID")
21 |
22 | # Use BlockFrostChainContext for simplicity. You can also implement your own chain context.
23 | chain_context = BlockFrostChainContext(
24 | block_forst_project_id, base_url="https://cardano-preview.blockfrost.io/api"
25 | )
26 |
27 |
28 | def build_transaction(data):
29 | input_addresses = [
30 | Address.from_primitive(bytes.fromhex(sender)) for sender in data["senders"]
31 | ]
32 | change_address = Address.from_primitive(bytes.fromhex(data["change_address"]))
33 | transaction_outputs = [
34 | TransactionOutput.from_primitive([address, int(amount) * 1000000])
35 | for address, amount in data["recipients"]
36 | ]
37 |
38 | print(f"Input addresses: {input_addresses}")
39 | print(f"Transaction outputs: {transaction_outputs}")
40 | print(f"Change address: {change_address}")
41 |
42 | builder = TransactionBuilder(chain_context)
43 | for input_address in input_addresses:
44 | builder.add_input_address(input_address)
45 | for transaction_output in transaction_outputs:
46 | builder.add_output(transaction_output)
47 |
48 | tx_body = builder.build(change_address=change_address)
49 |
50 | return Transaction(tx_body, TransactionWitnessSet())
51 |
52 |
53 | def compose_tx_and_witness(data):
54 | tx = Transaction.from_cbor(data["tx"])
55 | witness = TransactionWitnessSet.from_cbor(data["witness"])
56 | tx.transaction_witness_set = witness
57 | return tx
58 |
59 |
60 | @app.route("/")
61 | def home_page():
62 | return render_template("index.html")
63 |
64 |
65 | @app.route("/build_tx", methods=["POST"])
66 | def build_tx():
67 | tx = build_transaction(request.json)
68 | cbor_hex = tx.to_cbor_hex()
69 | print(cbor_hex)
70 | return {"tx": cbor_hex}
71 |
72 |
73 | @app.route("/submit_tx", methods=["POST"])
74 | def submit_tx():
75 | tx = compose_tx_and_witness(request.json)
76 | tx_id = tx.transaction_body.hash().hex()
77 | print(f"Transaction: \n {tx}")
78 | print(f"Transaction cbor: {tx.to_cbor_hex()}")
79 | print(f"Transaction ID: {tx_id}")
80 | chain_context.submit_tx(tx)
81 | return {"tx_id": tx_id}
82 |
--------------------------------------------------------------------------------
/examples/full_stack/static/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | height: 100%;
3 | color: #61DAFB;
4 | background: #2D2D2D;
5 | }
6 |
7 | h1 {
8 | margin: 100px 0 15px 0;
9 | }
10 |
11 | #main {
12 | width: 1000px;
13 | margin: 0 auto;
14 | text-align: left;
15 | }
16 |
17 | button {
18 | color: #2D2D2D;
19 | }
20 |
21 | ul {
22 | list-style: none;
23 | }
24 |
25 | ul>li:hover {
26 | background-color: #F5F5F5;
27 | }
28 |
29 | .form-inline .form-control {
30 | #width: 100%;
31 | #margin-left: 80px;
32 | }
33 |
34 | .done {
35 | color: red;
36 | text-decoration: line-through;
37 | }
38 |
39 | .undone {
40 | color: #2D2D2D;
41 | }
42 |
43 | .icon {
44 | margin: 6px 10px 6px 0;
45 | }
--------------------------------------------------------------------------------
/examples/full_stack/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | PyCardano Demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/more_examples/.env-example:
--------------------------------------------------------------------------------
1 | network="testnet"
2 | wallet_mnemonic="select calm scorpion mask furnace nerve fade slam bid suggest avoid remove half depend turn little midnight fossil submit cart sick glance inner slide"
3 | blockfrost_api_key="preprod...."
--------------------------------------------------------------------------------
/examples/more_examples/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | /keys/*
3 | !keys/.gitkeep
4 | tempfile.pdf
5 | tempfile_copy.pdf
--------------------------------------------------------------------------------
/examples/more_examples/01_address.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
4 | from dotenv import load_dotenv
5 |
6 | from pycardano import *
7 |
8 | load_dotenv()
9 | network = os.getenv("network")
10 | wallet_mnemonic = os.getenv("wallet_mnemonic")
11 |
12 |
13 | if network == "testnet":
14 | base_url = ApiUrls.preprod.value
15 | cardano_network = Network.TESTNET
16 | else:
17 | base_url = ApiUrls.mainnet.value
18 | cardano_network = Network.MAINNET
19 |
20 |
21 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
22 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
23 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
24 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
25 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
26 |
27 |
28 | print("Enterprise address (only payment):")
29 | print("Payment Derivation path: m/1852'/1815'/0'/0/0")
30 |
31 | enterprise_address = Address(
32 | payment_part=payment_skey.to_verification_key().hash(), network=cardano_network
33 | )
34 | print(enterprise_address)
35 |
36 | print(" ")
37 | print("Staking enabled address:")
38 | print("Payment Derivation path: m/1852'/1815'/0'/0/0")
39 | print("Staking Derivation path: m/1852'/1815'/0'/2/0")
40 |
41 | staking_enabled_address = Address(
42 | payment_part=payment_skey.to_verification_key().hash(),
43 | staking_part=staking_skey.to_verification_key().hash(),
44 | network=cardano_network,
45 | )
46 | print(staking_enabled_address)
47 |
48 | print(" ")
49 | next_step = input("Press Enter to continue...")
50 | print(" ")
51 |
52 | for i in range(5):
53 | derivation_path = f"m/1852'/1815'/0'/0/{i}"
54 |
55 | payment_key = new_wallet.derive_from_path(derivation_path)
56 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
57 |
58 | enterprise_address = Address(
59 | payment_part=payment_skey.to_verification_key().hash(), network=cardano_network
60 | )
61 | print(f"Address {derivation_path}: {enterprise_address}")
62 |
63 | print(" ")
64 | next_step = input("Press Enter to continue...")
65 | print(" ")
66 |
67 | for i in range(5):
68 | derivation_path = f"m/1852'/1815'/0'/0/{i}"
69 |
70 | payment_key = new_wallet.derive_from_path(derivation_path)
71 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
72 |
73 | staking_enabled_address = Address(
74 | payment_part=payment_skey.to_verification_key().hash(),
75 | staking_part=staking_skey.to_verification_key().hash(),
76 | network=cardano_network,
77 | )
78 | print(f"Address {derivation_path}: {staking_enabled_address}")
79 |
--------------------------------------------------------------------------------
/examples/more_examples/02_query_address.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
5 | from dotenv import load_dotenv
6 |
7 | from pycardano import *
8 |
9 | load_dotenv()
10 | network = os.getenv("network")
11 | wallet_mnemonic = os.getenv("wallet_mnemonic")
12 | blockfrost_api_key = os.getenv("blockfrost_api_key")
13 |
14 |
15 | if network == "testnet":
16 | base_url = ApiUrls.preprod.value
17 | cardano_network = Network.TESTNET
18 | else:
19 | base_url = ApiUrls.mainnet.value
20 | cardano_network = Network.MAINNET
21 |
22 |
23 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
24 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
25 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
26 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
27 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
28 |
29 |
30 | main_address = Address(
31 | payment_part=payment_skey.to_verification_key().hash(),
32 | staking_part=staking_skey.to_verification_key().hash(),
33 | network=cardano_network,
34 | )
35 |
36 | print(" ")
37 | print(f"Derived address: {main_address}")
38 | print(" ")
39 |
40 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
41 |
42 | try:
43 | utxos = api.address_utxos(main_address)
44 | except Exception as e:
45 | if e.status_code == 404:
46 | print("Address does not have any UTXOs. ")
47 | if network == "testnet":
48 | print(
49 | "Request tADA from the faucet: https://docs.cardano.org/cardano-testnets/tools/faucet/"
50 | )
51 | else:
52 | print(e.message)
53 | sys.exit(1)
54 |
55 | print(f"hash \t\t\t\t\t\t\t\t\t amount")
56 | print(
57 | "--------------------------------------------------------------------------------------"
58 | )
59 |
60 | for utxo in utxos:
61 | tokens = ""
62 | for token in utxo.amount:
63 | if token.unit != "lovelace":
64 | tokens += f"{token.quantity} {token.unit} + "
65 | print(
66 | f"{utxo.tx_hash}#{utxo.tx_index} \t {int(utxo.amount[0].quantity)/1000000} ADA [{tokens}]"
67 | )
68 |
--------------------------------------------------------------------------------
/examples/more_examples/03_distribute.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
5 | from dotenv import load_dotenv
6 |
7 | from pycardano import *
8 |
9 | load_dotenv()
10 | network = os.getenv("network")
11 | wallet_mnemonic = os.getenv("wallet_mnemonic")
12 | blockfrost_api_key = os.getenv("blockfrost_api_key")
13 |
14 |
15 | if network == "testnet":
16 | base_url = ApiUrls.preprod.value
17 | cardano_network = Network.TESTNET
18 | else:
19 | base_url = ApiUrls.mainnet.value
20 | cardano_network = Network.MAINNET
21 |
22 |
23 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
24 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
25 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
26 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
27 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
28 |
29 |
30 | main_address = Address(
31 | payment_part=payment_skey.to_verification_key().hash(),
32 | staking_part=staking_skey.to_verification_key().hash(),
33 | network=cardano_network,
34 | )
35 |
36 | print(" ")
37 | print(f"Derived address: {main_address}")
38 | print(" ")
39 |
40 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
41 |
42 | try:
43 | utxos = api.address_utxos(main_address)
44 | except Exception as e:
45 | if e.status_code == 404:
46 | print("Address does not have any UTXOs. ")
47 | if network == "testnet":
48 | print(
49 | "Request tADA from the faucet: https://docs.cardano.org/cardano-testnets/tools/faucet/"
50 | )
51 | else:
52 | print(e.message)
53 | sys.exit(1)
54 |
55 |
56 | cardano = BlockFrostChainContext(project_id=blockfrost_api_key, base_url=base_url)
57 |
58 | builder = TransactionBuilder(cardano)
59 |
60 | for i in range(20):
61 | output = TransactionOutput(main_address, Value(4000000))
62 | builder.add_output(output)
63 |
64 | builder.add_input_address(main_address)
65 | signed_tx = builder.build_and_sign([payment_skey], change_address=main_address)
66 | result = cardano.submit_tx(signed_tx.to_cbor())
67 | print(f"Number of inputs: \t {len(signed_tx.transaction_body.inputs)}")
68 | print(f"Number of outputs: \t {len(signed_tx.transaction_body.outputs)}")
69 | print(f"Fee: \t\t\t {signed_tx.transaction_body.fee/1000000} ADA")
70 | print(f"Transaction submitted! ID: {result}")
71 |
--------------------------------------------------------------------------------
/examples/more_examples/04_consolidate.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
5 | from dotenv import load_dotenv
6 |
7 | from pycardano import *
8 |
9 | load_dotenv()
10 | network = os.getenv("network")
11 | wallet_mnemonic = os.getenv("wallet_mnemonic")
12 | blockfrost_api_key = os.getenv("blockfrost_api_key")
13 |
14 |
15 | if network == "testnet":
16 | base_url = ApiUrls.preprod.value
17 | cardano_network = Network.TESTNET
18 | else:
19 | base_url = ApiUrls.mainnet.value
20 | cardano_network = Network.MAINNET
21 |
22 |
23 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
24 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
25 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
26 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
27 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
28 |
29 |
30 | main_address = Address(
31 | payment_part=payment_skey.to_verification_key().hash(),
32 | staking_part=staking_skey.to_verification_key().hash(),
33 | network=cardano_network,
34 | )
35 |
36 | print(" ")
37 | print(f"Derived address: {main_address}")
38 | print(" ")
39 |
40 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
41 |
42 | try:
43 | utxos = api.address_utxos(main_address)
44 | except Exception as e:
45 | if e.status_code == 404:
46 | print("Address does not have any UTXOs. ")
47 | if network == "testnet":
48 | print(
49 | "Request tADA from the faucet: https://docs.cardano.org/cardano-testnets/tools/faucet/"
50 | )
51 | else:
52 | print(e.message)
53 | sys.exit(1)
54 |
55 |
56 | cardano = BlockFrostChainContext(project_id=blockfrost_api_key, base_url=base_url)
57 |
58 | builder = TransactionBuilder(cardano)
59 |
60 | inputs = []
61 |
62 | total_ada_used = 0
63 |
64 | for utxo in utxos:
65 | input = TransactionInput.from_primitive([utxo.tx_hash, utxo.tx_index])
66 | inputs.append(input)
67 | builder.add_input(input)
68 | total_ada_used += int(utxo.amount[0].quantity)
69 |
70 | output = TransactionOutput(main_address, Value(total_ada_used))
71 |
72 | tx_body = TransactionBody(inputs=inputs, outputs=[output], fee=100000)
73 |
74 | signature = payment_skey.sign(tx_body.hash())
75 | vk = PaymentVerificationKey.from_signing_key(payment_skey)
76 | vk_witnesses = [VerificationKeyWitness(vk, signature)]
77 | signed_tx = Transaction(tx_body, TransactionWitnessSet(vkey_witnesses=vk_witnesses))
78 |
79 | calculated_fee = fee(cardano, len(signed_tx.to_cbor()))
80 |
81 |
82 | total_ada_available = total_ada_used - calculated_fee
83 | output = TransactionOutput(main_address, Value(total_ada_available))
84 |
85 | tx_body = TransactionBody(inputs=inputs, outputs=[output], fee=calculated_fee)
86 |
87 | signature = payment_skey.sign(tx_body.hash())
88 | vk = PaymentVerificationKey.from_signing_key(payment_skey)
89 | vk_witnesses = [VerificationKeyWitness(vk, signature)]
90 | signed_tx = Transaction(tx_body, TransactionWitnessSet(vkey_witnesses=vk_witnesses))
91 |
92 | try:
93 | result = cardano.submit_tx(signed_tx.to_cbor())
94 | print(f"Number of inputs: \t {len(signed_tx.transaction_body.inputs)}")
95 | print(f"Number of outputs: \t {len(signed_tx.transaction_body.outputs)}")
96 | print(f"Fee: \t\t\t {signed_tx.transaction_body.fee/1000000} ADA")
97 | print(f"Transaction submitted! ID: {result}")
98 | except Exception as e:
99 | if "BadInputsUTxO" in str(e):
100 | print("Trying to spend an input that doesn't exist (or no longer exist).")
101 | elif "ValueNotConservedUTxO" in str(e):
102 | print(
103 | "Transaction not correctly balanced. Inputs and outputs (+fee) don't match."
104 | )
105 | else:
106 | print(e)
107 |
--------------------------------------------------------------------------------
/examples/more_examples/06_query_receive_address.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
5 | from dotenv import load_dotenv
6 |
7 | from pycardano import *
8 |
9 | load_dotenv()
10 | network = os.getenv("network")
11 | wallet_mnemonic = os.getenv("wallet_mnemonic")
12 | blockfrost_api_key = os.getenv("blockfrost_api_key")
13 |
14 |
15 | if network == "testnet":
16 | base_url = ApiUrls.preprod.value
17 | cardano_network = Network.TESTNET
18 | else:
19 | base_url = ApiUrls.mainnet.value
20 | cardano_network = Network.MAINNET
21 |
22 |
23 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
24 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/1")
25 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
26 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
27 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
28 |
29 |
30 | main_address = Address(
31 | payment_part=payment_skey.to_verification_key().hash(),
32 | staking_part=staking_skey.to_verification_key().hash(),
33 | network=cardano_network,
34 | )
35 |
36 | print(" ")
37 | print(f"Derived address: {main_address}")
38 | print(" ")
39 |
40 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
41 |
42 | try:
43 | utxos = api.address_utxos(main_address)
44 | except Exception as e:
45 | if e.status_code == 404:
46 | print("Address does not have any UTXOs. ")
47 | if network == "testnet":
48 | print(
49 | "Request tADA from the faucet: https://docs.cardano.org/cardano-testnets/tools/faucet/"
50 | )
51 | else:
52 | print(e.message)
53 | sys.exit(1)
54 |
55 | print(f"hash \t\t\t\t\t\t\t\t\t amount")
56 | print(
57 | "--------------------------------------------------------------------------------------"
58 | )
59 | for utxo in utxos:
60 | tokens = ""
61 | for token in utxo.amount:
62 | if token.unit != "lovelace":
63 | tokens += f"{token.quantity} {token.unit} + "
64 | print(
65 | f"{utxo.tx_hash}#{utxo.tx_index} \t {int(utxo.amount[0].quantity)/1000000} ADA [{tokens}]"
66 | )
67 |
--------------------------------------------------------------------------------
/examples/more_examples/09_sign_document_data.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import random
4 | import sys
5 | import urllib.request
6 | from hashlib import sha256
7 | from os.path import exists
8 |
9 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
10 | from dotenv import load_dotenv
11 | from reportlab.pdfgen import canvas
12 |
13 | from pycardano import *
14 |
15 |
16 | def split_into_64chars(string):
17 | return [string[i : i + 64] for i in range(0, len(string), 64)]
18 |
19 |
20 | load_dotenv()
21 | network = os.getenv("network")
22 | wallet_mnemonic = os.getenv("wallet_mnemonic")
23 | blockfrost_api_key = os.getenv("blockfrost_api_key")
24 |
25 |
26 | filename = "tempfile.pdf"
27 | pdf = canvas.Canvas(filename)
28 | pdf.drawString(100, 750, "Hello, this is an example PDF!")
29 |
30 | pdf.save()
31 |
32 |
33 | h256 = sha256()
34 | h256.update(open(filename, "rb").read())
35 | document_hash = h256.hexdigest()
36 |
37 |
38 | if network == "testnet":
39 | base_url = ApiUrls.preprod.value
40 | cardano_network = Network.TESTNET
41 | else:
42 | base_url = ApiUrls.mainnet.value
43 | cardano_network = Network.MAINNET
44 |
45 |
46 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
47 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
48 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
49 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
50 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
51 |
52 |
53 | main_address = Address(
54 | payment_part=payment_skey.to_verification_key().hash(),
55 | staking_part=staking_skey.to_verification_key().hash(),
56 | network=cardano_network,
57 | )
58 |
59 |
60 | print(" ")
61 | print(f"Derived address: {main_address}")
62 | print(" ")
63 |
64 | payload = {"document_hash": document_hash}
65 |
66 | payload = str(payload)
67 |
68 | result = cip8.sign(
69 | message=payload,
70 | signing_key=payment_skey,
71 | network=cardano_network,
72 | attach_cose_key=True,
73 | )
74 |
75 |
76 | metadata = {
77 | 1787: {
78 | document_hash: {
79 | "signature": split_into_64chars(result["signature"]),
80 | }
81 | }
82 | }
83 |
84 |
85 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
86 |
87 | try:
88 | utxos = api.address_utxos(main_address)
89 | except Exception as e:
90 | if e.status_code == 404:
91 | print("Address does not have any UTXOs. ")
92 | if network == "testnet":
93 | print(
94 | "Request tADA from the faucet: https://docs.cardano.org/cardano-testnets/tools/faucet/"
95 | )
96 | else:
97 | print(e.message)
98 | sys.exit(1)
99 |
100 |
101 | cardano = BlockFrostChainContext(project_id=blockfrost_api_key, base_url=base_url)
102 |
103 | builder = TransactionBuilder(cardano)
104 |
105 |
106 | auxiliary_data = AuxiliaryData(AlonzoMetadata(metadata=Metadata(metadata)))
107 | builder.auxiliary_data = auxiliary_data
108 |
109 |
110 | builder.add_input_address(main_address)
111 | signed_tx = builder.build_and_sign([payment_skey], change_address=main_address)
112 | result = cardano.submit_tx(signed_tx.to_cbor())
113 |
114 | print(f"Number of inputs: \t {len(signed_tx.transaction_body.inputs)}")
115 | print(f"Number of outputs: \t {len(signed_tx.transaction_body.outputs)}")
116 | print(f"Fee: \t\t\t {signed_tx.transaction_body.fee/1000000} ADA")
117 | print(f"Transaction submitted! ID: {result}")
118 |
--------------------------------------------------------------------------------
/examples/more_examples/10_verify_document.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import random
4 | import sys
5 | import urllib.request
6 | from hashlib import sha256
7 | from os.path import exists
8 |
9 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
10 | from dotenv import load_dotenv
11 |
12 | from pycardano import *
13 |
14 |
15 | def split_into_64chars(string):
16 | return [string[i : i + 64] for i in range(0, len(string), 64)]
17 |
18 |
19 | load_dotenv()
20 | network = os.getenv("network")
21 | wallet_mnemonic = os.getenv("wallet_mnemonic")
22 | blockfrost_api_key = os.getenv("blockfrost_api_key")
23 |
24 |
25 | if network == "testnet":
26 | base_url = ApiUrls.preprod.value
27 | cardano_network = Network.TESTNET
28 | else:
29 | base_url = ApiUrls.mainnet.value
30 | cardano_network = Network.MAINNET
31 |
32 |
33 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
34 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
35 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
36 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
37 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
38 |
39 |
40 | main_address = Address(
41 | payment_part=payment_skey.to_verification_key().hash(),
42 | staking_part=staking_skey.to_verification_key().hash(),
43 | network=cardano_network,
44 | )
45 |
46 |
47 | prefix = "a401010327200621"
48 | jsonkey = json.loads(payment_skey.to_verification_key().to_non_extended().to_json())
49 |
50 |
51 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
52 | cardano = BlockFrostChainContext(project_id=blockfrost_api_key, base_url=base_url)
53 |
54 | # get commandline arguments
55 |
56 | transaction_id = sys.argv[1]
57 | document_hash = sys.argv[2]
58 |
59 |
60 | onchain_metadata = api.transaction_metadata(transaction_id)
61 |
62 | if onchain_metadata is None:
63 | print("No metadata onchain.")
64 | sys.exit(1)
65 |
66 |
67 | if "1787" in onchain_metadata[0].label:
68 | print("This transaction has a 1787 metadata label onchain.")
69 |
70 | result = onchain_metadata[0].json_metadata
71 |
72 | if document_hash in str(result):
73 | print("Document hash found onchain.")
74 |
75 | if getattr(result, document_hash).signature:
76 | print("Signature found onchain.")
77 | signature = getattr(result, document_hash).signature
78 |
79 | public_key = f"{prefix}{jsonkey['cborHex']}"
80 |
81 | signed_message = {
82 | "signature": "".join(signature),
83 | "key": public_key,
84 | }
85 |
86 | result = cip8.verify(signed_message=signed_message, attach_cose_key=True)
87 |
88 | if result["verified"]:
89 | print(
90 | "This signature is verified correctly, this document was signed by this wallet/identity."
91 | )
92 | print("Original payload:")
93 | print(result["message"])
94 | else:
95 | print("This signature is NOT correct!")
96 | else:
97 | print("This transaction does not have a signatuer attribute")
98 | else:
99 | print(f"Document hash ({document_hash}) was not found in this transaction.")
100 | else:
101 | print("This transaction DOES NOT have a 1787 metadata label.")
102 |
--------------------------------------------------------------------------------
/examples/more_examples/11_verify_fake_document.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import random
4 | import sys
5 | import urllib.request
6 | from hashlib import sha256
7 | from os.path import exists
8 |
9 | from blockfrost import ApiError, ApiUrls, BlockFrostApi, BlockFrostIPFS
10 | from dotenv import load_dotenv
11 | from reportlab.pdfgen import canvas
12 |
13 | from pycardano import *
14 |
15 |
16 | def split_into_64chars(string):
17 | return [string[i : i + 64] for i in range(0, len(string), 64)]
18 |
19 |
20 | load_dotenv()
21 | network = os.getenv("network")
22 | wallet_mnemonic = os.getenv("wallet_mnemonic")
23 | blockfrost_api_key = os.getenv("blockfrost_api_key")
24 |
25 |
26 | if network == "testnet":
27 | base_url = ApiUrls.preprod.value
28 | cardano_network = Network.TESTNET
29 | else:
30 | base_url = ApiUrls.mainnet.value
31 | cardano_network = Network.MAINNET
32 |
33 |
34 | filename = "tempfile_copy.pdf"
35 | pdf = canvas.Canvas(filename)
36 | pdf.drawString(100, 750, "Hello, this is a copy of the example PDF!")
37 |
38 | pdf.save()
39 |
40 | h256 = sha256()
41 | h256.update(open(filename, "rb").read())
42 | document_hash = h256.hexdigest()
43 |
44 | print(f"Trying to verify document with hash: {document_hash}")
45 |
46 | new_wallet = crypto.bip32.HDWallet.from_mnemonic(wallet_mnemonic)
47 | payment_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/0/0")
48 | staking_key = new_wallet.derive_from_path(f"m/1852'/1815'/0'/2/0")
49 | payment_skey = ExtendedSigningKey.from_hdwallet(payment_key)
50 | staking_skey = ExtendedSigningKey.from_hdwallet(staking_key)
51 |
52 |
53 | main_address = Address(
54 | payment_part=payment_skey.to_verification_key().hash(),
55 | staking_part=staking_skey.to_verification_key().hash(),
56 | network=cardano_network,
57 | )
58 |
59 |
60 | prefix = "a401010327200621"
61 | jsonkey = json.loads(payment_skey.to_verification_key().to_non_extended().to_json())
62 |
63 |
64 | api = BlockFrostApi(project_id=blockfrost_api_key, base_url=base_url)
65 | cardano = BlockFrostChainContext(project_id=blockfrost_api_key, base_url=base_url)
66 |
67 | # get commandline arguments
68 |
69 | transaction_id = sys.argv[1]
70 |
71 |
72 | onchain_metadata = api.transaction_metadata(transaction_id)
73 |
74 | if onchain_metadata is None:
75 | print("No metadata onchain.")
76 | sys.exit(1)
77 |
78 |
79 | if "1787" in onchain_metadata[0].label:
80 | print("This transaction has a 1787 metadata label onchain.")
81 |
82 | result = onchain_metadata[0].json_metadata
83 |
84 | if document_hash in str(result):
85 | print("Document hash found onchain.")
86 |
87 | if getattr(result, document_hash).signature:
88 | print("Signature found onchain.")
89 | signature = getattr(result, document_hash).signature
90 |
91 | public_key = f"{prefix}{jsonkey['cborHex']}"
92 |
93 | signed_message = {
94 | "signature": "".join(signature),
95 | "key": public_key,
96 | }
97 |
98 | result = cip8.verify(signed_message=signed_message, attach_cose_key=True)
99 |
100 | if result["verified"]:
101 | print("This signature is verified correctly!")
102 | if result["message"] == document_hash:
103 | print("TargetHash matches as well! ")
104 | else:
105 | print("This signature is NOT correct!")
106 | else:
107 | print("This transaction does not have a signatuer attribute")
108 | else:
109 | print(
110 | f"Document hash ({document_hash}) was not found in this transaction. Possible corruption."
111 | )
112 | else:
113 | print("This transaction DOES NOT have a 1787 metadata label.")
114 |
--------------------------------------------------------------------------------
/examples/more_examples/README.md:
--------------------------------------------------------------------------------
1 | ## Introduction into Cardano using PyCardano
2 |
3 | - [x] Derive addresses
4 | - [x] Query address balance
5 | - [x] Create transaction with multiple outputs
6 | - [x] Consolidate all inputs back into 1 utxo
7 | - [x] Mint a fungible asset within a policy and send it to an external address
8 | - [x] Query the receiver address
9 | - [x] Minting 5 NFT's with metadata (player characters in this example)
10 | - [x] Burning NFT's
11 | - [x] Downloading a document from a URL and signing it with CIP8
12 | - [x] Verify a valid CIP8 signature
13 | - [x] Verify an invalid CIP8 signature
14 | - [x] Example of transaction chaining with manually building and signing a transaction (instead of TransactionBuilder)
15 |
16 |
17 | ## How to use
18 | - Clone repo
19 | - rename .env-example to .env
20 | - update values in .env
21 | - play around!
--------------------------------------------------------------------------------
/examples/more_examples/keys/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/examples/more_examples/keys/.gitkeep
--------------------------------------------------------------------------------
/examples/plutus/forty_two/forty_two.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 | Off-chain code of taker and giver in fortytwo.
4 |
5 | """
6 |
7 | import os
8 |
9 | import cbor2
10 | from blockfrost import ApiUrls
11 | from retry import retry
12 |
13 | from pycardano import *
14 |
15 | NETWORK = Network.TESTNET
16 |
17 |
18 | def get_env_val(key):
19 | val = os.environ.get(key)
20 | if not val:
21 | raise Exception(f"Environment variable {key} is not set!")
22 | return val
23 |
24 |
25 | payment_skey = PaymentSigningKey.load(get_env_val("PAYMENT_KEY_PATH"))
26 | payment_vkey = PaymentVerificationKey.from_signing_key(payment_skey)
27 |
28 | chain_context = BlockFrostChainContext(
29 | project_id=get_env_val("BLOCKFROST_ID"),
30 | base_url=ApiUrls.preprod.value,
31 | )
32 |
33 |
34 | @retry(delay=20)
35 | def wait_for_tx(tx_id):
36 | chain_context.api.transaction(tx_id)
37 | print(f"Transaction {tx_id} has been successfully included in the blockchain.")
38 |
39 |
40 | def submit_tx(tx):
41 | print("############### Transaction created ###############")
42 | print(tx)
43 | print(tx.to_cbor_hex())
44 | print("############### Submitting transaction ###############")
45 | chain_context.submit_tx(tx)
46 | wait_for_tx(str(tx.id))
47 |
48 |
49 | with open("fortytwoV2.plutus", "r") as f:
50 | script_hex = f.read()
51 | forty_two_script = PlutusV2Script(cbor2.loads(bytes.fromhex(script_hex)))
52 |
53 |
54 | script_hash = plutus_script_hash(forty_two_script)
55 |
56 | script_address = Address(script_hash, network=NETWORK)
57 |
58 | giver_address = Address(payment_vkey.hash(), network=NETWORK)
59 |
60 | builder = TransactionBuilder(chain_context)
61 | builder.add_input_address(giver_address)
62 | builder.add_output(TransactionOutput(giver_address, 50000000, script=forty_two_script))
63 |
64 | signed_tx = builder.build_and_sign([payment_skey], giver_address)
65 |
66 | print("############### Transaction created ###############")
67 | print(signed_tx)
68 | print("############### Submitting transaction ###############")
69 | submit_tx(signed_tx)
70 |
71 |
72 | # ----------- Send ADA to the script address ---------------
73 |
74 | builder = TransactionBuilder(chain_context)
75 | builder.add_input_address(giver_address)
76 | datum = 42
77 | builder.add_output(TransactionOutput(script_address, 50000000, datum=datum))
78 |
79 | signed_tx = builder.build_and_sign([payment_skey], giver_address)
80 |
81 | print("############### Transaction created ###############")
82 | print(signed_tx)
83 | print("############### Submitting transaction ###############")
84 | submit_tx(signed_tx)
85 |
86 | # ----------- Taker take ---------------
87 |
88 | redeemer = Redeemer(42)
89 |
90 | utxo_to_spend = None
91 |
92 | # Spend the utxo with datum 42 sitting at the script address
93 | for utxo in chain_context.utxos(script_address):
94 | print(utxo)
95 | if utxo.output.datum:
96 | utxo_to_spend = utxo
97 | break
98 |
99 | # Find the reference script utxo
100 | reference_script_utxo = None
101 | for utxo in chain_context.utxos(giver_address):
102 | if utxo.output.script and utxo.output.script == forty_two_script:
103 | reference_script_utxo = utxo
104 | break
105 |
106 | taker_address = Address(payment_vkey.hash(), network=NETWORK)
107 |
108 | builder = TransactionBuilder(chain_context)
109 |
110 | builder.add_script_input(utxo_to_spend, script=reference_script_utxo, redeemer=redeemer)
111 | take_output = TransactionOutput(taker_address, 25123456)
112 | builder.add_output(take_output)
113 |
114 | signed_tx = builder.build_and_sign([payment_skey], taker_address)
115 |
116 | print("############### Transaction created ###############")
117 | print(signed_tx)
118 | print("############### Submitting transaction ###############")
119 | submit_tx(signed_tx)
120 |
--------------------------------------------------------------------------------
/examples/plutus/forty_two/fortytwo.plutus:
--------------------------------------------------------------------------------
1 | 59082459082101000033232332233223232333222323332223233333333222222223233322232333322223232332232333222323332223232332233223232333332222233223322332233223322332222223232533530313330063333573466e1cd55ce9baa0054800081248c98d4c120cd5ce0260248238231bad0043333573466e1cd55cea8012400046601264646464646464646464646666ae68cdc39aab9d500a480008cccccccccc05ccd40948c8c8cccd5cd19b8735573aa004900011980e981c1aba15002302a357426ae8940088c98d4c160cd5ce02e02c82b82b09aab9e5001137540026ae854028cd4094098d5d0a804999aa8163ae502b35742a010666aa058eb940acd5d0a80399a8128209aba15006335025335505204a75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a80f9919191999ab9a3370e6aae7540092000233502733504075a6ae854008c114d5d09aba25002232635305c3357380c00ba0b60b426aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a04a66a080eb4d5d0a80118229aba135744a004464c6a60b866ae7018017416c1684d55cf280089baa001357426ae8940088c98d4c160cd5ce02e02c82b82b09aab9e5001137540026ae854010cd4095d71aba15003335025335505275c40026ae854008c0dcd5d09aba2500223263530543357380b00aa0a60a426ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d400520062301c3039357426aae79400c8cccd5cd19b875002480108c06cc10cd5d09aab9e500423333573466e1d400d20022301b302e357426aae7940148cccd5cd19b875004480008c078dd71aba135573ca00c464c6a609e66ae7014c14013813413012c1284d55cea80089baa001357426ae8940088c98d4c120cd5ce026024823823082409931a982399ab9c49010350543500048046135573ca00226ea80048848cc00400c0088004888888888848cccccccccc00402c02802402001c01801401000c00880048848cc00400c008800448848cc00400c0084800448848cc00400c0084800448848cc00400c00848004848888c010014848888c00c014848888c008014848888c004014800448c88c008dd6000990009aa81a911999aab9f0012500e233500d30043574200460066ae880080cc8c8c8c8cccd5cd19b8735573aa006900011998039919191999ab9a3370e6aae754009200023300d303135742a00466a02605a6ae84d5d1280111931a981b99ab9c03b038036035135573ca00226ea8004d5d0a801999aa805bae500a35742a00466a01eeb8d5d09aba25002232635303333573806e06806406226ae8940044d55cf280089baa00122212333001004003002200122123300100300220011335500175ceb44488c88c008dd5800990009aa81791191999aab9f0022500923350083355031300635573aa004600a6aae794008c010d5d100181709aba10011122002122122330010040031200112232323333573466e1d400520002350083005357426aae79400c8cccd5cd19b87500248008940208c98d4c0a8cd5ce01701581481401389aab9d500113754002242446004006224400224002464646666ae68cdc39aab9d5002480008cc018c01cd5d0a8011bad357426ae8940088c98d4c090cd5ce01401281181109aab9e50011375400244246600200600440024646666ae68cdc39aab9d5001480008dd71aba135573ca004464c6a604066ae7009008407c0784dd500089119191999ab9a3370ea00290021280391999ab9a3370ea004900111a80518031aba135573ca00846666ae68cdc3a801a40004a014464c6a604666ae7009c09008808408007c4d55cea80089baa00112122230030041122200211222001120012323333573466e1d40052002200623333573466e1d400920002006232635301b33573803e03803403203026aae74dd50008910010910009000919191919191999ab9a3370ea0029006100591999ab9a3370ea0049005100691999ab9a3370ea00690041198059bae35742a00a6eb4d5d09aba2500523333573466e1d4011200623300d375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846602460286ae854024dd71aba135744a01246666ae68cdc3a8032400446028602a6ae84d55cf280591999ab9a3370ea00e900011809980b1aba135573ca018464c6a604066ae7009008407c07807407006c0680640604d55cea80209aab9e5003135573ca00426aae7940044dd500090911111118038041109111111198030048041091111111802804091111110020911111100191091111111980100480411091111111980080480410009191919191999ab9a3370ea002900111998041bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c028c02cd5d09aab9e5006232635301133573802a02402001e01c26aae75400c4d5d1280089aab9e5001137540024244600400644424466600200a0080064002464646666ae68cdc3a800a40044600c6eb8d5d09aab9e500323333573466e1d4009200023008375c6ae84d55cf280211931a980599ab9c00f00c00a009008135573aa00226ea80048488c00800c8488c00400c800444888c8c8cccd5cd19b8735573aa0049000119aa80598031aba150023005357426ae8940088c98d4c020cd5ce00600480380309aab9e5001137540029309000900088910919800801801089000a4903505431001123230010012233003300200200133322222253353004333573466e1c00920540060051006133573892010e77726f6e672072656465656d65720000512200212200120011
--------------------------------------------------------------------------------
/examples/plutus/forty_two/fortytwoV2.plutus:
--------------------------------------------------------------------------------
1 | 58775875010000323232322225335323253350021001100933320015007003332001500648150ccc8005401800ccc8005401520541004132632498cd5ce2491d496e636f727265637420646174756d2e2045787065637465642034322e0000412001123750002244666ae68cdd780100089100100189100081
--------------------------------------------------------------------------------
/examples/raw_multi_asset_transaction.py:
--------------------------------------------------------------------------------
1 | """An example that demonstrates low-level construction of a transaction that involves multi-asset."""
2 |
3 | from pycardano import (
4 | Address,
5 | PaymentSigningKey,
6 | PaymentVerificationKey,
7 | Transaction,
8 | TransactionBody,
9 | TransactionInput,
10 | TransactionOutput,
11 | TransactionWitnessSet,
12 | Value,
13 | VerificationKeyWitness,
14 | )
15 |
16 | # Define a transaction input
17 | tx_id_hex = "732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e5"
18 | tx_in = TransactionInput.from_primitive([tx_id_hex, 0])
19 |
20 | # Define an output address
21 | addr = Address.decode("addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x")
22 |
23 | # Define two transaction outputs, both to the same address, but one with multi-assets.
24 | output1 = TransactionOutput(addr, 100000000000)
25 |
26 | # Output2 will send ADA along with multi-assets
27 | policy_id = b"1" * 28 # A dummy policy ID
28 | multi_asset = Value.from_primitive(
29 | [
30 | 2, # Amount of ADA (in lovelace) to send
31 | {
32 | policy_id: {
33 | b"Token1": 100, # Send 100 Token1 under `policy_id`
34 | b"Token2": 200, # Send 200 Token2 under `policy_id`
35 | }
36 | },
37 | ]
38 | )
39 | output2 = TransactionOutput(addr, multi_asset)
40 |
41 | # Create a transaction body from inputs and outputs
42 | tx_body = TransactionBody(inputs=[tx_in], outputs=[output1, output2], fee=165897)
43 |
44 | # Create signing key from a secret json file
45 | sk = PaymentSigningKey.from_json(
46 | """{
47 | "type": "GenesisUTxOSigningKey_ed25519",
48 | "description": "Genesis Initial UTxO Signing Key",
49 | "cborHex": "5820093be5cd3987d0c9fd8854ef908f7746b69e2d73320db6dc0f780d81585b84c2"
50 | }"""
51 | )
52 |
53 | # Derive a verification key from the signing key
54 | vk = PaymentVerificationKey.from_signing_key(sk)
55 |
56 | # Sign the transaction body hash
57 | signature = sk.sign(tx_body.hash())
58 |
59 | # Add verification key and the signature to the witness set
60 | vk_witnesses = [VerificationKeyWitness(vk, signature)]
61 |
62 | # Create final signed transaction
63 | signed_tx = Transaction(tx_body, TransactionWitnessSet(vkey_witnesses=vk_witnesses))
64 |
--------------------------------------------------------------------------------
/examples/raw_transaction.py:
--------------------------------------------------------------------------------
1 | """An example that demonstrates low-level construction of a transaction."""
2 |
3 | from pycardano import (
4 | PaymentSigningKey,
5 | PaymentVerificationKey,
6 | Transaction,
7 | TransactionBody,
8 | TransactionInput,
9 | TransactionOutput,
10 | TransactionWitnessSet,
11 | VerificationKeyWitness,
12 | )
13 |
14 | # Define a transaction input
15 | tx_id = "732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e5"
16 | tx_in = TransactionInput.from_primitive([tx_id, 0])
17 |
18 | # Define an output address
19 | addr = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
20 |
21 | # Define two transaction outputs, both to the same address, but with different amount.
22 | output1 = TransactionOutput.from_primitive([addr, 100000000000])
23 | output2 = TransactionOutput.from_primitive([addr, 799999834103])
24 |
25 | # Create a transaction body from inputs and outputs
26 | tx_body = TransactionBody(inputs=[tx_in], outputs=[output1, output2], fee=165897)
27 |
28 | # Create signing key from a secret json file
29 | sk = PaymentSigningKey.from_json(
30 | """{
31 | "type": "GenesisUTxOSigningKey_ed25519",
32 | "description": "Genesis Initial UTxO Signing Key",
33 | "cborHex": "5820093be5cd3987d0c9fd8854ef908f7746b69e2d73320db6dc0f780d81585b84c2"
34 | }"""
35 | )
36 |
37 | # Derive a verification key from the signing key
38 | vk = PaymentVerificationKey.from_signing_key(sk)
39 |
40 | # Sign the transaction body hash
41 | signature = sk.sign(tx_body.hash())
42 |
43 | # Add verification key and the signature to the witness set
44 | vk_witnesses = [VerificationKeyWitness(vk, signature)]
45 |
46 | # Create final signed transaction
47 | signed_tx = Transaction(tx_body, TransactionWitnessSet(vkey_witnesses=vk_witnesses))
48 |
--------------------------------------------------------------------------------
/examples/tx_builder.py:
--------------------------------------------------------------------------------
1 | """Build a transaction using transaction builder"""
2 |
3 | from blockfrost import ApiUrls
4 |
5 | from pycardano import *
6 |
7 | # Use testnet
8 | network = Network.TESTNET
9 |
10 | # Read keys to memory
11 | # Assume there is a payment.skey file sitting in current directory
12 | psk = PaymentSigningKey.load("payment.skey")
13 | # Assume there is a stake.skey file sitting in current directory
14 | ssk = StakeSigningKey.load("stake.skey")
15 |
16 | pvk = PaymentVerificationKey.from_signing_key(psk)
17 | svk = StakeVerificationKey.from_signing_key(ssk)
18 |
19 | # Derive an address from payment verification key and stake verification key
20 | address = Address(pvk.hash(), svk.hash(), network)
21 |
22 | # Create a BlockFrost chain context. In this example, we will use preprod network.
23 | context = BlockFrostChainContext(
24 | "your_blockfrost_project_id", base_url=ApiUrls.preprod.value
25 | )
26 |
27 | # Create a transaction builder
28 | builder = TransactionBuilder(context)
29 |
30 | # Tell the builder that transaction input will come from a specific address, assuming that there are some ADA and native
31 | # assets sitting at this address. "add_input_address" could be called multiple times with different address.
32 | builder.add_input_address(address)
33 |
34 | # Get all UTxOs currently sitting at this address
35 | utxos = context.utxos(address)
36 |
37 | # We can also tell the builder to include a specific UTxO in the transaction.
38 | # Similarly, "add_input" could be called multiple times.
39 | builder.add_input(utxos[0])
40 |
41 | # Send 1.5 ADA and a native asset (CHOC) in quantity of 2000 to an address.
42 | builder.add_output(
43 | TransactionOutput(
44 | Address.from_primitive(
45 | "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
46 | ),
47 | Value.from_primitive(
48 | [
49 | 1500000,
50 | {
51 | bytes.fromhex(
52 | "57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522" # Policy ID
53 | ): {
54 | b"CHOC": 2000 # Asset name and amount
55 | }
56 | },
57 | ]
58 | ),
59 | )
60 | )
61 |
62 | # We can add multiple outputs, similar to what we can do with inputs.
63 | # Send 2 ADA and a native asset (CHOC) in quantity of 200 to ourselves
64 | builder.add_output(
65 | TransactionOutput(
66 | address,
67 | Value.from_primitive(
68 | [
69 | 2000000,
70 | {
71 | bytes.fromhex(
72 | "57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522" # Policy ID
73 | ): {
74 | b"CHOC": 200 # Asset name and amount
75 | }
76 | },
77 | ]
78 | ),
79 | )
80 | )
81 |
82 | # Create final signed transaction
83 | signed_tx = builder.build_and_sign([psk], change_address=address)
84 |
85 | # Submit signed transaction to the network
86 | context.submit_tx(signed_tx)
87 |
--------------------------------------------------------------------------------
/examples/tx_builder_with_metadata.py:
--------------------------------------------------------------------------------
1 | from blockfrost import ApiUrls
2 |
3 | from pycardano import (
4 | Address,
5 | AlonzoMetadata,
6 | AuxiliaryData,
7 | BlockFrostChainContext,
8 | Metadata,
9 | Network,
10 | PaymentSigningKey,
11 | PaymentVerificationKey,
12 | TransactionBuilder,
13 | TransactionOutput,
14 | )
15 |
16 | # Use testnet
17 | network = Network.TESTNET
18 |
19 | # Read keys to memory
20 | # Assume there is a payment.skey file sitting in current directory
21 | payment_signing_key = PaymentSigningKey.load("payment.skey")
22 | payment_verification_key = PaymentVerificationKey.from_signing_key(payment_signing_key)
23 |
24 | from_address = Address(payment_verification_key.hash(), network=network)
25 |
26 | # Create a BlockFrost chain context. In this example, we will use preprod network.
27 | context = BlockFrostChainContext(
28 | "your_blockfrost_project_id", base_url=ApiUrls.preprod.value
29 | )
30 |
31 | # Metadata that follows the CIP-20 standard. More info here https://cips.cardano.org/cip/CIP-20/
32 | metadata = {
33 | 674: {
34 | "msg": [
35 | "Invoice-No: 1234567890",
36 | "Customer-No: 555-1234",
37 | "P.S.: i will shop again at your store :-)",
38 | ]
39 | }
40 | }
41 |
42 | # Place metadata in AuxiliaryData, the format acceptable by a transaction.
43 | auxiliary_data = AuxiliaryData(AlonzoMetadata(metadata=Metadata(metadata)))
44 | # Set transaction metadata
45 | builder.auxiliary_data = auxiliary_data
46 | # Create a transaction builder
47 | builder = TransactionBuilder(context)
48 | # Set your address
49 | builder.add_input_address(from_address)
50 | # Recipient address
51 | to_address = "cardano_address_you_want_to_send_ada_to"
52 | # Add output and sign transaction
53 | builder.add_output(TransactionOutput.from_primitive([to_address, 100000000000]))
54 | signed_tx = builder.build_and_sign([payment_signing_key], change_address=from_address)
55 | # Send transaction
56 | context.submit_tx(signed_tx)
57 |
--------------------------------------------------------------------------------
/integration-test/README.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | Runtime environments for integration tests.
4 |
5 | `docker-compose.yml` kicks off two components, [cardano-node](https://github.com/input-output-hk/cardano-node) and
6 | [ogmios](https://github.com/CardanoSolutions/ogmios), which are necessary to run deterministic integration tests.
7 |
8 | Good things about a customizable and deterministic ledger:
9 |
10 | * Deterministic UTxO set and deterministic actors (isolation).
11 | * Deterministic fees.
12 | * Flexible configurations.
13 | * Reproducible.
14 |
15 | To achieve a relatively good degree of determinism, we use a local cardano node that runs as a single
16 | BFT node in the network. The node will produce all blocks and the environment/ledger is isolated.
17 |
18 | ## Instructions
19 |
20 | ### Pre-requisites
21 |
22 | * Install [Docker](https://www.docker.com/)
23 |
24 | ### Launch containers
25 |
26 | Bootstrap config files for a single BFT node:
27 |
28 | `./bootstrap.sh local-alonzo`
29 |
30 |
31 | Compose docker services (node + ogmios):
32 |
33 | `docker-compose up -d`
34 |
35 |
36 | Clean up docker containers and volumes when done with testing:
37 |
38 | `docker-compose down`
39 |
40 |
41 | ### Test
42 |
43 | Current, all integration tests could be kicked off by running:
44 |
45 | `./run_tests.sh`
--------------------------------------------------------------------------------
/integration-test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/integration-test/__init__.py
--------------------------------------------------------------------------------
/integration-test/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | if [ "$#" -ne 1 ] || [ "$1" = "-h" ]; then
6 | echo "Bootstrap network configs and environment variables."
7 | echo "Usage: $0 [network] (e.g. local-alonzo, testnet, mainnet)"
8 | exit 0
9 | fi
10 |
11 | if [ -d "./tmp_configs" ]; then
12 | echo "Removing tmp_configs"
13 | rm -rf ./tmp_configs
14 | fi
15 |
16 | echo "Copying configs to tmp_configs"
17 | cp -r configs tmp_configs
18 |
19 | NETWORK=$1
20 |
21 | echo "Bootstrapping network: $NETWORK"
22 |
23 | if [ "$NETWORK" = "local-alonzo" ] || [ "$NETWORK" = "local-vasil" ] || [ "$NETWORK" = "local-chang" ]; then
24 | echo "Updating byron startTime to present in local mode, $NETWORK era"
25 | jq -M ".startTime = ($(date +%s) + 60)" configs/"$NETWORK"/byron-genesis.json > \
26 | tmp_configs/"$NETWORK"/byron-genesis.json
27 | fi
28 |
29 | echo "NETWORK=$NETWORK" >.env
30 | NETWORK_MAGIC=$(jq .networkMagic tmp_configs/"$NETWORK"/shelley-genesis.json)
31 | echo "Found network magic: $NETWORK_MAGIC"
32 | echo "NETWORK_MAGIC=$NETWORK_MAGIC" >>.env
33 | echo "Done"
34 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/byron-genesis.json:
--------------------------------------------------------------------------------
1 | { "bootStakeholders":
2 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402": 1 }
3 | , "heavyDelegation":
4 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402":
5 | { "omega": 0
6 | , "issuerPk":
7 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
8 | , "delegatePk":
9 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
10 | , "cert":
11 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
12 | } }
13 | , "startTime": 1640212228
14 | , "nonAvvmBalances":
15 | { "2657WMsDfac6ef4bngGRU7FmksmW8QRfAifshdj4XyDxPeVT4DbPeoiUgzRdKjYYF":
16 | "10020000000" }
17 | , "blockVersionData":
18 | { "scriptVersion": 0
19 | , "slotDuration": "1000"
20 | , "maxBlockSize": "2000000"
21 | , "maxHeaderSize": "2000000"
22 | , "maxTxSize": "4096"
23 | , "maxProposalSize": "700"
24 | , "mpcThd": "20000000000000"
25 | , "heavyDelThd": "300000000000"
26 | , "updateVoteThd": "1000000000000"
27 | , "updateProposalThd": "100000000000000"
28 | , "updateImplicit": "10000"
29 | , "softforkRule":
30 | { "initThd": "900000000000000"
31 | , "minThd": "600000000000000"
32 | , "thdDecrement": "50000000000000"
33 | }
34 | , "txFeePolicy":
35 | { "summand": "155381000000000" , "multiplier": "43946000000" }
36 | , "unlockStakeEpoch": "18446744073709551615"
37 | }
38 | , "protocolConsts": { "k": 10 , "protocolMagic": 42 }
39 | , "avvmDistr": {}
40 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/byron/delegate.cert:
--------------------------------------------------------------------------------
1 | { "omega": 0
2 | , "issuerPk":
3 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
4 | , "delegatePk":
5 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
6 | , "cert":
7 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
8 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/byron/delegate.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/integration-test/configs/local-alonzo/byron/delegate.key
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "ByronGenesisFile": "byron-genesis.json",
3 | "ShelleyGenesisFile": "shelley-genesis.json",
4 | "AlonzoGenesisFile": "alonzo-genesis.json",
5 | "ConwayGenesisFile": "conway-genesis.json",
6 | "SocketPath": "db/node.socket",
7 | "MaxConcurrencyBulkSync": 1,
8 | "MaxConcurrencyDeadline": 2,
9 | "Protocol": "Cardano",
10 | "PBftSignatureThreshold": 0.6,
11 | "RequiresNetworkMagic": "RequiresMagic",
12 | "LastKnownBlockVersion-Major": 5,
13 | "LastKnownBlockVersion-Minor": 0,
14 | "LastKnownBlockVersion-Alt": 0,
15 | "ApplicationName": "cardano-sl",
16 | "ApplicationVersion": 1,
17 | "TurnOnLogging": true,
18 | "TurnOnLogMetrics": true,
19 | "minSeverity": "Debug",
20 | "TracingVerbosity": "NormalVerbosity",
21 | "setupBackends": [
22 | "KatipBK"
23 | ],
24 | "defaultBackends": [
25 | "KatipBK"
26 | ],
27 | "setupScribes": [
28 | {
29 | "scKind": "FileSK",
30 | "scName": "logs/mainnet.log",
31 | "scFormat": "ScText"
32 | },
33 | {
34 | "scKind": "StdoutSK",
35 | "scName": "stdout",
36 | "scFormat": "ScText"
37 | }
38 | ],
39 | "defaultScribes": [
40 | [
41 | "FileSK",
42 | "logs/mainnet.log"
43 | ],
44 | [
45 | "StdoutSK",
46 | "stdout"
47 | ]
48 | ],
49 | "rotation": {
50 | "rpLogLimitBytes": 5000000,
51 | "rpKeepFilesNum": 3,
52 | "rpMaxAgeHours": 24
53 | },
54 | "TraceBlockFetchClient": false,
55 | "TraceBlockFetchDecisions": false,
56 | "TraceBlockFetchProtocol": false,
57 | "TraceBlockFetchProtocolSerialised": false,
58 | "TraceBlockFetchServer": false,
59 | "TraceBlockchainTime": false,
60 | "TraceChainDb": true,
61 | "TraceChainSyncClient": false,
62 | "TraceChainSyncBlockServer": false,
63 | "TraceChainSyncHeaderServer": false,
64 | "TraceChainSyncProtocol": false,
65 | "TraceDNSResolver": true,
66 | "TraceDNSSubscription": true,
67 | "TraceErrorPolicy": true,
68 | "TraceLocalErrorPolicy": true,
69 | "TraceForge": true,
70 | "TraceHandshake": false,
71 | "TraceIpSubscription": true,
72 | "TraceLocalChainSyncProtocol": false,
73 | "TraceLocalHandshake": false,
74 | "TraceLocalTxSubmissionProtocol": false,
75 | "TraceLocalTxSubmissionServer": false,
76 | "TraceMempool": true,
77 | "TraceMux": false,
78 | "TraceTxInbound": false,
79 | "TraceTxOutbound": false,
80 | "TraceTxSubmissionProtocol": false,
81 | "options": {
82 | "mapBackends": {
83 | "cardano.node.metrics": [
84 | "EKGViewBK"
85 | ]
86 | },
87 | "mapScribes": {
88 | "cardano.node.metrics": [
89 | "FileSK::logs/mainnet.log"
90 | ]
91 | },
92 | "mapSeverity": {
93 | "cardano.node.ChainDB": "Notice",
94 | "cardano.node.DnsSubscription": "Debug"
95 | }
96 | },
97 | "EnableLogMetrics": false,
98 | "EnableLogging": true,
99 | "TestShelleyHardForkAtEpoch": 0,
100 | "TestAllegraHardForkAtEpoch": 0,
101 | "TestMaryHardForkAtEpoch": 0,
102 | "TestAlonzoHardForkAtEpoch": 0,
103 | "EnableDevelopmentHardForkEras": true,
104 | "ExperimentalProtocolsEnabled": true
105 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/conway-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "poolVotingThresholds": {
3 | "committeeNormal": 0.51,
4 | "committeeNoConfidence": 0.51,
5 | "hardForkInitiation": 0.51,
6 | "motionNoConfidence": 0.51,
7 | "ppSecurityGroup": 0.51
8 | },
9 | "dRepVotingThresholds": {
10 | "motionNoConfidence": 0.51,
11 | "committeeNormal": 0.51,
12 | "committeeNoConfidence": 0.51,
13 | "updateToConstitution": 0.51,
14 | "hardForkInitiation": 0.51,
15 | "ppNetworkGroup": 0.51,
16 | "ppEconomicGroup": 0.51,
17 | "ppTechnicalGroup": 0.51,
18 | "ppGovGroup": 0.51,
19 | "treasuryWithdrawal": 0.51
20 | },
21 | "committeeMinSize": 0,
22 | "committeeMaxTermLength": 200,
23 | "govActionLifetime": 10,
24 | "govActionDeposit": 1000000000,
25 | "dRepDeposit": 2000000,
26 | "dRepActivity": 20,
27 | "constitution": {
28 | "anchor": {
29 | "url": "",
30 | "dataHash": "0000000000000000000000000000000000000000000000000000000000000000"
31 | }
32 | },
33 | "committee": {
34 | "members": {
35 |
36 | },
37 | "quorum": 0
38 | }
39 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "maxLovelaceSupply": 1000000000000,
3 | "securityParam": 1000000000,
4 | "slotsPerKESPeriod": 1000000000,
5 | "updateQuorum": 2,
6 | "activeSlotsCoeff": 0.5,
7 | "protocolParams": {
8 | "minUTxOValue": 1000000,
9 | "eMax": 18,
10 | "extraEntropy": {
11 | "tag": "NeutralNonce"
12 | },
13 | "minFeeB": 155381,
14 | "tau": 0.1,
15 | "maxBlockBodySize": 65536,
16 | "minPoolCost": 0,
17 | "minFeeA": 44,
18 | "maxTxSize": 16384,
19 | "nOpt": 100,
20 | "maxBlockHeaderSize": 1100,
21 | "keyDeposit": 1000000,
22 | "protocolVersion": {
23 | "minor": 0,
24 | "major": 5
25 | },
26 | "poolDeposit": 1000000,
27 | "a0": 0.0,
28 | "rho": 0.1,
29 | "decentralisationParam": 0.1
30 | },
31 | "networkMagic": 42,
32 | "initialFunds": {
33 | "60d413c1745d306023e49589e658a7b7a4b4dda165ff5c97d8c8b979bf": 900000000000
34 | },
35 | "maxKESEvolutions": 60000000,
36 | "networkId": "Testnet",
37 | "genDelegs": {
38 | "37c2ef3cfb83c1004fcc21c75f42fee8013ac994afde92c1af419d1c": {
39 | "delegate": "5bd3a54bf30412243d4616c145c79467322164b81aa577814b74a520",
40 | "vrf": "fb66920eb17f426d4f513535be0eed59859a0e83963860090bb6db571f8a5b55"
41 | }
42 | },
43 | "slotLength": 1,
44 | "systemStart": "2021-12-21T03:17:14.803874404Z",
45 | "staking": {
46 | "pools": {},
47 | "stake": {}
48 | },
49 | "epochLength": 2
50 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/kes.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesSigningKey_ed25519_kes_2^6",
3 | "description": "KES Signing Key",
4 | "cborHex": "59026051c2b5536d23bbd7ff92aa8b58a011fb57b669183b7083961ae979a7b2ad1fbcbf1ee580c9e39567b88562b370cdccd27cababc4812a2ce1a7a0c7369274cf5f18f3e4796482babf0ea8d4e97157d6221bb6448da0cf3f173bbc1b13e708e40c25559347cc225b6d916bf611bc133d265482d0c503e94493456bb607ce34fd7b51a13e8908d9d85582edbed89e0fd2a0fb34d45480cef5b277dbb46b23322ea191760cafdf5c2f3bc5307f2128c121e5f8f54fdf6ca2925c034fc11dcc933855b595493e629e717a1b2ced715dfac5bf42838928edd19c287d55c1ef04ecf31070fe52ab805cf813e752f001353ac637f8f3f76db4b8c0e12f8552335182af76683b819debaa623a730e12f2f7d9f63190c835e8211bdf86d2bf244e8ad114328621535a63fd1a1497389356220e818e5d2f530f50494401b7ee027172ca72093645465b2c83e0dcd1d9c4a81b6871849601a8706d95e3c58a4c0841fdfb214b0bb82ec1e18ba7bea9e4f3eb9a0abbb39e57a9ab96799379ca8cadeb2e1a8df84b3e0e7ca0af3d6665a12029f6cefe4d309c5b3fad5bec4ca7812d5bede426b6fff6f37da99a286cd837b327b35b645ca5bfabf0935ea87cbd29b3ce2b7b80f83f386a474c69f86f553e35069f40b04f9a6bb6a13b583c0a911126c8aed1301b4014e0ea8229d5dcce81a56836f5bb286bd28c1ee5c69fd358c16a4fdbd5b6e9b0ed1ef766dcf6c56c7a845104309c92a2013bd5a7c8354fb8a866b61b23e014a07a78ed5b69469f4121c97bce50864d8555b91e3c2d812f4760a6318750c7b71fccbc8bab1c54c0be28f60c97cc8e33cbd8da235e4ca9344c48f13d81a37459"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/kes.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesVerificationKey_ed25519_kes_2^6",
3 | "description": "KES Verification Key",
4 | "cborHex": "58206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/node.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificate",
3 | "description": "",
4 | "cborHex": "828458206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec201005840853403f4d2e63e027b26f59c45ce81c74b1dfd708dc561b5ede5204262253451b7560f1c75425d3ee08fd4d933392f7fe3f1017efb3c8ee565a5493a061a270d582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/operator.counter:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificateIssueCounter",
3 | "description": "Next certificate issue number: 2",
4 | "cborHex": "8202582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/operator.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateSigningKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "5820351111fb3058c30c976b57f1b13e0e333243126768eae52133294cfe1481e943"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/operator.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateVerificationKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/utxo-keys/payment.addr:
--------------------------------------------------------------------------------
1 | addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/utxo-keys/utxo1.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOSigningKey_ed25519",
3 | "description": "Genesis Initial UTxO Signing Key",
4 | "cborHex": "5820093be5cd3987d0c9fd8854ef908f7746b69e2d73320db6dc0f780d81585b84c2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/utxo-keys/utxo1.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOVerificationKey_ed25519",
3 | "description": "Genesis Initial UTxO Verification Key",
4 | "cborHex": "58208be8339e9f3addfa6810d59e2f072f85e64d4c024c087e0d24f8317c6544f62f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/vrf.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfSigningKey_PraosVRF",
3 | "description": "VRF Signing Key",
4 | "cborHex": "5840b504af084d200455b08e72f0d278cf23bd9f2acddf834755d007e87536e19d1158cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/shelley/vrf.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfVerificationKey_PraosVRF",
3 | "description": "VRF Verification Key",
4 | "cborHex": "582058cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-alonzo/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "172.20.0.102",
5 | "port": 3000,
6 | "valency": 1
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/byron-genesis.json:
--------------------------------------------------------------------------------
1 | { "bootStakeholders":
2 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402": 1 }
3 | , "heavyDelegation":
4 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402":
5 | { "omega": 0
6 | , "issuerPk":
7 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
8 | , "delegatePk":
9 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
10 | , "cert":
11 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
12 | } }
13 | , "startTime": 1640212228
14 | , "nonAvvmBalances":
15 | { "2657WMsDfac6ef4bngGRU7FmksmW8QRfAifshdj4XyDxPeVT4DbPeoiUgzRdKjYYF":
16 | "10020000000" }
17 | , "blockVersionData":
18 | { "scriptVersion": 0
19 | , "slotDuration": "1000"
20 | , "maxBlockSize": "2000000"
21 | , "maxHeaderSize": "2000000"
22 | , "maxTxSize": "4096"
23 | , "maxProposalSize": "700"
24 | , "mpcThd": "20000000000000"
25 | , "heavyDelThd": "300000000000"
26 | , "updateVoteThd": "1000000000000"
27 | , "updateProposalThd": "100000000000000"
28 | , "updateImplicit": "10000"
29 | , "softforkRule":
30 | { "initThd": "900000000000000"
31 | , "minThd": "600000000000000"
32 | , "thdDecrement": "50000000000000"
33 | }
34 | , "txFeePolicy":
35 | { "summand": "155381000000000" , "multiplier": "43946000000" }
36 | , "unlockStakeEpoch": "18446744073709551615"
37 | }
38 | , "protocolConsts": { "k": 10 , "protocolMagic": 42 }
39 | , "avvmDistr": {}
40 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/byron/delegate.cert:
--------------------------------------------------------------------------------
1 | { "omega": 0
2 | , "issuerPk":
3 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
4 | , "delegatePk":
5 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
6 | , "cert":
7 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
8 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/byron/delegate.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/integration-test/configs/local-chang/byron/delegate.key
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "ByronGenesisFile": "./byron-genesis.json",
3 | "ShelleyGenesisFile": "./shelley-genesis.json",
4 | "AlonzoGenesisFile": "./alonzo-genesis.json",
5 | "ConwayGenesisFile": "./conway-genesis.json",
6 | "SocketPath": "db/node.socket",
7 | "Protocol": "Cardano",
8 | "PBftSignatureThreshold": 0.6,
9 | "RequiresNetworkMagic": "RequiresMagic",
10 | "LastKnownBlockVersion-Alt": 0,
11 | "LastKnownBlockVersion-Major": 3,
12 | "LastKnownBlockVersion-Minor": 1,
13 | "ApplicationName": "cardano-sl",
14 | "MinNodeVersion": "9.0",
15 | "ApplicationVersion": 1,
16 | "TurnOnLogging": true,
17 | "TurnOnLogMetrics": true,
18 | "minSeverity": "Debug",
19 | "TracingVerbosity": "NormalVerbosity",
20 | "setupBackends": [
21 | "KatipBK"
22 | ],
23 | "defaultBackends": [
24 | "KatipBK"
25 | ],
26 | "setupScribes": [
27 | {
28 | "scKind": "FileSK",
29 | "scName": "logs/mainnet.log",
30 | "scFormat": "ScText"
31 | },
32 | {
33 | "scKind": "StdoutSK",
34 | "scName": "stdout",
35 | "scFormat": "ScText"
36 | }
37 | ],
38 | "defaultScribes": [
39 | [
40 | "FileSK",
41 | "logs/mainnet.log"
42 | ],
43 | [
44 | "StdoutSK",
45 | "stdout"
46 | ]
47 | ],
48 | "rotation": {
49 | "rpLogLimitBytes": 5000000,
50 | "rpKeepFilesNum": 3,
51 | "rpMaxAgeHours": 24
52 | },
53 | "TraceBlockFetchClient": false,
54 | "TraceBlockFetchDecisions": false,
55 | "TraceBlockFetchProtocol": false,
56 | "TraceBlockFetchProtocolSerialised": false,
57 | "TraceBlockFetchServer": false,
58 | "TraceBlockchainTime": false,
59 | "TraceChainDb": true,
60 | "TraceChainSyncClient": false,
61 | "TraceChainSyncBlockServer": false,
62 | "TraceChainSyncHeaderServer": false,
63 | "TraceChainSyncProtocol": false,
64 | "TraceDNSResolver": true,
65 | "TraceDNSSubscription": true,
66 | "TraceErrorPolicy": true,
67 | "TraceLocalErrorPolicy": true,
68 | "TraceForge": true,
69 | "TraceHandshake": false,
70 | "TraceIpSubscription": true,
71 | "TraceLocalChainSyncProtocol": false,
72 | "TraceLocalHandshake": false,
73 | "TraceLocalTxSubmissionProtocol": false,
74 | "TraceLocalTxSubmissionServer": false,
75 | "TraceMempool": true,
76 | "TraceMux": false,
77 | "TraceTxInbound": false,
78 | "TraceTxOutbound": false,
79 | "TraceTxSubmissionProtocol": false,
80 | "options": {
81 | "mapBackends": {
82 | "cardano.node.metrics": [
83 | "EKGViewBK"
84 | ]
85 | },
86 | "mapScribes": {
87 | "cardano.node.metrics": [
88 | "FileSK::logs/mainnet.log"
89 | ]
90 | },
91 | "mapSeverity": {
92 | "cardano.node.ChainDB": "Notice",
93 | "cardano.node.DnsSubscription": "Debug"
94 | }
95 | },
96 | "EnableLogMetrics": false,
97 | "EnableLogging": true,
98 | "TestShelleyHardForkAtEpoch": 0,
99 | "TestAllegraHardForkAtEpoch": 0,
100 | "TestMaryHardForkAtEpoch": 0,
101 | "TestAlonzoHardForkAtEpoch": 0,
102 | "TestBabbageHardForkAtEpoch": 4,
103 | "TestConwayHardForkAtEpoch": 5,
104 | "EnableDevelopmentHardForkEras": true,
105 | "ExperimentalProtocolsEnabled": true
106 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "maxLovelaceSupply": 1000000000000,
3 | "securityParam": 1000000000,
4 | "slotsPerKESPeriod": 1000000000,
5 | "updateQuorum": 2,
6 | "activeSlotsCoeff": 0.5,
7 | "protocolParams": {
8 | "minUTxOValue": 1000000,
9 | "eMax": 18,
10 | "extraEntropy": {
11 | "tag": "NeutralNonce"
12 | },
13 | "minFeeB": 155381,
14 | "tau": 0.1,
15 | "maxBlockBodySize": 65536,
16 | "minPoolCost": 0,
17 | "minFeeA": 44,
18 | "maxTxSize": 16384,
19 | "nOpt": 100,
20 | "maxBlockHeaderSize": 1100,
21 | "keyDeposit": 1000000,
22 | "protocolVersion": {
23 | "minor": 0,
24 | "major": 10
25 | },
26 | "poolDeposit": 1000000,
27 | "a0": 0.0,
28 | "rho": 0.1,
29 | "decentralisationParam": 0.1
30 | },
31 | "networkMagic": 42,
32 | "initialFunds": {
33 | "60d413c1745d306023e49589e658a7b7a4b4dda165ff5c97d8c8b979bf": 900000000000
34 | },
35 | "maxKESEvolutions": 60000000,
36 | "networkId": "Testnet",
37 | "genDelegs": {
38 | "37c2ef3cfb83c1004fcc21c75f42fee8013ac994afde92c1af419d1c": {
39 | "delegate": "5bd3a54bf30412243d4616c145c79467322164b81aa577814b74a520",
40 | "vrf": "fb66920eb17f426d4f513535be0eed59859a0e83963860090bb6db571f8a5b55"
41 | }
42 | },
43 | "slotLength": 1,
44 | "systemStart": "2021-12-21T03:17:14.803874404Z",
45 | "staking": {
46 | "pools": {},
47 | "stake": {}
48 | },
49 | "epochLength": 10
50 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/kes.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesSigningKey_ed25519_kes_2^6",
3 | "description": "KES Signing Key",
4 | "cborHex": "59026051c2b5536d23bbd7ff92aa8b58a011fb57b669183b7083961ae979a7b2ad1fbcbf1ee580c9e39567b88562b370cdccd27cababc4812a2ce1a7a0c7369274cf5f18f3e4796482babf0ea8d4e97157d6221bb6448da0cf3f173bbc1b13e708e40c25559347cc225b6d916bf611bc133d265482d0c503e94493456bb607ce34fd7b51a13e8908d9d85582edbed89e0fd2a0fb34d45480cef5b277dbb46b23322ea191760cafdf5c2f3bc5307f2128c121e5f8f54fdf6ca2925c034fc11dcc933855b595493e629e717a1b2ced715dfac5bf42838928edd19c287d55c1ef04ecf31070fe52ab805cf813e752f001353ac637f8f3f76db4b8c0e12f8552335182af76683b819debaa623a730e12f2f7d9f63190c835e8211bdf86d2bf244e8ad114328621535a63fd1a1497389356220e818e5d2f530f50494401b7ee027172ca72093645465b2c83e0dcd1d9c4a81b6871849601a8706d95e3c58a4c0841fdfb214b0bb82ec1e18ba7bea9e4f3eb9a0abbb39e57a9ab96799379ca8cadeb2e1a8df84b3e0e7ca0af3d6665a12029f6cefe4d309c5b3fad5bec4ca7812d5bede426b6fff6f37da99a286cd837b327b35b645ca5bfabf0935ea87cbd29b3ce2b7b80f83f386a474c69f86f553e35069f40b04f9a6bb6a13b583c0a911126c8aed1301b4014e0ea8229d5dcce81a56836f5bb286bd28c1ee5c69fd358c16a4fdbd5b6e9b0ed1ef766dcf6c56c7a845104309c92a2013bd5a7c8354fb8a866b61b23e014a07a78ed5b69469f4121c97bce50864d8555b91e3c2d812f4760a6318750c7b71fccbc8bab1c54c0be28f60c97cc8e33cbd8da235e4ca9344c48f13d81a37459"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/kes.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesVerificationKey_ed25519_kes_2^6",
3 | "description": "KES Verification Key",
4 | "cborHex": "58206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/node.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificate",
3 | "description": "",
4 | "cborHex": "828458206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec201005840853403f4d2e63e027b26f59c45ce81c74b1dfd708dc561b5ede5204262253451b7560f1c75425d3ee08fd4d933392f7fe3f1017efb3c8ee565a5493a061a270d582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/operator.counter:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificateIssueCounter",
3 | "description": "Next certificate issue number: 2",
4 | "cborHex": "8202582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/operator.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateSigningKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "5820351111fb3058c30c976b57f1b13e0e333243126768eae52133294cfe1481e943"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/operator.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateVerificationKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/utxo-keys/payment.addr:
--------------------------------------------------------------------------------
1 | addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/utxo-keys/utxo1.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOSigningKey_ed25519",
3 | "description": "Genesis Initial UTxO Signing Key",
4 | "cborHex": "5820093be5cd3987d0c9fd8854ef908f7746b69e2d73320db6dc0f780d81585b84c2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/utxo-keys/utxo1.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOVerificationKey_ed25519",
3 | "description": "Genesis Initial UTxO Verification Key",
4 | "cborHex": "58208be8339e9f3addfa6810d59e2f072f85e64d4c024c087e0d24f8317c6544f62f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/vrf.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfSigningKey_PraosVRF",
3 | "description": "VRF Signing Key",
4 | "cborHex": "5840b504af084d200455b08e72f0d278cf23bd9f2acddf834755d007e87536e19d1158cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/shelley/vrf.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfVerificationKey_PraosVRF",
3 | "description": "VRF Verification Key",
4 | "cborHex": "582058cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-chang/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "172.20.0.102",
5 | "port": 3000,
6 | "valency": 1
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/byron-genesis.json:
--------------------------------------------------------------------------------
1 | { "bootStakeholders":
2 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402": 1 }
3 | , "heavyDelegation":
4 | { "b733bf8070781d30a0c8d5ca66392188f78c6604b631629cd055f402":
5 | { "omega": 0
6 | , "issuerPk":
7 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
8 | , "delegatePk":
9 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
10 | , "cert":
11 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
12 | } }
13 | , "startTime": 1640212228
14 | , "nonAvvmBalances":
15 | { "2657WMsDfac6ef4bngGRU7FmksmW8QRfAifshdj4XyDxPeVT4DbPeoiUgzRdKjYYF":
16 | "10020000000" }
17 | , "blockVersionData":
18 | { "scriptVersion": 0
19 | , "slotDuration": "1000"
20 | , "maxBlockSize": "2000000"
21 | , "maxHeaderSize": "2000000"
22 | , "maxTxSize": "4096"
23 | , "maxProposalSize": "700"
24 | , "mpcThd": "20000000000000"
25 | , "heavyDelThd": "300000000000"
26 | , "updateVoteThd": "1000000000000"
27 | , "updateProposalThd": "100000000000000"
28 | , "updateImplicit": "10000"
29 | , "softforkRule":
30 | { "initThd": "900000000000000"
31 | , "minThd": "600000000000000"
32 | , "thdDecrement": "50000000000000"
33 | }
34 | , "txFeePolicy":
35 | { "summand": "155381000000000" , "multiplier": "43946000000" }
36 | , "unlockStakeEpoch": "18446744073709551615"
37 | }
38 | , "protocolConsts": { "k": 10 , "protocolMagic": 42 }
39 | , "avvmDistr": {}
40 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/byron/delegate.cert:
--------------------------------------------------------------------------------
1 | { "omega": 0
2 | , "issuerPk":
3 | "ckPV1Ypq8uRkxwoDj93p7cCm4G+uB9R8SGGOKyc6KyIR8NDVVwu1FS3AwSoUjra02uiF5AlAUXUvVqZvnT8nCw=="
4 | , "delegatePk":
5 | "MYL9xuLMepgsQxRtqOu57nJw16pMWel79j0APRV1NSqH3ZUeBu+p7XaNoVCzw7yemMb4vwLiRDcMnnqHXztFVA=="
6 | , "cert":
7 | "643985a3022fedf3d9aaee8ab18d35e0cdc894beb5edb502ca47c37cce678741dd502fba0c2b8ee38513e0a75f6ee2dcc0f05d5b3c1d7ce72cc1c22a8a910909"
8 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/byron/delegate.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/integration-test/configs/local-vasil/byron/delegate.key
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "ByronGenesisFile": "byron-genesis.json",
3 | "ShelleyGenesisFile": "shelley-genesis.json",
4 | "AlonzoGenesisFile": "alonzo-genesis.json",
5 | "ConwayGenesisFile": "conway-genesis.json",
6 | "SocketPath": "db/node.socket",
7 | "MaxConcurrencyBulkSync": 1,
8 | "MaxConcurrencyDeadline": 2,
9 | "Protocol": "Cardano",
10 | "PBftSignatureThreshold": 0.6,
11 | "RequiresNetworkMagic": "RequiresMagic",
12 | "LastKnownBlockVersion-Major": 5,
13 | "LastKnownBlockVersion-Minor": 0,
14 | "LastKnownBlockVersion-Alt": 0,
15 | "ApplicationName": "cardano-sl",
16 | "ApplicationVersion": 1,
17 | "TurnOnLogging": true,
18 | "TurnOnLogMetrics": true,
19 | "minSeverity": "Debug",
20 | "TracingVerbosity": "NormalVerbosity",
21 | "setupBackends": [
22 | "KatipBK"
23 | ],
24 | "defaultBackends": [
25 | "KatipBK"
26 | ],
27 | "setupScribes": [
28 | {
29 | "scKind": "FileSK",
30 | "scName": "logs/mainnet.log",
31 | "scFormat": "ScText"
32 | },
33 | {
34 | "scKind": "StdoutSK",
35 | "scName": "stdout",
36 | "scFormat": "ScText"
37 | }
38 | ],
39 | "defaultScribes": [
40 | [
41 | "FileSK",
42 | "logs/mainnet.log"
43 | ],
44 | [
45 | "StdoutSK",
46 | "stdout"
47 | ]
48 | ],
49 | "rotation": {
50 | "rpLogLimitBytes": 5000000,
51 | "rpKeepFilesNum": 3,
52 | "rpMaxAgeHours": 24
53 | },
54 | "TraceBlockFetchClient": false,
55 | "TraceBlockFetchDecisions": false,
56 | "TraceBlockFetchProtocol": false,
57 | "TraceBlockFetchProtocolSerialised": false,
58 | "TraceBlockFetchServer": false,
59 | "TraceBlockchainTime": false,
60 | "TraceChainDb": true,
61 | "TraceChainSyncClient": false,
62 | "TraceChainSyncBlockServer": false,
63 | "TraceChainSyncHeaderServer": false,
64 | "TraceChainSyncProtocol": false,
65 | "TraceDNSResolver": true,
66 | "TraceDNSSubscription": true,
67 | "TraceErrorPolicy": true,
68 | "TraceLocalErrorPolicy": true,
69 | "TraceForge": true,
70 | "TraceHandshake": false,
71 | "TraceIpSubscription": true,
72 | "TraceLocalChainSyncProtocol": false,
73 | "TraceLocalHandshake": false,
74 | "TraceLocalTxSubmissionProtocol": false,
75 | "TraceLocalTxSubmissionServer": false,
76 | "TraceMempool": true,
77 | "TraceMux": false,
78 | "TraceTxInbound": false,
79 | "TraceTxOutbound": false,
80 | "TraceTxSubmissionProtocol": false,
81 | "options": {
82 | "mapBackends": {
83 | "cardano.node.metrics": [
84 | "EKGViewBK"
85 | ]
86 | },
87 | "mapScribes": {
88 | "cardano.node.metrics": [
89 | "FileSK::logs/mainnet.log"
90 | ]
91 | },
92 | "mapSeverity": {
93 | "cardano.node.ChainDB": "Notice",
94 | "cardano.node.DnsSubscription": "Debug"
95 | }
96 | },
97 | "EnableLogMetrics": false,
98 | "EnableLogging": true,
99 | "TestShelleyHardForkAtEpoch": 0,
100 | "TestAllegraHardForkAtEpoch": 0,
101 | "TestMaryHardForkAtEpoch": 0,
102 | "TestAlonzoHardForkAtEpoch": 0,
103 | "TestBabbageHardForkAtEpoch": 10,
104 | "EnableDevelopmentHardForkEras": true,
105 | "ExperimentalProtocolsEnabled": true
106 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/conway-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "poolVotingThresholds": {
3 | "committeeNormal": 0.51,
4 | "committeeNoConfidence": 0.51,
5 | "hardForkInitiation": 0.51,
6 | "motionNoConfidence": 0.51,
7 | "ppSecurityGroup": 0.51
8 | },
9 | "dRepVotingThresholds": {
10 | "motionNoConfidence": 0.51,
11 | "committeeNormal": 0.51,
12 | "committeeNoConfidence": 0.51,
13 | "updateToConstitution": 0.51,
14 | "hardForkInitiation": 0.51,
15 | "ppNetworkGroup": 0.51,
16 | "ppEconomicGroup": 0.51,
17 | "ppTechnicalGroup": 0.51,
18 | "ppGovGroup": 0.51,
19 | "treasuryWithdrawal": 0.51
20 | },
21 | "committeeMinSize": 0,
22 | "committeeMaxTermLength": 200,
23 | "govActionLifetime": 10,
24 | "govActionDeposit": 1000000000,
25 | "dRepDeposit": 2000000,
26 | "dRepActivity": 20,
27 | "constitution": {
28 | "anchor": {
29 | "url": "",
30 | "dataHash": "0000000000000000000000000000000000000000000000000000000000000000"
31 | }
32 | },
33 | "committee": {
34 | "members": {
35 |
36 | },
37 | "quorum": 0
38 | }
39 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "maxLovelaceSupply": 1000000000000,
3 | "securityParam": 1000000000,
4 | "slotsPerKESPeriod": 1000000000,
5 | "updateQuorum": 2,
6 | "activeSlotsCoeff": 0.5,
7 | "protocolParams": {
8 | "minUTxOValue": 1000000,
9 | "eMax": 18,
10 | "extraEntropy": {
11 | "tag": "NeutralNonce"
12 | },
13 | "minFeeB": 155381,
14 | "tau": 0.1,
15 | "maxBlockBodySize": 65536,
16 | "minPoolCost": 0,
17 | "minFeeA": 44,
18 | "maxTxSize": 16384,
19 | "nOpt": 100,
20 | "maxBlockHeaderSize": 1100,
21 | "keyDeposit": 1000000,
22 | "protocolVersion": {
23 | "minor": 0,
24 | "major": 7
25 | },
26 | "poolDeposit": 1000000,
27 | "a0": 0.0,
28 | "rho": 0.1,
29 | "decentralisationParam": 0.1
30 | },
31 | "networkMagic": 42,
32 | "initialFunds": {
33 | "60d413c1745d306023e49589e658a7b7a4b4dda165ff5c97d8c8b979bf": 900000000000
34 | },
35 | "maxKESEvolutions": 60000000,
36 | "networkId": "Testnet",
37 | "genDelegs": {
38 | "37c2ef3cfb83c1004fcc21c75f42fee8013ac994afde92c1af419d1c": {
39 | "delegate": "5bd3a54bf30412243d4616c145c79467322164b81aa577814b74a520",
40 | "vrf": "fb66920eb17f426d4f513535be0eed59859a0e83963860090bb6db571f8a5b55"
41 | }
42 | },
43 | "slotLength": 1,
44 | "systemStart": "2021-12-21T03:17:14.803874404Z",
45 | "staking": {
46 | "pools": {},
47 | "stake": {}
48 | },
49 | "epochLength": 4
50 | }
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/kes.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesSigningKey_ed25519_kes_2^6",
3 | "description": "KES Signing Key",
4 | "cborHex": "59026051c2b5536d23bbd7ff92aa8b58a011fb57b669183b7083961ae979a7b2ad1fbcbf1ee580c9e39567b88562b370cdccd27cababc4812a2ce1a7a0c7369274cf5f18f3e4796482babf0ea8d4e97157d6221bb6448da0cf3f173bbc1b13e708e40c25559347cc225b6d916bf611bc133d265482d0c503e94493456bb607ce34fd7b51a13e8908d9d85582edbed89e0fd2a0fb34d45480cef5b277dbb46b23322ea191760cafdf5c2f3bc5307f2128c121e5f8f54fdf6ca2925c034fc11dcc933855b595493e629e717a1b2ced715dfac5bf42838928edd19c287d55c1ef04ecf31070fe52ab805cf813e752f001353ac637f8f3f76db4b8c0e12f8552335182af76683b819debaa623a730e12f2f7d9f63190c835e8211bdf86d2bf244e8ad114328621535a63fd1a1497389356220e818e5d2f530f50494401b7ee027172ca72093645465b2c83e0dcd1d9c4a81b6871849601a8706d95e3c58a4c0841fdfb214b0bb82ec1e18ba7bea9e4f3eb9a0abbb39e57a9ab96799379ca8cadeb2e1a8df84b3e0e7ca0af3d6665a12029f6cefe4d309c5b3fad5bec4ca7812d5bede426b6fff6f37da99a286cd837b327b35b645ca5bfabf0935ea87cbd29b3ce2b7b80f83f386a474c69f86f553e35069f40b04f9a6bb6a13b583c0a911126c8aed1301b4014e0ea8229d5dcce81a56836f5bb286bd28c1ee5c69fd358c16a4fdbd5b6e9b0ed1ef766dcf6c56c7a845104309c92a2013bd5a7c8354fb8a866b61b23e014a07a78ed5b69469f4121c97bce50864d8555b91e3c2d812f4760a6318750c7b71fccbc8bab1c54c0be28f60c97cc8e33cbd8da235e4ca9344c48f13d81a37459"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/kes.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesVerificationKey_ed25519_kes_2^6",
3 | "description": "KES Verification Key",
4 | "cborHex": "58206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/node.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificate",
3 | "description": "",
4 | "cborHex": "828458206e59b21f538b5fdbe50df62f793488f8783e19d261d3fd59a700d2c41963cec201005840853403f4d2e63e027b26f59c45ce81c74b1dfd708dc561b5ede5204262253451b7560f1c75425d3ee08fd4d933392f7fe3f1017efb3c8ee565a5493a061a270d582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/operator.counter:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificateIssueCounter",
3 | "description": "Next certificate issue number: 2",
4 | "cborHex": "8202582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/operator.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateSigningKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "5820351111fb3058c30c976b57f1b13e0e333243126768eae52133294cfe1481e943"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/operator.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisDelegateVerificationKey_ed25519",
3 | "description": "Genesis delegate operator key",
4 | "cborHex": "582091934010118a86e2628e8188413cfa3eeac1237f3f699ebe16892f41671ccf3f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/utxo-keys/payment.addr:
--------------------------------------------------------------------------------
1 | addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/utxo-keys/utxo1.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOSigningKey_ed25519",
3 | "description": "Genesis Initial UTxO Signing Key",
4 | "cborHex": "5820093be5cd3987d0c9fd8854ef908f7746b69e2d73320db6dc0f780d81585b84c2"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/utxo-keys/utxo1.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GenesisUTxOVerificationKey_ed25519",
3 | "description": "Genesis Initial UTxO Verification Key",
4 | "cborHex": "58208be8339e9f3addfa6810d59e2f072f85e64d4c024c087e0d24f8317c6544f62f"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/vrf.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfSigningKey_PraosVRF",
3 | "description": "VRF Signing Key",
4 | "cborHex": "5840b504af084d200455b08e72f0d278cf23bd9f2acddf834755d007e87536e19d1158cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/shelley/vrf.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfVerificationKey_PraosVRF",
3 | "description": "VRF Verification Key",
4 | "cborHex": "582058cc502328977455f71db641249286ce07c11de5cb1f7429db0584eca3cabb7e"
5 | }
6 |
--------------------------------------------------------------------------------
/integration-test/configs/local-vasil/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "172.20.0.102",
5 | "port": 3000,
6 | "valency": 1
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/configs/mainnet/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "AlonzoGenesisFile": "alonzo-genesis.json",
3 | "AlonzoGenesisHash": "7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874",
4 | "ApplicationName": "cardano-sl",
5 | "ApplicationVersion": 1,
6 | "ByronGenesisFile": "byron-genesis.json",
7 | "ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb",
8 | "LastKnownBlockVersion-Alt": 0,
9 | "LastKnownBlockVersion-Major": 3,
10 | "LastKnownBlockVersion-Minor": 0,
11 | "MaxKnownMajorProtocolVersion": 2,
12 | "Protocol": "Cardano",
13 | "RequiresNetworkMagic": "RequiresNoMagic",
14 | "ShelleyGenesisFile": "shelley-genesis.json",
15 | "ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81",
16 | "TraceAcceptPolicy": true,
17 | "TraceBlockFetchClient": false,
18 | "TraceBlockFetchDecisions": false,
19 | "TraceBlockFetchProtocol": false,
20 | "TraceBlockFetchProtocolSerialised": false,
21 | "TraceBlockFetchServer": false,
22 | "TraceChainDb": true,
23 | "TraceChainSyncBlockServer": false,
24 | "TraceChainSyncClient": false,
25 | "TraceChainSyncHeaderServer": false,
26 | "TraceChainSyncProtocol": false,
27 | "TraceConnectionManager": true,
28 | "TraceDNSResolver": true,
29 | "TraceDNSSubscription": true,
30 | "TraceDiffusionInitialization": true,
31 | "TraceErrorPolicy": true,
32 | "TraceForge": true,
33 | "TraceHandshake": false,
34 | "TraceInboundGovernor": true,
35 | "TraceIpSubscription": true,
36 | "TraceLedgerPeers": true,
37 | "TraceLocalChainSyncProtocol": false,
38 | "TraceLocalErrorPolicy": true,
39 | "TraceLocalHandshake": false,
40 | "TraceLocalRootPeers": true,
41 | "TraceLocalTxSubmissionProtocol": false,
42 | "TraceLocalTxSubmissionServer": false,
43 | "TraceMempool": true,
44 | "TraceMux": false,
45 | "TracePeerSelection": true,
46 | "TracePeerSelectionActions": true,
47 | "TracePublicRootPeers": true,
48 | "TraceServer": true,
49 | "TraceTxInbound": false,
50 | "TraceTxOutbound": false,
51 | "TraceTxSubmissionProtocol": false,
52 | "TracingVerbosity": "NormalVerbosity",
53 | "TurnOnLogMetrics": true,
54 | "TurnOnLogging": true,
55 | "defaultBackends": [
56 | "KatipBK"
57 | ],
58 | "defaultScribes": [
59 | [
60 | "StdoutSK",
61 | "stdout"
62 | ]
63 | ],
64 | "hasEKG": 12788,
65 | "hasPrometheus": [
66 | "127.0.0.1",
67 | 12798
68 | ],
69 | "minSeverity": "Info",
70 | "options": {
71 | "mapBackends": {
72 | "cardano.node.metrics": [
73 | "EKGViewBK"
74 | ],
75 | "cardano.node.resources": [
76 | "EKGViewBK"
77 | ]
78 | },
79 | "mapSubtrace": {
80 | "cardano.node.metrics": {
81 | "subtrace": "Neutral"
82 | }
83 | }
84 | },
85 | "rotation": {
86 | "rpKeepFilesNum": 10,
87 | "rpLogLimitBytes": 5000000,
88 | "rpMaxAgeHours": 24
89 | },
90 | "setupBackends": [
91 | "KatipBK"
92 | ],
93 | "setupScribes": [
94 | {
95 | "scFormat": "ScText",
96 | "scKind": "StdoutSK",
97 | "scName": "stdout",
98 | "scRotation": null
99 | }
100 | ]
101 | }
102 |
--------------------------------------------------------------------------------
/integration-test/configs/mainnet/shelley-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "activeSlotsCoeff": 0.05,
3 | "protocolParams": {
4 | "protocolVersion": {
5 | "minor": 0,
6 | "major": 2
7 | },
8 | "decentralisationParam": 1,
9 | "eMax": 18,
10 | "extraEntropy": {
11 | "tag": "NeutralNonce"
12 | },
13 | "maxTxSize": 16384,
14 | "maxBlockBodySize": 65536,
15 | "maxBlockHeaderSize": 1100,
16 | "minFeeA": 44,
17 | "minFeeB": 155381,
18 | "minUTxOValue": 1000000,
19 | "poolDeposit": 500000000,
20 | "minPoolCost": 340000000,
21 | "keyDeposit": 2000000,
22 | "nOpt": 150,
23 | "rho": 0.003,
24 | "tau": 0.20,
25 | "a0": 0.3
26 | },
27 | "genDelegs": {
28 | "ad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950c": {
29 | "delegate": "d9e5c76ad5ee778960804094a389f0b546b5c2b140a62f8ec43ea54d",
30 | "vrf": "64fa87e8b29a5b7bfbd6795677e3e878c505bc4a3649485d366b50abadec92d7"
31 | },
32 | "b9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497": {
33 | "delegate": "855d6fc1e54274e331e34478eeac8d060b0b90c1f9e8a2b01167c048",
34 | "vrf": "66d5167a1f426bd1adcc8bbf4b88c280d38c148d135cb41e3f5a39f948ad7fcc"
35 | },
36 | "60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1": {
37 | "delegate": "7f72a1826ae3b279782ab2bc582d0d2958de65bd86b2c4f82d8ba956",
38 | "vrf": "c0546d9aa5740afd569d3c2d9c412595cd60822bb6d9a4e8ce6c43d12bd0f674"
39 | },
40 | "f7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757": {
41 | "delegate": "69ae12f9e45c0c9122356c8e624b1fbbed6c22a2e3b4358cf0cb5011",
42 | "vrf": "6394a632af51a32768a6f12dac3485d9c0712d0b54e3f389f355385762a478f2"
43 | },
44 | "162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82": {
45 | "delegate": "4485708022839a7b9b8b639a939c85ec0ed6999b5b6dc651b03c43f6",
46 | "vrf": "aba81e764b71006c515986bf7b37a72fbb5554f78e6775f08e384dbd572a4b32"
47 | },
48 | "2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6": {
49 | "delegate": "6535db26347283990a252313a7903a45e3526ec25ddba381c071b25b",
50 | "vrf": "fcaca997b8105bd860876348fc2c6e68b13607f9bbd23515cd2193b555d267af"
51 | },
52 | "268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819b": {
53 | "delegate": "1d4f2e1fda43070d71bb22a5522f86943c7c18aeb4fa47a362c27e23",
54 | "vrf": "63ef48bc5355f3e7973100c371d6a095251c80ceb40559f4750aa7014a6fb6db"
55 | }
56 | },
57 | "updateQuorum": 5,
58 | "networkId": "Mainnet",
59 | "initialFunds": {},
60 | "maxLovelaceSupply": 45000000000000000,
61 | "networkMagic": 764824073,
62 | "epochLength": 432000,
63 | "systemStart": "2017-09-23T21:44:51Z",
64 | "slotsPerKESPeriod": 129600,
65 | "slotLength": 1,
66 | "maxKESEvolutions": 62,
67 | "securityParam": 2160
68 | }
69 |
--------------------------------------------------------------------------------
/integration-test/configs/mainnet/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "relays-new.cardano-mainnet.iohk.io",
5 | "port": 3001,
6 | "valency": 2
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/configs/testnet/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "AlonzoGenesisFile": "alonzo-genesis.json",
3 | "AlonzoGenesisHash": "7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874",
4 | "ApplicationName": "cardano-sl",
5 | "ApplicationVersion": 0,
6 | "ByronGenesisFile": "byron-genesis.json",
7 | "ByronGenesisHash": "96fceff972c2c06bd3bb5243c39215333be6d56aaf4823073dca31afe5038471",
8 | "LastKnownBlockVersion-Alt": 0,
9 | "LastKnownBlockVersion-Major": 3,
10 | "LastKnownBlockVersion-Minor": 0,
11 | "MaxKnownMajorProtocolVersion": 2,
12 | "Protocol": "Cardano",
13 | "RequiresNetworkMagic": "RequiresMagic",
14 | "ShelleyGenesisFile": "shelley-genesis.json",
15 | "ShelleyGenesisHash": "849a1764f152e1b09c89c0dfdbcbdd38d711d1fec2db5dfa0f87cf2737a0eaf4",
16 | "TraceAcceptPolicy": true,
17 | "TraceBlockFetchClient": false,
18 | "TraceBlockFetchDecisions": false,
19 | "TraceBlockFetchProtocol": false,
20 | "TraceBlockFetchProtocolSerialised": false,
21 | "TraceBlockFetchServer": false,
22 | "TraceChainDb": true,
23 | "TraceChainSyncBlockServer": false,
24 | "TraceChainSyncClient": false,
25 | "TraceChainSyncHeaderServer": false,
26 | "TraceChainSyncProtocol": false,
27 | "TraceConnectionManager": true,
28 | "TraceDNSResolver": true,
29 | "TraceDNSSubscription": true,
30 | "TraceDiffusionInitialization": true,
31 | "TraceErrorPolicy": true,
32 | "TraceForge": true,
33 | "TraceHandshake": false,
34 | "TraceInboundGovernor": true,
35 | "TraceIpSubscription": true,
36 | "TraceLedgerPeers": true,
37 | "TraceLocalChainSyncProtocol": false,
38 | "TraceLocalErrorPolicy": true,
39 | "TraceLocalHandshake": false,
40 | "TraceLocalRootPeers": true,
41 | "TraceLocalTxSubmissionProtocol": false,
42 | "TraceLocalTxSubmissionServer": false,
43 | "TraceMempool": true,
44 | "TraceMux": false,
45 | "TracePeerSelection": true,
46 | "TracePeerSelectionActions": true,
47 | "TracePublicRootPeers": true,
48 | "TraceServer": true,
49 | "TraceTxInbound": false,
50 | "TraceTxOutbound": false,
51 | "TraceTxSubmissionProtocol": false,
52 | "TracingVerbosity": "NormalVerbosity",
53 | "TurnOnLogMetrics": true,
54 | "TurnOnLogging": true,
55 | "defaultBackends": [
56 | "KatipBK"
57 | ],
58 | "defaultScribes": [
59 | [
60 | "StdoutSK",
61 | "stdout"
62 | ]
63 | ],
64 | "hasEKG": 12788,
65 | "hasPrometheus": [
66 | "127.0.0.1",
67 | 12798
68 | ],
69 | "minSeverity": "Info",
70 | "options": {
71 | "mapBackends": {
72 | "cardano.node.metrics": [
73 | "EKGViewBK"
74 | ],
75 | "cardano.node.resources": [
76 | "EKGViewBK"
77 | ]
78 | },
79 | "mapSubtrace": {
80 | "cardano.node.metrics": {
81 | "subtrace": "Neutral"
82 | }
83 | }
84 | },
85 | "rotation": {
86 | "rpKeepFilesNum": 10,
87 | "rpLogLimitBytes": 5000000,
88 | "rpMaxAgeHours": 24
89 | },
90 | "setupBackends": [
91 | "KatipBK"
92 | ],
93 | "setupScribes": [
94 | {
95 | "scFormat": "ScText",
96 | "scKind": "StdoutSK",
97 | "scName": "stdout",
98 | "scRotation": null
99 | }
100 | ]
101 | }
102 |
--------------------------------------------------------------------------------
/integration-test/configs/testnet/shelley-genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "activeSlotsCoeff": 0.05,
3 | "protocolParams": {
4 | "protocolVersion": {
5 | "minor": 0,
6 | "major": 2
7 | },
8 | "decentralisationParam": 1,
9 | "eMax": 18,
10 | "extraEntropy": {
11 | "tag": "NeutralNonce"
12 | },
13 | "maxTxSize": 16384,
14 | "maxBlockBodySize": 65536,
15 | "maxBlockHeaderSize": 1100,
16 | "minFeeA": 44,
17 | "minFeeB": 155381,
18 | "minUTxOValue": 1000000,
19 | "poolDeposit": 500000000,
20 | "minPoolCost": 340000000,
21 | "keyDeposit": 2000000,
22 | "nOpt": 150,
23 | "rho": 0.003,
24 | "tau": 0.20,
25 | "a0": 0.3
26 | },
27 | "genDelegs": {
28 | "2f56e87d67b8e5216582cfeb95dbdc9083110a3ef68faaa51bef3a80": {
29 | "delegate": "bd5933d3c5417f17a64c7214711a26abc3bc03e2c90dc1bb38e0c39f",
30 | "vrf": "9a0b0f537874d089cedfa9e250150405e47ea29acee87c40a223ae0a175d26f8"
31 | },
32 | "514e81afb082fce01678809eebd90eda4f7918354ec7d0433ad16274": {
33 | "delegate": "eff1b5b26e65b791d6f236c7c0264012bd1696759d22bdb4dd0f6f56",
34 | "vrf": "e6f70fb10c7523aa76648e20d17e65fd9b2ed53960fbd20b308f223b703f2e23"
35 | },
36 | "2fca486b4d8f1a0432f5bf18ef473ee4294c795a1a32e3132bc6b90f": {
37 | "delegate": "de665a71064706f946030505eae950583f08c316f0f58997961092b1",
38 | "vrf": "c3fde629add60e30142cd7ef3c680610975208b08aee42203a5c40ad5992e8f6"
39 | },
40 | "4ee98623920698b77c1c7f77288cbdac5f9011ff8970b1f507567d0d": {
41 | "delegate": "bf07107c6f632de95e34af7e009d2aafa19916c7ba89b944fbedcd72",
42 | "vrf": "9d7d12e3d6b02835be3e76cfc6ae93d937035ee0e006d04a0eef9dea19754e21"
43 | },
44 | "0d06d2547ed371fdf95fb5c4c735eecdd53e6a5bb831561bd0fcfd3d": {
45 | "delegate": "6df3e1b4b8a84c63c805076a85e5aa00924997a4eae85fddf0aee3ca",
46 | "vrf": "0774e5810fe02a014ec97ef424797172f2b8c5dcfb6e4cfc98b411c31d5096d8"
47 | },
48 | "581e23030b6038bae716e5d64b9e053db10541b12e6b0b4eff485454": {
49 | "delegate": "b0dca078b823cde627da136200d6618c49ad712b77972a1c5e135763",
50 | "vrf": "16a4e883b72ddbd09a4f8a1170fc346ab11e4202f814faa73e9d2433ee03e7b0"
51 | },
52 | "e5f27655371b54aed91cc916b2569060978be80056768fee2cc5ce1b": {
53 | "delegate": "b3873a254459f506e47b9a252ee7912e538b364447f31576a170db65",
54 | "vrf": "cc5c897fdf5db0017326656fe35aeb20c72b175540793f9b9b8dc9ade001bbc4"
55 | }
56 | },
57 | "updateQuorum": 5,
58 | "networkId": "Testnet",
59 | "initialFunds": {},
60 | "maxLovelaceSupply": 45000000000000000,
61 | "networkMagic": 1097911063,
62 | "epochLength": 432000,
63 | "systemStart": "2019-07-24T20:20:16Z",
64 | "slotsPerKESPeriod": 129600,
65 | "slotLength": 1,
66 | "maxKESEvolutions": 62,
67 | "securityParam": 2160
68 | }
69 |
--------------------------------------------------------------------------------
/integration-test/configs/testnet/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "relays-new.cardano-testnet.iohkdev.io",
5 | "port": 3001,
6 | "valency": 2
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/integration-test/docker-compose-chang.yml:
--------------------------------------------------------------------------------
1 | version: "3.5"
2 |
3 | networks:
4 | cluster:
5 | ipam:
6 | config:
7 | - subnet: 172.20.0.0/24
8 |
9 | services:
10 |
11 | cardano-node:
12 | image: ghcr.io/intersectmbo/cardano-node:${CARDANO_NODE_VERSION:-10.1.4}
13 | platform: linux/amd64
14 | entrypoint: bash
15 | environment:
16 | NETWORK: "${NETWORK:-local-alonzo}"
17 | CARDANO_NODE_SOCKET_PATH: "/ipc/node.socket"
18 | command: /code/run_node.sh
19 |
20 | networks:
21 | cluster:
22 | ipv4_address: 172.20.0.101
23 |
24 | volumes:
25 | - .:/code
26 | - /tmp:/tmp
27 | - node-db:/data/db
28 | - node-ipc:/ipc
29 | ports:
30 | - ${BFT_NODE_PORT:-3000}:3000
31 | logging:
32 | driver: "json-file"
33 | options:
34 | max-size: "200k"
35 | max-file: "10"
36 |
37 | cardano-pool:
38 | image: ghcr.io/intersectmbo/cardano-node:${CARDANO_NODE_VERSION:-10.1.4}
39 | platform: linux/amd64
40 | entrypoint: bash
41 | environment:
42 | NETWORK: "${NETWORK:-local-alonzo}"
43 | command: /code/run_pool.sh
44 |
45 | networks:
46 | cluster:
47 | ipv4_address: 172.20.0.102
48 |
49 | volumes:
50 | - .:/code
51 | - node-ipc:/ipc
52 | logging:
53 | driver: "json-file"
54 | options:
55 | max-size: "200k"
56 | max-file: "10"
57 |
58 | ogmios:
59 | image: cardanosolutions/ogmios:v6.11.2
60 | platform: linux/amd64
61 | environment:
62 | NETWORK: "${NETWORK:-local-alonzo}"
63 |
64 | command: [
65 | "--host", "0.0.0.0",
66 | "--node-socket", "/ipc/pool.socket",
67 | "--node-config", "/code/configs/${NETWORK:-local-alonzo}/config.json",
68 | "--log-level-websocket", "Debug"
69 | ]
70 | volumes:
71 | - .:/code
72 | - node-ipc:/ipc
73 | ports:
74 | - ${OGMIOS_PORT:-1337}:1337
75 | logging:
76 | driver: "json-file"
77 | options:
78 | max-size: "200k"
79 | max-file: "10"
80 |
81 | kupo:
82 | image: cardanosolutions/kupo:v2.9.0
83 | platform: linux/amd64
84 | environment:
85 | NETWORK: "${NETWORK:-local}"
86 |
87 | command: [
88 | "--node-socket", "/ipc/pool.socket",
89 | "--node-config", "/code/configs/${NETWORK:-local-alonzo}/config.json",
90 | "--host", "0.0.0.0",
91 | "--since", "origin",
92 | "--match", "*",
93 | "--in-memory"
94 | ]
95 | volumes:
96 | - .:/code
97 | - node-ipc:/ipc
98 | ports:
99 | - ${KUPO_PORT:-1442}:1442
100 |
101 | volumes:
102 | node-db:
103 | node-ipc:
104 |
--------------------------------------------------------------------------------
/integration-test/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.5"
2 |
3 | networks:
4 | cluster:
5 | ipam:
6 | config:
7 | - subnet: 172.20.0.0/24
8 |
9 | services:
10 |
11 | cardano-node:
12 | image: ghcr.io/intersectmbo/cardano-node:${CARDANO_NODE_VERSION:-8.9.2}
13 | platform: linux/amd64
14 | entrypoint: bash
15 | environment:
16 | NETWORK: "${NETWORK:-local-alonzo}"
17 | CARDANO_NODE_SOCKET_PATH: "/ipc/node.socket"
18 | command: /code/run_node.sh
19 |
20 | networks:
21 | cluster:
22 | ipv4_address: 172.20.0.101
23 |
24 | volumes:
25 | - .:/code
26 | - /tmp:/tmp
27 | - node-db:/data/db
28 | - node-ipc:/ipc
29 | ports:
30 | - ${BFT_NODE_PORT:-3000}:3000
31 | logging:
32 | driver: "json-file"
33 | options:
34 | max-size: "200k"
35 | max-file: "10"
36 |
37 | cardano-pool:
38 | image: ghcr.io/intersectmbo/cardano-node:${CARDANO_NODE_VERSION:-8.9.2}
39 | platform: linux/amd64
40 | entrypoint: bash
41 | environment:
42 | NETWORK: "${NETWORK:-local-alonzo}"
43 | command: /code/run_pool.sh
44 |
45 | networks:
46 | cluster:
47 | ipv4_address: 172.20.0.102
48 |
49 | volumes:
50 | - .:/code
51 | - node-ipc:/ipc
52 | logging:
53 | driver: "json-file"
54 | options:
55 | max-size: "200k"
56 | max-file: "10"
57 |
58 | ogmios:
59 | image: cardanosolutions/ogmios:v6.2.0
60 | platform: linux/amd64
61 | environment:
62 | NETWORK: "${NETWORK:-local-alonzo}"
63 |
64 | command: [
65 | "--host", "0.0.0.0",
66 | "--node-socket", "/ipc/node.socket",
67 | "--node-config", "/code/configs/${NETWORK:-local-alonzo}/config.json"
68 | ]
69 | volumes:
70 | - .:/code
71 | - node-ipc:/ipc
72 | ports:
73 | - ${OGMIOS_PORT:-1337}:1337
74 | logging:
75 | driver: "json-file"
76 | options:
77 | max-size: "200k"
78 | max-file: "10"
79 |
80 | kupo:
81 | image: cardanosolutions/kupo:v2.4.0
82 | platform: linux/amd64
83 | environment:
84 | NETWORK: "${NETWORK:-local}"
85 |
86 | command: [
87 | "--node-socket", "/ipc/node.socket",
88 | "--node-config", "/code/configs/${NETWORK:-local-alonzo}/config.json",
89 | "--host", "0.0.0.0",
90 | "--since", "origin",
91 | "--match", "*",
92 | "--in-memory"
93 | ]
94 | volumes:
95 | - .:/code
96 | - node-ipc:/ipc
97 | ports:
98 | - ${KUPO_PORT:-1442}:1442
99 |
100 | volumes:
101 | node-db:
102 | node-ipc:
103 |
--------------------------------------------------------------------------------
/integration-test/keys/extended.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
3 | "description": "Payment Signing Key",
4 | "cborHex": "5880e8428867ab9cc9304379a3ce0c238a592bd6d2349d2ebaf8a6ed2c6d2974a15ad59c74b6d8fa3edd032c6261a73998b7deafe983b6eeaff8b6fb3fab06bdf8019b693a62bce7a3cad1b9c02d22125767201c65db27484bb67d3cee7df7288d62c099ac0ce4a215355b149fd3114a2a7ef0438f01f8872c4487a61b469e26aae4"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/cold.counter:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificateIssueCounter",
3 | "description": "Next certificate issue number: 0",
4 | "cborHex": "820058202f896875fd81ee621cd8ef450c46a4e3c62a7b68ae0cc7b4372c2b02774cf759"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/cold.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakePoolSigningKey_ed25519",
3 | "description": "Stake Pool Operator Signing Key",
4 | "cborHex": "58201a516a8fd768f95c919917f4151a82ad62abb2080400f921da4b8808fae42dcf"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/cold.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakePoolVerificationKey_ed25519",
3 | "description": "Stake Pool Operator Verification Key",
4 | "cborHex": "58202f896875fd81ee621cd8ef450c46a4e3c62a7b68ae0cc7b4372c2b02774cf759"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/delegation.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "CertificateShelley",
3 | "description": "Stake Address Delegation Certificate",
4 | "cborHex": "83028200581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69581cc2105401f5b4e8dfcc3b04f7a2722f72a8f6c4b1c00f9b5b8f46dd5e"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/full.addr:
--------------------------------------------------------------------------------
1 | addr_test1qrxrqjtlfluk9axpmjj5enh0uw0cduwhz7txsqyl36m3uk2g9z3d4kaf0j5l6rxunxt43x28pssehhqds2x05mwld45sjncs0p
--------------------------------------------------------------------------------
/integration-test/keys/pool/kes.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesSigningKey_ed25519_kes_2^6",
3 | "description": "KES Signing Key",
4 | "cborHex": "590260ae3a6ac34fa31150694cf978c7c7992cdc9a2f6612c6dbbab17fde0b9b6747fe77544ca65d14673aab1519b8dc3795ed045cc05cf7bae957dd953f0595b17325d98db714af3b0e77649b98080d33d0c9582294422df18cd435e25c81ab020b99b9bef7f3cc39146b52dd35177a2fa533c005e0f851939a393d4e90ba568e30669033171c4a5e4f1626a95118c3108e41ed778664ac2a36e34e4dfac8c0a9b0d675bd99fa5cd4e2d975e0661fa0ce28615b13ca128110dbc46a37e4d28baae5940fbe4496b3d8317d6d01a7ed2a692b663f0c8fef0823f423a3537135482cc3cdd8647601f5f39281079373ac4710bf38c3af728b64692bcb3d78d9ca3d607f91580f45c30a0fa5d081ef050a28988317f3e1260a55cdc4835b96d011754a2188246848a1df4fe26541e23424c7639a32c452146457270d577e235fd211205a5f890ef53011f3f30bbab61e78b9068eec18b95c72a0f5a527bcae61cfd34ae61b6be0e6ba90427b4e29df1236f969d2d60aff95d656b82577ba1131fd145809120f6e6e82ea90ed4d02fdd8eaa51a12746a9b42df785672e2ff79508544dbeb510735b068d18f3ab46c6e4a916f63b082625cceaa8c18d1cd26d73579e1b58f1f6e3102daa31fd047dbd43140f4bda388193a8a1dcab0b5b5dfb2562b9e6d0e8ae179c487f223fed1d0a50c322d679b3e44166b0167bdd33c57a823373eba958696b78066fb898ac70bb67d9ec8f10df1c6b50c4ce2dc3764971547cbabe4d9ca6e10313d25fe5355cafcc26e480d184ee29d400a9c6cbaed36e89cf8f76a0bb0af734e3922d9bc9abb640df7b2c20aa8d9e7c622b259fec177b64ea8b533ef1e"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/kes.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "KesVerificationKey_ed25519_kes_2^6",
3 | "description": "KES Verification Key",
4 | "cborHex": "5820c73ee7d0502bdd3cbc24c76a75404727d8e85e17ca771a70c5464ba7b9702055"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/node.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "NodeOperationalCertificate",
3 | "description": "",
4 | "cborHex": "82845820c73ee7d0502bdd3cbc24c76a75404727d8e85e17ca771a70c5464ba7b97020550000584077cb7194ab7ab34bb07e3a0e8405891b71c388c8c300984e41f0ae47f4555613c76d1682d3a4e85a71ba3d2b17a6401e4fc604b0c567907d8ebd7195aff4040558202f896875fd81ee621cd8ef450c46a4e3c62a7b68ae0cc7b4372c2b02774cf759"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/payment.addr:
--------------------------------------------------------------------------------
1 | addr_test1vrxrqjtlfluk9axpmjj5enh0uw0cduwhz7txsqyl36m3ukgm9y0gt
--------------------------------------------------------------------------------
/integration-test/keys/pool/payment.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "PaymentSigningKeyShelley_ed25519",
3 | "description": "Payment Signing Key",
4 | "cborHex": "58204d9fc18b873d0cd70b614462418ac719d9ca12d0bfcdf7edac2a44fb385d26d8"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/payment.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "PaymentVerificationKeyShelley_ed25519",
3 | "description": "Payment Verification Key",
4 | "cborHex": "58205797dc2cc919dfec0bb849551ebdf30d96e5cbe0f33f734a87fe826db30f7ef9"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/pool-registration.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "CertificateShelley",
3 | "description": "Stake Pool Registration Certificate",
4 | "cborHex": "8a03581cc2105401f5b4e8dfcc3b04f7a2722f72a8f6c4b1c00f9b5b8f46dd5e5820d5daee7ab045f90495107b9997b677cf3b469d0f42fcf8528a80510a7d1c270b00190154d81e820001581de04828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d6981581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69818400190bb84400000000f682782768747470733a2f2f746573747374616b65706f6f6c2e636f6d2f6d657461646174612e6a736f6e5820c5c38833176e2d575bd8693e206e3af2e1088e556def86cae9f6c2fc45579f36"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/pool.id:
--------------------------------------------------------------------------------
1 | c2105401f5b4e8dfcc3b04f7a2722f72a8f6c4b1c00f9b5b8f46dd5e
--------------------------------------------------------------------------------
/integration-test/keys/pool/pool_registration_tx.signed:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Witnessed Tx AlonzoEra",
3 | "description": "Ledger Cddl Format",
4 | "cborHex": "84a50081825820732bfd67e66be8e8288349fcaaa2294973ef6271cc189a239bb431275401b8e500018282583900cc30497f4ff962f4c1dca54cceefe39f86f1d7179668009f8eb71e594828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d691b00000068c617140082581d60d413c1745d306023e49589e658a7b7a4b4dda165ff5c97d8c8b979bf1b00000068c5f572f7021a00031c89031b00005af3107a4000048382008200581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d698a03581cc2105401f5b4e8dfcc3b04f7a2722f72a8f6c4b1c00f9b5b8f46dd5e5820d5daee7ab045f90495107b9997b677cf3b469d0f42fcf8528a80510a7d1c270b00190154d81e820001581de04828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d6981581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69818400190bb84400000000f682782768747470733a2f2f746573747374616b65706f6f6c2e636f6d2f6d657461646174612e6a736f6e5820c5c38833176e2d575bd8693e206e3af2e1088e556def86cae9f6c2fc45579f3683028200581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69581cc2105401f5b4e8dfcc3b04f7a2722f72a8f6c4b1c00f9b5b8f46dd5ea100838258205edaa384c658c2bd8945ae389edac0a5bd452d0cfd5d1245e3ecd540030d1e3c5840109f3ca65a4173c986e0841f454e49805cda9f091a90e57203307fffadb0f9ed6237c81411cdf25a1122d4ffb16579cf70be41de49305529a03c62e1929e9a028258202f896875fd81ee621cd8ef450c46a4e3c62a7b68ae0cc7b4372c2b02774cf7595840fca096a9180245137d6194e7294c20c31800d397fa1ea5d731224dcf19280c0ea9c1fbab4942b11d00ac1d969fcf64ca417c270a5ae033d19f241c772cf6830e8258208be8339e9f3addfa6810d59e2f072f85e64d4c024c087e0d24f8317c6544f62f58406f9b7ea9bef5613d4dd7bc553daec40a0a2865a29885475d16558a554c565a6f2f8518bc65f6ddb1501aa9f35273956a6749c68bacee7082b6ae18bbf95d8305f5f6"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/stake.addr:
--------------------------------------------------------------------------------
1 | stake_test1upyz3gk6mw5he20apnwfn96cn9rscgvmmsxc9r86dh0k66gswf59n
--------------------------------------------------------------------------------
/integration-test/keys/pool/stake.cert:
--------------------------------------------------------------------------------
1 | {
2 | "type": "CertificateShelley",
3 | "description": "Stake Address Registration Certificate",
4 | "cborHex": "82008200581c4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/stake.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakeSigningKeyShelley_ed25519",
3 | "description": "Stake Signing Key",
4 | "cborHex": "5820ff3a330df8859e4e5f42a97fcaee73f6a00d0cf864f4bca902bd106d423f02c0"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/stake.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakeVerificationKeyShelley_ed25519",
3 | "description": "Stake Verification Key",
4 | "cborHex": "58205edaa384c658c2bd8945ae389edac0a5bd452d0cfd5d1245e3ecd540030d1e3c"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/topology.json:
--------------------------------------------------------------------------------
1 | {
2 | "Producers": [
3 | {
4 | "addr": "172.20.0.101",
5 | "port": 3000,
6 | "valency": 1
7 | }
8 | ]
9 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/vrf.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfSigningKey_PraosVRF",
3 | "description": "VRF Signing Key",
4 | "cborHex": "58407ccc63cc09619432b2f7e8958bc6da897df5802220ad5a12e85b2d744c74d08e7153171ad1b55f6fcf36e747fe30a9f061d27cf46e24b9033be11448e1631e78"
5 | }
--------------------------------------------------------------------------------
/integration-test/keys/pool/vrf.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "VrfVerificationKey_PraosVRF",
3 | "description": "VRF Verification Key",
4 | "cborHex": "58207153171ad1b55f6fcf36e747fe30a9f061d27cf46e24b9033be11448e1631e78"
5 | }
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/always_succeeds.plutus:
--------------------------------------------------------------------------------
1 | 49480100002221200101
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/fortytwo.plutus:
--------------------------------------------------------------------------------
1 | 59082459082101000033232332233223232333222323332223233333333222222223233322232333322223232332232333222323332223232332233223232333332222233223322332233223322332222223232533530313330063333573466e1cd55ce9baa0054800081248c98d4c120cd5ce0260248238231bad0043333573466e1cd55cea8012400046601264646464646464646464646666ae68cdc39aab9d500a480008cccccccccc05ccd40948c8c8cccd5cd19b8735573aa004900011980e981c1aba15002302a357426ae8940088c98d4c160cd5ce02e02c82b82b09aab9e5001137540026ae854028cd4094098d5d0a804999aa8163ae502b35742a010666aa058eb940acd5d0a80399a8128209aba15006335025335505204a75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a80f9919191999ab9a3370e6aae7540092000233502733504075a6ae854008c114d5d09aba25002232635305c3357380c00ba0b60b426aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a04a66a080eb4d5d0a80118229aba135744a004464c6a60b866ae7018017416c1684d55cf280089baa001357426ae8940088c98d4c160cd5ce02e02c82b82b09aab9e5001137540026ae854010cd4095d71aba15003335025335505275c40026ae854008c0dcd5d09aba2500223263530543357380b00aa0a60a426ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d400520062301c3039357426aae79400c8cccd5cd19b875002480108c06cc10cd5d09aab9e500423333573466e1d400d20022301b302e357426aae7940148cccd5cd19b875004480008c078dd71aba135573ca00c464c6a609e66ae7014c14013813413012c1284d55cea80089baa001357426ae8940088c98d4c120cd5ce026024823823082409931a982399ab9c49010350543500048046135573ca00226ea80048848cc00400c0088004888888888848cccccccccc00402c02802402001c01801401000c00880048848cc00400c008800448848cc00400c0084800448848cc00400c0084800448848cc00400c00848004848888c010014848888c00c014848888c008014848888c004014800448c88c008dd6000990009aa81a911999aab9f0012500e233500d30043574200460066ae880080cc8c8c8c8cccd5cd19b8735573aa006900011998039919191999ab9a3370e6aae754009200023300d303135742a00466a02605a6ae84d5d1280111931a981b99ab9c03b038036035135573ca00226ea8004d5d0a801999aa805bae500a35742a00466a01eeb8d5d09aba25002232635303333573806e06806406226ae8940044d55cf280089baa00122212333001004003002200122123300100300220011335500175ceb44488c88c008dd5800990009aa81791191999aab9f0022500923350083355031300635573aa004600a6aae794008c010d5d100181709aba10011122002122122330010040031200112232323333573466e1d400520002350083005357426aae79400c8cccd5cd19b87500248008940208c98d4c0a8cd5ce01701581481401389aab9d500113754002242446004006224400224002464646666ae68cdc39aab9d5002480008cc018c01cd5d0a8011bad357426ae8940088c98d4c090cd5ce01401281181109aab9e50011375400244246600200600440024646666ae68cdc39aab9d5001480008dd71aba135573ca004464c6a604066ae7009008407c0784dd500089119191999ab9a3370ea00290021280391999ab9a3370ea004900111a80518031aba135573ca00846666ae68cdc3a801a40004a014464c6a604666ae7009c09008808408007c4d55cea80089baa00112122230030041122200211222001120012323333573466e1d40052002200623333573466e1d400920002006232635301b33573803e03803403203026aae74dd50008910010910009000919191919191999ab9a3370ea0029006100591999ab9a3370ea0049005100691999ab9a3370ea00690041198059bae35742a00a6eb4d5d09aba2500523333573466e1d4011200623300d375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846602460286ae854024dd71aba135744a01246666ae68cdc3a8032400446028602a6ae84d55cf280591999ab9a3370ea00e900011809980b1aba135573ca018464c6a604066ae7009008407c07807407006c0680640604d55cea80209aab9e5003135573ca00426aae7940044dd500090911111118038041109111111198030048041091111111802804091111110020911111100191091111111980100480411091111111980080480410009191919191999ab9a3370ea002900111998041bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c028c02cd5d09aab9e5006232635301133573802a02402001e01c26aae75400c4d5d1280089aab9e5001137540024244600400644424466600200a0080064002464646666ae68cdc3a800a40044600c6eb8d5d09aab9e500323333573466e1d4009200023008375c6ae84d55cf280211931a980599ab9c00f00c00a009008135573aa00226ea80048488c00800c8488c00400c800444888c8c8cccd5cd19b8735573aa0049000119aa80598031aba150023005357426ae8940088c98d4c020cd5ce00600480380309aab9e5001137540029309000900088910919800801801089000a4903505431001123230010012233003300200200133322222253353004333573466e1c00920540060051006133573892010e77726f6e672072656465656d65720000512200212200120011
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/fortytwoV2.plutus:
--------------------------------------------------------------------------------
1 | 58775875010000323232322225335323253350021001100933320015007003332001500648150ccc8005401800ccc8005401520541004132632498cd5ce2491d496e636f727265637420646174756d2e2045787065637465642034322e0000412001123750002244666ae68cdd780100089100100189100081
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/helloworldV3.plutus:
--------------------------------------------------------------------------------
1 | 59011d0100003232323232323225333002323232323253330073370e900118041baa0011323232533300a3370e900018059baa005132533300e0011613253333330120011616161613253330103012003132533300e3370e900018079baa005132533300f002100114a06644646600200200644a66602a00229404c94ccc04ccdc79bae301700200414a2266006006002602e0026eb0c048c04cc04cc04cc04cc04cc04cc04cc04cc040dd50059bae301230103754602460206ea801458cdc79bae3011300f375401091010d48656c6c6f2c20576f726c64210016375c002601e00260186ea801458c034c038008c030004c024dd50008b1805180580118048009804801180380098021baa00114984d9595cd2ab9d5573caae7d5d0aba25749
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/pass_certifying_and_rewarding.plutus:
--------------------------------------------------------------------------------
1 | 5901e9010000323232323232323232323232322232323232323232323232323374a90001bb1498c8c8ccccd400c01001401840084004030030488888c8c8c94ccd5cd19180d88009980c180aa8012400c2930992999ab9a32301c100133019301650034801052615333573464603820029404c00452613263357389201136e6f7420612076616c696420707572706f7365004988c00852624984004c0454004405840584c98cd5ce2481104e616d654572726f723a207e626f6f6c004984c98cd5ce2481144e616d654572726f723a2076616c696461746f72004984c98cd5ce2481124e616d654572726f723a20707572706f7365004984c98cd5ce2481104e616d654572726f723a20646174756d004984c98cd5ce2481124e616d654572726f723a20636f6e74657874004984c98cd5ce2481144e616d654572726f723a20526577617264696e67004984c98cd5ce2481154e616d654572726f723a2043657274696679696e67004980080088c010c0200048c0140040108c018c94ccd55cf800899319ab9c49010a496e6465784572726f72004984d5d1000800919000a80091aab9d3754002e1c8d55cf1baa00123253335573e002264c66ae712410a496e6465784572726f72004984d5d0800800919ba548018cd5d028009bb14988cdd2a400866ae814004dd8a4c1
--------------------------------------------------------------------------------
/integration-test/plutus_scripts/unroll.plutus:
--------------------------------------------------------------------------------
1 | 58a20100003232232323232323374a90001bb1498c8d4008400401448c8c92610013330063758a00246eb400452f580264c66ae712410c4e616d654572726f723a207a004984c98cd5ce2481144e616d654572726f723a2076616c696461746f72004984c98cd5ce24810d4e616d654572726f723a20723300498888cc8c014894ccd55cf8008a802099aba0300335742002660040046ae8800400800c8c8c0040040041
--------------------------------------------------------------------------------
/integration-test/run_node.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$NETWORK" = "local-alonzo" ] || [ "$NETWORK" = "local-vasil" ] || [ "$NETWORK" = "local-chang" ]
4 | then
5 | chmod 400 /code/tmp_configs/"$NETWORK"/shelley/*.skey
6 | chmod 400 /code/tmp_configs/"$NETWORK"/shelley/*.vkey
7 | cardano-node run \
8 | --config /code/tmp_configs/"$NETWORK"/config.json \
9 | --topology /code/tmp_configs/"$NETWORK"/topology.json \
10 | --database-path /data/db --socket-path /ipc/node.socket \
11 | --shelley-kes-key /code/tmp_configs/"$NETWORK"/shelley/kes.skey \
12 | --shelley-vrf-key /code/tmp_configs/"$NETWORK"/shelley/vrf.skey \
13 | --shelley-operational-certificate /code/tmp_configs/"$NETWORK"/shelley/node.cert \
14 | --host-addr 0.0.0.0 \
15 | --port 3000
16 | else
17 | cardano-node run \
18 | --config /code/tmp_configs/"$NETWORK"/config.json \
19 | --topology /code/tmp_configs/"$NETWORK"/topology.json \
20 | --database-path /data/db --socket-path /ipc/node.socket
21 | fi
--------------------------------------------------------------------------------
/integration-test/run_pool.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "$NETWORK"
4 | if [ "$NETWORK" = "local-alonzo" ] || [ "$NETWORK" = "local-vasil" ] || [ "$NETWORK" = "local-chang" ]
5 | then
6 |
7 | # Waiting for BFT node to be ready
8 | while [ ! -S /ipc/node.socket ]
9 | do
10 | sleep 0.1
11 | done
12 |
13 | sleep 5
14 |
15 | export CARDANO_NODE_SOCKET_PATH=/ipc/node.socket
16 |
17 | cardano-cli alonzo transaction submit \
18 | --tx-file /code/keys/pool/pool_registration_tx.signed \
19 | --testnet-magic 42
20 |
21 | mkdir -p /data/db
22 | chmod 400 /code/keys/pool/*.skey
23 | chmod 400 /code/keys/pool/*.vkey
24 |
25 | # Start pool node
26 | cardano-node run \
27 | --config /code/tmp_configs/"$NETWORK"/config.json \
28 | --topology /code/keys/pool/topology.json \
29 | --database-path /data/db \
30 | --socket-path /ipc/pool.socket \
31 | --shelley-kes-key /code/keys/pool/kes.skey \
32 | --shelley-vrf-key /code/keys/pool/vrf.skey \
33 | --shelley-operational-certificate /code/keys/pool/node.cert \
34 | --host-addr 0.0.0.0 \
35 | --port 3000
36 | fi
--------------------------------------------------------------------------------
/integration-test/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -o pipefail
5 |
6 | ROOT=$(pwd)
7 |
8 | poetry install -C ..
9 | make ensure-pure-cbor2 -f ../Makefile
10 | #poetry run pip install ogmios
11 |
12 | ##########
13 | # Alonzo #
14 | ##########
15 | #
16 | ## Cleanup containers and volumes in case there is any running
17 | #docker-compose down --volumes --remove-orphans
18 | #
19 | ## Run alonzo integration tests
20 | #./bootstrap.sh local-alonzo
21 | #
22 | ## Launch containers
23 | #docker-compose up -d
24 | #
25 | #export PAYMENT_KEY="$ROOT"/configs/local-alonzo/shelley/utxo-keys/utxo1.skey
26 | #export EXTENDED_PAYMENT_KEY="$ROOT"/keys/extended.skey
27 | #export POOL_ID=$(cat "$ROOT"/keys/pool/pool.id)
28 | #
29 | ## Wait for stake pool to start producing blocks
30 | #sleep 10
31 | #
32 | ## Cleanup
33 | #docker-compose down --volumes --remove-orphans
34 | #
35 | ##########
36 | ## Vasil #
37 | ##########
38 | #
39 | ## Cleanup containers and volumes in case there is any running
40 | #docker-compose down --volumes --remove-orphans
41 | #
42 | ## Run integration tests
43 | #./bootstrap.sh local-vasil
44 | #
45 | ## Launch containers
46 | #docker-compose up -d
47 | #
48 | #export PAYMENT_KEY="$ROOT"/configs/local-vasil/shelley/utxo-keys/utxo1.skey
49 | #export EXTENDED_PAYMENT_KEY="$ROOT"/keys/extended.skey
50 | #export POOL_ID=$(cat "$ROOT"/keys/pool/pool.id)
51 | #
52 | ## Wait for stake pool to start producing blocks
53 | #sleep 30
54 | #
55 | #poetry run pytest -s -vv -n 4 "$ROOT"/test
56 | #
57 | ## Cleanup
58 | #docker-compose down --volumes --remove-orphans
59 |
60 |
61 | #########
62 | # Chang #
63 | #########
64 |
65 | # Cleanup containers and volumes in case there is any running
66 | docker compose -f docker-compose-chang.yml down --volumes --remove-orphans
67 |
68 | # Run integration tests
69 | ./bootstrap.sh local-chang
70 |
71 | # Launch containers
72 | docker compose -f docker-compose-chang.yml up -d
73 |
74 | export PAYMENT_KEY="$ROOT"/configs/local-chang/shelley/utxo-keys/utxo1.skey
75 | export EXTENDED_PAYMENT_KEY="$ROOT"/keys/extended.skey
76 | export POOL_COLD_KEY="$ROOT"/keys/pool/cold.skey
77 | export POOL_PAYMENT_KEY="$ROOT"/keys/pool/payment.skey
78 | export POOL_STAKE_KEY="$ROOT"/keys/pool/stake.skey
79 | export POOL_ID=$(cat "$ROOT"/keys/pool/pool.id)
80 |
81 | sleep 10
82 |
83 | while true; do
84 | response=$(curl -s -H 'Accept: application/json' http://localhost:1337/health)
85 | current_era=$(echo "$response" | jq -r '.currentEra')
86 |
87 | if [ "$current_era" == "conway" ]; then
88 | echo "Ogmios is ready! Current era: $current_era"
89 | break
90 | fi
91 |
92 | echo -n "."
93 | sleep 2
94 | done
95 |
96 | poetry run pytest -m "not (CardanoCLI)" -s -vv "$ROOT"/test --cov=pycardano --cov-config=../.coveragerc --cov-report=xml:../coverage.xml
97 |
98 | # Cleanup
99 | docker compose -f docker-compose-chang.yml down --volumes --remove-orphans
--------------------------------------------------------------------------------
/integration-test/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/integration-test/test/__init__.py
--------------------------------------------------------------------------------
/integration-test/test/base.py:
--------------------------------------------------------------------------------
1 | """An example that demonstrates low-level construction of a transaction."""
2 |
3 | import os
4 | import time
5 |
6 | import ogmios as python_ogmios
7 | from retry import retry
8 |
9 | from pycardano import *
10 |
11 | TEST_RETRIES = 8
12 |
13 |
14 | @retry(tries=10, delay=4)
15 | def check_chain_context(chain_context):
16 | print(f"Current chain tip: {chain_context.last_block_slot}")
17 |
18 |
19 | class TestBase:
20 | # Define chain context
21 | NETWORK = Network.TESTNET
22 |
23 | # TODO: Bring back kupo test
24 | KUPO_URL = "http://localhost:1442"
25 |
26 | chain_context = OgmiosV6ChainContext(
27 | host="localhost",
28 | port=1337,
29 | network=Network.TESTNET,
30 | refetch_chain_tip_interval=1,
31 | )
32 |
33 | check_chain_context(chain_context)
34 |
35 | payment_key_path = os.environ.get("PAYMENT_KEY")
36 | extended_key_path = os.environ.get("EXTENDED_PAYMENT_KEY")
37 | pool_cold_key_path = os.environ.get("POOL_COLD_KEY")
38 | pool_payment_key_path = os.environ.get("POOL_PAYMENT_KEY")
39 | pool_stake_key_path = os.environ.get("POOL_STAKE_KEY")
40 | if not payment_key_path or not extended_key_path:
41 | raise Exception(
42 | "Cannot find payment key. Please specify environment variable PAYMENT_KEY and extended_key_path"
43 | )
44 | payment_skey = PaymentSigningKey.load(payment_key_path)
45 | payment_vkey = PaymentVerificationKey.from_signing_key(payment_skey)
46 | extended_payment_skey = PaymentExtendedSigningKey.load(extended_key_path)
47 | extended_payment_vkey = PaymentExtendedVerificationKey.from_signing_key(
48 | extended_payment_skey
49 | )
50 | pool_cold_skey = PaymentSigningKey.load(pool_cold_key_path)
51 | pool_cold_vkey = PaymentVerificationKey.from_signing_key(pool_cold_skey)
52 | pool_payment_skey = PaymentSigningKey.load(pool_payment_key_path)
53 | pool_payment_vkey = PaymentVerificationKey.from_signing_key(pool_payment_skey)
54 | pool_stake_skey = StakeSigningKey.load(pool_stake_key_path)
55 | pool_stake_vkey = StakeVerificationKey.from_signing_key(pool_stake_skey)
56 |
57 | payment_key_pair = PaymentKeyPair.generate()
58 | stake_key_pair = StakeKeyPair.generate()
59 |
60 | @retry(tries=10, delay=3)
61 | def assert_output(self, target_address, target):
62 | utxos = self.chain_context.utxos(target_address)
63 | found = False
64 |
65 | for utxo in utxos:
66 | if isinstance(target, UTxO):
67 | if utxo == target:
68 | found = True
69 | if isinstance(target, TransactionOutput):
70 | if utxo.output == target:
71 | found = True
72 | if isinstance(target, TransactionId):
73 | if utxo.input.transaction_id == target:
74 | found = True
75 |
76 | assert found, f"Cannot find target UTxO in address: {target_address}"
77 |
78 | @retry(tries=TEST_RETRIES, delay=6, backoff=2, jitter=(1, 3))
79 | def fund(self, source_address, source_key, target_address, amount=5000000):
80 | builder = TransactionBuilder(self.chain_context)
81 |
82 | builder.add_input_address(source_address)
83 | output = TransactionOutput(target_address, amount)
84 | builder.add_output(output)
85 |
86 | signed_tx = builder.build_and_sign([source_key], source_address)
87 |
88 | print("############### Transaction created ###############")
89 | print(signed_tx)
90 | print(signed_tx.to_cbor_hex())
91 | print("############### Submitting transaction ###############")
92 | self.chain_context.submit_tx(signed_tx)
93 | target_utxo = UTxO(TransactionInput(signed_tx.id, 0), output)
94 | self.assert_output(target_address, target_utxo)
95 |
--------------------------------------------------------------------------------
/integration-test/test/test_cardano_cli.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pathlib import Path
3 |
4 | import pytest
5 | from retry import retry
6 |
7 | from pycardano import (
8 | CardanoCliChainContext,
9 | CardanoCliNetwork,
10 | GenesisParameters,
11 | Network,
12 | ProtocolParameters,
13 | )
14 | from pycardano.backend.cardano_cli import DockerConfig
15 |
16 | from .base import TEST_RETRIES
17 |
18 |
19 | @pytest.mark.CardanoCLI
20 | class TestCardanoCli:
21 | network_env = os.getenv("NETWORK", "local-alonzo")
22 | host_socket = os.getenv("DOCKER_HOST", None)
23 | network_magic = os.getenv("NETWORK_MAGIC", 42)
24 |
25 | configs_dir = Path(__file__).parent.parent / "configs"
26 |
27 | chain_context = CardanoCliChainContext(
28 | binary=Path("cardano-cli"),
29 | socket=Path("/ipc/node.socket"),
30 | config_file=configs_dir / network_env / "config.json",
31 | network=CardanoCliNetwork.CUSTOM,
32 | docker_config=DockerConfig(
33 | container_name="integration-test_cardano-node_1",
34 | host_socket=Path(host_socket) if host_socket else None,
35 | ),
36 | network_magic_number=int(network_magic),
37 | )
38 |
39 | @retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
40 | def test_protocol_param(self):
41 | protocol_param = self.chain_context.protocol_param
42 |
43 | assert protocol_param is not None
44 | assert isinstance(protocol_param, ProtocolParameters)
45 | assert protocol_param.coins_per_utxo_byte is not None
46 |
47 | cost_models = protocol_param.cost_models
48 | for cost_model in cost_models.items():
49 | assert len(cost_model) > 0
50 |
51 | def test_genesis_param(self):
52 | genesis_param = self.chain_context.genesis_param
53 |
54 | assert genesis_param is not None
55 | assert isinstance(genesis_param, GenesisParameters)
56 |
57 | def test_network(self):
58 | network = self.chain_context.network
59 |
60 | assert network is not None
61 | assert isinstance(network, Network)
62 |
63 | def test_epoch(self):
64 | epoch = self.chain_context.epoch
65 |
66 | assert epoch is not None
67 | assert isinstance(epoch, int)
68 | assert epoch > 0
69 |
70 | def test_last_block_slot(self):
71 | last_block_slot = self.chain_context.last_block_slot
72 |
73 | assert isinstance(last_block_slot, int)
74 | assert last_block_slot > 0
75 |
--------------------------------------------------------------------------------
/integration-test/test/test_certificate_script.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 |
4 | import cbor2
5 | from retry import retry
6 |
7 | from pycardano import *
8 |
9 | from .base import TEST_RETRIES, TestBase
10 |
11 |
12 | class TestDelegation(TestBase):
13 | @retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
14 | def test_stake_delegation(self):
15 | with open("./plutus_scripts/pass_certifying_and_rewarding.plutus", "r") as f:
16 | script_hex = f.read()
17 | stake_script = PlutusV2Script(bytes.fromhex(script_hex))
18 | cert_script_hash = plutus_script_hash(stake_script)
19 | address = Address(
20 | self.payment_key_pair.verification_key.hash(),
21 | cert_script_hash,
22 | self.NETWORK,
23 | )
24 |
25 | utxos = self.chain_context.utxos(address)
26 |
27 | if not utxos:
28 | giver_address = Address(self.payment_vkey.hash(), network=self.NETWORK)
29 |
30 | builder = TransactionBuilder(self.chain_context)
31 |
32 | builder.add_input_address(giver_address)
33 | builder.add_output(TransactionOutput(address, 44000000000))
34 |
35 | signed_tx = builder.build_and_sign([self.payment_skey], giver_address)
36 |
37 | print("############### Transaction created ###############")
38 | print(signed_tx)
39 | print(signed_tx.to_cbor_hex())
40 | print("############### Submitting transaction ###############")
41 | self.chain_context.submit_tx(signed_tx)
42 |
43 | time.sleep(3)
44 |
45 | stake_credential = StakeCredential(cert_script_hash)
46 | stake_registration = StakeRegistration(stake_credential)
47 | pool_hash = PoolKeyHash(bytes.fromhex(os.environ.get("POOL_ID").strip()))
48 | stake_delegation = StakeDelegation(stake_credential, pool_keyhash=pool_hash)
49 |
50 | builder = TransactionBuilder(self.chain_context)
51 |
52 | builder.add_input_address(address)
53 | builder.add_output(TransactionOutput(address, 35000000))
54 | builder.certificates = [stake_registration, stake_delegation]
55 | redeemer = Redeemer(0)
56 | builder.add_certificate_script(stake_script, redeemer=redeemer)
57 |
58 | signed_tx = builder.build_and_sign(
59 | [self.payment_key_pair.signing_key],
60 | address,
61 | )
62 |
63 | print("############### Transaction created ###############")
64 | print(signed_tx)
65 | print(signed_tx.to_cbor_hex())
66 | print("############### Submitting transaction ###############")
67 | self.chain_context.submit_tx(signed_tx)
68 |
69 |
70 | # time.sleep(8)
71 | #
72 | # builder = TransactionBuilder(self.chain_context)
73 | #
74 | # builder.add_input_address(address)
75 | #
76 | # stake_address = Address(
77 | # staking_part=cert_script_hash,
78 | # network=self.NETWORK,
79 | # )
80 | #
81 | # builder.withdrawals = Withdrawals({bytes(stake_address): 0})
82 | #
83 | # builder.add_output(TransactionOutput(address, 1000000))
84 | # redeemer = Redeemer(0)
85 | # builder.add_withdrawal_script(stake_script, redeemer=redeemer)
86 | #
87 | # signed_tx = builder.build_and_sign(
88 | # [self.payment_key_pair.signing_key],
89 | # address,
90 | # )
91 | #
92 | # print("############### Transaction created ###############")
93 | # print(signed_tx)
94 | # print(signed_tx.to_cbor_hex())
95 | # print("############### Submitting transaction ###############")
96 | # self.chain_context.submit_tx(signed_tx)
97 | #
98 |
--------------------------------------------------------------------------------
/integration-test/test/test_min_utxo.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | import tempfile
3 | from dataclasses import dataclass
4 |
5 | import cbor2
6 | import pytest
7 | from retry import retry
8 |
9 | from pycardano import *
10 |
11 | from .base import TEST_RETRIES, TestBase
12 |
13 |
14 | class TestMint(TestBase):
15 | @retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
16 | @pytest.mark.post_alonzo
17 | def test_min_utxo(self):
18 | address = Address(self.payment_vkey.hash(), network=self.NETWORK)
19 |
20 | with open("./plutus_scripts/always_succeeds.plutus", "r") as f:
21 | script_hex = f.read()
22 | anymint_script = PlutusV1Script(cbor2.loads(bytes.fromhex(script_hex)))
23 |
24 | policy_id = plutus_script_hash(anymint_script)
25 |
26 | my_nft = MultiAsset.from_primitive(
27 | {
28 | policy_id.payload: {
29 | b"MY_SCRIPT_NFT_1": 1, # Name of our NFT1 # Quantity of this NFT
30 | b"MY_SCRIPT_NFT_2": 1, # Name of our NFT2 # Quantity of this NFT
31 | }
32 | }
33 | )
34 |
35 | metadata = {
36 | 721: {
37 | policy_id.payload.hex(): {
38 | "MY_SCRIPT_NFT_1": {
39 | "description": "This is my first NFT thanks to PyCardano",
40 | "name": "PyCardano NFT example token 1",
41 | "id": 1,
42 | "image": "ipfs://QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw",
43 | },
44 | "MY_SCRIPT_NFT_2": {
45 | "description": "This is my second NFT thanks to PyCardano",
46 | "name": "PyCardano NFT example token 2",
47 | "id": 2,
48 | "image": "ipfs://QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw",
49 | },
50 | }
51 | }
52 | }
53 |
54 | # Place metadata in AuxiliaryData, the format acceptable by a transaction.
55 | auxiliary_data = AuxiliaryData(AlonzoMetadata(metadata=Metadata(metadata)))
56 |
57 | # Create a transaction builder
58 | builder = TransactionBuilder(self.chain_context)
59 |
60 | # Add our own address as the input address
61 | builder.add_input_address(address)
62 |
63 | @dataclass
64 | class MyPlutusData(PlutusData):
65 | a: int
66 |
67 | # Add minting script with an empty datum and a minting redeemer
68 | builder.add_minting_script(
69 | anymint_script, redeemer=Redeemer(MyPlutusData(a=42))
70 | )
71 |
72 | # Set nft we want to mint
73 | builder.mint = my_nft
74 |
75 | # Set transaction metadata
76 | builder.auxiliary_data = auxiliary_data
77 |
78 | # Calculate the minimum amount of lovelace that need to hold the NFT we are going to mint
79 | min_val = min_lovelace(
80 | output=TransactionOutput(address, Value(0, my_nft)),
81 | context=self.chain_context,
82 | )
83 |
84 | # Send the NFT to our own address
85 | nft_output = TransactionOutput(address, Value(min_val, my_nft))
86 | pure_ada_output = TransactionOutput(
87 | address,
88 | min_lovelace(
89 | context=self.chain_context, output=TransactionOutput(address, 0)
90 | ),
91 | )
92 | builder.add_output(nft_output)
93 | builder.add_output(pure_ada_output)
94 |
95 | # Build and sign transaction
96 | signed_tx = builder.build_and_sign([self.payment_skey], address)
97 | # signed_tx.transaction_witness_set.plutus_data
98 |
99 | print("############### Transaction created ###############")
100 | print(signed_tx)
101 | print(signed_tx.to_cbor_hex())
102 |
103 | # Submit signed transaction to the network
104 | print("############### Submitting transaction ###############")
105 | self.chain_context.submit_tx(signed_tx)
106 |
107 | self.assert_output(address, nft_output)
108 |
--------------------------------------------------------------------------------
/integration-test/test/test_ogmios.py:
--------------------------------------------------------------------------------
1 | from retry import retry
2 |
3 | from .base import TEST_RETRIES, TestBase
4 |
5 |
6 | class TestProtocolParam(TestBase):
7 | @retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
8 | def test_protocol_param_cost_models(self):
9 | protocol_param = self.chain_context.protocol_param
10 |
11 | cost_models = protocol_param.cost_models
12 | for _, cost_model in cost_models.items():
13 | assert len(cost_model) > 0
14 |
--------------------------------------------------------------------------------
/pycardano/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa
2 |
3 | from .address import *
4 | from .backend import *
5 | from .certificate import *
6 | from .cip import *
7 | from .coinselection import *
8 | from .crypto import *
9 | from .exception import *
10 | from .governance import *
11 | from .hash import *
12 | from .key import *
13 | from .metadata import *
14 | from .nativescript import *
15 | from .network import *
16 | from .plutus import *
17 | from .pool_params import *
18 | from .serialization import *
19 | from .transaction import *
20 | from .txbuilder import *
21 | from .utils import *
22 | from .witness import *
23 |
--------------------------------------------------------------------------------
/pycardano/backend/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa
2 |
3 | from .base import *
4 | from .blockfrost import *
5 | from .cardano_cli import *
6 | from .ogmios_v5 import *
7 | from .ogmios_v6 import *
8 |
--------------------------------------------------------------------------------
/pycardano/cip/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa
2 |
3 | from .cip8 import *
4 | from .cip14 import *
5 |
--------------------------------------------------------------------------------
/pycardano/cip/cip14.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 |
3 | from nacl.encoding import RawEncoder
4 | from nacl.hash import blake2b
5 |
6 | from pycardano.crypto.bech32 import encode
7 | from pycardano.hash import ScriptHash
8 | from pycardano.transaction import AssetName
9 |
10 |
11 | def encode_asset(
12 | policy_id: Union[ScriptHash, bytes, str], asset_name: Union[AssetName, bytes, str]
13 | ) -> str:
14 | """Implementation of CIP14 asset fingerprinting
15 |
16 | This function encodes the asset policy and name into an asset fingerprint, which is
17 | bech32 compliant.
18 |
19 | For more information:
20 | https://developers.cardano.org/docs/governance/cardano-improvement-proposals/cip-0014/
21 |
22 | Args:
23 | policy_id: The asset policy as `ScriptHash`, `bytes`, or a hex `str`
24 | asset_name: The asset name as `AssetName`, `bytes`, or a hex `str`
25 | """
26 | if isinstance(policy_id, str):
27 | policy_id = bytes.fromhex(policy_id)
28 | elif isinstance(policy_id, ScriptHash):
29 | policy_id = policy_id.payload
30 |
31 | if isinstance(asset_name, str):
32 | asset_name = bytes.fromhex(asset_name)
33 | elif isinstance(asset_name, AssetName):
34 | asset_name = asset_name.payload
35 |
36 | asset_hash = blake2b(
37 | policy_id + asset_name,
38 | digest_size=20,
39 | encoder=RawEncoder,
40 | )
41 |
42 | return encode("asset", asset_hash)
43 |
--------------------------------------------------------------------------------
/pycardano/crypto/__init__.py:
--------------------------------------------------------------------------------
1 | # flake8: noqa
2 |
3 | from .bip32 import *
4 |
--------------------------------------------------------------------------------
/pycardano/exception.py:
--------------------------------------------------------------------------------
1 | class PyCardanoException(Exception):
2 | pass
3 |
4 |
5 | class DecodingException(PyCardanoException):
6 | pass
7 |
8 |
9 | class InvalidKeyTypeException(PyCardanoException):
10 | pass
11 |
12 |
13 | class InvalidAddressInputException(PyCardanoException):
14 | pass
15 |
16 |
17 | class InvalidDataException(PyCardanoException):
18 | pass
19 |
20 |
21 | class InvalidArgumentException(PyCardanoException):
22 | pass
23 |
24 |
25 | class InvalidOperationException(PyCardanoException):
26 | pass
27 |
28 |
29 | class SerializeException(PyCardanoException):
30 | pass
31 |
32 |
33 | class DeserializeException(PyCardanoException):
34 | pass
35 |
36 |
37 | class InvalidTransactionException(PyCardanoException):
38 | pass
39 |
40 |
41 | class TransactionBuilderException(PyCardanoException):
42 | pass
43 |
44 |
45 | class TransactionFailedException(PyCardanoException):
46 | pass
47 |
48 |
49 | class UTxOSelectionException(PyCardanoException):
50 | pass
51 |
52 |
53 | class InsufficientUTxOBalanceException(UTxOSelectionException):
54 | pass
55 |
56 |
57 | class MaxInputCountExceededException(UTxOSelectionException):
58 | pass
59 |
60 |
61 | class InputUTxODepletedException(UTxOSelectionException):
62 | pass
63 |
64 |
65 | class CardanoCliError(PyCardanoException):
66 | pass
67 |
--------------------------------------------------------------------------------
/pycardano/logging.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from pprintpp import pformat
4 |
5 | __all__ = ["logger", "log_state"]
6 |
7 | # create logger
8 | logger = logging.getLogger("PyCardano")
9 |
10 | # create console handler and set level to debug
11 | ch = logging.StreamHandler()
12 |
13 | # create formatter
14 | formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
15 |
16 | # add formatter to ch
17 | ch.setFormatter(formatter)
18 |
19 | # add ch to logger
20 | logger.addHandler(ch)
21 |
22 |
23 | def log_state(func):
24 | """Decorator to log the state of an object after its function call."""
25 |
26 | def wrapper(obj, *args, **kwargs):
27 | try:
28 | output = func(obj, *args, **kwargs)
29 | logger.debug(
30 | f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}"
31 | )
32 | return output
33 | except Exception as e:
34 | logger.warning(
35 | f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}"
36 | )
37 | raise e
38 |
39 | return wrapper
40 |
--------------------------------------------------------------------------------
/pycardano/network.py:
--------------------------------------------------------------------------------
1 | """Cardano network types."""
2 |
3 | from __future__ import annotations
4 |
5 | from enum import Enum
6 | from typing import Type
7 |
8 | from pycardano.serialization import CBORSerializable, limit_primitive_type
9 |
10 | __all__ = ["Network"]
11 |
12 |
13 | class Network(CBORSerializable, Enum):
14 | """
15 | Network ID
16 | """
17 |
18 | TESTNET = 0
19 | MAINNET = 1
20 |
21 | def to_primitive(self) -> int:
22 | return self.value
23 |
24 | @classmethod
25 | @limit_primitive_type(int)
26 | def from_primitive(cls: Type[Network], value: int) -> Network:
27 | return cls(value)
28 |
--------------------------------------------------------------------------------
/pycardano/types.py:
--------------------------------------------------------------------------------
1 | import os
2 | from functools import partial
3 | from typing import Any, Dict
4 |
5 | import typeguard
6 |
7 | # https://github.com/python/typing/issues/182#issuecomment-199532520
8 | JsonDict = Dict[str, Any]
9 |
10 |
11 | def typechecked(func=None, *args, **kwargs):
12 | if os.getenv("PYCARDANO_NO_TYPE_CHECK", "False").lower() in ("true", "1"):
13 | if func is None:
14 | return partial(typechecked, *args, **kwargs)
15 | return func
16 | return typeguard.typechecked(func, *args, **kwargs)
17 |
18 |
19 | def check_type(*args, **kwargs):
20 | if os.getenv("PYCARDANO_NO_TYPE_CHECK", "False").lower() in ("true", "1"):
21 | return None
22 | return typeguard.check_type(*args, **kwargs)
23 |
--------------------------------------------------------------------------------
/pycardano/witness.py:
--------------------------------------------------------------------------------
1 | """Transaction witness."""
2 |
3 | from __future__ import annotations
4 |
5 | from dataclasses import dataclass, field
6 | from typing import Any, List, Optional, Type, Union
7 |
8 | from pycardano.key import ExtendedVerificationKey, VerificationKey
9 | from pycardano.nativescript import NativeScript
10 | from pycardano.plutus import (
11 | PlutusV1Script,
12 | PlutusV2Script,
13 | PlutusV3Script,
14 | RawPlutusData,
15 | Redeemers,
16 | )
17 | from pycardano.serialization import (
18 | ArrayCBORSerializable,
19 | MapCBORSerializable,
20 | NonEmptyOrderedSet,
21 | limit_primitive_type,
22 | list_hook,
23 | )
24 |
25 | __all__ = ["VerificationKeyWitness", "TransactionWitnessSet"]
26 |
27 |
28 | @dataclass(repr=False)
29 | class VerificationKeyWitness(ArrayCBORSerializable):
30 | vkey: Union[VerificationKey, ExtendedVerificationKey]
31 | signature: bytes
32 |
33 | def __post_init__(self):
34 | # When vkey is in extended format, we need to convert it to non-extended, so it can match the
35 | # key hash of the input address we are trying to spend.
36 | if isinstance(self.vkey, ExtendedVerificationKey):
37 | self.vkey = self.vkey.to_non_extended()
38 |
39 | @classmethod
40 | @limit_primitive_type(list, tuple)
41 | def from_primitive(
42 | cls: Type[VerificationKeyWitness], values: Union[list, tuple]
43 | ) -> VerificationKeyWitness:
44 | return cls(
45 | vkey=VerificationKey.from_primitive(values[0]),
46 | signature=values[1],
47 | )
48 |
49 |
50 | @dataclass(repr=False)
51 | class TransactionWitnessSet(MapCBORSerializable):
52 | vkey_witnesses: Optional[
53 | Union[List[VerificationKeyWitness], NonEmptyOrderedSet[VerificationKeyWitness]]
54 | ] = field(
55 | default=None,
56 | metadata={
57 | "key": 0,
58 | "optional": True,
59 | },
60 | )
61 |
62 | native_scripts: Optional[
63 | Union[List[NativeScript], NonEmptyOrderedSet[NativeScript]]
64 | ] = field(
65 | default=None,
66 | metadata={
67 | "key": 1,
68 | "optional": True,
69 | },
70 | )
71 |
72 | # TODO: Add bootstrap witness (byron) support
73 | bootstrap_witness: Optional[List[Any]] = field(
74 | default=None, metadata={"optional": True, "key": 2}
75 | )
76 |
77 | plutus_v1_script: Optional[
78 | Union[List[PlutusV1Script], NonEmptyOrderedSet[PlutusV1Script]]
79 | ] = field(
80 | default=None,
81 | metadata={
82 | "key": 3,
83 | "optional": True,
84 | },
85 | )
86 |
87 | plutus_data: Optional[List[Any]] = field(
88 | default=None,
89 | metadata={"optional": True, "key": 4, "object_hook": list_hook(RawPlutusData)},
90 | )
91 |
92 | redeemer: Optional[Redeemers] = field(
93 | default=None,
94 | metadata={"optional": True, "key": 5},
95 | )
96 |
97 | plutus_v2_script: Optional[
98 | Union[List[PlutusV2Script], NonEmptyOrderedSet[PlutusV2Script]]
99 | ] = field(
100 | default=None,
101 | metadata={
102 | "key": 6,
103 | "optional": True,
104 | },
105 | )
106 |
107 | plutus_v3_script: Optional[
108 | Union[List[PlutusV3Script], NonEmptyOrderedSet[PlutusV3Script]]
109 | ] = field(
110 | default=None,
111 | metadata={
112 | "key": 7,
113 | "optional": True,
114 | },
115 | )
116 |
117 | def __post_init__(self):
118 | # Convert lists to NonEmptyOrderedSet for fields that should use NonEmptyOrderedSet
119 | if isinstance(self.vkey_witnesses, list):
120 | self.vkey_witnesses = NonEmptyOrderedSet(self.vkey_witnesses)
121 | if isinstance(self.native_scripts, list):
122 | self.native_scripts = NonEmptyOrderedSet(self.native_scripts)
123 | if isinstance(self.plutus_v1_script, list):
124 | self.plutus_v1_script = NonEmptyOrderedSet(self.plutus_v1_script)
125 | if isinstance(self.plutus_v2_script, list):
126 | self.plutus_v2_script = NonEmptyOrderedSet(self.plutus_v2_script)
127 | if isinstance(self.plutus_v3_script, list):
128 | self.plutus_v3_script = NonEmptyOrderedSet(self.plutus_v3_script)
129 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "pycardano"
3 | version = "0.14.0"
4 | classifiers = [
5 | "Intended Audience :: Developers",
6 | "License :: OSI Approved :: MIT License",
7 | "Natural Language :: English",
8 | "Programming Language :: Python :: 3",
9 | "Programming Language :: Python :: 3.9",
10 | "Programming Language :: Python :: 3.10",
11 | "Programming Language :: Python :: 3.11",
12 | "Programming Language :: Python :: 3.12",
13 | "Programming Language :: Python :: 3.13",
14 | ]
15 | description = "A Cardano library in Python"
16 | homepage = "https://github.com/Python-Cardano/pycardano"
17 | documentation = "https://pycardano.readthedocs.io/en/latest/"
18 | keywords = ["python", "cardano", "blockchain", "crypto"]
19 | authors = ["Jerry "]
20 | readme = "README.md"
21 | repository = "https://github.com/Python-Cardano/pycardano"
22 | license = "MIT"
23 |
24 | [tool.poetry.dependencies]
25 | python = "^3.9.1"
26 | PyNaCl = "^1.5.0"
27 | cbor2 = "^5.6.5"
28 | typeguard = "^4.3.0"
29 | blockfrost-python = "0.6.0"
30 | websocket-client = "^1.4.1"
31 | cose = "0.9.dev8"
32 | pprintpp = "^0.4.0"
33 | mnemonic = "^0.21"
34 | ECPy = "^1.2.5"
35 | frozendict = "^2.3.8"
36 | frozenlist = "^1.3.3"
37 | cachetools = "^5.3.0"
38 | docker = "^7.1.0"
39 | ogmios = "^1.4.2"
40 | requests = "^2.32.3"
41 | websockets = "^13.0"
42 |
43 | [tool.poetry.group.dev.dependencies]
44 | Sphinx = "^5.0.0"
45 | sphinx-rtd-theme = "^2.0.0"
46 | pytest = "^8.2.0"
47 | pytest-cov = "^5.0.0"
48 | flake8 = "^7.0.0"
49 | isort = "^5.11.4"
50 | black = "^24.4.2"
51 | sphinx-copybutton = "^0.5.0"
52 | retry = "^0.9.2"
53 | Flask = "^2.0.3"
54 | pytest-xdist = "^3.5.0"
55 | mypy = "1.14.1"
56 |
57 | [build-system]
58 | requires = ["poetry-core>=1.0.0"]
59 | build-backend = "poetry.core.masonry.api"
60 |
61 |
62 | [tool.pytest.ini_options]
63 | addopts = "--doctest-modules --ignore=examples --ignore=integration-test --ignore=test/resources/haskell"
64 | minversion = "6.0"
65 | markers = [
66 | "post_alonzo",
67 | "single",
68 | "CardanoCLI",
69 | "post_chang"
70 | ]
71 |
72 |
73 | [tool.isort]
74 | profile = "black"
75 |
76 | [tool.mypy]
77 | ignore_missing_imports = true
78 | disable_error_code = ["str-bytes-safe"]
79 | python_version = 3.9
80 | exclude = [
81 | '^pycardano/crypto/bech32.py$',
82 | ]
83 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/test/__init__.py
--------------------------------------------------------------------------------
/test/conftest.py:
--------------------------------------------------------------------------------
1 | from fractions import Fraction
2 | from test.pycardano.util import FixedChainContext
3 |
4 | import pytest
5 |
6 | from pycardano import (
7 | POOL_KEY_HASH_SIZE,
8 | POOL_METADATA_HASH_SIZE,
9 | REWARD_ACCOUNT_HASH_SIZE,
10 | VERIFICATION_KEY_HASH_SIZE,
11 | VRF_KEY_HASH_SIZE,
12 | PoolKeyHash,
13 | PoolMetadataHash,
14 | RewardAccountHash,
15 | VerificationKeyHash,
16 | VrfKeyHash,
17 | )
18 | from pycardano.pool_params import (
19 | MultiHostName,
20 | PoolMetadata,
21 | PoolParams,
22 | SingleHostAddr,
23 | SingleHostName,
24 | )
25 |
26 |
27 | @pytest.fixture
28 | def chain_context():
29 | return FixedChainContext()
30 |
31 |
32 | @pytest.fixture
33 | def pool_params():
34 | return PoolParams(
35 | operator=PoolKeyHash(b"1" * POOL_KEY_HASH_SIZE),
36 | vrf_keyhash=VrfKeyHash(b"1" * VRF_KEY_HASH_SIZE),
37 | pledge=100_000_000,
38 | cost=340_000_000,
39 | margin=Fraction(1, 50),
40 | reward_account=RewardAccountHash(b"1" * REWARD_ACCOUNT_HASH_SIZE),
41 | pool_owners=[VerificationKeyHash(b"1" * VERIFICATION_KEY_HASH_SIZE)],
42 | relays=[
43 | SingleHostAddr(port=3001, ipv4="192.168.0.1", ipv6="::1"),
44 | SingleHostName(port=3001, dns_name="relay1.example.com"),
45 | MultiHostName(dns_name="relay1.example.com"),
46 | ],
47 | pool_metadata=PoolMetadata(
48 | url="https://meta1.example.com",
49 | pool_metadata_hash=PoolMetadataHash(b"1" * POOL_METADATA_HASH_SIZE),
50 | ),
51 | )
52 |
--------------------------------------------------------------------------------
/test/pycardano/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/test/pycardano/__init__.py
--------------------------------------------------------------------------------
/test/pycardano/backend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/test/pycardano/backend/__init__.py
--------------------------------------------------------------------------------
/test/pycardano/backend/test_blockfrost.py:
--------------------------------------------------------------------------------
1 | from unittest.mock import MagicMock, patch
2 |
3 | from blockfrost import ApiUrls
4 |
5 | from pycardano.backend.blockfrost import BlockFrostChainContext
6 | from pycardano.network import Network
7 |
8 |
9 | @patch("pycardano.backend.blockfrost.BlockFrostApi")
10 | def test_blockfrost_chain_context(mock_api):
11 | mock_api.return_value = MagicMock()
12 | chain_context = BlockFrostChainContext("project_id", base_url=ApiUrls.mainnet.value)
13 | assert chain_context.network == Network.MAINNET
14 |
15 | chain_context = BlockFrostChainContext("project_id", base_url=ApiUrls.testnet.value)
16 | assert chain_context.network == Network.TESTNET
17 |
18 | chain_context = BlockFrostChainContext("project_id", base_url=ApiUrls.preprod.value)
19 | assert chain_context.network == Network.TESTNET
20 |
21 | chain_context = BlockFrostChainContext("project_id", base_url=ApiUrls.preview.value)
22 | assert chain_context.network == Network.TESTNET
23 |
--------------------------------------------------------------------------------
/test/pycardano/crypto/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Python-Cardano/pycardano/7d63d0e1da1b0e64cd2b9d389ed4f9e2e5c076ae/test/pycardano/crypto/__init__.py
--------------------------------------------------------------------------------
/test/pycardano/test_cip14.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from pycardano.cip.cip14 import encode_asset
4 | from pycardano.hash import ScriptHash
5 | from pycardano.transaction import AssetName
6 |
7 |
8 | @pytest.mark.parametrize(
9 | "input_types", [(str, str), (bytes, bytes), (ScriptHash, AssetName)]
10 | )
11 | @pytest.mark.parametrize(
12 | "asset",
13 | [
14 | {
15 | "policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
16 | "asset_name": "",
17 | "asset_fingerprint": "asset1rjklcrnsdzqp65wjgrg55sy9723kw09mlgvlc3",
18 | },
19 | {
20 | "policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc37e",
21 | "asset_name": "",
22 | "asset_fingerprint": "asset1nl0puwxmhas8fawxp8nx4e2q3wekg969n2auw3",
23 | },
24 | {
25 | "policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
26 | "asset_name": "",
27 | "asset_fingerprint": "asset1uyuxku60yqe57nusqzjx38aan3f2wq6s93f6ea",
28 | },
29 | {
30 | "policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
31 | "asset_name": "504154415445",
32 | "asset_fingerprint": "asset13n25uv0yaf5kus35fm2k86cqy60z58d9xmde92",
33 | },
34 | {
35 | "policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
36 | "asset_name": "504154415445",
37 | "asset_fingerprint": "asset1hv4p5tv2a837mzqrst04d0dcptdjmluqvdx9k3",
38 | },
39 | {
40 | "policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
41 | "asset_name": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
42 | "asset_fingerprint": "asset1aqrdypg669jgazruv5ah07nuyqe0wxjhe2el6f",
43 | },
44 | {
45 | "policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
46 | "asset_name": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
47 | "asset_fingerprint": "asset17jd78wukhtrnmjh3fngzasxm8rck0l2r4hhyyt",
48 | },
49 | {
50 | "policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
51 | "asset_name": "0000000000000000000000000000000000000000000000000000000000000000",
52 | "asset_fingerprint": "asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w",
53 | },
54 | ],
55 | )
56 | def test_encode_asset(asset, input_types):
57 | if isinstance(input_types[0], bytes):
58 | policy_id = bytes.fromhex(asset["policy_id"])
59 | asset_name = bytes.fromhex(asset["asset_name"])
60 | elif isinstance(input_types[0], str):
61 | policy_id = asset["policy_id"]
62 | asset_name = asset["asset_name"]
63 |
64 | if isinstance(input_types[0], ScriptHash):
65 | policy_id = ScriptHash(policy_id)
66 | asset_name = AssetName(asset_name)
67 |
68 | fingerprint = encode_asset(
69 | policy_id=asset["policy_id"], asset_name=asset["asset_name"]
70 | )
71 |
72 | assert fingerprint == asset["asset_fingerprint"]
73 |
--------------------------------------------------------------------------------
/test/pycardano/test_network.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from pycardano.exception import DeserializeException
4 | from pycardano.network import Network
5 |
6 |
7 | def test_from_primitive_invalid_primitive_input():
8 | value = "a string value"
9 | with pytest.raises(DeserializeException):
10 | Network.from_primitive(value)
11 |
12 |
13 | def test_from_primitive_testnet():
14 | testnet_value = 0
15 | network = Network.from_primitive(testnet_value)
16 | assert network.value == testnet_value
17 |
18 |
19 | def test_from_primitive_mainnet():
20 | mainnet_value = 1
21 | network = Network.from_primitive(mainnet_value)
22 | assert network.value == mainnet_value
23 |
24 |
25 | def test_to_primitive_testnet():
26 | network = Network(0)
27 | assert network.to_primitive() == 0
28 |
29 |
30 | def test_to_primitive_mainnet():
31 | network = Network(1)
32 | assert network.to_primitive() == 1
33 |
--------------------------------------------------------------------------------
/test/pycardano/test_types.py:
--------------------------------------------------------------------------------
1 | import typeguard
2 |
3 | from pycardano.types import check_type, typechecked
4 |
5 |
6 | def test_types(monkeypatch):
7 | monkeypatch.setenv("PYCARDANO_NO_TYPE_CHECK", "true")
8 |
9 | assert typeguard.typechecked != typechecked
10 | assert typeguard.check_type != check_type
11 |
12 | @typechecked
13 | def func1():
14 | pass
15 |
16 | @typechecked()
17 | def func2():
18 | pass
19 |
20 | check_type()
21 |
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/.gitignore:
--------------------------------------------------------------------------------
1 | dist-newstyle/
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/README.md:
--------------------------------------------------------------------------------
1 | ## Plutus data CBOR generator
2 |
3 | This is a utility package that generates CBOR hex for any Plutus
4 | data, including datum and redeemer. We use this it to generate some ground truth values
5 | for some plutus tests.
6 |
7 | ### How to use
8 |
9 | 1. Install [nix](https://nixos.org/download.html)
10 | 2. Clone [plutus-apps](https://github.com/input-output-hk/plutus-apps).
11 | 3. Inside `plutus-apps`, start a nix shell with command `nix-shell`.
12 | 4. Change directory to the parent folder of this README file.
13 | 5. Modify file `src/PlutusData.hs` to create data structures you are interested in.
14 | 6. Run `cabal run PlutusData`, and the cbor of your target data structure will be written to `plutus-data.cbor`.
15 |
16 |
17 | Some part of the source code is copied from [Deploy.hs](https://github.com/input-output-hk/plutus-pioneer-program/blob/79b0816b6f84f171c8f01073e5445033869c41b7/code/week03/src/Week03/Deploy.hs)
18 | in plutus-pioneer-program.
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/hie.yaml:
--------------------------------------------------------------------------------
1 | cradle:
2 | cabal:
3 | - path: "./src"
4 | component: "lib:plutus-data"
5 |
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/plutus-data.cabal:
--------------------------------------------------------------------------------
1 | Cabal-Version: 2.4
2 | Name: PlutusData-cbor-generator
3 | Version: 0.1.0.0
4 | Build-Type: Simple
5 | License: Apache-2.0
6 | License-files: LICENSE
7 |
8 | executable PlutusData
9 | hs-source-dirs: src
10 | main-is: PlutusData.hs
11 |
12 | build-depends: aeson
13 | , base ^>=4.14.1.0
14 | , bytestring
15 | , cardano-api
16 | , containers
17 | , data-default
18 | , playground-common
19 | , plutus-contract
20 | , plutus-ledger
21 | , plutus-ledger-api
22 | , plutus-ledger-constraints
23 | , plutus-tx-plugin
24 | , plutus-tx
25 | , serialise
26 | , text
27 | default-language: Haskell2010
28 | ghc-options: -Wall -fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas -fno-strictness -fno-spec-constr -fno-specialise
29 |
30 |
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/plutus-data.cbor:
--------------------------------------------------------------------------------
1 | "d87a9f581cc2ff616e11299d9094ce0a7eb5b7284b705147a822f4ffbd471f971a1b0000017e9874d2a0d905019fd8668218829f187b44313233349f040506ffa2014131024132ffffd9050280ff"
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/plutus-data.json:
--------------------------------------------------------------------------------
1 | {"constructor":1,"fields":[{"bytes":"c2ff616e11299d9094ce0a7eb5b7284b705147a822f4ffbd471f971a"},{"int":1643235300000},{"constructor":8,"fields":[{"constructor":130,"fields":[{"int":123},{"bytes":"31323334"},{"list":[{"int":4},{"int":5},{"int":6}]},{"map":[{"v":{"bytes":"31"},"k":{"int":1}},{"v":{"bytes":"32"},"k":{"int":2}}]}]}]},{"constructor":9,"fields":[]}]}
--------------------------------------------------------------------------------
/test/resources/haskell/PlutusData/src/PlutusData.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DataKinds #-}
2 | {-# LANGUAGE MultiParamTypeClasses #-}
3 | {-# LANGUAGE OverloadedStrings #-}
4 | {-# LANGUAGE ScopedTypeVariables #-}
5 | {-# LANGUAGE TemplateHaskell #-}
6 |
7 |
8 | module Main where
9 |
10 | import Cardano.Api
11 | import Data.Aeson (encode)
12 | import qualified Data.ByteString.Lazy as LBS
13 | import qualified Data.ByteString.Lazy.Char8 as C
14 | import PlutusTx (Data (..))
15 | import qualified PlutusTx
16 | import qualified PlutusTx.AssocMap as AssocMap
17 | import PlutusTx.Prelude ( BuiltinByteString, )
18 | import Ledger ( PaymentPubKeyHash(PaymentPubKeyHash), POSIXTime )
19 |
20 | writeCBORToPath :: PlutusTx.ToData a => FilePath -> a -> IO ()
21 | writeCBORToPath file = LBS.writeFile file . encode . PlutusTx.toData
22 |
23 | printCBOR :: PlutusTx.ToData a => a -> IO ()
24 | printCBOR = putStrLn . C.unpack . encode . PlutusTx.toData
25 |
26 | dataToScriptData :: Data -> ScriptData
27 | dataToScriptData (Constr n xs) = ScriptDataConstructor n $ dataToScriptData <$> xs
28 | dataToScriptData (Map xs) = ScriptDataMap [(dataToScriptData x, dataToScriptData y) | (x, y) <- xs]
29 | dataToScriptData (List xs) = ScriptDataList $ dataToScriptData <$> xs
30 | dataToScriptData (I n) = ScriptDataNumber n
31 | dataToScriptData (B bs) = ScriptDataBytes bs
32 |
33 | toJSONByteString :: PlutusTx.ToData a => a -> LBS.ByteString
34 | toJSONByteString = encode . scriptDataToJson ScriptDataJsonDetailedSchema . dataToScriptData . PlutusTx.toData
35 |
36 | printJSON :: PlutusTx.ToData a => a -> IO ()
37 | printJSON = putStrLn . C.unpack . toJSONByteString
38 |
39 | writeJSON :: PlutusTx.ToData a => FilePath -> a -> IO ()
40 | writeJSON file = LBS.writeFile file . toJSONByteString
41 |
42 |
43 | data Test = Test
44 | {
45 | a :: !Integer,
46 | b :: !BuiltinByteString,
47 | c :: !([Integer]),
48 | d :: !(AssocMap.Map Integer BuiltinByteString)
49 | }
50 | deriving (Show)
51 |
52 | PlutusTx.makeLift ''Test
53 | PlutusTx.makeIsDataIndexed ''Test [('Test, 130)]
54 |
55 |
56 | data BigTest = BigTest Test | LargestTest deriving (Show)
57 |
58 | PlutusTx.makeLift ''BigTest
59 | PlutusTx.makeIsDataIndexed ''BigTest [('BigTest, 8), ('LargestTest, 9)]
60 |
61 | data VestingParam = VestingParam
62 | { beneficiary :: PaymentPubKeyHash
63 | , deadline :: POSIXTime
64 | , testa :: BigTest
65 | , testb :: BigTest
66 | } deriving (Show)
67 |
68 | PlutusTx.makeLift ''VestingParam
69 |
70 | PlutusTx.makeIsDataIndexed ''VestingParam [('VestingParam, 1)]
71 |
72 |
73 | test :: Test
74 | test = Test
75 | { a = 123
76 | , b = "1234"
77 | , c = [4, 5, 6]
78 | , d = AssocMap.fromList [(1, "1"), (2, "2")]
79 | }
80 |
81 | param :: VestingParam
82 | param = VestingParam
83 | { beneficiary = Ledger.PaymentPubKeyHash "c2ff616e11299d9094ce0a7eb5b7284b705147a822f4ffbd471f971a"
84 | , deadline = 1643235300000
85 | , testa = BigTest test
86 | , testb = LargestTest
87 | }
88 |
89 | main :: IO ()
90 | main = do
91 | putStrLn "Plutus data cbor:"
92 | printCBOR param
93 | writeCBORToPath "plutus-data.cbor" param
94 |
95 | putStrLn "Plutus data json:"
96 | printJSON param
97 | writeJSON "plutus-data.json" param
98 |
--------------------------------------------------------------------------------
/test/resources/keys/cold.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakePoolSigningKey_ed25519",
3 | "description": "StakePoolSigningKey_ed25519",
4 | "cborHex": "582044181bd0e6be21cea5b0751b8c6d4f88a5cb2d5dfec31a271add617f7ce559a9"
5 | }
6 |
--------------------------------------------------------------------------------
/test/resources/keys/cold.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakePoolVerificationKey_ed25519",
3 | "description": "StakePoolVerificationKey_ed25519",
4 | "cborHex": "5820354ce32da92e7116f6c70e9be99a3a601d33137d0685ab5b7e2ff5b656989299"
5 | }
6 |
--------------------------------------------------------------------------------
/test/resources/keys/payment.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "PaymentSigningKeyShelley_ed25519",
3 | "description": "Payment Signing Key",
4 | "cborHex": "58204d9fc18b873d0cd70b614462418ac719d9ca12d0bfcdf7edac2a44fb385d26d8"
5 | }
--------------------------------------------------------------------------------
/test/resources/keys/payment.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "PaymentVerificationKeyShelley_ed25519",
3 | "description": "Payment Verification Key",
4 | "cborHex": "58205797dc2cc919dfec0bb849551ebdf30d96e5cbe0f33f734a87fe826db30f7ef9"
5 | }
--------------------------------------------------------------------------------
/test/resources/keys/staking.skey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakeSigningKeyShelley_ed25519",
3 | "description": "Stake Signing Key",
4 | "cborHex": "5820ff3a330df8859e4e5f42a97fcaee73f6a00d0cf864f4bca902bd106d423f02c0"
5 | }
--------------------------------------------------------------------------------
/test/resources/keys/staking.vkey:
--------------------------------------------------------------------------------
1 | {
2 | "type": "StakeVerificationKeyShelley_ed25519",
3 | "description": "Stake Verification Key",
4 | "cborHex": "58205edaa384c658c2bd8945ae389edac0a5bd452d0cfd5d1245e3ecd540030d1e3c"
5 | }
--------------------------------------------------------------------------------