├── docs
├── .nojekyll
├── source
│ ├── logo
│ │ ├── logo.png
│ │ ├── readme
│ │ │ └── defichainpython-logo-big.png
│ │ ├── twitter
│ │ │ ├── defichainpython-logo-big.png
│ │ │ └── defichainpython-logo-small.png
│ │ └── svg
│ │ │ └── defichainpython-logo-small.svg
│ ├── api
│ │ ├── node
│ │ │ ├── loan.rst
│ │ │ ├── evm.rst
│ │ │ ├── node.rst
│ │ │ ├── spv.rst
│ │ │ ├── util.rst
│ │ │ ├── zmq.rst
│ │ │ ├── stats.rst
│ │ │ ├── vault.rst
│ │ │ ├── mining.rst
│ │ │ ├── tokens.rst
│ │ │ ├── wallet.rst
│ │ │ ├── control.rst
│ │ │ ├── network.rst
│ │ │ ├── oracles.rst
│ │ │ ├── accounts.rst
│ │ │ ├── poolpair.rst
│ │ │ ├── proposals.rst
│ │ │ ├── blockchain.rst
│ │ │ ├── generating.rst
│ │ │ ├── masternodes.rst
│ │ │ ├── rawtransactions.rst
│ │ │ └── rawMethodsOverview.rst
│ │ ├── ocean
│ │ │ ├── ocean.rst
│ │ │ ├── fee.rst
│ │ │ ├── rpc.rst
│ │ │ ├── loan.rst
│ │ │ ├── rawTx.rst
│ │ │ ├── stats.rst
│ │ │ ├── address.rst
│ │ │ ├── blocks.rst
│ │ │ ├── prices.rst
│ │ │ ├── tokens.rst
│ │ │ ├── oracles.rst
│ │ │ ├── poolpair.rst
│ │ │ ├── consortium.rst
│ │ │ ├── governance.rst
│ │ │ ├── masternodes.rst
│ │ │ └── transactions.rst
│ │ └── exceptions.rst
│ ├── guides
│ │ ├── example
│ │ │ ├── chainedTransactions.rst
│ │ │ ├── extractPrivateKeys.rst
│ │ │ └── index.rst
│ │ ├── guides
│ │ │ └── index.rst
│ │ └── index.rst
│ ├── sdk
│ │ ├── hdwallet
│ │ │ ├── utils.rst
│ │ │ ├── wallet.rst
│ │ │ ├── account.rst
│ │ │ └── exceptions.rst
│ │ └── transactions
│ │ │ ├── builder
│ │ │ ├── pool.rst
│ │ │ ├── utxo.rst
│ │ │ ├── data.rst
│ │ │ ├── loans.rst
│ │ │ ├── vault.rst
│ │ │ ├── txbuilder.rst
│ │ │ ├── accounts.rst
│ │ │ ├── governance.rst
│ │ │ └── masternode.rst
│ │ │ ├── advanced
│ │ │ ├── remotedata
│ │ │ │ ├── index.rst
│ │ │ │ ├── node.rst
│ │ │ │ └── ocean.rst
│ │ │ ├── address
│ │ │ │ ├── p2sh.rst
│ │ │ │ ├── p2pkh.rst
│ │ │ │ ├── p2wpkh.rst
│ │ │ │ └── index.rst
│ │ │ ├── defitx
│ │ │ │ ├── index.rst
│ │ │ │ ├── loans.rst
│ │ │ │ ├── governance.rst
│ │ │ │ ├── masternode.rst
│ │ │ │ ├── pool.rst
│ │ │ │ ├── accounts.rst
│ │ │ │ └── vault.rst
│ │ │ ├── rawtransactions
│ │ │ │ ├── fee.rst
│ │ │ │ ├── index.rst
│ │ │ │ ├── tx.rst
│ │ │ │ ├── witness.rst
│ │ │ │ ├── sign.rst
│ │ │ │ ├── txoutput.rst
│ │ │ │ └── txinput.rst
│ │ │ ├── index.rst
│ │ │ ├── keys.rst
│ │ │ └── utils.rst
│ │ │ ├── exceptions.rst
│ │ │ └── index.rst
│ ├── utils
│ │ ├── logger.rst
│ │ └── mnemonic.rst
│ ├── index.rst
│ ├── main
│ │ ├── statusAndTasks.rst
│ │ └── quickstart.rst
│ └── legal
│ │ └── licenseAndDisclaimer.rst
├── index.html
├── additionalInfos
│ ├── pictures
│ │ ├── CFP_02
│ │ │ ├── docs_getblock_ide.png
│ │ │ ├── docs_getblock_web.png
│ │ │ ├── github_traffic_views.png
│ │ │ └── github_traffic_clones.png
│ │ └── announcement03
│ │ │ └── lightwallet.jpg
│ ├── formatRawMethodsOverview.py
│ └── reddit
│ │ ├── announcement02.md
│ │ └── announcement01.md
├── requirements_docs.txt
├── Makefile
├── make.bat
└── README.md
├── tests
├── __init__.py
├── node
│ ├── test_spv.py
│ ├── test_zmq.py
│ ├── test_stats.py
│ ├── __init__.py
│ ├── test_generating.py
│ ├── test_control.py
│ ├── test_node.py
│ ├── test_evm.py
│ └── test_exceptions.py
├── hdwallet
│ ├── __init__.py
│ └── test_utils.py
├── transactions
│ ├── __init__.py
│ ├── remotedata
│ │ ├── test_node.py
│ │ ├── __init__.py
│ │ └── test_ocean.py
│ ├── rawtransactions
│ │ ├── test_sign.py
│ │ ├── test_fee.py
│ │ ├── test_tx.py
│ │ └── test_txinput.py
│ ├── builder
│ │ ├── test_replaceable.py
│ │ ├── test_loans.py
│ │ ├── test_data.py
│ │ ├── test_governance.py
│ │ ├── test_accounts.py
│ │ ├── test_vault.py
│ │ ├── test_masternode.py
│ │ ├── test_txbuilder.py
│ │ ├── test_pool.py
│ │ └── test_utxo.py
│ ├── utils
│ │ ├── test_verify.py
│ │ ├── test_calculate.py
│ │ ├── test_converter.py
│ │ └── test_token.py
│ ├── defitx
│ │ ├── test_governance.py
│ │ ├── test_vaults.py
│ │ ├── test_pool.py
│ │ └── test_loans.py
│ └── address
│ │ └── test_address.py
├── requirements_tests.txt
├── ocean
│ ├── __init__.py
│ ├── test_rpc.py
│ ├── test_fee.py
│ ├── test_ocean.py
│ ├── test_tokens.py
│ ├── test_stats.py
│ ├── test_masternodes.py
│ ├── test_consortium.py
│ ├── test_transactions.py
│ ├── test_blocks.py
│ ├── test_oracles.py
│ ├── test_governance.py
│ ├── test_rawTx.py
│ ├── test_prices.py
│ ├── test_address.py
│ ├── test_poolpairs.py
│ └── test_loan.py
├── pytest.ini
├── secrets_conf.example.py
├── util.py
└── README.md
├── defichain
├── libs
│ ├── __init__.py
│ └── base58.py
├── exceptions
│ ├── __init__.py
│ ├── transactions
│ │ ├── tokenerror.py
│ │ ├── defitxerror.py
│ │ ├── inputerror.py
│ │ ├── keyerror.py
│ │ ├── verifyerror.py
│ │ ├── txbuildererror.py
│ │ ├── addresserror.py
│ │ ├── deserializeerror.py
│ │ ├── notsupported.py
│ │ ├── rawtransactionerror.py
│ │ └── __init__.py
│ ├── hdwallet
│ │ ├── WalletError.py
│ │ ├── __init__.py
│ │ ├── NetworkError.py
│ │ └── DerivationError.py
│ └── http
│ │ ├── BadMethod.py
│ │ ├── WrongParmeters.py
│ │ ├── ServiceUnavailable.py
│ │ ├── NotFound.py
│ │ ├── BadRequest.py
│ │ ├── Forbidden.py
│ │ ├── UnprocessableEntity.py
│ │ ├── Unauthorized.py
│ │ ├── InternalServerError.py
│ │ ├── __init__.py
│ │ └── HTTPStatusCode.py
├── node
│ ├── modules
│ │ ├── __init__.py
│ │ ├── spv.py
│ │ ├── generating.py
│ │ └── zmq.py
│ └── __init__.py
├── ocean
│ ├── modules
│ │ ├── __init__.py
│ │ ├── fee.py
│ │ ├── rpc.py
│ │ ├── masternodes.py
│ │ ├── tokens.py
│ │ ├── rawTx.py
│ │ ├── consortium.py
│ │ ├── transactions.py
│ │ ├── stats.py
│ │ ├── blocks.py
│ │ └── oracles.py
│ ├── __init__.py
│ └── connection.py
├── mnemonic
│ ├── wordlist
│ │ └── __init__.py
│ └── __init__.py
├── transactions
│ ├── __init__.py
│ ├── defitx
│ │ ├── modules
│ │ │ ├── __init__.py
│ │ │ └── basedefitx.py
│ │ ├── __init__.py
│ │ └── builddefitx.py
│ ├── builder
│ │ ├── __init__.py
│ │ └── modules
│ │ │ ├── __init__.py
│ │ │ └── governance.py
│ ├── remotedata
│ │ ├── __init__.py
│ │ ├── ocean.py
│ │ ├── remotedata.py
│ │ └── node.py
│ ├── constants
│ │ ├── mainnet
│ │ │ └── __init__.py
│ │ ├── testnet
│ │ │ ├── __init__.py
│ │ │ └── LOAN_tokens.json
│ │ ├── rawtransactions.py
│ │ ├── address.py
│ │ ├── fees.py
│ │ └── __init__.py
│ ├── README.md
│ ├── utils
│ │ ├── __init__.py
│ │ └── verify.py
│ ├── address
│ │ ├── __init__.py
│ │ ├── script.py
│ │ ├── bech32address.py
│ │ └── p2sh.py
│ └── rawtransactions
│ │ ├── __init__.py
│ │ ├── fee.py
│ │ └── sign.py
├── networks
│ └── __init__.py
├── hdwallet
│ ├── __init__.py
│ ├── encrypt.py
│ └── account.py
└── __init__.py
├── requirements.txt
├── MANIFEST.in
├── pyproject.toml
├── .github
├── ISSUE_TEMPLATE
│ ├── improvement_report.md
│ └── bug_report.md
└── workflows
│ ├── tests.yml
│ ├── publish_docs.yml
│ ├── publish_pypi.yml
│ └── update_token.yml
├── tox.ini
├── pytest.ini
├── LICENSE
├── setup.py
└── .gitignore
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/node/test_spv.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/libs/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/hdwallet/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/exceptions/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/transactions/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/node/modules/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/mnemonic/wordlist/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/transactions/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/defichain/transactions/defitx/modules/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defichain/mnemonic/__init__.py:
--------------------------------------------------------------------------------
1 | from .mnemonic import Mnemonic
2 |
3 |
--------------------------------------------------------------------------------
/defichain/transactions/builder/__init__.py:
--------------------------------------------------------------------------------
1 | from .txbuilder import TxBuilder
2 |
--------------------------------------------------------------------------------
/tests/requirements_tests.txt:
--------------------------------------------------------------------------------
1 | pytest>=7.0.1
2 | pytest-cov>=4.0.0
3 | tox>=3.26.0
4 | setuptools>=65.5.1
5 |
--------------------------------------------------------------------------------
/docs/source/logo/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/source/logo/logo.png
--------------------------------------------------------------------------------
/defichain/networks/__init__.py:
--------------------------------------------------------------------------------
1 | from .networks import Network, DefichainMainnet, DefichainTestnet, DefichainRegtest
2 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests>=2.31.0
2 | six>=1.16.0
3 | ecdsa>=0.18.0
4 | base58>=2.1.1
5 | pycryptodome>=3.18.0
6 |
--------------------------------------------------------------------------------
/defichain/hdwallet/__init__.py:
--------------------------------------------------------------------------------
1 | from .derivations import Derivation
2 |
3 | from .wallet import Wallet
4 | from .account import Account
5 |
--------------------------------------------------------------------------------
/defichain/transactions/remotedata/__init__.py:
--------------------------------------------------------------------------------
1 | # Remote Data Source
2 | from .ocean import RemoteDataOcean
3 | from .node import RemoteDataNode
4 |
--------------------------------------------------------------------------------
/docs/source/api/node/loan.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: defichain.node
2 | :noindex:
3 |
4 | Loan
5 | ----
6 |
7 | .. autoclass:: Loan
8 | :members:
--------------------------------------------------------------------------------
/docs/source/guides/example/chainedTransactions.rst:
--------------------------------------------------------------------------------
1 | Chain Transactions
2 | ==================
3 |
4 | .. literalinclude:: chainedTransactions.py
5 |
--------------------------------------------------------------------------------
/docs/source/sdk/hdwallet/utils.rst:
--------------------------------------------------------------------------------
1 | .. _HDWallet utils:
2 |
3 | Utils
4 | ------
5 |
6 | .. automodule:: defichain.hdwallet.utils
7 | :members:
--------------------------------------------------------------------------------
/docs/source/guides/example/extractPrivateKeys.rst:
--------------------------------------------------------------------------------
1 | Extract Private Keys
2 | ====================
3 |
4 | .. literalinclude:: extractPrivateKeys.py
5 |
--------------------------------------------------------------------------------
/tests/transactions/remotedata/test_node.py:
--------------------------------------------------------------------------------
1 | """
2 | This implementation has to be tested manually because it requires a running defichain node
3 | """
4 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include README.md
3 | include requirements.txt
4 |
5 | recursive-exclude * __pycache__
6 | recursive-exclude * *.py[co]
7 |
--------------------------------------------------------------------------------
/docs/source/utils/logger.rst:
--------------------------------------------------------------------------------
1 | .. _Logger:
2 |
3 | Logger
4 | ======
5 |
6 | .. automodule:: defichain.logger
7 |
8 | .. autoclass:: Logger
9 | :members:
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/tokenerror.py:
--------------------------------------------------------------------------------
1 | class TokenError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"TokensError: {msg}")
--------------------------------------------------------------------------------
/docs/source/guides/example/index.rst:
--------------------------------------------------------------------------------
1 | Examples
2 | ========
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | chainedTransactions
8 | extractPrivateKeys
--------------------------------------------------------------------------------
/docs/source/guides/guides/index.rst:
--------------------------------------------------------------------------------
1 | Guides
2 | ======
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | basicUsageOfRawTransactions
8 | automateAddress
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/defitxerror.py:
--------------------------------------------------------------------------------
1 | class DefiTxError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"InputError: {msg}")
4 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/inputerror.py:
--------------------------------------------------------------------------------
1 | class InputError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"InputError: {msg}")
4 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/keyerror.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | class KeyError(Exception):
4 | def __init__(self, msg):
5 | super().__init__(f"KeyError: {msg}")
6 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/verifyerror.py:
--------------------------------------------------------------------------------
1 | class VerifyError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"InputError: {msg}")
4 |
--------------------------------------------------------------------------------
/docs/source/guides/index.rst:
--------------------------------------------------------------------------------
1 | Guides and Examples
2 | ===================
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | guides/index
8 | example/index
9 |
--------------------------------------------------------------------------------
/docs/source/logo/readme/defichainpython-logo-big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/source/logo/readme/defichainpython-logo-big.png
--------------------------------------------------------------------------------
/docs/source/logo/twitter/defichainpython-logo-big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/source/logo/twitter/defichainpython-logo-big.png
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/txbuildererror.py:
--------------------------------------------------------------------------------
1 | class TxBuilderError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"TxBuilderError: {msg}")
--------------------------------------------------------------------------------
/docs/source/logo/twitter/defichainpython-logo-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/source/logo/twitter/defichainpython-logo-small.png
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/addresserror.py:
--------------------------------------------------------------------------------
1 |
2 | class AddressError(Exception):
3 | def __init__(self, msg):
4 | super().__init__(f"AddressError: {msg}")
5 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/deserializeerror.py:
--------------------------------------------------------------------------------
1 | class DeserializeError(Exception):
2 | def __init__(self, msg):
3 | super().__init__(f"DeserializeError: {msg}")
--------------------------------------------------------------------------------
/docs/additionalInfos/pictures/CFP_02/docs_getblock_ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/additionalInfos/pictures/CFP_02/docs_getblock_ide.png
--------------------------------------------------------------------------------
/docs/additionalInfos/pictures/CFP_02/docs_getblock_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/additionalInfos/pictures/CFP_02/docs_getblock_web.png
--------------------------------------------------------------------------------
/docs/source/api/node/evm.rst:
--------------------------------------------------------------------------------
1 | .. _Node EVM:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | EVM
7 | ---
8 |
9 | .. autoclass:: EVM
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/node.rst:
--------------------------------------------------------------------------------
1 | .. _Node Node:
2 |
3 | .. automodule:: defichain
4 | :noindex:
5 |
6 | Node
7 | ----
8 |
9 | .. autoclass:: Node
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/spv.rst:
--------------------------------------------------------------------------------
1 | .. _Node Spv:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Spv
7 | ---
8 |
9 | .. autoclass:: Spv
10 | :members:
--------------------------------------------------------------------------------
/tests/ocean/__init__.py:
--------------------------------------------------------------------------------
1 | from defichain import Ocean
2 | from defichain.logger import Logger
3 |
4 | logger = Logger(log_level="all")
5 |
6 | ocean = Ocean(logger=logger)
7 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/notsupported.py:
--------------------------------------------------------------------------------
1 |
2 | class NotYetSupportedError(Exception):
3 | def __init__(self):
4 | super().__init__(f"NotYetSupportedError")
5 |
--------------------------------------------------------------------------------
/docs/additionalInfos/pictures/CFP_02/github_traffic_views.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/additionalInfos/pictures/CFP_02/github_traffic_views.png
--------------------------------------------------------------------------------
/docs/additionalInfos/pictures/announcement03/lightwallet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/additionalInfos/pictures/announcement03/lightwallet.jpg
--------------------------------------------------------------------------------
/docs/source/api/node/util.rst:
--------------------------------------------------------------------------------
1 | .. _Node Util:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Util
7 | ----
8 |
9 | .. autoclass:: Util
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/zmq.rst:
--------------------------------------------------------------------------------
1 | .. _Node Zmq:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Zmq
7 | ------
8 |
9 | .. autoclass:: Zmq
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/ocean.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Ocean:
2 |
3 | .. automodule:: defichain
4 | :noindex:
5 |
6 | Ocean
7 | -----
8 |
9 | .. autoclass:: Ocean
10 | :members:
--------------------------------------------------------------------------------
/docs/additionalInfos/pictures/CFP_02/github_traffic_clones.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eric-volz/DefichainPython/HEAD/docs/additionalInfos/pictures/CFP_02/github_traffic_clones.png
--------------------------------------------------------------------------------
/docs/source/api/node/stats.rst:
--------------------------------------------------------------------------------
1 | .. _Node Stats:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Stats
7 | ------
8 |
9 | .. autoclass:: Stats
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/vault.rst:
--------------------------------------------------------------------------------
1 | .. _Node Vault:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Vault
7 | -----
8 |
9 | .. autoclass:: Vault
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/fee.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Fee:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Fee
7 | ---
8 |
9 | .. autoclass:: Fee
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/rpc.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean RPC:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Rpc
7 | ---
8 |
9 | .. autoclass:: Rpc
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/node/mining.rst:
--------------------------------------------------------------------------------
1 | .. _Node Mining:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Mining
7 | ------
8 |
9 | .. autoclass:: Mining
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/tokens.rst:
--------------------------------------------------------------------------------
1 | .. _Node Tokens:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Tokens
7 | ------
8 |
9 | .. autoclass:: Tokens
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/wallet.rst:
--------------------------------------------------------------------------------
1 | .. _Node Wallet:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Wallet
7 | ------
8 |
9 | .. autoclass:: Wallet
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/loan.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Loan:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Loan
7 | ----
8 |
9 | .. autoclass:: Loan
10 | :members:
11 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/rawtransactionerror.py:
--------------------------------------------------------------------------------
1 |
2 | class RawTransactionError(Exception):
3 | def __init__(self, msg):
4 | super().__init__(f"RawTransactionError: {msg}")
5 |
--------------------------------------------------------------------------------
/docs/source/api/node/control.rst:
--------------------------------------------------------------------------------
1 | .. _Node Control:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Control
7 | -------
8 |
9 | .. autoclass:: Control
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/network.rst:
--------------------------------------------------------------------------------
1 | .. _Node Network:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Network
7 | -------
8 |
9 | .. autoclass:: Network
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/oracles.rst:
--------------------------------------------------------------------------------
1 | .. _Node Oracles:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Oracles
7 | -------
8 |
9 | .. autoclass:: Oracles
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/rawTx.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean RawTx:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | RawTx
7 | -----
8 |
9 | .. autoclass:: RawTx
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/stats.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Stats:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Stats
7 | -----
8 |
9 | .. autoclass:: Stats
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/hdwallet/wallet.rst:
--------------------------------------------------------------------------------
1 | .. _HDWallet wallet:
2 |
3 | .. automodule:: defichain
4 | :noindex:
5 |
6 | Wallet
7 | ------
8 |
9 | .. autoclass:: Wallet
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/accounts.rst:
--------------------------------------------------------------------------------
1 | .. _Node Accounts:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Accounts
7 | --------
8 |
9 | .. autoclass:: Accounts
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/poolpair.rst:
--------------------------------------------------------------------------------
1 | .. _Node Poolpair:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Poolpair
7 | --------
8 |
9 | .. autoclass:: Poolpair
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/address.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Address:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Address
7 | -------
8 |
9 | .. autoclass:: Address
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/blocks.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Blocks:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Blocks
7 | ------
8 |
9 | .. autoclass:: Blocks
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/prices.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Prices:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Prices
7 | ------
8 |
9 | .. autoclass:: Prices
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/tokens.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Tokens:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Tokens
7 | ------
8 |
9 | .. autoclass:: Tokens
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/hdwallet/account.rst:
--------------------------------------------------------------------------------
1 | .. _HDWallet Account:
2 |
3 | .. automodule:: defichain
4 | :noindex:
5 |
6 | Account
7 | =======
8 |
9 | .. autoclass:: Account
10 | :members:
--------------------------------------------------------------------------------
/defichain/node/modules/spv.py:
--------------------------------------------------------------------------------
1 | class Spv:
2 | """
3 | Currently not supported.
4 |
5 | Will be added when needed.
6 | """
7 | def __init__(self, node):
8 | self._node = node
9 |
--------------------------------------------------------------------------------
/docs/source/api/node/proposals.rst:
--------------------------------------------------------------------------------
1 | .. _Node Proposals:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Proposals
7 | ---------
8 |
9 | .. autoclass:: Proposals
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/oracles.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Oracles:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Oracles
7 | -------
8 |
9 | .. autoclass:: Oracles
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/poolpair.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Poolpair:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Poolpairs
7 | ---------
8 |
9 | .. autoclass:: Poolpairs
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/blockchain.rst:
--------------------------------------------------------------------------------
1 | .. _Node Blockchain:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Blockchain
7 | ----------
8 |
9 | .. autoclass:: Blockchain
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/generating.rst:
--------------------------------------------------------------------------------
1 | .. _Node Generating:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Generating
7 | ----------
8 |
9 | .. autoclass:: Generating
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/node/masternodes.rst:
--------------------------------------------------------------------------------
1 | .. _Node Masternodes:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Masternodes
7 | -----------
8 |
9 | .. autoclass:: Masternodes
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/consortium.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Consortium:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Consortium
7 | ----------
8 |
9 | .. autoclass:: Consortium
10 | :members:
--------------------------------------------------------------------------------
/docs/source/api/ocean/governance.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Governance:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Governance
7 | ----------
8 |
9 | .. autoclass:: Governance
10 | :members:
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=42.0", "wheel"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [tool.pytest.ini_options]
6 | testpaths = [
7 | "tests/hdwallet", "tests/ocean"
8 | ]
--------------------------------------------------------------------------------
/tests/ocean/test_rpc.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | @pytest.mark.query
5 | def test_call(): # 01
6 | assert ocean.rpc.call("getblockcount")
7 | assert ocean.rpc.call("getblockhash", 100)
8 |
--------------------------------------------------------------------------------
/docs/requirements_docs.txt:
--------------------------------------------------------------------------------
1 | sphinx==6.2.1
2 | furo==2023.3.27
3 | sphinx_mdinclude>=0.5.1
4 | sphinx_inline_tabs>=2022.1.2b11
5 | sphinxemoji>=0.2.0
6 | sphinx-copybutton>=0.5.2
7 | sphinx-sitemap
8 | requests>=2.31.0
9 |
--------------------------------------------------------------------------------
/tests/ocean/test_fee.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 |
5 | @pytest.mark.query
6 | def test_estimate(): # 01
7 | assert ocean.fee.estimate(10)
8 | assert ocean.fee.estimate(confirmationTarget=10)
--------------------------------------------------------------------------------
/docs/source/api/ocean/masternodes.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Masternodes:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Masternodes
7 | -----------
8 |
9 | .. autoclass:: Masternodes
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/api/ocean/transactions.rst:
--------------------------------------------------------------------------------
1 | .. _Ocean Transactions:
2 |
3 | .. automodule:: defichain.ocean
4 | :noindex:
5 |
6 | Transactions
7 | ------------
8 |
9 | .. autoclass:: Transactions
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/hdwallet/exceptions.rst:
--------------------------------------------------------------------------------
1 | .. _HDWallet Exceptions:
2 |
3 | Wallet Exceptions
4 | =================
5 |
6 | .. automodule:: defichain.exceptions.hdwallet
7 |
8 | .. autoclass:: DerivationError
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/node/test_zmq.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import node
4 |
5 |
6 | @pytest.mark.query
7 | def test_getzmqnotifications(): # 01
8 | zmq = node.zmq.getzmqnotifications()
9 | assert zmq or zmq == []
10 |
--------------------------------------------------------------------------------
/docs/source/api/node/rawtransactions.rst:
--------------------------------------------------------------------------------
1 | .. _Node Rawtransactions:
2 |
3 | .. automodule:: defichain.node
4 | :noindex:
5 |
6 | Rawtransactions
7 | ---------------
8 |
9 | .. autoclass:: Rawtransactions
10 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/pool.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Pool:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Pool
7 | ----
8 |
9 | .. autoclass:: Pool
10 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/utxo.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder UTXO:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | UTXO
7 | ----
8 |
9 | .. autoclass:: UTXO
10 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/remotedata/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RemoteData Index:
2 |
3 | Remote Data Source
4 | ==================
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 |
9 | node
10 | ocean
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/data.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Data:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Data
7 | ----
8 |
9 | .. autoclass:: Data
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/loans.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Loans:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Loans
7 | -----
8 |
9 | .. autoclass:: Loans
10 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/vault.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Vault:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Vault
7 | -----
8 |
9 | .. autoclass:: Vault
10 | :members:
--------------------------------------------------------------------------------
/defichain/exceptions/hdwallet/WalletError.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 |
4 | class WalletError(Exception):
5 |
6 | def __init__(self, msg):
7 | self.message = msg
8 | super().__init__(f"WalletError: {self.message}")
9 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/address/p2sh.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Address P2SH:
2 |
3 | P2SH
4 | ====
5 |
6 | .. automodule:: defichain.transactions.address
7 | :noindex:
8 |
9 | .. autoclass:: P2SH
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/txbuilder.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder TxBuilder:
2 |
3 | .. automodule:: defichain.transactions.builder
4 | :noindex:
5 |
6 | TxBuilder
7 | ---------
8 |
9 | .. autoclass:: TxBuilder
10 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/address/p2pkh.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Address P2PKH:
2 |
3 | P2PKH
4 | =====
5 |
6 | .. automodule:: defichain.transactions.address
7 | :noindex:
8 |
9 | .. autoclass:: P2PKH
10 | :members:
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/improvement_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Improvement request
3 | about: Suggest an improvement for DefichainPython
4 | labels: improvement
5 | ---
6 |
7 | #### What would you like to be added:
8 |
9 | #### Why is this needed:
10 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/address/p2wpkh.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Address P2WPKH:
2 |
3 | P2WPKH
4 | ======
5 |
6 | .. automodule:: defichain.transactions.address
7 | :noindex:
8 |
9 | .. autoclass:: P2WPKH
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/accounts.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Accounts:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Accounts
7 | --------
8 |
9 | .. autoclass:: Accounts
10 | :members:
11 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/BadMethod.py:
--------------------------------------------------------------------------------
1 | class BadMethod(Exception):
2 | """
3 | The called method is not existent.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"BadMethod(405): {self.message}")
8 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/mainnet/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | class SchemeIDMainnet:
3 | MIN1000: str = "MIN1000"
4 | MIN500: str = "MIN500"
5 | MIN350: str = "MIN350"
6 | MIN200: str = "MIN200"
7 | MIN175: str = "MIN175"
8 | MIN150: str = "MIN150"
9 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/governance.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Governance:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Governance
7 | ----------
8 |
9 | .. autoclass:: Governance
10 | :members:
11 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/builder/masternode.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Builder Basternode:
2 |
3 | .. automodule:: defichain.transactions.builder.modules
4 | :noindex:
5 |
6 | Masternode
7 | ----------
8 |
9 | .. autoclass:: Masternode
10 | :members:
11 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/testnet/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | class SchemeIDTestnet:
4 | MIN1000: str = "C1000"
5 | MIN500: str = "C500"
6 | MIN350: str = "C350"
7 | MIN200: str = "C200"
8 | MIN175: str = "C175"
9 | MIN150: str = "C150"
10 |
--------------------------------------------------------------------------------
/defichain/exceptions/hdwallet/__init__.py:
--------------------------------------------------------------------------------
1 | # hdwallet exceptions
2 | from defichain.exceptions.hdwallet.DerivationError import DerivationError
3 | from defichain.exceptions.hdwallet.NetworkError import NetworkError
4 | from defichain.exceptions.hdwallet.WalletError import WalletError
5 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/WrongParmeters.py:
--------------------------------------------------------------------------------
1 | class WrongParameters(Exception):
2 | """
3 | If the expected paremeters were not passed.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"WrongParameters: {self.message}")
8 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Index:
2 |
3 | DefiTx
4 | ======
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 |
9 | accounts
10 | governance
11 | loans
12 | masternode
13 | pool
14 | vault
15 |
16 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/ServiceUnavailable.py:
--------------------------------------------------------------------------------
1 | class ServiceUnavailable(Exception):
2 | """
3 | The server cannot handle the request.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"ServiceUnavailable(503): {self.message}")
8 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/rawtransactions.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | # TxInput
4 | SEQUENCE: str = "ffffffff"
5 | SCRIPTSIG: str = "00"
6 |
7 | # Transaction SigHash
8 | SIGHASH = 1
9 |
10 | # Signing Order
11 | ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
12 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/remotedata/node.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RemoteData Node:
2 |
3 | Remote Data Node
4 | ================
5 |
6 | .. automodule:: defichain.transactions.remotedata
7 | :noindex:
8 |
9 | .. autoclass:: RemoteDataNode
10 | :members:
11 |
--------------------------------------------------------------------------------
/defichain/transactions/builder/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from .accounts import Accounts
2 | from .governance import Governance
3 | from .pool import Pool
4 | from .loans import Loans
5 | from .masternode import Masternode
6 | from .data import Data
7 | from .utxo import UTXO
8 | from .vault import Vault
9 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/remotedata/ocean.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RemoteData Ocean:
2 |
3 | Remote Data Ocean
4 | =================
5 |
6 | .. automodule:: defichain.transactions.remotedata
7 | :noindex:
8 |
9 | .. autoclass:: RemoteDataOcean
10 | :members:
11 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/NotFound.py:
--------------------------------------------------------------------------------
1 | class NotFound(Exception):
2 | """
3 | The requested resource could not be found but may be available in the future.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"NotFound(404): {self.message}")
8 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/fee.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions Fee:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions
4 | :noindex:
5 |
6 | Fee
7 | ===
8 |
9 | Estimate Fee
10 | ------------
11 |
12 | .. autofunction:: estimate_fee
13 |
--------------------------------------------------------------------------------
/defichain/exceptions/hdwallet/NetworkError.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 |
4 | class NetworkError(Exception):
5 | """
6 | Bad network
7 | """
8 |
9 | def __init__(self, msg):
10 | self.message = msg
11 | super().__init__(f"NetworkError: {self.message}")
12 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions Index:
2 |
3 | Raw Transactions
4 | ================
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 |
9 | fee
10 | sign
11 | tx
12 | txinput
13 | txoutput
14 | witness
15 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/BadRequest.py:
--------------------------------------------------------------------------------
1 | class BadRequest(Exception):
2 | """
3 | The server cannot or will not process the request due to an apparent client error.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"BadRequest(400): {self.message}")
8 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/tx.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions Transaction:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions
4 | :noindex:
5 |
6 | Transaction
7 | ===========
8 |
9 | .. autoclass:: Transaction
10 | :members:
11 |
12 |
13 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/Forbidden.py:
--------------------------------------------------------------------------------
1 | class Forbidden(Exception):
2 | """
3 | The request contained valid data and was understood by the server, but the server is refusing action.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"Forbidden(403): {self.message}")
8 |
--------------------------------------------------------------------------------
/defichain/transactions/README.md:
--------------------------------------------------------------------------------
1 | # Transactions
2 |
3 | For the beginning I have written a small tutorial, which will introduce you to the implementation of a transaction.
4 | I would appreciate some [feedback on reddit](https://www.reddit.com/r/defiblockchain/comments/11zsod4/bringing_python_for_defichain_to_the_next_level/) :)
--------------------------------------------------------------------------------
/defichain/transactions/defitx/__init__.py:
--------------------------------------------------------------------------------
1 | # DefiTx
2 | from .defitx import DefiTx
3 |
4 | # Import DefiTx
5 | from .modules.accounts import *
6 | from .modules.governance import *
7 | from .modules.loans import *
8 | from .modules.masternode import *
9 | from .modules.pool import *
10 | from .modules.vault import *
11 |
12 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Index:
2 |
3 | Advanced
4 | ========
5 |
6 | Will be documented soon!❤️
7 |
8 | .. toctree::
9 | :maxdepth: 1
10 |
11 | address/index
12 | defitx/index
13 | rawtransactions/index
14 | remotedata/index
15 | keys
16 | utils
--------------------------------------------------------------------------------
/defichain/exceptions/http/UnprocessableEntity.py:
--------------------------------------------------------------------------------
1 | class UnprocessableEntity(Exception):
2 | """
3 | The request was well-formed but was unable to be followed due to semantic errors.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"UnprocessableEntity(422): {self.message}")
8 |
--------------------------------------------------------------------------------
/defichain/transactions/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Convert
2 | from .converter import Converter
3 |
4 | # Calculate
5 | from .calculate import Calculate
6 |
7 | # Verify
8 | from .verify import Verify
9 |
10 | # Tokens
11 | from .token import Token
12 |
13 | # Build
14 | from defichain.node.util import BuildAmounts, BuildAddressAmounts
15 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/Unauthorized.py:
--------------------------------------------------------------------------------
1 | class Unauthorized(Exception):
2 | """
3 | Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.
4 | """
5 | def __init__(self):
6 | super().__init__(f"Unauthorized(401): Authorization failed: Incorrect rpcuser or rpcpassword")
7 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/address.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Charsets
4 | CHARSET: str = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
5 | CHARSET_BASE = len(CHARSET)
6 |
7 |
8 | # Address Types
9 | class AddressTypes:
10 | P2PKH: str = "P2PKH"
11 | P2SH: str = "P2SH"
12 | P2WPKH: str = "P2WPKH"
13 |
14 |
15 | # Max Script Length
16 | MAX_OP_LENGTH = 76
17 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/InternalServerError.py:
--------------------------------------------------------------------------------
1 | class InternalServerError(Exception):
2 | """
3 | A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
4 | """
5 | def __init__(self, msg):
6 | self.message = msg
7 | super().__init__(f"InternalServerError(500): {self.message}")
8 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/keys.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Keys:
2 |
3 | .. automodule:: defichain.transactions.keys
4 | :noindex:
5 |
6 | Keys
7 | ====
8 |
9 | PublicKey
10 | ---------
11 |
12 | .. autoclass:: PublicKey
13 | :members:
14 |
15 |
16 | PrivateKey
17 | ----------
18 |
19 | .. autoclass:: PrivateKey
20 | :members:
21 |
--------------------------------------------------------------------------------
/docs/source/api/node/rawMethodsOverview.rst:
--------------------------------------------------------------------------------
1 | .. Hidden:
2 | .. _Node RawMethodsOverview:
3 |
4 | Raw Methods Overview
5 | ======================
6 |
7 | This is an overview of all methods which are available via Node / RPC.
8 |
9 | The methods were output from the help method.
10 |
11 | Methods
12 | -------
13 |
14 | .. include:: ../../../additionalInfos/rawMethodsOverview.txt
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/address/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Address Index:
2 |
3 | .. automodule:: defichain.transactions.address
4 | :noindex:
5 |
6 | Addresses
7 | =========
8 |
9 | .. toctree::
10 | :maxdepth: 1
11 |
12 | p2pkh
13 | p2sh
14 | p2wpkh
15 |
16 | Address
17 | -------
18 |
19 | .. autoclass:: Address
20 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/loans.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Loans:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Loans
7 | =====
8 |
9 | TakeLoan
10 | --------
11 |
12 | .. autoclass:: TakeLoan
13 | :members:
14 |
15 |
16 | PaybackLoan
17 | -----------
18 |
19 | .. autoclass:: PaybackLoan
20 | :members:
21 |
--------------------------------------------------------------------------------
/defichain/transactions/address/__init__.py:
--------------------------------------------------------------------------------
1 | # Static Method Address
2 | from .address import Address
3 |
4 | # Base58 Addresses
5 | from .base58address import Base58Address
6 | from .p2pkh import P2PKH
7 | from .p2sh import P2SH
8 |
9 | # Bech32 Addresses
10 | from .bech32address import Bech32Address
11 | from .p2wpkh import P2WPKH
12 |
13 | # Script
14 | from .script import Script
15 |
16 |
--------------------------------------------------------------------------------
/tests/ocean/test_ocean.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from defichain import Ocean
3 |
4 |
5 | @pytest.mark.mandatory
6 | def test_createOcean():
7 | """
8 | Checking if the Ocean Object builds as wanted
9 | """
10 | assert Ocean()
11 | assert Ocean("https://ocean.defichain.com", "v0", "mainnet")
12 | assert Ocean(url="https://ocean.defichain.com", version="v0", network="mainnet")
13 |
--------------------------------------------------------------------------------
/tests/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | markers =
3 | mandatory: object or methods that are mandatory for the library
4 | query: methods that are just querying data from the node
5 | tx: methods that are sending a transaction via the node into the blockchain
6 | hdwallet: classes and methods that are belong to hdwallet
7 | transactions: classes and methods that are belong to transactions
8 |
9 |
--------------------------------------------------------------------------------
/tests/node/test_stats.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import node
4 |
5 |
6 | @pytest.mark.query
7 | def test_getrpcstats(): # 01
8 | node.blockchain.getblockcount()
9 | assert node.stats.getrpcstats("getblockcount")
10 | assert node.stats.getrpcstats(command="getblockcount")
11 |
12 |
13 | @pytest.mark.query
14 | def test_listrpcstats(): # 02
15 | assert node.stats.listrpcstats()
16 |
--------------------------------------------------------------------------------
/tests/secrets_conf.example.py:
--------------------------------------------------------------------------------
1 | """
2 | The place to store credentials for your Defichain Node
3 |
4 | --> Uncomment all variables and fill in your credentials
5 | --> Save the new file as secrets_conf.py
6 | """
7 | # Mandatory
8 | # USER =
9 | # PASSWORD =
10 | # URL =
11 | # PORT =
12 | # WALLET_ADDRESS = # a legacy address is required
13 | # VAULT_ADDRESS =
14 | # WALLET_NAME =
15 | # WALLET_PASSWORD =
16 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/witness.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions Witness:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions
4 | :noindex:
5 |
6 | Wittness
7 | ========
8 |
9 | WitnessHash
10 | -----------
11 |
12 | .. autoclass:: WitnessHash
13 | :members:
14 |
15 |
16 | Witness
17 | -------
18 |
19 | .. autoclass:: Witness
20 | :members:
21 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/sign.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions Sign:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions.sign
4 | :noindex:
5 |
6 | Sign
7 | ====
8 |
9 | Sign Legacy Input
10 | -----------------
11 |
12 | .. autofunction:: sign_legacy_input
13 |
14 |
15 | Sign Segwit Input
16 | -----------------
17 |
18 | .. autofunction:: sign_segwit_input
19 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | minversion = 3.7.0
3 | envlist = python3.7, python3.8, python3.9, python3.10
4 | isolated_build = true
5 |
6 | [gh-actions]
7 | python =
8 | 3.7: python3.7
9 | 3.8: python3.8
10 | 3.9: python3.9
11 | 3.10: python3.10
12 |
13 | [testenv]
14 | setenv =
15 | PYTHONPATH = {toxinidir}
16 | deps =
17 | -r{toxinidir}/tests/requirements_tests.txt
18 | commands =
19 | pytest --basetemp={envtmpdir}
20 |
--------------------------------------------------------------------------------
/docs/source/api/exceptions.rst:
--------------------------------------------------------------------------------
1 | .. _API Exceptions:
2 |
3 | HTTP Exceptions
4 | ===============
5 |
6 | .. automodule:: defichain.exceptions.http
7 |
8 | .. autoclass:: BadMethod
9 | .. autoclass:: BadRequest
10 | .. autoclass:: Forbidden
11 | .. autoclass:: InternalServerError
12 | .. autoclass:: NotFound
13 | .. autoclass:: ServiceUnavailable
14 | .. autoclass:: Unauthorized
15 | .. autoclass:: UnprocessableEntity
16 | .. autoclass:: WrongParameters
17 |
--------------------------------------------------------------------------------
/tests/ocean/test_tokens.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.tokens.list()
11 | assert ocean.tokens.list(SIZE, NEXT)
12 | assert ocean.tokens.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_get(): # 02
17 | id = 0 # DFI
18 | assert ocean.tokens.get(id)
19 | assert ocean.tokens.get(id=id)
20 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/governance.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Governance:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Governance
7 | ==========
8 |
9 | CreateCfp
10 | ---------
11 |
12 | .. autoclass:: CreateCfp
13 | :members:
14 |
15 |
16 | CreateVoc
17 | ---------
18 |
19 | .. autoclass:: CreateVoc
20 | :members:
21 |
22 |
23 | Vote
24 | ----
25 |
26 | .. autoclass:: Vote
27 | :members:
--------------------------------------------------------------------------------
/tests/node/__init__.py:
--------------------------------------------------------------------------------
1 | from defichain import Node
2 | from defichain.logger import Logger
3 | from ..util import load_secrets_conf
4 |
5 | secrets = load_secrets_conf()
6 | logger = Logger(log_level="all")
7 |
8 | node = Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"],
9 | wallet_name=secrets["wallet_name"], wallet_password=secrets["wallet_password"], wallet_timeout=3600,
10 | logger=logger)
11 |
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | markers =
3 | mandatory: object or methods that are mandatory for the library
4 | query: methods that are just querying data from the node
5 | tx: methods that are sending a transaction via the node into the blockchain
6 | hdwallet: classes and methods that are belong to hdwallet
7 | transactions: classes and methods that are belong to transactions
8 |
9 | testpaths =
10 | tests/hdwallet
11 | tests/ocean
12 | tests/transactions
--------------------------------------------------------------------------------
/defichain/transactions/constants/fees.py:
--------------------------------------------------------------------------------
1 | FEE_PER_BYTE: int = 1
2 |
3 |
4 | class TxSize:
5 | """
6 | Specifies the size in bytes for each element of a transaction
7 |
8 | https://bitcoinops.org/en/tools/calc-size/
9 | """
10 | # P2PKH Signature
11 | SCRIPTSIG_SIGNATURE: int = 107
12 |
13 | # P2SH and P2WPKH Witness
14 | WITNESS_SIGNATURE_LENGTH: int = 1
15 | WITNESS_SIGNATURE: int = 73
16 | PUBLIC_KEY_LENGTH: int = 1
17 | PUBLIC_KEY: int = 34
18 |
--------------------------------------------------------------------------------
/defichain/transactions/rawtransactions/__init__.py:
--------------------------------------------------------------------------------
1 | # Transaction
2 | from .tx import Transaction
3 |
4 | # Transaction Input
5 | from .txinput import TxInput, TxP2PKHInput, TxP2SHInput, TxP2WPKHInput, TxCoinbaseInput
6 |
7 | # Transaction Output
8 | from .txoutput import TxOutput, TxAddressOutput, TxDataOutput, TxDefiOutput, TxCoinbaseOutput
9 |
10 | # Witness
11 | from .witness import WitnessHash, Witness
12 |
13 | # Fee
14 | from .fee import estimate_size, estimate_fee, estimate_vsize
15 |
--------------------------------------------------------------------------------
/tests/ocean/test_stats.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 |
5 | @pytest.mark.query
6 | def test_get(): # 01
7 | assert ocean.stats.get()
8 |
9 |
10 | @pytest.mark.query
11 | def test_RewardDistributiong(): # 02
12 | assert ocean.stats.getRewardDistribution()
13 |
14 |
15 | @pytest.mark.query
16 | def test_getSupply(): # 03
17 | assert ocean.stats.getSupply()
18 |
19 |
20 | @pytest.mark.query
21 | def test_getBurn(): # 04
22 | assert ocean.stats.getBurn()
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: 'BUG: '
5 | labels: bug
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:
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Additional context**
20 | Add any other context about the problem here.
21 |
--------------------------------------------------------------------------------
/defichain/__init__.py:
--------------------------------------------------------------------------------
1 | # Main Classes
2 |
3 | # Node
4 | from defichain.node.node import Node
5 |
6 | # Ocean
7 | from defichain.ocean.ocean import Ocean
8 |
9 | # Wallet
10 | from defichain.hdwallet import Wallet
11 | from defichain.hdwallet import Account
12 |
13 | # Mnemonic
14 | from defichain.mnemonic.mnemonic import Mnemonic
15 |
16 | # Transaction Builder
17 | from defichain.transactions.builder.txbuilder import TxBuilder
18 |
19 | # Helping Classes
20 | from defichain.node.util import BuildToJson
21 |
--------------------------------------------------------------------------------
/defichain/exceptions/transactions/__init__.py:
--------------------------------------------------------------------------------
1 | # Transaction Exceptions
2 |
3 | from .addresserror import AddressError
4 | from .keyerror import KeyError
5 | from .notsupported import NotYetSupportedError
6 | from .rawtransactionerror import RawTransactionError
7 | from .txbuildererror import TxBuilderError
8 | from .tokenerror import TokenError
9 | from .inputerror import InputError
10 | from .defitxerror import DefiTxError
11 | from .verifyerror import VerifyError
12 | from .deserializeerror import DeserializeError
13 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/exceptions.rst:
--------------------------------------------------------------------------------
1 | .. _Transactions Exceptions:
2 |
3 | Transactions Exceptions
4 | =======================
5 |
6 | .. automodule:: defichain.exceptions.transactions
7 |
8 | .. autoclass:: AddressError
9 | .. autoclass:: DefiTxError
10 | .. autoclass:: DeserializeError
11 | .. autoclass:: InputError
12 | .. autoclass:: KeyError
13 | .. autoclass:: NotYetSupportedError
14 | .. autoclass:: RawTransactionError
15 | .. autoclass:: TokenError
16 | .. autoclass:: TxBuilderError
17 | .. autoclass:: VerifyError
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/utils.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced Utils:
2 |
3 | .. automodule:: defichain.transactions.utils
4 | :noindex:
5 |
6 | Utils
7 | =====
8 |
9 | Calculate
10 | ---------
11 |
12 | .. autoclass:: Calculate
13 | :members:
14 |
15 |
16 | Converter
17 | ---------
18 |
19 | .. autoclass:: Converter
20 | :members:
21 |
22 |
23 | Token
24 | -----
25 |
26 | .. autoclass:: Token
27 | :members:
28 |
29 |
30 | Verify
31 | ------
32 |
33 | .. autoclass:: Verify
34 | :members:
35 |
--------------------------------------------------------------------------------
/defichain/exceptions/hdwallet/DerivationError.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 |
4 | class DerivationError(Exception):
5 | """
6 | Bad derivation index
7 | """
8 |
9 | def __init__(self, error_message: str, error_detail: Optional[str] = None):
10 | self.error_message = error_message
11 | self.error_detail = error_detail
12 |
13 | def __str__(self):
14 | if self.error_detail:
15 | return f"{self.error_message}, {self.error_detail}"
16 | return f"{self.error_message}"
17 |
--------------------------------------------------------------------------------
/tests/ocean/test_masternodes.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.masternodes.list()
11 | assert ocean.masternodes.list(SIZE, NEXT)
12 | assert ocean.masternodes.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_get(): # 02
17 | id = "6be52cb3ce612b6949b7652e35aa42e3ad7174d284c9d5685ee42a9f230a1fe6"
18 | assert ocean.masternodes.get(id)
19 | assert ocean.masternodes.get(id=id)
20 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/masternode.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Masternode:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Masternode
7 | ==========
8 |
9 | CreateMasternode
10 | ----------------
11 |
12 | .. autoclass:: CreateMasternode
13 | :members:
14 |
15 |
16 | ResignMasternode
17 | ----------------
18 |
19 | .. autoclass:: ResignMasternode
20 | :members:
21 |
22 |
23 | UpdateMasternode
24 | ----------------
25 |
26 | .. autoclass:: UpdateMasternode
27 | :members:
28 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | # Address
3 | from .address import AddressTypes, CHARSET, CHARSET_BASE, MAX_OP_LENGTH
4 |
5 | # Defi Transaction
6 | from .defitx import DefiTxType, DefiTx_SIGNATURE
7 |
8 | # Fee
9 | from .fees import FEE_PER_BYTE, TxSize
10 |
11 | # OP Codes
12 | from .opcodes import OPCodes
13 |
14 | # Raw Transactions
15 | from .rawtransactions import ORDER, SCRIPTSIG, SEQUENCE, SIGHASH
16 |
17 | # Tokens
18 | from .tokens import TokenTypes, Tokens
19 |
20 | # Network Constants
21 | from .mainnet import *
22 | from .testnet import *
23 |
--------------------------------------------------------------------------------
/tests/transactions/rawtransactions/test_sign.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.transactions.rawtransactions.sign import sign_legacy_input, sign_segwit_input
4 | from . import Keys, TestSign
5 |
6 |
7 | @pytest.mark.transactions
8 | def test_sign_legacy_input(): # 01
9 | assert sign_legacy_input(Keys.privateKey, TestSign.DataBytes, TestSign.SigHashBytes) == TestSign.LegacySignature
10 |
11 |
12 | @pytest.mark.transactions
13 | def test_sign_segwit_input(): # 02
14 | assert sign_segwit_input(Keys.privateKey, TestSign.DataBytes) == TestSign.SegwitSignature
15 |
--------------------------------------------------------------------------------
/docs/additionalInfos/formatRawMethodsOverview.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | FILE_PATH = "rawMethodsOverview.txt"
4 |
5 | with open(FILE_PATH) as input:
6 | with open(FILE_PATH + ".tmp", "w") as output:
7 | while True:
8 | line = input.readline()
9 | if line == "":
10 | break
11 |
12 | line = line + "\n"
13 |
14 | output.writelines(line)
15 |
16 | with open(FILE_PATH + ".tmp") as input:
17 | with open(FILE_PATH, "w") as output:
18 | output.write(input.read())
19 |
20 | os.remove(FILE_PATH + ".tmp")
21 |
--------------------------------------------------------------------------------
/tests/ocean/test_consortium.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 | from defichain.exceptions.http.NotFound import NotFound
4 |
5 |
6 | @pytest.mark.query
7 | def test_getAssetBreakdown(): # 01
8 | assert ocean.consortium.getAssetBreakdown()
9 |
10 |
11 | @pytest.mark.query
12 | def test_getMemberStats(): # 02
13 | string = "Consortium member not found"
14 | memberId = "member"
15 | with pytest.raises(NotFound, match=string):
16 | assert ocean.consortium.getMemberStats(memberId)
17 | assert ocean.consortium.getMemberStats(memberId=memberId)
18 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_replaceable.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_replaceable, TestReplaceableTransactions, Addresses
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_replaceable(): # 01
10 | tx = builder_replaceable.utxo.sendall(Addresses.P2WPKH)
11 |
12 | assert tx.serialize() == TestReplaceableTransactions.replaceable_transaction_serialized
13 |
14 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/pool.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Pool:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Pool
7 | ====
8 |
9 | PoolSwap
10 | --------
11 |
12 | .. autoclass:: PoolSwap
13 | :members:
14 |
15 |
16 | CompositeSwap
17 | -------------
18 |
19 | .. autoclass:: CompositeSwap
20 | :members:
21 |
22 |
23 | AddPoolLiquidity
24 | ----------------
25 |
26 | .. autoclass:: AddPoolLiquidity
27 | :members:
28 |
29 |
30 | RemovePoolLiquidity
31 | -------------------
32 |
33 | .. autoclass:: RemovePoolLiquidity
34 | :members:
--------------------------------------------------------------------------------
/tests/transactions/remotedata/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | ADDRESS = "df1q29x7wpn8flcqgscre4xfjgp99mppcmaus83uzt"
3 | MASTERNODE = "b4365354a83f8ac420d6292b1c032aeff16e92405b404d29a70377df8ad9acf3"
4 | RAWTX = "0400000000010190756f77269730c3c76be2f47fdb42b31fa155fbdba1730c69d01bcd419f26260100000000ffffffff01604d000000" \
5 | "000000160014514de706674ff0044303cd4c9920252ec21c6fbc0002483045022100ecc53b62d79208491c001b182c732b5fcf340900" \
6 | "34fa76c5f0a7d8c6fcbec726022056e5447032169c0e892f07a7f484d907f07c1a88c0b3104778d1d165a31545f3012102d87647e048" \
7 | "f26b8bc81edfef026d44c51ad2a176b78135377cce81cf1359d0cc00000000"
8 |
--------------------------------------------------------------------------------
/docs/source/utils/mnemonic.rst:
--------------------------------------------------------------------------------
1 | .. _Mnemonic:
2 |
3 | Mnemonic
4 | ========
5 |
6 | This is a class with which you can generate and check mnemonic seed's
7 |
8 | Example
9 | -------
10 |
11 | >>> from defichain import Mnemonic
12 | >>> mnemonic = Mnemonic(language="english")
13 | >>> seed = mnemonic.generate(256)
14 | "shoulder unusual practice sight apart course eager true diesel rescue diagram denial oppose total fun rocket spend chapter spider paddle benefit empower type purse"
15 | >>> Mnemonic.detect_language(seed)
16 | "english"
17 | >>> mnemonic.check(seed)
18 | True
19 |
20 | .. automodule:: defichain.mnemonic
21 |
22 | .. autoclass:: Mnemonic
23 | :members:
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/txoutput.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions TxOutput:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions
4 | :noindex:
5 |
6 | Transactions Output
7 | ===================
8 |
9 | TxOutput
10 | --------
11 |
12 | .. autoclass:: TxOutput
13 | :members:
14 |
15 |
16 | TxAddressOutput
17 | ---------------
18 |
19 | .. autoclass:: TxAddressOutput
20 | :members:
21 |
22 |
23 | TxDefiOutput
24 | ------------
25 |
26 | .. autoclass:: TxDefiOutput
27 | :members:
28 |
29 |
30 | TxCoinbaseOutput
31 | ----------------
32 |
33 | .. autoclass:: TxCoinbaseOutput
34 | :members:
35 |
36 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/__init__.py:
--------------------------------------------------------------------------------
1 | # http exceptions
2 | from defichain.exceptions.http.BadMethod import BadMethod
3 | from defichain.exceptions.http.BadRequest import BadRequest
4 | from defichain.exceptions.http.Forbidden import Forbidden
5 | from defichain.exceptions.http.InternalServerError import InternalServerError
6 | from defichain.exceptions.http.NotFound import NotFound
7 | from defichain.exceptions.http.ServiceUnavailable import ServiceUnavailable
8 | from defichain.exceptions.http.Unauthorized import Unauthorized
9 | from defichain.exceptions.http.UnprocessableEntity import UnprocessableEntity
10 | from defichain.exceptions.http.WrongParmeters import WrongParameters
11 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. include:: ../../README.rst
2 |
3 | .. toctree::
4 | :hidden:
5 | :maxdepth: 1
6 |
7 | main/quickstart
8 | main/statusAndTasks
9 | guides/index
10 |
11 | .. toctree::
12 | :caption: API
13 | :hidden:
14 |
15 | api/node/index
16 | api/ocean/index
17 | api/exceptions
18 |
19 | .. toctree::
20 | :caption: SDK
21 | :hidden:
22 |
23 | sdk/hdwallet/index
24 | sdk/transactions/index
25 |
26 | .. toctree::
27 | :caption: Utils
28 | :hidden:
29 |
30 | utils/logger
31 | utils/mnemonic
32 |
33 | .. toctree::
34 | :caption: Legal
35 | :hidden:
36 |
37 | legal/community
38 | legal/licenseAndDisclaimer
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | - push
5 | - pull_request
6 |
7 | jobs:
8 | test:
9 | runs-on: ${{ matrix.os }}
10 | strategy:
11 | matrix:
12 | os: [ubuntu-latest, windows-latest, macos-latest]
13 | python-version: ['3.7', '3.8','3.9', '3.10']
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Set up Python ${{ matrix.python-version }}
18 | uses: actions/setup-python@v2
19 | with:
20 | python-version: ${{ matrix.python-version }}
21 | - name: Install dependencies
22 | run: |
23 | python -m pip install --upgrade pip
24 | pip install tox tox-gh-actions
25 | - name: Test with tox
26 | run: tox
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/util.py:
--------------------------------------------------------------------------------
1 | from os import path
2 |
3 | LENGTH_OF_TXID = 64
4 |
5 |
6 | def load_secrets_conf():
7 | # Check if file exists
8 | if not path.isfile("secrets_conf.py"):
9 | raise Exception("There is not secrets_conf.py File: \n"
10 | "To create one: read secrets_conf.example.py!")
11 |
12 | # load mandatory config
13 | from tests.secrets_conf import USER, PASSWORD, URL, PORT, WALLET_ADDRESS, VAULT_ADDRESS, WALLET_NAME, WALLET_PASSWORD
14 | json = {"user": USER, "password": PASSWORD, "url": URL, "port": PORT, "wallet_address": WALLET_ADDRESS,
15 | "vault_address": VAULT_ADDRESS, "wallet_name": WALLET_NAME, "wallet_password": WALLET_PASSWORD}
16 |
17 | return json
18 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/fee.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Fee.ts
2 |
3 | class Fee:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def estimate(self, confirmationTarget: int = 10) -> {}: # 01
8 | """
9 | Estimates the fee for transaction to get confirmed
10 |
11 | :param confirmationTarget: (optional) confirmationTarget in blocks till fee get confirmed
12 | :type confirmationTarget: str
13 | :return: (json string) {data: float}
14 |
15 | :example:
16 |
17 | >>> ocean.fee.estimate(10)
18 | """
19 | return self._ocean._conn.get(f"fee/estimate?confirmationTarget={confirmationTarget}")
20 |
--------------------------------------------------------------------------------
/defichain/transactions/constants/testnet/LOAN_tokens.json:
--------------------------------------------------------------------------------
1 | [{"id": "10", "symbol": "TWTR", "name": "TWTR", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "57", "symbol": "IBIT", "name": "iShares Bitcoin Trust", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "60", "symbol": "DUSD", "name": "DUSD", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "61", "symbol": "MSFT", "name": "MSFT", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "62", "symbol": "GOOGL", "name": "GOOGL", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "63", "symbol": "eol/FB", "name": "FB", "isDAT": true, "isLPS": false, "isLoanToken": true}, {"id": "64", "symbol": "eol/TSLA", "name": "TSLA", "isDAT": true, "isLPS": false, "isLoanToken": true}]
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/rawtransactions/txinput.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced RawTransactions TxInput:
2 |
3 | .. automodule:: defichain.transactions.rawtransactions
4 | :noindex:
5 |
6 | Transactions Inputs
7 | ===================
8 |
9 | TxInput
10 | -------
11 |
12 | .. autoclass:: TxInput
13 | :members:
14 |
15 |
16 | TxP2PKHInput
17 | ------------
18 |
19 | .. autoclass:: TxP2PKHInput
20 | :members:
21 |
22 |
23 | TxP2SHInput
24 | -----------
25 |
26 | .. autoclass:: TxP2SHInput
27 | :members:
28 |
29 |
30 | TxP2WPKHInput
31 | -------------
32 |
33 | .. autoclass:: TxP2WPKHInput
34 | :members:
35 |
36 |
37 | TxCoinbaseInput
38 | ---------------
39 |
40 | .. autoclass:: TxCoinbaseInput
41 | :members:
42 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/accounts.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Accounts:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Accounts
7 | ========
8 |
9 | UtxosToAccount
10 | --------------
11 |
12 | .. autoclass:: UtxosToAccount
13 | :members:
14 |
15 |
16 | AccountToUtxos
17 | --------------
18 |
19 | .. autoclass:: AccountToUtxos
20 | :members:
21 |
22 |
23 | AccountToAccount
24 | ----------------
25 |
26 | .. autoclass:: AccountToAccount
27 | :members:
28 |
29 |
30 | AnyAccountToAccount
31 | -------------------
32 |
33 | .. autoclass:: AnyAccountToAccount
34 | :members:
35 |
36 |
37 | SetFutureSwap
38 | -------------
39 |
40 | .. autoclass:: SetFutureSwap
41 | :members:
42 |
--------------------------------------------------------------------------------
/tests/node/test_generating.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from tests.util import load_secrets_conf
3 |
4 | # Import Exceptions
5 | from defichain.exceptions.http.InternalServerError import InternalServerError
6 |
7 | from . import node
8 | address = load_secrets_conf()["wallet_address"]
9 |
10 |
11 | @pytest.mark.query
12 | def test_generatetoaddress(): # 01
13 | nblocks = 11
14 | maxtries = 1
15 | string = ".* RPC_INVALID_ADDRESS_OR_KEY: Error: I am not masternode operator"
16 | with pytest.raises(InternalServerError, match=string):
17 | assert node.generating.generatetoaddress(nblocks, address)
18 | assert node.generating.generatetoaddress(nblocks, address, maxtries)
19 | assert node.generating.generatetoaddress(nblocks=nblocks, address=address, maxtries=maxtries)
20 |
--------------------------------------------------------------------------------
/tests/transactions/remotedata/test_ocean.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain import Ocean
4 | from defichain.transactions.remotedata import RemoteDataOcean
5 | from defichain.exceptions.http import BadRequest
6 | from . import *
7 |
8 | remote = RemoteDataOcean(Ocean())
9 |
10 |
11 | @pytest.mark.transactions
12 | def test_get_unspent(): # 01
13 | assert remote.get_unspent(ADDRESS)
14 |
15 |
16 | @pytest.mark.transactions
17 | def test_check_masternode(): # 02
18 | assert remote.check_masternode(MASTERNODE)
19 |
20 |
21 | @pytest.mark.transactions
22 | def test_test_tx(): # 03
23 | assert remote.test_tx(RAWTX) is False
24 |
25 |
26 | @pytest.mark.transactions
27 | def test_send_tx(): # 04
28 | with pytest.raises(BadRequest):
29 | assert remote.send_tx(RAWTX)
30 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/rpc.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Rpc.ts
2 |
3 | class Rpc:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def call(self, method: str, *params: []) -> {}:
8 | """
9 | Call an RPC method
10 |
11 | :param method: (required) method of the RPC method
12 | :type method: str
13 | :param params: (optinal) params to send upstream
14 | :type params: array
15 | :return: json string
16 |
17 | :example:
18 |
19 | >>> ocean.rpc.call("getblockcount")
20 | """
21 | if params == ():
22 | return self._ocean._conn.post(f"rpc/{method}", [])
23 | else:
24 | return self._ocean._conn.post(f"rpc/{method}", params)
25 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/advanced/defitx/vault.rst:
--------------------------------------------------------------------------------
1 | .. _Transaction Advanced DefiTx Vault:
2 |
3 | .. automodule:: defichain.transactions.defitx
4 | :noindex:
5 |
6 | Vault
7 | =====
8 |
9 | CreateVault
10 | -----------
11 |
12 | .. autoclass:: CreateVault
13 | :members:
14 |
15 |
16 | UpdateVault
17 | -----------
18 |
19 | .. autoclass:: UpdateVault
20 | :members:
21 |
22 |
23 | DepositToVault
24 | --------------
25 |
26 | .. autoclass:: DepositToVault
27 | :members:
28 |
29 |
30 | WithdrawFromVault
31 | -----------------
32 |
33 | .. autoclass:: WithdrawFromVault
34 | :members:
35 |
36 |
37 | CloseVault
38 | ----------
39 |
40 | .. autoclass:: CloseVault
41 | :members:
42 |
43 |
44 | PlaceAuctionBid
45 | ---------------
46 |
47 | .. autoclass:: PlaceAuctionBid
48 | :members:
49 |
50 |
--------------------------------------------------------------------------------
/tests/ocean/test_transactions.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | TXID = "bfb4bab92292e9c9b260c30e110bbbea0d8e0c78015a9058f67f1770d84f478f"
5 | SIZE = 30
6 | NEXT = None
7 |
8 |
9 | @pytest.mark.query
10 | def test_get(): # 01
11 | assert ocean.transactions.get(TXID)
12 | assert ocean.transactions.get(id=TXID)
13 |
14 |
15 | @pytest.mark.query
16 | def test_getVins(): # 02
17 | assert ocean.transactions.getVins(TXID)
18 | assert ocean.transactions.getVins(TXID, SIZE, NEXT)
19 | assert ocean.transactions.getVins(txid=TXID, size=SIZE, next=NEXT)
20 |
21 |
22 | @pytest.mark.query
23 | def test_getVouts(): # 03
24 | assert ocean.transactions.getVouts(TXID)
25 | assert ocean.transactions.getVouts(TXID, SIZE, NEXT)
26 | assert ocean.transactions.getVouts(txid=TXID, size=SIZE, next=NEXT)
27 |
--------------------------------------------------------------------------------
/defichain/transactions/defitx/modules/basedefitx.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 | from typing import Any
3 | import json
4 |
5 |
6 | class BaseDefiTx(ABC):
7 | @staticmethod
8 | @abstractmethod
9 | def deserialize(network: Any, hex: str) -> "BaseDefiTx":
10 | pass
11 |
12 | @abstractmethod
13 | def __bytes__(self) -> bytes:
14 | pass
15 |
16 | def __str__(self):
17 | return json.dumps(self.to_json(), indent=5)
18 |
19 | @abstractmethod
20 | def to_json(self) -> {}:
21 | pass
22 |
23 | def size(self) -> int:
24 | return len(self.bytes())
25 |
26 | def serialize(self) -> str:
27 | return bytes(self).hex()
28 |
29 | def bytes(self) -> bytes:
30 | return bytes(self)
31 |
32 | @abstractmethod
33 | def get_defiTxType(self) -> str:
34 | pass
35 |
36 |
--------------------------------------------------------------------------------
/defichain/ocean/__init__.py:
--------------------------------------------------------------------------------
1 | # Just to be present: Ocean
2 | from defichain.ocean.modules.address import Address
3 | from defichain.ocean.modules.blocks import Blocks
4 | from defichain.ocean.modules.consortium import Consortium
5 | from defichain.ocean.modules.fee import Fee
6 | from defichain.ocean.modules.governance import Governance
7 | from defichain.ocean.modules.loan import Loan
8 | from defichain.ocean.modules.masternodes import Masternodes
9 | from defichain.ocean.modules.oracles import Oracles
10 | from defichain.ocean.modules.poolpairs import Poolpairs
11 | from defichain.ocean.modules.prices import Prices
12 | from defichain.ocean.modules.rawTx import RawTx
13 | from defichain.ocean.modules.rpc import Rpc
14 | from defichain.ocean.modules.stats import Stats
15 | from defichain.ocean.modules.tokens import Tokens
16 | from defichain.ocean.modules.transactions import Transactions
17 |
--------------------------------------------------------------------------------
/.github/workflows/publish_docs.yml:
--------------------------------------------------------------------------------
1 | name: Docs Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build-and-deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout Repository
13 | uses: actions/checkout@v2
14 |
15 | - name: Set up Python
16 | uses: actions/setup-python@v2
17 | with:
18 | python-version: '3.8'
19 |
20 | - name: Install Dependencies
21 | run: |
22 | pip install -r requirements.txt
23 | cd docs
24 | pip install -r requirements_docs.txt
25 |
26 | - name: Build Sphinx Documentation
27 | run: |
28 | cd docs
29 | make clean html
30 |
31 | - name: Deploy to GitHub Pages
32 | uses: JamesIves/github-pages-deploy-action@v4.4.2
33 | with:
34 | branch: gh-pages
35 | folder: docs/
--------------------------------------------------------------------------------
/tests/transactions/builder/test_loans.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, TestLoans, Addresses
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_takeloan(): # 01
10 | tx = builder_p2wpkh.loans.takeloan(TestLoans.vault_id, Addresses.P2WPKH, TestLoans.amounts)
11 |
12 | assert tx.serialize() == TestLoans.take_loan_serialized
13 |
14 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_paybackloan(): # 02
19 | tx = builder_p2wpkh.loans.paybackloan(TestLoans.vault_id, Addresses.P2WPKH, TestLoans.amounts)
20 |
21 | assert tx.serialize() == TestLoans.payback_loan_serialized
22 |
23 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
24 |
25 |
--------------------------------------------------------------------------------
/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 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
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 |
--------------------------------------------------------------------------------
/.github/workflows/publish_pypi.yml:
--------------------------------------------------------------------------------
1 | name: Publish to PyPi
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | build-n-publish:
9 | name: Build and publish Python 🐍 distributions 📦 to PyPI
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 |
14 | - name: Set up Python 🐍
15 | uses: actions/setup-python@v2
16 | with:
17 | python-version: 3.8
18 |
19 | - name: Install pypa/build
20 | run: >-
21 | python -m
22 | pip install
23 | build
24 | --user
25 |
26 | - name: Build a binary wheel and a source tarball
27 | run: >-
28 | python -m
29 | build
30 | --sdist
31 | --wheel
32 | --outdir dist/
33 |
34 | - name: Publish distribution 📦 to PyPI
35 | uses: pypa/gh-action-pypi-publish@release/v1
36 | with:
37 | user: __token__
38 | password: ${{ secrets.pypi_password }}
39 |
--------------------------------------------------------------------------------
/defichain/node/modules/generating.py:
--------------------------------------------------------------------------------
1 | class Generating:
2 | def __init__(self, node):
3 | self._node = node
4 |
5 | def generatetoaddress(self, nblocks: int, address: str, maxtries: int = 1) -> ["str"]: # 01
6 | """
7 | Mine blocks immediately to a specified address (before the RPC call returns)
8 |
9 | :param nblocks: (required) How many blocks are generated immediately
10 | :type nblocks: int
11 | :param address: (required) The address to send the newly generated DFI to
12 | :type address: str
13 | :param maxtries: (optional) How many iterations to try
14 | :type maxtries: int
15 | :return: [...] (array) -- hashes of blocks generated
16 |
17 | :example:
18 |
19 | Generate 11 blocks to myaddress
20 |
21 | >>> node.generating.generatetoaddress(11, address)
22 | """
23 | return self._node._rpc.call("generatetoaddress", nblocks, address, maxtries)
24 |
--------------------------------------------------------------------------------
/defichain/node/modules/zmq.py:
--------------------------------------------------------------------------------
1 | class Zmq:
2 | def __init__(self, node):
3 | self._node = node
4 |
5 | def getzmqnotifications(self) -> {}:
6 | """
7 | Returns information about the active ZeroMQ notifications
8 |
9 | :return: [{...}] (json array) -- returns information about the active ZeroMQ notifications
10 |
11 | .. code-block:: text
12 |
13 | [
14 | { (json object)
15 | "type": "pubhashtx", (string) Type of notification
16 | "address": "...", (string) Address of the publisher
17 | "hwm": n (numeric) Outbound message high water mark
18 | },
19 | ...
20 | ]
21 |
22 | :example:
23 |
24 | >>> node.control.getzmqnotifications()
25 | """
26 | return self._node._rpc.call("getzmqnotifications")
27 |
--------------------------------------------------------------------------------
/tests/ocean/test_blocks.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.blocks.list()
11 | assert ocean.blocks.list(SIZE, NEXT)
12 | assert ocean.blocks.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_get(): # 02
17 | blockheight = 100
18 | blockhash = "b6e0ee6da7e61f6b672b72b9a8a68413cdf0344102acecccf9cf2a6d338630c6"
19 | assert ocean.blocks.get(blockheight)
20 | assert ocean.blocks.get(blockhash)
21 | assert ocean.blocks.get(id=blockheight)
22 | assert ocean.blocks.get(id=blockhash)
23 |
24 |
25 | @pytest.mark.query
26 | def test_getTransactions(): # 03
27 | blockhash = "b6e0ee6da7e61f6b672b72b9a8a68413cdf0344102acecccf9cf2a6d338630c6"
28 | assert ocean.blocks.getTransactions(blockhash)
29 | assert ocean.blocks.getTransactions(blockhash, SIZE, NEXT)
30 | assert ocean.blocks.getTransactions(hash=blockhash, size=SIZE, next=NEXT)
31 |
32 |
--------------------------------------------------------------------------------
/tests/ocean/test_oracles.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.oracles.list()
11 | assert ocean.oracles.list(SIZE, NEXT)
12 | assert ocean.oracles.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_getPriceFeed(): # 02
17 | oracleId = "d6c72ef84c9246b0800a9fb1f76a3c1ec071ff566a2aefc1faa20a4bd204ac14"
18 | token = "BTC"
19 | currency = "USD"
20 | assert ocean.oracles.getPriceFeed(oracleId, token, currency)
21 | assert ocean.oracles.getPriceFeed(oracleId, token, currency, SIZE, NEXT)
22 | assert ocean.oracles.getPriceFeed(oracleId=oracleId, token=token, currency=currency, size=SIZE, next=NEXT)
23 |
24 |
25 | @pytest.mark.query
26 | def test_getOracleByAddress(): # 03
27 | address = "df1quc4qephru0a2m58ctusw2qx4cmksdqrvayeklg"
28 | assert ocean.oracles.getOracleByAddress(address)
29 | assert ocean.oracles.getOracleByAddress(address=address)
30 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_data.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, Addresses, TestData
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_hex_data(): # 01
10 | tx = builder_p2wpkh.data.hex_data(data=TestData.hex, addressAmountTo=TestData.addressAmountTo.build(),
11 | changeAddress=Addresses.P2WPKH)
12 |
13 | assert tx.serialize() == TestData.hex_serialized
14 |
15 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
16 |
17 |
18 | @pytest.mark.transactions
19 | def test_str_data(): # 02
20 | tx = builder_p2wpkh.data.str_data(data=TestData.string, addressAmountTo=TestData.addressAmountTo.build(),
21 | changeAddress=Addresses.P2WPKH)
22 |
23 | assert tx.serialize() == TestData.hex_serialized
24 |
25 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Eric Volz
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 |
--------------------------------------------------------------------------------
/tests/node/test_control.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from tests.util import load_secrets_conf
3 |
4 | # Import Exceptions
5 |
6 | from . import node
7 | address = load_secrets_conf()["wallet_address"]
8 |
9 |
10 | @pytest.mark.query
11 | def test_getmemoryinfo(): # 01
12 | assert node.control.getmemoryinfo()
13 | assert node.control.getmemoryinfo("stats")
14 | assert node.control.getmemoryinfo(mode="stats")
15 |
16 |
17 | @pytest.mark.query
18 | def test_getrpcinfo(): # 02
19 | assert node.control.getrpcinfo()
20 |
21 |
22 | @pytest.mark.query
23 | def test_help(): # 03
24 | assert node.control.help()
25 | assert node.control.help("help")
26 | assert node.control.help(command="help")
27 |
28 |
29 | @pytest.mark.query
30 | def test_logging(): # 04
31 | assert node.control.logging()
32 | assert node.control.logging([], [])
33 | assert node.control.logging(include=[], exclude=[])
34 |
35 |
36 | @pytest.mark.query
37 | def test_stop(): # 05
38 | # assert node.control.stop() --> should work :)
39 | assert True
40 |
41 |
42 | @pytest.mark.query
43 | def test_uptime(): # 06
44 | assert node.control.uptime()
45 |
--------------------------------------------------------------------------------
/tests/ocean/test_governance.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 |
5 | @pytest.mark.query
6 | def test_listGovProposals(): # 01
7 | assert ocean.governance.listGovProposals()
8 | assert ocean.governance.listGovProposals("all", "all", 0, False, 30, None)
9 | assert ocean.governance.listGovProposals(status="all", type="all", cycle=0, all=False, size=30, next=None)
10 |
11 |
12 | @pytest.mark.query
13 | def test_getGovProposal(): # 02
14 | proposalId = "a252bea49341adb75842dd30442e5836f9e204e7fa96a1585983eca3b3b5407c"
15 | assert ocean.governance.getGovProposal(proposalId)
16 | assert ocean.governance.getGovProposal(id=proposalId)
17 |
18 |
19 | @pytest.mark.query
20 | def test_listGovProposalVotes(): # 03
21 | proposalId = "a252bea49341adb75842dd30442e5836f9e204e7fa96a1585983eca3b3b5407c"
22 | assert ocean.governance.listGovProposalVotes(proposalId)
23 | assert ocean.governance.listGovProposalVotes(proposalId, "all", 0, False, 30, None)
24 | assert ocean.governance.listGovProposalVotes(id=proposalId, masternodeId="all", cycle=0, all=False, size=30,
25 | next=None)
26 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_governance.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, TestGovernance
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_vote(): # 01
10 | tx_yes = builder_p2wpkh.governance.vote(TestGovernance.proposal_id, TestGovernance.mn_id, "yes")
11 | tx_no = builder_p2wpkh.governance.vote(TestGovernance.proposal_id, TestGovernance.mn_id, "no")
12 | tx_neutral = builder_p2wpkh.governance.vote(TestGovernance.proposal_id, TestGovernance.mn_id, "neutral")
13 |
14 | assert tx_yes.serialize() == TestGovernance.vote_yes_serialized
15 | assert tx_no.serialize() == TestGovernance.vote_no_serialized
16 | assert tx_neutral.serialize() == TestGovernance.vote_neutral_serialized
17 |
18 | assert Transaction.deserialize(DefichainMainnet, tx_yes.serialize()).serialize() == tx_yes.serialize()
19 | assert Transaction.deserialize(DefichainMainnet, tx_no.serialize()).serialize() == tx_no.serialize()
20 | assert Transaction.deserialize(DefichainMainnet, tx_neutral.serialize()).serialize() == tx_neutral.serialize()
21 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation of the Defichain Python Library
2 |
3 | ### **The documentation can be found at:**
4 | **https://docs.defichain-python.de**
5 |
6 |
7 | ---
8 |
9 | # Components of documentation
10 | The documentation website is hosted via GitHub Pages.
11 | All build files can be found on the `gh-pages` branch.
12 |
13 | ## ℹ️ /additionalInfos
14 | A place to store additional information of the documentation such as
15 | reddit posts, instructions or pictures.
16 |
17 | ## 🏗️ /build
18 | This folder is only visible n the `gh-pages` branch and contains all
19 | files which are necessary to display the HTML page.
20 |
21 | ## 📚 /source
22 | This folder contains all the files that define the documentation.
23 | These can be compiled and are saved in the `/build` folder as HTML.
24 |
25 |
26 | # Build Documentation
27 | To build the documentation yourself, follow these steps:
28 |
29 | ```bash
30 | cd docs # change directory to docs
31 | pip install -r requirements_docs.txt # install dependencies
32 |
33 | make clean html # builds the documentation as html
34 | ```
35 | The compiled documentation is now accessible via the `index.html` in the `/build/html` folder.
--------------------------------------------------------------------------------
/defichain/transactions/utils/verify.py:
--------------------------------------------------------------------------------
1 | from defichain.exceptions.transactions import VerifyError
2 | from .converter import Converter
3 |
4 |
5 | class Verify:
6 |
7 | @staticmethod
8 | def is_hex(h: str) -> bool:
9 | try:
10 | Converter.hex_to_int(h)
11 | return True
12 | except:
13 | raise VerifyError("The given value is not a hex string")
14 |
15 | @staticmethod
16 | def is_int(i: int) -> bool:
17 | if isinstance(i, int):
18 | return True
19 | raise VerifyError("The given value is not an integer")
20 |
21 | @staticmethod
22 | def is_float(f: float) -> bool:
23 | if isinstance(f, float):
24 | return True
25 | raise VerifyError("The given value is not an float")
26 |
27 | @staticmethod
28 | def is_str(s: str) -> bool:
29 | if isinstance(s, str):
30 | return True
31 | raise VerifyError("The given value is not an string")
32 |
33 | @staticmethod
34 | def is_only_number_str(s: str) -> bool:
35 | try:
36 | int(s)
37 | return True
38 | except:
39 | return False
40 |
41 |
--------------------------------------------------------------------------------
/tests/transactions/rawtransactions/test_fee.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.transactions.rawtransactions import estimate_fee
4 | from . import TestFee
5 |
6 |
7 | @pytest.mark.transactions
8 | def test_p2pkh_inputs(): # 01
9 | assert estimate_fee(TestFee.P2PKH_Input_Tx, 1) == 190
10 |
11 |
12 | @pytest.mark.transactions
13 | def test_p2sh_inputs(): # 02
14 | assert estimate_fee(TestFee.P2SH_Input_Tx, 1) == 215
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_p2wpkh_inputs(): # 03
19 | assert estimate_fee(TestFee.P2WPKH_Input_Tx, 1) == 192
20 |
21 |
22 | @pytest.mark.transactions
23 | def test_p2pkh_and_p2sh_inputs(): # 04
24 | assert estimate_fee(TestFee.P2PKH_and_P2SH_Input_Tx, 1) == 363
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_p2pkh_and_p2wpkh_inputs(): # 05
29 | assert estimate_fee(TestFee.P2PKH_and_P2WPKH_Input_Tx, 1) == 340
30 |
31 |
32 | @pytest.mark.transactions
33 | def test_p2sh_and_p2wpkh_inputs(): # 06
34 | assert estimate_fee(TestFee.P2SH_and_P2WPKH_Input_Tx, 1) == 365
35 |
36 |
37 | @pytest.mark.transactions
38 | def test_p2pkh_and_p2sh_and_p2wpkh_inputs(): # 07
39 | assert estimate_fee(TestFee.P2PKH_and_P2SH_and_P2WPKH_Input_Tx, 1) == 513
40 |
--------------------------------------------------------------------------------
/defichain/transactions/address/script.py:
--------------------------------------------------------------------------------
1 | from defichain.transactions.constants import OPCodes
2 | from defichain.transactions.utils import Converter, Calculate
3 |
4 |
5 | class Script(object):
6 |
7 | @staticmethod
8 | def build_script(data: []) -> str:
9 | """
10 | Builds the script with the given parameters
11 |
12 | -> the length of the script is not included at the front of the script
13 |
14 | :param data: script parameters and a decoded address
15 | :type data: [hex]
16 | :return: the script that was asked for
17 | """
18 | result = ""
19 | for a in data:
20 | if len(a) > 2:
21 | length_address_decode = int(len(a) / 2)
22 | result += Converter.int_to_hex(length_address_decode, 1) + a
23 | else:
24 | result += a
25 | return result
26 |
27 | @staticmethod
28 | def custom_script(msg: str) -> bytes:
29 | op_return = Converter.hex_to_bytes(OPCodes.OP_RETURN)
30 | msg = Converter.hex_to_bytes(Converter.str_to_hex(msg))
31 | length_msg = Converter.hex_to_bytes(Calculate.write_compactSize(len(msg)))
32 | return op_return + length_msg + msg
33 |
--------------------------------------------------------------------------------
/defichain/node/__init__.py:
--------------------------------------------------------------------------------
1 | # Just to be present: Node
2 | from defichain.node.modules.accounts import Accounts, DVM, EVM
3 | from defichain.node.modules.blockchain import Blockchain
4 | from defichain.node.modules.control import Control
5 | from defichain.node.modules.evm import Evm
6 | from defichain.node.modules.generating import Generating
7 | from defichain.node.modules.loan import Loan
8 | from defichain.node.modules.masternodes import Masternodes
9 | from defichain.node.modules.mining import Mining
10 | from defichain.node.modules.network import Network
11 | from defichain.node.modules.oracles import Oracles
12 | from defichain.node.modules.poolpair import Poolpair
13 | from defichain.node.modules.proposals import Proposals
14 | from defichain.node.modules.rawtransactions import Rawtransactions
15 | from defichain.node.modules.spv import Spv
16 | from defichain.node.modules.stats import Stats
17 | from defichain.node.modules.tokens import Tokens
18 | from defichain.node.modules.util import Util
19 | from defichain.node.modules.vault import Vault
20 | from defichain.node.modules.wallet import Wallet
21 | from defichain.node.modules.zmq import Zmq
22 |
23 | # Util methods
24 |
25 | from defichain.node.util import BuildAmounts, BuildAddressAmounts, BuildTransferDomainData
26 |
--------------------------------------------------------------------------------
/.github/workflows/update_token.yml:
--------------------------------------------------------------------------------
1 | name: UpdateToken
2 |
3 | on:
4 | schedule:
5 | - cron: '0 0 * * *'
6 |
7 | env:
8 | branch: main
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Checkout repository
16 | uses: actions/checkout@v2
17 | with:
18 | ref: ${{ env.branch }}
19 |
20 | - name: Setup python
21 | uses: actions/setup-python@v4
22 | with:
23 | python-version: 3.8
24 |
25 | - name: Install dependencies
26 | run: |
27 | sudo pip install defichain==3.0.0b3
28 | - name: Execute Script
29 | run: |
30 | cd defichain/transactions/constants
31 | sudo python3 tokens.py
32 | - name: Commit changes
33 | run: |
34 | status=$(git status --porcelain)
35 | if [ -z "$status" ]; then
36 | echo "No changes to the repo, skipping the commit"
37 | exit 0
38 | fi
39 |
40 | git config user.name "DefichainPython Bot"
41 | git config user.email "action@github.com"
42 | git add .
43 | git commit -m "Updated token at $(date +'%Y-%m-%d %H:%M:%S')"
44 | - name: Push changes
45 | run: |
46 | git push
47 |
--------------------------------------------------------------------------------
/tests/transactions/utils/test_verify.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import TestVerify
4 | from defichain.exceptions.transactions import VerifyError
5 | from defichain.transactions.utils import Verify
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_is_hex(): # 01
10 | assert Verify.is_hex(TestVerify.HEX_TRUE) is True
11 | with pytest.raises(VerifyError):
12 | assert Verify.is_hex(TestVerify.HEX_FALSE)
13 |
14 |
15 | @pytest.mark.transactions
16 | def test_is_int(): # 02
17 | assert Verify.is_int(TestVerify.INT_TRUE) is True
18 | with pytest.raises(VerifyError):
19 | assert Verify.is_int(TestVerify.INT_FALSE)
20 |
21 |
22 | @pytest.mark.transactions
23 | def test_is_float(): # 03
24 | assert Verify.is_float(TestVerify.FLOAT_TRUE) is True
25 | with pytest.raises(VerifyError):
26 | assert Verify.is_float(TestVerify.FLOAT_FALSE)
27 |
28 |
29 | @pytest.mark.transactions
30 | def test_is_str(): # 04
31 | assert Verify.is_str(TestVerify.STR_TRUE) is True
32 | with pytest.raises(VerifyError):
33 | assert Verify.is_str(TestVerify.STR_FALSE)
34 |
35 |
36 | @pytest.mark.transactions
37 | def test_is_only_number_str(): # 05
38 | assert Verify.is_only_number_str(TestVerify.STR_NUMBER_TRUE) is True
39 | assert Verify.is_only_number_str(TestVerify.STR_NUMBER_FALSE) is False
40 |
--------------------------------------------------------------------------------
/defichain/hdwallet/encrypt.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | from Crypto import Random
4 | from Crypto.Cipher import AES
5 |
6 |
7 | class AESCipher(object):
8 |
9 | def __init__(self, key):
10 | self._bs = AES.block_size
11 | self._key = hashlib.sha256(key.encode()).digest()
12 |
13 | def get_block_size(self) -> int:
14 | return self._bs
15 |
16 | def get_key(self) -> str:
17 | return self._key.hex()
18 |
19 | def _get_bytes_key(self) -> bytes:
20 | return self._key
21 |
22 | def encrypt(self, raw: str) -> str:
23 | raw = self._pad(raw)
24 | iv = Random.new().read(AES.block_size)
25 | cipher = AES.new(self._get_bytes_key(), AES.MODE_CBC, iv)
26 | return base64.b64encode(iv + cipher.encrypt(raw.encode())).hex()
27 |
28 | def decrypt(self, enc: str) -> str:
29 | enc = base64.b64decode(bytes.fromhex(enc))
30 | iv = enc[:AES.block_size]
31 | cipher = AES.new(self._get_bytes_key(), AES.MODE_CBC, iv)
32 | return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
33 |
34 | def _pad(self, s):
35 | return s + (self.get_block_size() - len(s) % self.get_block_size()) * \
36 | chr(self.get_block_size() - len(s) % self.get_block_size())
37 |
38 | @staticmethod
39 | def _unpad(s):
40 | return s[:-ord(s[len(s)-1:])]
41 |
--------------------------------------------------------------------------------
/docs/source/main/statusAndTasks.rst:
--------------------------------------------------------------------------------
1 | .. _instruction statusAndTasks:
2 |
3 | Status and Tasks
4 | ================
5 |
6 | This is a page where you can follow the progress of the project.
7 |
8 | .. admonition:: Obligation
9 | :class: caution
10 |
11 | **Since this is a community supported project, the community also has the right to know about the progress of
12 | the project.**
13 |
14 | Status
15 | ------
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | Tasks
22 | -----
23 |
24 | You can follow the current development an their progress on github via the
25 | `project board `_. In the following
26 | `notion page `_
27 | you can see a representation of all open `github issues `_
28 |
29 | .. raw:: html
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/node/test_node.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from defichain import Node
3 | from tests.util import load_secrets_conf
4 |
5 |
6 | secrets = load_secrets_conf()
7 |
8 |
9 | @pytest.mark.mandatory
10 | def test_createNode():
11 | """
12 | Checking if the Node Object builds as wanted
13 | """
14 | assert Node(secrets["user"], secrets["password"], secrets["url"], secrets["port"])
15 | assert Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"])
16 | if "wallet_path" in secrets:
17 | assert Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"],
18 | wallet_path=secrets["wallet_path"])
19 | assert Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"],
20 | wallet_name=secrets["wallet_path"])
21 | if "wallet_password" in secrets:
22 | if "wallet_path" in secrets:
23 | assert Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"],
24 | wallet_path=secrets["wallet_path"], wallet_timeout=3600)
25 | else:
26 | assert Node(user=secrets["user"], password=secrets["password"], url=secrets["url"], port=secrets["port"],
27 | wallet_password=secrets["wallet_password"], wallet_timeout=3600)
28 |
--------------------------------------------------------------------------------
/tests/transactions/utils/test_calculate.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import TestCalculate
4 | from defichain.transactions.utils import Calculate
5 |
6 |
7 | @pytest.mark.transactions
8 | def test_dHash256(): # 01
9 | assert Calculate.dHash256(bytes.fromhex("6a")).hex() == TestCalculate.DHASH
10 |
11 |
12 | @pytest.mark.transactions
13 | def test_length_varInt(): # 02
14 | assert Calculate.length_varInt(TestCalculate.VARINT) == 3
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_write_varInt(): # 03
19 | assert Calculate.write_varInt(TestCalculate.INT) == TestCalculate.VARINT
20 |
21 |
22 | @pytest.mark.transactions
23 | def test_raed_varInt(): # 04
24 | assert Calculate.read_varInt(TestCalculate.VARINT) == TestCalculate.INT
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_length_compactSize(): # 05
29 | assert Calculate.length_compactSize(TestCalculate.COMPACT_SIZE) == 3
30 |
31 |
32 | @pytest.mark.transactions
33 | def test_write_compactSize(): # 06
34 | assert Calculate.write_compactSize(TestCalculate.INT) == TestCalculate.COMPACT_SIZE
35 |
36 |
37 | @pytest.mark.transactions
38 | def test_raed_compactSize(): # 07
39 | assert Calculate.read_compactSize(TestCalculate.COMPACT_SIZE) == TestCalculate.INT
40 |
41 |
42 | @pytest.mark.transactions
43 | def test_addressAmountSum(): # 08
44 | assert Calculate.addressAmountSum(TestCalculate.ADDRESS_AMOUNT) == 32898
45 |
--------------------------------------------------------------------------------
/tests/README.md:
--------------------------------------------------------------------------------
1 | # DefichainPython Tests
2 |
3 | ## Intention:
4 |
5 | ### Node & Ocean
6 |
7 | The task of the test is to guarantee the always same functionality of all classes and methods
8 |
9 | I assume that all methods are implemented correctly.
10 |
11 | The task of the tests is therefore not to test the correctness of the return of a method,
12 | this is the task of a correct node software.
13 |
14 | ### HDWallet
15 |
16 | The tests of hdwallet are verifying the correctness of the implementation.
17 |
18 | ## Preconditions
19 |
20 | ### Node
21 |
22 | 1. a fix address for all tests for node
23 | 2. a vault on the same address
24 | 3. have funds on the listed places
25 | - 0.5 <= UTXO <= 2 on address
26 | - DFI Token >= 0.01 on address
27 | - DUSD >= 0.01 on address
28 | - vault with big collateralization ratio
29 | 4. create a **secrets_conf.py** and fill out all mandatory information
30 | 5. check if everything is set up properly with the check_setup.py script
31 |
32 | ### Ocean & HDWallet
33 |
34 | There are no preconditions for the tests of ocean and hdwallet.
35 |
36 | ## Testing
37 |
38 | ### Install requirements
39 |
40 | ```bash
41 | pip install -r requirements_tests.txt
42 | ```
43 |
44 | ### Run tests
45 |
46 | #### Run all tests
47 |
48 | ```bash
49 | cd tests
50 | pytest
51 | ```
52 |
53 | #### Run specific tests
54 | ```bash
55 | cd tests
56 | pytest node
57 | pytest ocean
58 | pytest hdwallet
59 | ```
--------------------------------------------------------------------------------
/tests/node/test_evm.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | # Import Exceptions
3 | from defichain.exceptions.http.InternalServerError import InternalServerError
4 |
5 | from . import node
6 |
7 |
8 | @pytest.mark.query
9 | def test_evmtx(): # 01
10 | evm_address = "0xB553De274BFc1293DC703B013464202fC65E3FDF"
11 |
12 | string = ".* RPC_TYPE_ERROR: Invalid amount"
13 | with pytest.raises(InternalServerError, match=string):
14 | assert node.evm.evmtx(evm_address, 0x0, 0x09184e72a000, 0x2710, evm_address, 0x1e4876e800)
15 | with pytest.raises(InternalServerError, match=string):
16 | assert node.evm.evmtx(_from=evm_address, nonce=0x0, gasPrice=0x09184e72a000, gasLimit=0x2710,
17 | to=evm_address, value=0x1e4876e800)
18 | with pytest.raises(InternalServerError, match=string):
19 | assert node.evm.evmtx(_from=evm_address, nonce=0x0, gasPrice=0x09184e72a000, gasLimit=0x2710,
20 | to=evm_address, value=0x1e4876e800, data=0x0)
21 |
22 |
23 | @pytest.mark.query
24 | def test_logvmmaps(): # 02
25 | assert node.evm.logvmmaps(0)
26 | assert node.evm.logvmmaps(type=0)
27 |
28 |
29 | @pytest.mark.query
30 | def test_vmmap(): # 03
31 | string = ".* RPC_INVALID_PARAMETER: Key not found: *."
32 | with pytest.raises(InternalServerError, match=string):
33 | assert node.evm.vmmap("1600000", 0)
34 | with pytest.raises(InternalServerError, match=string):
35 | assert node.evm.vmmap(input="1600000", type=0)
36 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_accounts.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, Addresses, TestAccounts
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_utxotoaccount(): # 01
10 | tx = builder_p2wpkh.accounts.utxostoaccount(address=Addresses.P2WPKH, amount=0.00001, tokenId=0)
11 |
12 | assert tx.serialize() == TestAccounts.utxo_to_account_serialized
13 |
14 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_accounttoutxo(): # 02
19 | tx = builder_p2wpkh.accounts.accounttoutxos(addressFrom=Addresses.P2WPKH,
20 | addressAmountTo=TestAccounts.addressAmountTo.build())
21 |
22 | assert tx.serialize() == TestAccounts.account_to_utxo_serialized
23 |
24 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_accounttoaccount(): # 03
29 | tx = builder_p2wpkh.accounts.accounttoaccount(addressFrom=Addresses.P2WPKH,
30 | addressAmountTo=TestAccounts.addressAmountTo.build())
31 |
32 | assert tx.serialize() == TestAccounts.account_to_account_serialized
33 |
34 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
35 |
--------------------------------------------------------------------------------
/defichain/transactions/remotedata/ocean.py:
--------------------------------------------------------------------------------
1 | from .remotedata import RemoteData
2 | from defichain import Ocean
3 |
4 |
5 | class RemoteDataOcean(RemoteData):
6 |
7 | def __init__(self, source: Ocean):
8 | self.ocean = source
9 |
10 | def get_unspent(self, address: str) -> [{}]:
11 | data = self.ocean.address.listTransactionUnspent(address, 200)["data"]
12 | unspent = []
13 | for u in data:
14 | txid = u["vout"]["txid"]
15 | index = u["vout"]["n"]
16 | value = int(round(float(u["vout"]["value"]) * 100000000))
17 | script = u["script"]["hex"]
18 | unspent.append({"txid": txid, "vout": index, "value": value, "scriptPubKey": script})
19 | return unspent
20 |
21 | def check_masternode(self, masternodeId: str) -> bool:
22 | data = self.ocean.masternodes.get(masternodeId)["data"]
23 | if "error" in data or data["state"] not in ('PRE_ENABLED', 'ENABLED', 'PRE_RESIGNED'):
24 | return False
25 | return True
26 |
27 | def test_tx(self, hex: str, maxFeeRate: float = None) -> bool:
28 | try:
29 | self.ocean.rawTx.test(hex, maxFeeRate)
30 | return True
31 | except:
32 | return False
33 |
34 | def send_tx(self, hex: str, maxFeeRate: float = None) -> str:
35 | result = self.ocean.rawTx.send(hex, maxFeeRate)
36 | if "data" in result:
37 | return result["data"]
38 | else:
39 | return result
40 |
41 |
--------------------------------------------------------------------------------
/tests/transactions/defitx/test_governance.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.networks import DefichainMainnet
4 | from defichain.transactions.defitx import DefiTx, CreateCfp, CreateVoc, Vote
5 | from . import TestGovernance
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_vote(): # 01
10 | vote_yes: Vote = Vote(proposalId=TestGovernance.proposalId, masternodeId=TestGovernance.masternodeId,
11 | decision=TestGovernance.decision[0])
12 | vote_no: Vote = Vote(proposalId=TestGovernance.proposalId, masternodeId=TestGovernance.masternodeId,
13 | decision=TestGovernance.decision[1])
14 | vote_neutral: Vote = Vote(proposalId=TestGovernance.proposalId, masternodeId=TestGovernance.masternodeId,
15 | decision=TestGovernance.decision[2])
16 |
17 | assert vote_yes.serialize() == TestGovernance.vote_yes_serialized
18 | assert vote_no.serialize() == TestGovernance.vote_no_serialized
19 | assert vote_neutral.serialize() == TestGovernance.vote_neutral_serialized
20 |
21 | assert DefiTx.deserialize(DefichainMainnet, TestGovernance.vote_yes_serialized).serialize() == \
22 | TestGovernance.vote_yes_serialized
23 | assert DefiTx.deserialize(DefichainMainnet, TestGovernance.vote_no_serialized).serialize() == \
24 | TestGovernance.vote_no_serialized
25 | assert DefiTx.deserialize(DefichainMainnet, TestGovernance.vote_neutral_serialized).serialize() == \
26 | TestGovernance.vote_neutral_serialized
27 |
28 |
--------------------------------------------------------------------------------
/docs/source/legal/licenseAndDisclaimer.rst:
--------------------------------------------------------------------------------
1 | .. _legal license&disclaimer:
2 |
3 | License & Disclaimer
4 | ====================
5 |
6 | By using (this repo), you (the user) agree to be bound by the
7 | `terms of this license `_ (MIT License).
8 |
9 | .. code-block:: text
10 |
11 | MIT License
12 |
13 | Copyright (c) 2023 Eric Volz
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the "Software"), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in all
23 | copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 | SOFTWARE.
--------------------------------------------------------------------------------
/tests/ocean/test_rawTx.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 | from defichain.exceptions.http.BadRequest import BadRequest
4 |
5 | HEX = "0400000001616cd43cb0d396c52d6a5342f9411307a4dc4847f9237ff8bbb62e0c247be803010000006a4730440220119839df669bf6e" \
6 | "b24dd7b806cdb782ffc1ffa892fd663b5be6bf3d22cc9fdd9022028f4e981bcbcfbec0ff508a9b67fd353840ed3132c4528ecc894b90c" \
7 | "da49382f012102d9438499f4280c74afa1e9cf1d3df9cff599d05740d9355acc6be97f45575251fdffffff0262390f00000000001976a" \
8 | "9147d8c7b0c6e867e3034afc49eabc16ed33590400388ac007950d705000000001976a9147d8c7b0c6e867e3034afc49eabc16ed33590" \
9 | "400388ac0000000000"
10 |
11 |
12 | @pytest.mark.query
13 | def test_send(): # 01
14 | string = ".*'Missing inputs'"
15 | with pytest.raises(BadRequest, match=string):
16 | assert ocean.rawTx.send(HEX)
17 | assert ocean.rawTx.send(HEX, 0.001)
18 | assert ocean.rawTx.send(hex=HEX, maxFeeRate=0.001)
19 |
20 |
21 | @pytest.mark.query
22 | def test_test(): # 02
23 | string = ".*'Transaction is not allowed to be inserted'"
24 | with pytest.raises(BadRequest, match=string):
25 | assert ocean.rawTx.test(HEX)
26 | assert ocean.rawTx.test(HEX, 0.001)
27 | assert ocean.rawTx.test(hex=HEX, maxFeeRate=0.001)
28 |
29 |
30 | @pytest.mark.query
31 | def test_get(): # 03
32 | assert ocean.rawTx.get("af6294e9729c6a4f31439e86374541658f35f4cc372a51e06c725429d875ac5c")
33 | assert ocean.rawTx.get("af6294e9729c6a4f31439e86374541658f35f4cc372a51e06c725429d875ac5c")
34 |
--------------------------------------------------------------------------------
/tests/hdwallet/test_utils.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from defichain.hdwallet.utils import *
3 |
4 | ENTROPY = "ee535b143b0d9d1f87546f9df0d06b1a"
5 | MNEMONIC = "unusual onion shallow invite supply more bubble mistake over make bracket cry"
6 |
7 |
8 | @pytest.mark.hdwallet
9 | def test_generate_passphrase(): # 01
10 | assert len(generate_passphrase(length=32)) == 32
11 |
12 |
13 | @pytest.mark.hdwallet
14 | def test_generate_entropy(): # 02
15 | assert get_entropy_strength(generate_entropy(strength=256)) == 256
16 |
17 |
18 | @pytest.mark.hdwallet
19 | def test_generate_mnemonic(): # 03
20 | assert len(generate_mnemonic(language="english", strength=256).split(" ")) == 24
21 |
22 |
23 | @pytest.mark.hdwallet
24 | def test_is_entropy(): # 04
25 | assert is_entropy(entropy=ENTROPY) is True
26 |
27 |
28 | @pytest.mark.hdwallet
29 | def test_is_mnemonic(): # 05
30 | assert is_mnemonic(mnemonic=MNEMONIC, language="english") is True
31 |
32 |
33 | @pytest.mark.hdwallet
34 | def test_get_entropy_strength(): # 06
35 | assert get_entropy_strength(entropy=ENTROPY) == 128
36 |
37 |
38 | @pytest.mark.hdwallet
39 | def test_get_mnemonic_language(): # 07
40 | assert get_mnemonic_language(mnemonic=MNEMONIC) == "english"
41 |
42 |
43 | @pytest.mark.hdwallet
44 | def test_entropy_to_mnemonic(): # 08
45 | assert entropy_to_mnemonic(ENTROPY, language="english") == MNEMONIC
46 |
47 |
48 | @pytest.mark.hdwallet
49 | def test_mnemonic_to_entropy(): # 09
50 | assert mnemonic_to_entropy(mnemonic=MNEMONIC, language="english") == ENTROPY
51 |
52 |
53 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_vault.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, TestVault, Addresses
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_createvault(): # 01
10 | tx = builder_p2wpkh.vault.createvault(ownerAddress=Addresses.P2WPKH, schemeId="MIN150", inputs=[TestVault.input])
11 |
12 | assert tx.serialize() == TestVault.create_vault_serialized
13 |
14 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_deposittovault(): # 02
19 | tx = builder_p2wpkh.vault.deposittovault(vaultId=TestVault.vault_id,
20 | addressFrom=Addresses.P2WPKH,
21 | amount=TestVault.amount)
22 |
23 | assert tx.serialize() == TestVault.deposit_to_vault_serialized
24 |
25 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
26 |
27 |
28 | @pytest.mark.transactions
29 | def test_withdrawfromvault(): # 03
30 | tx = builder_p2wpkh.vault.deposittovault(vaultId=TestVault.vault_id,
31 | addressFrom=Addresses.P2WPKH,
32 | amount=TestVault.amount)
33 |
34 | assert tx.serialize() == TestVault.withdraw_from_vault_serialized
35 |
36 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
37 |
--------------------------------------------------------------------------------
/defichain/transactions/builder/modules/governance.py:
--------------------------------------------------------------------------------
1 | from defichain.transactions.defitx import Vote
2 | from defichain.transactions.utils import Converter
3 | from defichain.transactions.builder.rawtransactionbuilder import RawTransactionBuilder, Transaction
4 |
5 |
6 | class Governance:
7 | """
8 | **The methods of this module create governance transactions**
9 |
10 | 1. **vote**: transaction witch includes your own hexadecimal data
11 | """
12 |
13 | def __init__(self, builder):
14 | self._builder: RawTransactionBuilder = builder
15 |
16 | def vote(self, proposalId: str, masternodeId: str, decision: str, inputs=[]) -> Transaction:
17 | """
18 | Creates a transaction that votes for proposal
19 |
20 | >>> builder.governance.vote("1f4039ab714cf73ff1d92b58608ed20a73a799cde88c103b679bdafd83eb472b", "33abc61982725be797f83b47da6f41a344f4d64879d84e31d87a91281070add8", "neutral") # creates a vote transaction
21 |
22 | :param proposalId: (required) the proposal txid
23 | :type proposalId: str
24 | :param masternodeId: (required) the masternodeId to vote with
25 | :type masternodeId: str
26 | :param decision: (required) the vote decision (yes / no / neutral)
27 | :type decision: str
28 | :param inputs: (optional) additional inputs to spend
29 | :type inputs: [TxInput]
30 | :return: :ref:`Transaction Advanced RawTransactions Transaction`
31 | """
32 |
33 | defiTx = Vote(proposalId, masternodeId, decision)
34 | return self._builder.build_defiTx(0, defiTx, inputs)
35 |
--------------------------------------------------------------------------------
/tests/transactions/address/test_address.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import MainNet, TestNet
4 | from defichain.transactions.address import Address, P2PKH, P2SH, P2WPKH
5 | from defichain.transactions.constants import AddressTypes
6 |
7 | network = (MainNet, TestNet)
8 |
9 |
10 | @pytest.mark.transactions
11 | def test_get_addressType(): # 01
12 | for n in network:
13 | assert Address.get_addressType(n.P2PKH) == (n.NETWORK, AddressTypes.P2PKH)
14 | assert Address.get_addressType(n.P2SH) == (n.NETWORK, AddressTypes.P2SH)
15 | assert Address.get_addressType(n.P2WPKH) == (n.NETWORK, AddressTypes.P2WPKH)
16 |
17 |
18 | @pytest.mark.transactions
19 | def test_from_address(): # 02
20 | for n in network:
21 | assert isinstance(Address.from_address(n.P2PKH), P2PKH)
22 | assert isinstance(Address.from_address(n.P2SH), P2SH)
23 | assert isinstance(Address.from_address(n.P2WPKH), P2WPKH)
24 |
25 |
26 | @pytest.mark.transactions
27 | def test_from_scriptPublicKey(): # 03
28 | for n in network:
29 | assert Address.from_scriptPublicKey(n.NETWORK, n.P2PKH_SCRIPTPUBLICKEY).get_address() == n.P2PKH
30 | assert Address.from_scriptPublicKey(n.NETWORK, n.P2SH_SCRIPTPUBLICKEY).get_address() == n.P2SH
31 | assert Address.from_scriptPublicKey(n.NETWORK, n.P2WPKH_SCRIPTPUBLICKEY).get_address() == n.P2WPKH
32 |
33 |
34 | @pytest.mark.transactions
35 | def test_verify_address(): # 04
36 | for n in network:
37 | assert Address.verify_address(n.P2PKH)
38 | assert Address.verify_address(n.P2SH)
39 | assert Address.verify_address(n.P2WPKH)
40 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/masternodes.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/MasterNodes.ts
2 |
3 | class Masternodes:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def list(self, size: int = 30, next: str = None) -> {}: # 01
8 | """
9 | Get list of masternodes
10 |
11 | :param size: (optional) size masternodes size to query
12 | :type size: int
13 | :param next: (optional) next set of masternodes to get
14 | :type next: str
15 | :return: (json string) {id: str, sort: str, state: MasternodeState, mintedBlocks: int, owner: {address: str},
16 | operator: {address: str}, creation: {height: int}, resign: {tx: str, height: int},
17 | timelock: int}
18 |
19 | :example:
20 |
21 | >>> ocean.masternodes.list()
22 | """
23 | return self._ocean._conn.get("masternodes", size=size, next=next)
24 |
25 | def get(self, id: str) -> {}: # 02
26 | """
27 | Get information about a masternode with given id
28 |
29 | :param id: (required) id masternode id to get
30 | :type id: str
31 | :return: (json string) {id: str, sort: str, state: MasternodeState, mintedBlocks: int, owner: {address: str},
32 | operator: {address: str}, creation: {height: int}, resign: {tx: str, height: int},
33 | timelock: int}
34 |
35 | :example:
36 |
37 | >>> ocean.masternodes.get("bbdd23cfb429680fd10a3ce169595ff6123ef576bb936add069812528f73ceaa")
38 | """
39 | return self._ocean._conn.get(f"masternodes/{id}")
40 |
--------------------------------------------------------------------------------
/docs/additionalInfos/reddit/announcement02.md:
--------------------------------------------------------------------------------
1 | ## The Defichain Python Library implements HDWallet!
2 |
3 | Dear Defichain Community,
4 |
5 | a few days ago I released version 2.0.0 of the [Defichain Python Library](https://github.com/eric-volz/DefichainPython).
6 |
7 | ### What is new?
8 | #### Hierarchical Deterministic Wallet
9 | The new feature of this version is the implementation of Hierarchical Deterministic Wallet.
10 | With this mnemonic seeds can be generated and addresses and private keys can be extracted.
11 |
12 | The HDWallet implementation corresponds to the addresses of the lightwallet.
13 | So it is possible to find out private keys to addresses using the mnemonic seeds of the lightwallet.
14 | These private keys can then be imported into a defichain node wallet.
15 | With that is possible to control your lightwallet address.
16 |
17 | More information about how to use the HDWallet can be found on the
18 | [documentation page](https://docs.defichain-python.de/build/html/api/hdwallet/index.html).
19 |
20 | ### What's next?
21 | - implementation of new Ocean API methods
22 | - implementation of the [Historic Defichain Data API](https://github.com/DeFiCh/dfips/issues/209) (when available)
23 |
24 | ### Here are some important links around the project:
25 | - [Github](https://github.com/eric-volz/DefichainPython)
26 | - [Documentation](https://docs.defichain-python.de/)
27 | - [PyPI](https://pypi.org/project/defichain/)
28 |
29 | If you have suggestions for improvement
30 | or other ideas open an [issue](https://github.com/eric-volz/DefichainPython/issues),
31 | write me on [Twitter](https://twitter.com/Intr0c) or via email (introc@volz.link)!
32 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_masternode.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, TestMasternode
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_createmasternode(): # 01
10 | tx = builder_p2wpkh.masternode.createmasternode(operatorAddress=TestMasternode.operatorAddress,
11 | timeLock=0, inputs=[TestMasternode.input])
12 |
13 | assert tx.serialize() == TestMasternode.createmasternode_serialized
14 |
15 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
16 |
17 |
18 | @pytest.mark.transactions
19 | def test_resignmasternode(): # 02
20 | tx = builder_p2wpkh.masternode.resignmasternode(masternodeId=TestMasternode.mn_id)
21 |
22 | assert tx.serialize() == TestMasternode.resignmasternode_serialized
23 |
24 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_updatemasternode(): # 03
29 | tx = builder_p2wpkh.masternode.updatemasternode(masternodeId=TestMasternode.mn_id,
30 | ownerAddress=TestMasternode.ownerAddress,
31 | operatorAddress=TestMasternode.operatorAddress,
32 | rewardAddress=TestMasternode.rewardAddress)
33 |
34 | assert tx.serialize() == TestMasternode.updatemasternode_serialized
35 |
36 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
37 |
--------------------------------------------------------------------------------
/defichain/transactions/remotedata/remotedata.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 |
4 | class RemoteData(ABC):
5 | """
6 | This class contains all abstract methods that has to implement to be usable as a remote data source
7 | """
8 | @abstractmethod
9 | def __init__(self, source: object):
10 | pass
11 |
12 | @abstractmethod
13 | def get_unspent(self, address: str) -> [{}]:
14 | """
15 | Contains all needed information about the unspent input of an address
16 |
17 | :param address: the address to list the unspent from
18 | :return: [{txid: ..., vout: ..., value: ..., scriptPubKey: ...}, ...]
19 | """
20 | pass
21 |
22 | @abstractmethod
23 | def check_masternode(self, masternodeId: str) -> bool:
24 | """
25 | Returns True if the given masternode exists and is Pre-Enabled, Enabled or Pre-Resigned
26 |
27 | :param masternodeId: txid of the creation of the masternode
28 | :type masternodeId: str
29 | :return: bool
30 | """
31 |
32 | @abstractmethod
33 | def test_tx(self, hex: str, maxFeeRate: float = None) -> bool:
34 | """
35 | Test the given raw transaction
36 |
37 | :param hex: raw transaction
38 | :param maxFeeRate: maximum fee rate to pay
39 | :return: bool
40 | """
41 | pass
42 |
43 | @abstractmethod
44 | def send_tx(self, hex: str, maxFeeRate: float = None) -> str:
45 | """
46 | Sends the given raw transaction to the blockchain
47 |
48 | :param hex: raw transaction
49 | :param maxFeeRate: maximum fee rate to pay
50 | :return: txid
51 | """
52 | pass
53 |
54 |
--------------------------------------------------------------------------------
/tests/transactions/rawtransactions/test_tx.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from defichain.transactions.rawtransactions import Transaction
3 | from defichain.networks import DefichainMainnet
4 |
5 | from . import TestTx, Addresses
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_create_transaction(): # 01
10 | for i in range(len(TestTx.tx_unsigned)):
11 | assert TestTx.tx_unsigned[i].serialize() == TestTx.serialized_unsigned[i]
12 |
13 |
14 | @pytest.mark.transactions
15 | def test_deserialize_transaction(): # 02
16 | for i in TestTx.serialized_unsigned:
17 | assert Transaction.deserialize(DefichainMainnet, i).serialize() == i
18 |
19 | for i in TestTx.serialized_signed:
20 | assert Transaction.deserialize(DefichainMainnet, i).serialize() == i
21 |
22 |
23 | @pytest.mark.transactions
24 | def test_sign_transaction(): # 03
25 | for i in range(len(TestTx.tx_signed)):
26 | assert TestTx.tx_signed[i].serialize() == TestTx.serialized_signed[i]
27 |
28 |
29 | @pytest.mark.transactions
30 | def test_fee_transaction(): # 05
31 | for i in range(len(TestTx.tx_unsigned)):
32 | assert TestTx.tx_unsigned[i].get_fee() == TestTx.fee[i]
33 |
34 | for i in range(len(TestTx.tx_signed)):
35 | assert TestTx.tx_signed[i].get_fee() == TestTx.fee[i]
36 |
37 |
38 | @pytest.mark.transactions
39 | def test_txid_transaction(): # 07
40 | for i in range(len(TestTx.tx_signed)):
41 | assert TestTx.tx_signed[i].get_txid() == TestTx.txid[i]
42 |
43 |
44 | @pytest.mark.transactions
45 | def test_unspent_transaction(): # 06
46 | for tx in TestTx.tx_signed:
47 | for unspent in tx.get_unspent([Addresses.P2WPKH]):
48 | assert unspent.serialize() in TestTx.unspent_inputs
49 |
--------------------------------------------------------------------------------
/tests/transactions/defitx/test_vaults.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.networks import DefichainMainnet
4 | from defichain.transactions.defitx import DefiTx, CreateVault, DepositToVault, WithdrawFromVault
5 | from . import Addresses, TestVaults
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_craetevault(): # 01
10 | createvault: CreateVault = CreateVault(ownerAddress=TestVaults.ownerAddress, schemeId=TestVaults.schemeId)
11 |
12 | assert createvault.serialize() == TestVaults.createvault_serialized
13 |
14 | assert DefiTx.deserialize(DefichainMainnet, TestVaults.createvault_serialized).serialize() == \
15 | TestVaults.createvault_serialized
16 |
17 |
18 | @pytest.mark.transactions
19 | def test_deposittovault(): # 02
20 | deposittovault: DepositToVault = DepositToVault(vaultId=TestVaults.vaultId, addressFrom=TestVaults.addressFrom,
21 | amount=TestVaults.amount)
22 |
23 | assert deposittovault.serialize() == TestVaults.deposittovault_serialized
24 |
25 | assert DefiTx.deserialize(DefichainMainnet, TestVaults.deposittovault_serialized).serialize() == \
26 | TestVaults.deposittovault_serialized
27 |
28 |
29 | @pytest.mark.transactions
30 | def test_withdrawfromvault(): # 03
31 | withdrawfromvault: WithdrawFromVault = WithdrawFromVault(vaultId=TestVaults.vaultId, addressTo=TestVaults.addressTo,
32 | amount=TestVaults.amount)
33 |
34 | assert withdrawfromvault.serialize() == TestVaults.withdrawfromvault_serialized
35 |
36 | assert DefiTx.deserialize(DefichainMainnet, TestVaults.withdrawfromvault_serialized).serialize() == \
37 | TestVaults.withdrawfromvault_serialized
38 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/tokens.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Tokens.ts
2 |
3 | class Tokens:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def list(self, size: int = 30, next: str = None) -> [{}]:
8 | """
9 | Paginate query tokens
10 |
11 | :param size: (optional) size of tokens to query
12 | :type size: int
13 | :param next: (optional) next set of tokens
14 | :type next: str
15 | :return: (json string) {id: str, symbol: str, displaySymbol: str, symbolKey: str, name: str, decimal: float,
16 | limit: str, mintable: bool, tradeable: bool, isDAT: bool, isLPS: bool, isLoanToken: bool,
17 | finalized: bool, minted: str, creation: {tx: str, height: int}, destruction: {tx: str,
18 | height: int}, collateralAddress: str}
19 |
20 | :example:
21 |
22 | >>> ocean.tokens.list()
23 | """
24 | return self._ocean._conn.get("tokens", size=size, next=next)
25 |
26 | def get(self, id: str) -> {}:
27 | """
28 | Get information about a token with id of the token
29 |
30 | :param id: (required) id of the token
31 | :type id: str
32 | :return: (json string) {id: str, symbol: str, displaySymbol: str, symbolKey: str, name: str, decimal: float,
33 | limit: str, mintable: bool, tradeable: bool, isDAT: bool, isLPS: bool, isLoanToken: bool,
34 | finalized: bool, minted: str, creation: {tx: str, height: int}, destruction: {tx: str,
35 | height: int}, collateralAddress: str}
36 |
37 | :example:
38 |
39 | >>> ocean.tokens.get(0)
40 | """
41 | return self._ocean._conn.get(f"tokens/{id}")
42 |
--------------------------------------------------------------------------------
/docs/additionalInfos/reddit/announcement01.md:
--------------------------------------------------------------------------------
1 | ## The Defichain Python Library has reached version 1.0.0!
2 |
3 | Dear Defichain Community,
4 |
5 | a few weeks ago I released version 1.0.0 of the [Defichain Python Library](https://github.com/eric-volz/DefichainPython).
6 |
7 | All methods of the Defichain node and Ocean commands to pull data have already been implemented and tested.
8 |
9 | The documentation of the single methods is not finished yet, but will follow in the next weeks.
10 | You can see the progress of the different parts of the project [here](https://docs.defichain-python.de/build/html/instructions/progressAndUpdates.html).
11 |
12 | To ensure an easy start with the library I have created a [Quickstart](https://docs.defichain-python.de/build/html/instructions/quickstart.html) Guide.
13 |
14 | For people who want to get to know the Defichain Node through this library there will be a ["How to install and configure a Defichain Node"](https://docs.defichain-python.de/build/html/additionalInfos/installDefichainNode.html) Guide.
15 |
16 | ### Here are some important links around the project:
17 | - [Github](https://github.com/eric-volz/DefichainPython)
18 | - [Documentation](https://docs.defichain-python.de/)
19 | - [PyPI](https://pypi.org/project/defichain/)
20 |
21 | Now is the best time to develop new applications or trading bots: Money is made in bear markets!
22 |
23 | Install the Defichain Python library now via pip:
24 | ```bash
25 | pip install defichain
26 | ```
27 |
28 | If you have suggestions for improvement
29 | or other ideas open an [issue](https://github.com/eric-volz/DefichainPython/issues),
30 | write me on [Twitter](https://twitter.com/Intr0c) or via email (introc@volz.link)!
31 |
32 | ### A big thank you goes to [MarcelKB](https://mobile.twitter.com/marcelkb1) <3
--------------------------------------------------------------------------------
/defichain/transactions/rawtransactions/fee.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | from defichain.transactions.constants import TxSize
4 | from .txinput import TxP2PKHInput, TxP2SHInput, TxP2WPKHInput
5 | from .tx import Transaction
6 |
7 |
8 | def estimate_size(tx: Transaction):
9 | """
10 | Estimates the size of the later signed transaction.
11 |
12 | :param tx: (required) the unsigned transaction object
13 | :type tx: Transaction
14 | :return: "int" - size of the signed transaction
15 | """
16 | # Current Size
17 | size = tx.size()
18 |
19 | # Add witness and signature size
20 | for input in tx.get_inputs():
21 | if isinstance(input, TxP2SHInput) or isinstance(input, TxP2WPKHInput):
22 | size += TxSize.WITNESS_SIGNATURE_LENGTH + TxSize.WITNESS_SIGNATURE + \
23 | TxSize.PUBLIC_KEY_LENGTH + TxSize.PUBLIC_KEY
24 | elif isinstance(input, TxP2PKHInput):
25 | size += TxSize.SCRIPTSIG_SIGNATURE
26 | return size
27 |
28 |
29 | def estimate_fee(tx: Transaction, feePerByte: float):
30 | """
31 | Estimates fees for unsigned transaction
32 |
33 | :param tx: (required) the unsigned transaction object
34 | :type tx: Transaction
35 | :param feePerByte: (required) the amount of fee to pay per byte
36 | :type feePerByte: float
37 | :return: "int" - the amount of fee to pay
38 | """
39 |
40 | size = estimate_size(tx)
41 |
42 | return round(size * feePerByte)
43 |
44 |
45 | def estimate_vsize(tx: Transaction):
46 | """
47 | Estimates the vSize of the later signed transaction.
48 |
49 | :param tx: (required) the unsigned transaction object
50 | :type tx: Transaction
51 | :return: "int" - vSize of the signed transaction
52 | """
53 | unsigned_size = tx.size()
54 | signed_size = estimate_size(tx)
55 |
56 | return math.ceil(unsigned_size + (signed_size - unsigned_size) / 4)
57 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_txbuilder.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import Keys, TestTxBuilder, builder_p2wpkh, Addresses
3 |
4 | from defichain import TxBuilder, Ocean
5 | from defichain.exceptions.transactions import TxBuilderError
6 | from defichain.exceptions.http import BadRequest
7 |
8 |
9 | @pytest.mark.transactions
10 | def test_create(): # 01
11 | assert TxBuilder(address=Keys.account.get_p2wpkh(), account=Keys.account, dataSource=Ocean(), feePerByte=1.0)
12 | with pytest.raises(TxBuilderError, match="The given address does not match the given account!"):
13 | assert TxBuilder(address=Keys.account.get_p2wpkh(), account=Keys.wallet.get_account(10),
14 | dataSource=Ocean(), feePerByte=1.0)
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_send_tx(): # 02
19 | with pytest.raises(BadRequest):
20 | assert builder_p2wpkh.send_tx(TestTxBuilder.tx_serialized)
21 | with pytest.raises(BadRequest):
22 | assert builder_p2wpkh.send_tx(TestTxBuilder.tx)
23 |
24 |
25 | @pytest.mark.transactions
26 | def test_test_tx(): # 03
27 | assert builder_p2wpkh.test_tx(TestTxBuilder.tx_serialized)
28 | assert builder_p2wpkh.test_tx(TestTxBuilder.tx)
29 |
30 |
31 | @pytest.mark.transactions
32 | def test_get_inputs_tx(): # 04
33 | assert builder_p2wpkh.get_inputs_tx().serialize() == TestTxBuilder.inputs_tx_serialized
34 |
35 |
36 | @pytest.mark.transactions
37 | def test_get_address(): # 05
38 | assert builder_p2wpkh.get_address() == Addresses.P2WPKH
39 |
40 |
41 | @pytest.mark.transactions
42 | def test_get_account(): # 06
43 | assert builder_p2wpkh.get_account() == Keys.account
44 |
45 |
46 | @pytest.mark.transactions
47 | def test_get_dataSource(): # 07
48 | assert builder_p2wpkh.get_dataSource()
49 |
50 |
51 | @pytest.mark.transactions
52 | def test_get_feePerByte(): # 08
53 | assert builder_p2wpkh.get_feePerByte() == 1
54 |
55 |
--------------------------------------------------------------------------------
/tests/ocean/test_prices.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.prices.list()
11 | assert ocean.prices.list(SIZE, NEXT)
12 | assert ocean.prices.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_get(): # 02
17 | token = "DFI"
18 | currency = "USD"
19 | assert ocean.prices.get(token, currency)
20 | assert ocean.prices.get(token=token, currency=currency)
21 |
22 |
23 | @pytest.mark.query
24 | def test_getFeedActive(): # 03
25 | token = "DFI"
26 | currency = "USD"
27 | assert ocean.prices.getFeedActive(token, currency)
28 | assert ocean.prices.getFeedActive(token, currency, SIZE, NEXT)
29 | assert ocean.prices.getFeedActive(token=token, currency=currency, size=SIZE, next=NEXT)
30 |
31 |
32 | @pytest.mark.query
33 | def test_getFeed(): # 04
34 | token = "DFI"
35 | currency = "USD"
36 | assert ocean.prices.getFeed(token, currency)
37 | assert ocean.prices.getFeed(token, currency, SIZE, NEXT)
38 | assert ocean.prices.getFeed(token=token, currency=currency, size=SIZE, next=NEXT)
39 |
40 |
41 | @pytest.mark.query
42 | def test_getFeedWithInterval(): # 05
43 | token = "DFI"
44 | currency = "USD"
45 | interval = 3600
46 | assert ocean.prices.getFeedWithInterval(token, currency, interval)
47 | assert ocean.prices.getFeedWithInterval(token, currency, interval, SIZE, NEXT)
48 | assert ocean.prices.getFeedWithInterval(token=token, currency=currency, interval=interval, size=SIZE, next=NEXT)
49 |
50 |
51 | @pytest.mark.query
52 | def test_getOracles(): # 06
53 | token = "DFI"
54 | currency = "USD"
55 | assert ocean.prices.getOracles(token, currency)
56 | assert ocean.prices.getOracles(token, currency, SIZE, NEXT)
57 | assert ocean.prices.getOracles(token=token, currency=currency, size=SIZE, next=NEXT)
58 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/rawTx.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/RawTx.ts
2 | import json
3 | from defichain.node.util import BuildJson
4 |
5 |
6 | class RawTx:
7 | def __init__(self, ocean):
8 | self._ocean = ocean
9 |
10 | def send(self, hex: str, maxFeeRate: float = None) -> str:
11 | """
12 | Send a raw transaction
13 |
14 | :param hex: (required) rawTx to submit to the network
15 | :type hex: str
16 | :param maxFeeRate: (optional) maximum fee rate
17 | :type maxFeeRate: float
18 | :return: "txid" (string)
19 |
20 | :example:
21 |
22 | >>> ocean.rawTx.send("hex")
23 | """
24 | j = BuildJson()
25 | j.append("hex", hex)
26 | j.append("maxFeeRate", maxFeeRate)
27 | return self._ocean._conn.post("rawtx/send", json.dumps(j.build()))
28 |
29 | def test(self, hex: str, maxFeeRate: float = None):
30 | """
31 | Send a raw transaction to test the mempool acceptance
32 |
33 | :param hex: (required) rawTx to submit to the network
34 | :type hex: str
35 | :param maxFeeRate: (optional) maximum fee rate
36 | :type maxFeeRate: float
37 |
38 | :example:
39 |
40 | >>> ocean.rawTx.test("hex")
41 | """
42 | j = BuildJson()
43 | j.append("hex", hex)
44 | j.append("maxFeeRate", maxFeeRate)
45 | return self._ocean._conn.post("rawtx/test", json.dumps(j.build()))
46 |
47 | def get(self, txid: str) -> {}:
48 | """
49 | Get a raw transaction
50 |
51 | :param txid: (required) txid of transaction to query
52 | :type txid: str
53 | :return: json string
54 |
55 | :example:
56 |
57 | >>> ocean.rawTx.get("af6294e9729c6a4f31439e86374541658f35f4cc372a51e06c725429d875ac5c")
58 | """
59 | return self._ocean._conn.get(f"rawtx/{txid}")
60 |
--------------------------------------------------------------------------------
/defichain/transactions/remotedata/node.py:
--------------------------------------------------------------------------------
1 | from defichain.exceptions.transactions import TxBuilderError
2 | from .remotedata import RemoteData
3 | from defichain import Node
4 |
5 |
6 | class RemoteDataNode(RemoteData):
7 |
8 | def __init__(self, source: Node):
9 | self.node = source
10 |
11 | def get_unspent(self, address: str) -> [{}]:
12 | # Check if address is indexed by node / wallet
13 | if not self.node.wallet.getaddressinfo(address)["labels"]:
14 | error_string = f"To build a raw transaction from the given address: {address} the node needs to index " \
15 | f"the address first.\nYou can use the 'importaddress' method form your node for that."
16 | raise TxBuilderError(error_string)
17 |
18 | data = self.node.wallet.listunspent(addresses=[address])
19 | unspent = []
20 | for u in data:
21 | txid = u["txid"]
22 | index = u["vout"]
23 | value = int(round(float(u["amount"]) * 100000000))
24 | script = u["scriptPubKey"]
25 | unspent.append({"txid": txid, "vout": index, "value": value, "scriptPubKey": script})
26 | return unspent
27 |
28 | def check_masternode(self, masternodeId: str) -> bool:
29 | try:
30 | data = self.node.masternodes.getmasternode(masternodeId)[masternodeId]
31 | if data["state"] in ('PRE_ENABLED', 'ENABLED', 'PRE_RESIGNED'):
32 | return True
33 | except:
34 | pass
35 | return False
36 |
37 | def test_tx(self, hex: str, maxFeeRate: float = None) -> bool:
38 | try:
39 | self.node.rawtransactions.testmempoolaccept([hex], maxFeeRate)
40 | return True
41 | except:
42 | return False
43 |
44 | def send_tx(self, hex: str, maxFeeRate: float = None) -> str:
45 | return self.node.rawtransactions.sendrawtransaction(hex, maxFeeRate)
46 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 | from os import path
3 |
4 | VERSION = '3.1.3'
5 | DESCRIPTION = 'Defichain Python Library'
6 |
7 | # Project URLs
8 | project_urls = {
9 | "Tracker": "https://github.com/eric-volz/DefichainPython",
10 | "Documentation": "https://docs.defichain-python.de"
11 | }
12 |
13 | this_directory = path.abspath(path.dirname(__file__))
14 |
15 |
16 | def long_description():
17 | with open(path.join(this_directory, 'README.rst'), encoding='utf-8') as f:
18 | LONG_DESCRIPTION = f.read()
19 | return LONG_DESCRIPTION
20 |
21 |
22 | def requirements():
23 | with open("requirements.txt", "r") as _requirements:
24 | requirement: list = list(map(str.strip, _requirements.read().split("\n")))
25 | return requirement
26 |
27 |
28 | # Setting up
29 | if __name__ == "__main__":
30 | setup(
31 | name="defichain",
32 | version=VERSION,
33 | author="Intr0c",
34 | author_email="introc@volz.link",
35 | url="https://github.com/eric-volz/DefichainPython",
36 | description=DESCRIPTION,
37 | long_description=long_description(),
38 | packages=["defichain"] + ["defichain." + package for package in find_packages(where="defichain")],
39 | package_data={'': ['*.txt', '*.json']},
40 | install_requires=requirements(),
41 | keywords=['python', 'defichain', 'node', 'ocean', 'mnemonic', 'wallet', 'privateKey', 'transactions',
42 | 'raw transactions', 'P2PKH', 'P2SH', 'P2WPKH', 'DefiTx', 'custom transaction'],
43 | classifiers=[
44 | "Programming Language :: Python :: 3.7",
45 | "Programming Language :: Python :: 3.8",
46 | "Programming Language :: Python :: 3.9",
47 | "Programming Language :: Python :: 3.10",
48 | "Operating System :: Unix",
49 | "Operating System :: MacOS :: MacOS X",
50 | "Operating System :: Microsoft :: Windows",
51 | ]
52 | )
53 |
--------------------------------------------------------------------------------
/tests/transactions/utils/test_converter.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import TestConverter
4 | from defichain.transactions.utils import Converter
5 |
6 |
7 | @pytest.mark.transactions
8 | def test_int_to_bytes(): # 01
9 | assert Converter.int_to_bytes(TestConverter.INT, 5) == TestConverter.BYTES
10 |
11 |
12 | @pytest.mark.transactions
13 | def test_bytes_to_int(): # 02
14 | assert Converter.bytes_to_int(TestConverter.BYTES) == TestConverter.INT
15 |
16 |
17 | @pytest.mark.transactions
18 | def test_hex_to_bytes(): # 03
19 | assert Converter.hex_to_bytes(TestConverter.HEX) == TestConverter.BYTES
20 |
21 |
22 | @pytest.mark.transactions
23 | def test_bytes_to_hex(): # 04
24 | assert Converter.bytes_to_hex(TestConverter.BYTES) == TestConverter.HEX
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_hex_to_int(): # 05
29 | assert Converter.hex_to_int(TestConverter.HEX) == TestConverter.INT
30 |
31 |
32 | @pytest.mark.transactions
33 | def test_int_to_hex(): # 06
34 | assert Converter.int_to_hex(TestConverter.INT, 5) == TestConverter.HEX
35 |
36 |
37 | @pytest.mark.transactions
38 | def test_str_to_hex(): # 07
39 | assert Converter.str_to_hex(TestConverter.STR) == TestConverter.HEX
40 |
41 |
42 | @pytest.mark.transactions
43 | def test_hex_to_str(): # 08
44 | assert Converter.hex_to_str(TestConverter.HEX) == TestConverter.STR
45 |
46 |
47 | @pytest.mark.transactions
48 | def test_float_to_int(): # 09
49 | assert Converter.float_to_int(TestConverter.FLOAT) == TestConverter.INT
50 |
51 |
52 | @pytest.mark.transactions
53 | def test_int_to_float(): # 10
54 | assert Converter.int_to_float(TestConverter.INT) == TestConverter.FLOAT
55 |
56 |
57 | @pytest.mark.transactions
58 | def test_amount_float_to_int(): # 11
59 | assert Converter.amount_float_to_int(TestConverter.AMOUNT_FLOAT) == TestConverter.AMOUNT_INT
60 |
61 |
62 | @pytest.mark.transactions
63 | def test_addressAmount_float_to_int(): # 12
64 | assert Converter.addressAmount_float_to_int(TestConverter.ADDRESS_AMOUNT_FLOAT) == TestConverter.ADDRESS_AMOUNT_INT
65 |
--------------------------------------------------------------------------------
/tests/ocean/test_address.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | ADDRESS = "dN592sZaESZ8qnk4jqd5LgZdJUtCKcjZmQ"
5 | SIZE = 30
6 | NEXT = None
7 |
8 |
9 | @pytest.mark.query
10 | def test_getAccountHistory(): # 01
11 | assert ocean.address.getAccountHistory(ADDRESS, 1945985, 24)
12 | assert ocean.address.getAccountHistory(address=ADDRESS, height=1945985, txno=24)
13 |
14 |
15 | @pytest.mark.query
16 | def test_listAccountHistory(): # 02
17 | assert ocean.address.listAccountHistory(ADDRESS)
18 | assert ocean.address.listAccountHistory(ADDRESS, SIZE, NEXT)
19 | assert ocean.address.listAccountHistory(address=ADDRESS, size=SIZE, next=NEXT)
20 |
21 |
22 | @pytest.mark.query
23 | def test_getBalance(): # 03
24 | assert ocean.address.getBalance(ADDRESS)
25 | assert ocean.address.getBalance(address=ADDRESS)
26 |
27 |
28 | @pytest.mark.query
29 | def test_getAggregation(): # 04
30 | assert ocean.address.getAggregation(ADDRESS)
31 | assert ocean.address.getAggregation(address=ADDRESS)
32 |
33 |
34 | @pytest.mark.query
35 | def test_listToken(): # 05
36 | assert ocean.address.listToken(ADDRESS)
37 | assert ocean.address.listToken(ADDRESS, SIZE, NEXT)
38 | assert ocean.address.listToken(address=ADDRESS, size=SIZE, next=NEXT)
39 |
40 |
41 | @pytest.mark.query
42 | def test_listVault(): # 06
43 | assert ocean.address.listVault(ADDRESS)
44 | assert ocean.address.listVault(ADDRESS, SIZE, NEXT)
45 | assert ocean.address.listVault(address=ADDRESS, size=SIZE, next=NEXT)
46 |
47 |
48 | @pytest.mark.query
49 | def test_listTransaction(): # 07
50 | assert ocean.address.listTransaction(ADDRESS)
51 | assert ocean.address.listTransaction(ADDRESS, SIZE, NEXT)
52 | assert ocean.address.listTransaction(address=ADDRESS, size=SIZE, next=NEXT)
53 |
54 |
55 | @pytest.mark.query
56 | def test_listTransactionUnspent(): # 08
57 | assert ocean.address.listTransactionUnspent(ADDRESS)
58 | assert ocean.address.listTransactionUnspent(ADDRESS, SIZE, NEXT)
59 | assert ocean.address.listTransactionUnspent(address=ADDRESS, size=SIZE, next=NEXT)
60 |
--------------------------------------------------------------------------------
/docs/source/sdk/transactions/index.rst:
--------------------------------------------------------------------------------
1 | .. _Transactions index:
2 |
3 | Transactions
4 | ============
5 |
6 | This is the entry page to get information about building a raw transaction for defichain using python.
7 |
8 | **There are two ways to use this implementation:**
9 |
10 | 1. :ref:`Transaction Builder Index`: Abstracts the complexity of creating a transaction to a minimum
11 | **(recommended for 99% of users)**
12 | 2. :ref:`Transaction Advanced Index`: You can create transaction on your own behave and stay very flexible while
13 | using the infrastructure of the library
14 |
15 | .. toctree::
16 | :maxdepth: 1
17 | :hidden:
18 |
19 | builder/index
20 | advanced/index
21 |
22 | .. toctree::
23 | :maxdepth: 1
24 | :hidden:
25 |
26 | exceptions
27 |
28 | ----
29 |
30 | Default Input Structure
31 | -----------------------
32 |
33 | There will be some input structures throughout the implementation witch will be explained below:
34 |
35 | .. automodule:: defichain.transactions.utils
36 |
37 | .. _Transactions Amounts:
38 |
39 | Amounts
40 | _______
41 |
42 | The amount describes a combination of an token amount (int / float) and the corresponding token symbol: amount@token
43 |
44 | >>> "1@DFI" # one amount
45 |
46 | >>> ["1@DFI", "1@BTC", "1@ETH"] # multiple amounts
47 |
48 | There is an helper class to make the creation of amounts evan easier:
49 |
50 | .. autoclass:: BuildAmounts
51 | :members:
52 | :noindex:
53 |
54 | .. _Transactions AddressAmount:
55 |
56 | Address Amounts
57 | _______________
58 |
59 | The address is the key, the value are the :ref:`amounts `.
60 |
61 | .. code-block:: text
62 |
63 | {
64 | "address": "amounts"
65 | }
66 |
67 | Example:
68 |
69 | .. code-block:: text
70 |
71 | {
72 | "dcTKz5SQrqf4vGVsgra76ptXeNBcxPrenP": "1@DFI",
73 | "df1qzkf582h0sgfksj0yn0wxz0r9amyqfferm5wycs": ["2.0@BTC", "3.0@ETH"]
74 | }
75 |
76 | There is an helper class to make the creation of address amounts evan easier:
77 |
78 | .. autoclass:: BuildAddressAmounts
79 | :members:
80 | :noindex:
--------------------------------------------------------------------------------
/defichain/transactions/defitx/builddefitx.py:
--------------------------------------------------------------------------------
1 | from defichain.exceptions.transactions import RawTransactionError
2 | from defichain.transactions.constants import DefiTx_SIGNATURE, OPCodes
3 | from defichain.transactions.utils import Converter
4 |
5 |
6 | class BuildDefiTx:
7 | @staticmethod
8 | def get_hex_scriptLength(length: int) -> str:
9 | # https://github.com/JellyfishSDK/jellyfish/blob/main/packages/jellyfish-transaction/src/script/data.ts
10 | """
11 | Calculates the correct length parameter for a defi transaction
12 |
13 | If the defi transaction is loger than 76 characters, a separate length indicator is needed: in this case the
14 | first length operator (after op_return) is 4c (hex -> int 76). After this first length operator is the operator
15 | witch indicates the real length of the defi transaction.
16 |
17 | :param: length: number of bytes
18 | :return: "hex" - returns length in hexadecimal string
19 | """
20 | if length < 76:
21 | return Converter.int_to_hex(length, 1)
22 | elif length <= 255:
23 | return "4c" + Converter.int_to_hex(length, 1)
24 | elif length <= 65535:
25 | return "4d" + Converter.int_to_hex(length, 2)
26 | elif length <= 16777215:
27 | return "4e" + Converter.int_to_hex(length, 4)
28 | else:
29 | raise RawTransactionError("Script is to large")
30 |
31 | @staticmethod
32 | def build_defiTx(defiTx: bytes) -> bytes:
33 | """
34 | Builds the defi transaction. In this sate it can be implemented into a transaction and broadcasted to the
35 | blockchain.
36 |
37 | :param defiTx: (required) - Bytes of the defi transaction from BaseDefiTx Class
38 | :return: "bytes" - defi transaction with OP_RETURN code and calculated length
39 | """
40 | signature_defiTx = Converter.hex_to_bytes(DefiTx_SIGNATURE) + defiTx
41 | length_signature_defiTx = BuildDefiTx.get_hex_scriptLength(len(signature_defiTx))
42 |
43 | return Converter.hex_to_bytes(OPCodes.OP_RETURN) + Converter.hex_to_bytes(length_signature_defiTx) + \
44 | signature_defiTx
45 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_pool.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2wpkh, TestPool
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_poolswap(): # 01
10 | tx = builder_p2wpkh.pool.poolswap(addressFrom=TestPool.addressFrom, tokenFrom=TestPool.tokenFrom,
11 | amountFrom=TestPool.amountFrom, tokenTo=TestPool.tokenTo,
12 | addressTo=TestPool.addressTo, maxPrice=TestPool.maxPrice)
13 |
14 | assert tx.serialize() == TestPool.poolswap_serialized
15 |
16 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
17 |
18 |
19 | @pytest.mark.transactions
20 | def test_compositeswap(): # 02
21 | tx = builder_p2wpkh.pool.compositeswap(addressFrom=TestPool.addressFrom, tokenFrom=TestPool.tokenFrom,
22 | amountFrom=TestPool.amountFrom, tokenTo=TestPool.tokenTo,
23 | addressTo=TestPool.addressTo, maxPrice=TestPool.maxPrice,
24 | pools=TestPool.pools)
25 |
26 | assert tx.serialize() == TestPool.compositeswap_serialized
27 |
28 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
29 |
30 |
31 | @pytest.mark.transactions
32 | def test_addpoolliquidity(): # 03
33 | tx = builder_p2wpkh.pool.addpoolliquidity(addressAmountFrom=TestPool.addressAmountFrom.build(),
34 | shareAddress=TestPool.addressFrom)
35 |
36 | assert tx.serialize() == TestPool.addpoolliquidity_serialized
37 |
38 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
39 |
40 |
41 | @pytest.mark.transactions
42 | def test_removepoolliquidity(): # 04
43 | tx = builder_p2wpkh.pool.removepoolliquidity(addressFrom=TestPool.addressFrom, amount=TestPool.amount)
44 |
45 | assert tx.serialize() == TestPool.removepoolliquidity_serialized
46 |
47 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
48 |
--------------------------------------------------------------------------------
/docs/source/logo/svg/defichainpython-logo-small.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/tests/transactions/builder/test_utxo.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import builder_p2pkh, builder_p2sh, builder_p2wpkh, Addresses, TestUTXO
3 |
4 | from defichain.transactions.rawtransactions import Transaction
5 | from defichain.networks import DefichainMainnet
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_send(): # 01
10 | tx_p2pkh = builder_p2pkh.utxo.send(amount=0.00001, addressTo=Addresses.P2WPKH,
11 | changeAddress=builder_p2pkh.get_address())
12 | tx_p2sh = builder_p2sh.utxo.send(amount=0.00001, addressTo=Addresses.P2WPKH)
13 | tx_p2wpkh = builder_p2wpkh.utxo.send(amount=0.00001, addressTo=Addresses.P2WPKH)
14 |
15 | assert tx_p2pkh.serialize() == TestUTXO.send_p2pkh_serialized
16 | assert tx_p2sh.serialize() == TestUTXO.send_p2sh_serialized
17 | assert tx_p2wpkh.serialize() == TestUTXO.send_p2wpkh_serialized
18 |
19 | assert Transaction.deserialize(DefichainMainnet, tx_p2pkh.serialize()).serialize() == tx_p2pkh.serialize()
20 | assert Transaction.deserialize(DefichainMainnet, tx_p2sh.serialize()).serialize() == tx_p2sh.serialize()
21 | assert Transaction.deserialize(DefichainMainnet, tx_p2wpkh.serialize()).serialize() == tx_p2wpkh.serialize()
22 |
23 |
24 | @pytest.mark.transactions
25 | def test_sendall(): # 02
26 | tx = builder_p2wpkh.utxo.sendall(addressTo=Addresses.P2WPKH)
27 |
28 | assert tx.serialize() == TestUTXO.sendall_serialized
29 |
30 | assert Transaction.deserialize(DefichainMainnet, tx.serialize()).serialize() == tx.serialize()
31 |
32 |
33 | @pytest.mark.transactions
34 | def test_sendmany(): # 03
35 | tx_p2wpkh = builder_p2wpkh.utxo.sendmany(addressAmountTo=TestUTXO.addressAmountTo.build())
36 | tx_p2pkh = builder_p2wpkh.utxo.sendmany(addressAmountTo=TestUTXO.addressAmountTo.build(),
37 | changeAddress=Addresses.P2PKH)
38 |
39 | assert tx_p2wpkh.serialize() == TestUTXO.sendmany_same_change_address_serialized
40 | assert tx_p2pkh.serialize() == TestUTXO.sendmany_different_change_address_serialized
41 |
42 | assert Transaction.deserialize(DefichainMainnet, tx_p2wpkh.serialize()).serialize() == tx_p2wpkh.serialize()
43 | assert Transaction.deserialize(DefichainMainnet, tx_p2pkh.serialize()).serialize() == tx_p2pkh.serialize()
44 |
--------------------------------------------------------------------------------
/defichain/exceptions/http/HTTPStatusCode.py:
--------------------------------------------------------------------------------
1 | # HTTP Error Codes
2 | # https://pythonise.com/categories/python/http-status-code-enum
3 |
4 | from enum import Enum, unique
5 |
6 |
7 | @unique
8 | class HTTPStatusCode(Enum):
9 | # INFORMATIONAL RESPONSES (100–199)
10 | CONTINUE = 100
11 | SWITCHING_PROTOCOL = 101
12 | PROCESSING = 102
13 | EARLY_HINTS = 103
14 |
15 | # SUCCESSFUL RESPONSES (200–299)
16 | OK = 200
17 | CREATED = 201
18 | ACCEPTED = 202
19 | NON_AUTHORITATIVE_INFORMATION = 203
20 | NO_CONTENT = 204
21 | RESET_CONTENT = 205
22 | PARTIAL_CONTENT = 206
23 | MULTI_STATUS = 207
24 | ALREADY_REPORTED = 208
25 | IM_USED = 226
26 |
27 | # REDIRECTS (300–399)
28 | MULTIPLE_CHOICE = 300
29 | MOVED_PERMANENTLY = 301
30 | FOUND = 302
31 | SEE_OTHER = 303
32 | NOT_MODIFIED = 304
33 | USE_PROXY = 305
34 | UNUSED = 306
35 | TEMPORARY_REDIRECT = 307
36 | PERMANENT_REDIRECT = 308
37 |
38 | # CLIENT ERRORS (400–499)
39 | BAD_REQUEST = 400
40 | UNAUTHORIZED = 401
41 | PAYMENT_REQUIRED = 402
42 | FORBIDDEN = 403
43 | NOT_FOUND = 404
44 | METHOD_NOT_ALLOWED = 405
45 | NOT_ACCEPTABLE = 406
46 | PROXY_AUTHENTICATION_REQUIRED = 407
47 | REQUEST_TIMEOUT = 408
48 | CONFLICT = 409
49 | GONE = 410
50 | LENGTH_REQUIRED = 411
51 | PRECONDITION_FAILED = 412
52 | PAYLOAD_TOO_LARGE = 413
53 | URI_TOO_LONG = 414
54 | UNSUPPORTED_MEDIA_TYPE = 415
55 | REQUESTED_RANGE_NOT_SATISFIABLE = 416
56 | EXPECTATION_FAILED = 417
57 | IM_A_TEAPOT = 418
58 | MISDIRECTED_REQUEST = 421
59 | UNPROCESSABLE_ENTITY = 422
60 | LOCKED = 423
61 | FAILED_DEPENDENCY = 424
62 | TOO_EARLY = 425
63 | UPGRADE_REQUIRED = 426
64 | PRECONDITION_REQUIRED = 428
65 | TOO_MANY_REQUESTS = 429
66 | REQUEST_HEADER_FIELDS_TOO_LARGE = 431
67 | UNAVAILABLE_FOR_LEGAL_REASONS = 451
68 |
69 | # SERVER ERRORS (500–599)
70 | INTERNAL_SERVER_ERROR = 500
71 | NOT_IMPLEMENTED = 501
72 | BAD_GATEWAY = 502
73 | SERVICE_UNAVAILABLE = 503
74 | GATEWAY_TIMEOUT = 504
75 | HTTP_VERSION_NOT_SUPPORTED = 505
76 | VARIANT_ALSO_NEGOTIATES = 506
77 | INSUFFICIENT_STORAGE = 507
78 | LOOP_DETECTED = 508
79 | NOT_EXTENDED = 510
80 | NETWORK_AUTHENTICATION_REQUIRED = 511
81 |
--------------------------------------------------------------------------------
/defichain/hdwallet/account.py:
--------------------------------------------------------------------------------
1 | from .wallet import Wallet
2 | from typing import Any
3 | from defichain.networks import DefichainMainnet, DefichainTestnet, DefichainRegtest
4 |
5 |
6 | class Account:
7 |
8 | @staticmethod
9 | def _is_publicKey(network: Any, publicKey: str) -> bool:
10 | try:
11 | Wallet(network).from_public_key(publicKey)
12 | return True
13 | except:
14 | return False
15 |
16 | @staticmethod
17 | def _is_privateKey(network: Any, privateKey: str) -> bool:
18 | try:
19 | Wallet(network).from_private_key(privateKey)
20 | return True
21 | except:
22 | return False
23 |
24 | @staticmethod
25 | def _is_wif(network: Any, wif: str) -> bool:
26 | try:
27 | Wallet(network).from_wif(wif)
28 | return True
29 | except:
30 | return False
31 |
32 | def __init__(self, network: Any, key: str):
33 | self._network = None
34 | self._wallet: Wallet = Wallet(network)
35 | self.set_network(network)
36 | self.set_key(key)
37 |
38 | # Get information
39 | def get_network(self):
40 | return self._network
41 |
42 | def get_publicKey(self):
43 | return self._wallet.public_key()
44 |
45 | def get_privateKey(self):
46 | return self._wallet.private_key()
47 |
48 | def get_wif(self):
49 | return self._wallet.wif()
50 |
51 | def get_p2sh(self):
52 | return self._wallet.p2sh_address()
53 |
54 | def get_p2pkh(self):
55 | return self._wallet.p2pkh_address()
56 |
57 | def get_p2wpkh(self):
58 | return self._wallet.p2wpkh_address()
59 |
60 | def is_private(self):
61 | return self._is_privateKey(self.get_network(), self._wallet.private_key())
62 |
63 | # Set Information
64 | def set_network(self, network: "DefichainMainnet | DefichainTestnet") -> None:
65 | self._network = network
66 |
67 | def set_key(self, key: str):
68 | if self._is_publicKey(self.get_network(), key):
69 | self._wallet.from_public_key(key)
70 | elif self._is_privateKey(self.get_network(), key):
71 | self._wallet.from_private_key(key)
72 | elif self._is_wif(self.get_network(), key):
73 | self._wallet.from_wif(key)
74 |
--------------------------------------------------------------------------------
/tests/transactions/utils/test_token.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from . import TestToken
4 | from defichain.networks import DefichainMainnet, DefichainTestnet
5 | from defichain.transactions.utils import Token
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_get_symbol_from_id(): # 01
10 | # Mainnet
11 | for id in TestToken.MAINNET_IDs:
12 | assert Token.get_symbol_from_id(DefichainMainnet, id) in TestToken.MAINNET_SYMBOLS
13 |
14 | # Testnet
15 | for id in TestToken.TESTNET_IDs:
16 | assert Token.get_symbol_from_id(DefichainTestnet, id) in TestToken.TESTNET_SYMBOLS
17 |
18 |
19 | @pytest.mark.transactions
20 | def test_get_id_from_symbol(): # 02
21 | # Mainnet
22 | for symbol in TestToken.MAINNET_SYMBOLS:
23 | assert Token.get_id_from_symbol(DefichainMainnet, symbol) in TestToken.MAINNET_IDs
24 |
25 | # Testnet
26 | for symbol in TestToken.TESTNET_SYMBOLS:
27 | assert Token.get_id_from_symbol(DefichainTestnet, symbol) in TestToken.TESTNET_IDs
28 |
29 |
30 | @pytest.mark.transactions
31 | def test_get_name_from_id(): # 03
32 | # Mainnet
33 | for id in TestToken.MAINNET_IDs:
34 | Token.get_name_from_id(DefichainMainnet, id)
35 |
36 | # Testnet
37 | for id in TestToken.TESTNET_IDs:
38 | Token.get_name_from_id(DefichainTestnet, id)
39 |
40 |
41 | @pytest.mark.transactions
42 | def test_verify_tokenId(): # 04
43 | # Mainnet
44 | for id in TestToken.MAINNET_IDs:
45 | Token.verify_tokenId(DefichainMainnet, id)
46 |
47 | # Testnet
48 | for id in TestToken.TESTNET_IDs:
49 | Token.verify_tokenId(DefichainTestnet, id)
50 |
51 |
52 | @pytest.mark.transactions
53 | def test_checkAndConvert(): # 05
54 | # Mainnet
55 | # Test ID
56 | for id in TestToken.MAINNET_IDs:
57 | assert Token.checkAndConvert(DefichainMainnet, id) in TestToken.MAINNET_IDs
58 |
59 | # Test Symbol
60 | for symbol in TestToken.MAINNET_SYMBOLS:
61 | assert Token.checkAndConvert(DefichainMainnet, symbol) in TestToken.MAINNET_IDs
62 |
63 | # Testnet
64 | # Test ID
65 | for id in TestToken.TESTNET_IDs:
66 | assert Token.checkAndConvert(DefichainTestnet, id) in TestToken.TESTNET_IDs
67 |
68 | # Test Symbol
69 | for symbol in TestToken.TESTNET_SYMBOLS:
70 | assert Token.checkAndConvert(DefichainTestnet, symbol) in TestToken.TESTNET_IDs
71 |
--------------------------------------------------------------------------------
/tests/ocean/test_poolpairs.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_list(): # 01
10 | assert ocean.poolpairs.list()
11 | assert ocean.poolpairs.list(SIZE, NEXT)
12 | assert ocean.poolpairs.list(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_get(): # 02
17 | id = 4 # ETH-DFI
18 | assert ocean.poolpairs.get(id)
19 | assert ocean.poolpairs.get(id=id)
20 |
21 |
22 | @pytest.mark.query
23 | def test_listPoolSwaps(): # 03
24 | id = 4 # ETH-DFI
25 | assert ocean.poolpairs.listPoolSwaps(id)
26 | assert ocean.poolpairs.listPoolSwaps(id, SIZE, NEXT)
27 | assert ocean.poolpairs.listPoolSwaps(id=id, size=SIZE, next=NEXT)
28 |
29 |
30 | @pytest.mark.query
31 | def test_listPoolSwapsVerbose(): # 04
32 | id = 4 # ETH-DFI
33 | assert ocean.poolpairs.listPoolSwapsVerbose(id)
34 | assert ocean.poolpairs.listPoolSwapsVerbose(id, SIZE, NEXT)
35 | assert ocean.poolpairs.listPoolSwapsVerbose(id=id, size=SIZE, next=NEXT)
36 |
37 |
38 | @pytest.mark.query
39 | def test_listPoolSwapAggregates(): # 05
40 | id = 4 # ETH-DFI
41 | interval = 3600
42 | assert ocean.poolpairs.listPoolSwapAggregates(id, interval)
43 | assert ocean.poolpairs.listPoolSwapAggregates(id, interval, SIZE, NEXT)
44 | assert ocean.poolpairs.listPoolSwapAggregates(id=id, interval=interval, size=SIZE, next=NEXT)
45 |
46 |
47 | @pytest.mark.query
48 | def test_getSwappableTokens(): # 06
49 | tokenId = 0 # DFI
50 | assert ocean.poolpairs.getSwappableTokens(tokenId)
51 | assert ocean.poolpairs.getSwappableTokens(tokenId=tokenId)
52 |
53 |
54 | @pytest.mark.query
55 | def test_getBestPath(): # 07
56 | fromTokenId = 0 # DFI
57 | toTokenId = 26 # SPY
58 | assert ocean.poolpairs.getBestPath(fromTokenId, toTokenId)
59 | assert ocean.poolpairs.getBestPath(fromTokenId=fromTokenId, toTokenId=toTokenId)
60 |
61 |
62 | @pytest.mark.query
63 | def test_getAllPaths(): # 08
64 | fromTokenId = 0 # DFI
65 | toTokenId = 26 # SPY
66 | assert ocean.poolpairs.getAllPaths(fromTokenId, toTokenId)
67 | assert ocean.poolpairs.getAllPaths(fromTokenId=fromTokenId, toTokenId=toTokenId)
68 |
69 |
70 | @pytest.mark.query
71 | def test_listDexPrices(): # 09
72 | assert ocean.poolpairs.listDexPrices("DUSD")
73 | assert ocean.poolpairs.listDexPrices(denomination="DUSD")
74 |
--------------------------------------------------------------------------------
/tests/node/test_exceptions.py:
--------------------------------------------------------------------------------
1 | import re
2 | import pytest
3 | from defichain.node.RPCErrorHandler import RPCErrorHandler
4 | from requests.models import Response
5 | from . import logger
6 |
7 |
8 | response = Response()
9 | response._content = b'{"result": "None", "error": {"code": -32600, "message": "Das ist ein Test"}, "id": "None"}'
10 |
11 |
12 | @pytest.mark.query
13 | def test_BadMethod(): # 01
14 | response.status_code = 405
15 | string = "BadMethod(405): RPC_INVALID_REQUEST: Das ist ein Test"
16 | with pytest.raises(Exception, match=re.escape(string)):
17 | assert RPCErrorHandler(response, logger)
18 |
19 |
20 | @pytest.mark.query
21 | def test_BadRequest(): # 02
22 | response.status_code = 400
23 | string = "BadRequest(400): RPC_INVALID_REQUEST: Das ist ein Test"
24 | with pytest.raises(Exception, match=re.escape(string)):
25 | assert RPCErrorHandler(response, logger)
26 |
27 |
28 | @pytest.mark.query
29 | def test_Forbidden(): # 03
30 | response.status_code = 403
31 | string = "Forbidden(403): RPC_INVALID_REQUEST: Das ist ein Test"
32 | with pytest.raises(Exception, match=re.escape(string)):
33 | assert RPCErrorHandler(response, logger)
34 |
35 |
36 | @pytest.mark.query
37 | def test_InternalServerError(): # 04
38 | response.status_code = 500
39 | string = "InternalServerError(500): RPC_INVALID_REQUEST: Das ist ein Test"
40 | with pytest.raises(Exception, match=re.escape(string)):
41 | assert RPCErrorHandler(response, logger)
42 |
43 |
44 | @pytest.mark.query
45 | def test_NotFound(): # 05
46 | response.status_code = 404
47 | string = "NotFound(404): RPC_INVALID_REQUEST: Das ist ein Test"
48 | with pytest.raises(Exception, match=re.escape(string)):
49 | assert RPCErrorHandler(response, logger)
50 |
51 |
52 | @pytest.mark.query
53 | def test_ServiceUnavailable(): # 06
54 | response.status_code = 503
55 | string = "ServiceUnavailable(503): The service you are trying to connect to is not available"
56 | with pytest.raises(Exception, match=re.escape(string)):
57 | assert RPCErrorHandler(response, logger)
58 |
59 |
60 | @pytest.mark.query
61 | def test_Unauthorized(): # 07
62 | response.status_code = 401
63 | string = "Unauthorized(401): Authorization failed: Incorrect rpcuser or rpcpassword"
64 | with pytest.raises(Exception, match=re.escape(string)):
65 | assert RPCErrorHandler(response, logger)
66 |
--------------------------------------------------------------------------------
/tests/transactions/rawtransactions/test_txinput.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.transactions.rawtransactions import TxInput, TxP2PKHInput, TxP2SHInput, TxP2WPKHInput
4 | from defichain.transactions.constants.rawtransactions import SEQUENCE
5 | from defichain.networks import DefichainMainnet
6 |
7 | from . import TestInputs, Addresses
8 |
9 |
10 | @pytest.mark.transactions
11 | def test_p2pkh_inputs(): # 01
12 | txInput = TxP2PKHInput(TestInputs.TXID, TestInputs.VOUT, Addresses.P2PKH)
13 | assert TxP2PKHInput(txid=TestInputs.TXID, vout=TestInputs.VOUT, address=Addresses.P2PKH, value=TestInputs.VALUE,
14 | sequence=SEQUENCE)
15 | assert txInput.serialize() == TestInputs.P2PKH_Input_Serialized
16 | assert TxInput.deserialize(DefichainMainnet, TestInputs.P2PKH_Input_Serialized).serialize() == \
17 | TestInputs.P2PKH_Input_Serialized
18 | assert TxP2PKHInput.deserialize(DefichainMainnet, TestInputs.P2PKH_Input_Serialized).serialize() == \
19 | TestInputs.P2PKH_Input_Serialized
20 |
21 |
22 | @pytest.mark.transactions
23 | def test_p2sh_inputs(): # 02
24 | txInput = TxP2SHInput(TestInputs.TXID, TestInputs.VOUT, Addresses.P2WPKH, TestInputs.VALUE)
25 | assert TxP2SHInput(txid=TestInputs.TXID, vout=TestInputs.VOUT, address=Addresses.P2WPKH, value=TestInputs.VALUE,
26 | sequence=SEQUENCE)
27 | assert txInput.serialize() == TestInputs.P2SH_Input_Serialized
28 | assert TxInput.deserialize(DefichainMainnet, TestInputs.P2SH_Input_Serialized).serialize() == \
29 | TestInputs.P2SH_Input_Serialized
30 | assert TxP2SHInput.deserialize(DefichainMainnet, TestInputs.P2SH_Input_Serialized).serialize() == \
31 | TestInputs.P2SH_Input_Serialized
32 |
33 |
34 | @pytest.mark.transactions
35 | def test_p2wpkh_inputs(): # 03
36 | txInput = TxP2WPKHInput(TestInputs.TXID, TestInputs.VOUT, Addresses.P2WPKH, TestInputs.VALUE)
37 | assert TxP2WPKHInput(txid=TestInputs.TXID, vout=TestInputs.VOUT, address=Addresses.P2WPKH, value=TestInputs.VALUE, sequence=SEQUENCE)
38 | assert txInput.serialize() == TestInputs.P2WPKH_Input_Serialized
39 | assert TxInput.deserialize(DefichainMainnet, TestInputs.P2WPKH_Input_Serialized).serialize() == \
40 | TestInputs.P2WPKH_Input_Serialized
41 | assert TxP2SHInput.deserialize(DefichainMainnet, TestInputs.P2WPKH_Input_Serialized).serialize() == \
42 | TestInputs.P2WPKH_Input_Serialized
43 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/consortium.py:
--------------------------------------------------------------------------------
1 | # https://github.com/JellyfishSDK/jellyfish/blob/main/packages/whale-api-client/src/api/consortium.ts
2 |
3 |
4 | class Consortium:
5 | def __init__(self, ocean):
6 | self._ocean = ocean
7 |
8 | def getAssetBreakdown(self):
9 | """
10 | Gets the asset breakdown information of consortium members
11 |
12 | :return: Json String
13 |
14 | .. code-block::
15 |
16 | {
17 | tokenId: string
18 | id: string
19 | name: string
20 | backingAddresses: string[]
21 | minted: string
22 | burned: string
23 | }
24 |
25 | :example:
26 |
27 | >>> ocean.consortium.getAssetBreakdown()
28 | """
29 |
30 | return self._ocean._conn.get("consortium/assetbreakdown")
31 |
32 | def getMemberStats(self, memberId: str):
33 | """
34 | Gets the stats information of a specific consortium member
35 |
36 | :param memberId: (required) member id of the consortium member
37 | :type memberId: str
38 | :return: Json String
39 |
40 | .. code-block::
41 |
42 | {
43 | memberId: string
44 | memberName: string
45 | mintTokens:
46 | [
47 | {
48 | tokenSymbol: string
49 | tokenDisplaySymbol: string
50 | tokenId: string
51 | member:
52 | {
53 | minted: string
54 | mintedDaily: string
55 | mintLimit: string
56 | mintDailyLimit: string
57 | }
58 | token:
59 | {
60 | minted: string
61 | mintedDaily: string
62 | mintLimit: string
63 | mintDailyLimit: string
64 | }
65 | }
66 | ]
67 | }
68 |
69 | :example:
70 |
71 | >>> ocean.consortium.getMemberStats("memberId")
72 | """
73 |
74 | return self._ocean._conn.get(f"consortium/stats/{memberId}")
75 |
--------------------------------------------------------------------------------
/tests/ocean/test_loan.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from . import ocean
3 |
4 | SIZE = 30
5 | NEXT = None
6 |
7 |
8 | @pytest.mark.query
9 | def test_listScheme(): # 01
10 | assert ocean.loan.listScheme()
11 | assert ocean.loan.listScheme(SIZE, NEXT)
12 | assert ocean.loan.listScheme(size=SIZE, next=NEXT)
13 |
14 |
15 | @pytest.mark.query
16 | def test_getScheme(): # 02
17 | scheme = "MIN150"
18 | assert ocean.loan.getScheme(scheme)
19 | assert ocean.loan.getScheme(id=scheme)
20 |
21 |
22 | @pytest.mark.query
23 | def test_listCollateralToken(): # 03
24 | assert ocean.loan.listCollateralToken()
25 | assert ocean.loan.listCollateralToken(SIZE, NEXT)
26 | assert ocean.loan.listCollateralToken(size=SIZE, next=NEXT)
27 |
28 |
29 | @pytest.mark.query
30 | def test_getCollateralToken(): # 04
31 | token = 1 # ETH
32 | assert ocean.loan.getCollateralToken(token)
33 | assert ocean.loan.getCollateralToken(id=token)
34 |
35 |
36 | @pytest.mark.query
37 | def test_listLoanToken(): # 05
38 | assert ocean.loan.listLoanToken()
39 | assert ocean.loan.listLoanToken(SIZE, NEXT)
40 | assert ocean.loan.listLoanToken(size=SIZE, next=NEXT)
41 |
42 |
43 | @pytest.mark.query
44 | def test_getLoanToken(): # 06
45 | token = 26 # SPY
46 | assert ocean.loan.getLoanToken(token)
47 | assert ocean.loan.getLoanToken(id=token)
48 |
49 |
50 | @pytest.mark.query
51 | def test_listVault(): # 07
52 | assert ocean.loan.listVault()
53 | assert ocean.loan.listVault(SIZE, NEXT)
54 | assert ocean.loan.listVault(size=SIZE, next=NEXT)
55 |
56 |
57 | @pytest.mark.query
58 | def test_getVault(): # 08
59 | vault = "fb2dd56658bc2b13fc129539aca8a9ff1f86f8a966a02dbb91c365fc59c1898b" # SPY
60 | assert ocean.loan.getVault(vault)
61 | assert ocean.loan.getVault(id=vault)
62 |
63 |
64 | @pytest.mark.query
65 | def test_listVaultAuctionHistory(): # 09
66 | id = "00d1f13efe448980dea15824fd3df82d311a9daeba31428929f827e8c9764e2f"
67 | height = 1865100
68 | batchIndex = 0
69 | assert ocean.loan.listVaultAuctionHistory(id, height, batchIndex)
70 | assert ocean.loan.listVaultAuctionHistory(id, height, batchIndex, SIZE, NEXT)
71 | assert ocean.loan.listVaultAuctionHistory(id=id, height=height, batchIndex=batchIndex, size=SIZE, next=NEXT)
72 |
73 |
74 | @pytest.mark.query
75 | def test_listAction(): # 10
76 | assert ocean.loan.listAuction()
77 | assert ocean.loan.listAuction(SIZE, NEXT)
78 | assert ocean.loan.listAuction(size=SIZE, next=NEXT)
79 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | downloads/
14 | eggs/
15 | .eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | wheels/
22 | pip-wheel-metadata/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 |
53 | # Translations
54 | *.mo
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 | db.sqlite3
61 | db.sqlite3-journal
62 |
63 | # Flask stuff:
64 | instance/
65 | .webassets-cache
66 |
67 | # Scrapy stuff:
68 | .scrapy
69 |
70 | # Sphinx documentation
71 | docs/build/
72 | docs/build/html/_static
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 |
--------------------------------------------------------------------------------
/defichain/transactions/rawtransactions/sign.py:
--------------------------------------------------------------------------------
1 | from binascii import hexlify, unhexlify
2 | import struct
3 | from hashlib import sha256
4 | from ecdsa import SigningKey, SECP256k1
5 | from ecdsa.util import sigencode_der, sigencode_der_canonize
6 |
7 | from defichain.transactions.constants import ORDER
8 | from defichain.transactions.utils import Converter
9 |
10 |
11 | def sign_legacy_input(privateKey: str, data: bytes, sigHash: bytes) -> str:
12 | """
13 | Signs the given data with a given private key in a deterministic way
14 |
15 | :param privateKey: (required) private key to sign the input
16 | :type privateKey: str
17 | :param data: (required) data that has to be signed
18 | :type data: bytes
19 | :param sigHash: (required) sigHash to be signed with
20 | :type sigHash: bytes
21 | :return: "hex" - signature of data
22 | """
23 | sk = SigningKey.from_string(unhexlify(privateKey), curve=SECP256k1)
24 | s = sk.sign_deterministic(data, hashfunc=sha256, sigencode=sigencode_der_canonize)
25 | signature = Converter.bytes_to_hex(s) + Converter.bytes_to_hex(sigHash)[:2] # SIGHASH_ALL
26 | return signature
27 |
28 |
29 | def sign_segwit_input(privateKey: str, data: bytes) -> str:
30 | """
31 | Signs the given data with a given private key in a deterministic way
32 |
33 | :param privateKey: (required) private key to sign the input
34 | :type privateKey: str
35 | :param data: (required) data that has to be signed
36 | :type data: bytes
37 | :return: "hex" - signature of data
38 | """
39 |
40 | sk = SigningKey.from_string(unhexlify(privateKey), curve=SECP256k1)
41 | sig = sk.sign_digest_deterministic(data, sigencode=sigencode_der, hashfunc=sha256)
42 |
43 | der_prefix = sig[0]
44 | length_total = sig[1]
45 | der_type_int = sig[2]
46 | length_r = sig[3]
47 | R = sig[4:4 + length_r]
48 | length_s = sig[5 + length_r]
49 | S = sig[5 + length_r + 1:]
50 | S_as_bigint = int(hexlify(S).decode('utf-8'), 16)
51 |
52 | half_order = ORDER // 2
53 | if S_as_bigint > half_order:
54 | new_S_as_bigint = ORDER - S_as_bigint
55 | new_S = unhexlify(format(new_S_as_bigint, 'x').zfill(64))
56 | length_s -= 1
57 | length_total -= 1
58 | else:
59 | new_S = S
60 |
61 | sig = struct.pack('BBBB', der_prefix, length_total, der_type_int, length_r) + R + \
62 | struct.pack('BB', der_type_int, length_s) + new_S
63 |
64 | sig += struct.pack('B', 1)
65 |
66 | return hexlify(sig).decode('utf-8')
67 |
--------------------------------------------------------------------------------
/docs/source/main/quickstart.rst:
--------------------------------------------------------------------------------
1 | .. _instruction quickstart:
2 |
3 | Quickstart
4 | ==========
5 |
6 | Install the Defichain Python Package
7 | ------------------------------------
8 |
9 | The library can be installed and used in two ways
10 |
11 | 1. The library was published on PyPi and can be installed with only one command.
12 |
13 | .. code-block:: bash
14 |
15 | pip install defichain -U
16 |
17 | 2. if you need the latest release or just want to view the code, then clone the GitHub repository
18 |
19 | .. code-block:: bash
20 |
21 | git clone https://github.com/eric-volz/DefichainPython.git
22 |
23 | .. _instruction quickstart node:
24 |
25 | Make a request to the Node
26 | --------------------------
27 |
28 | Here is an example of how you can connect to the node and how individual requests are executed:
29 |
30 | >>> from defichain import Node
31 | >>> node = Node("user", "password", "127.0.0.1", 8554)
32 | >>> node.blockchain.getblockcount() # returns block height of the latest block
33 | >>> node.poolpair.compositeswap("fromAddress", "BTC", 0.01, "toAddress", "DFI") # swaps 0.01 BTC to DFI
34 |
35 | For more information check the :ref:`Node index` section.
36 |
37 | .. _instruction quickstart ocean:
38 |
39 | Make a request to Ocean
40 | -----------------------
41 |
42 | Here is an example of how you can connect to Ocean and how to request blockchain data:
43 |
44 | >>> from defichain import Ocean
45 | >>> ocean = Ocean() # creates the connection to Ocean
46 | >>> ocean.blocks.list() # returns the latest 30 blocks
47 | >>> ocean.poolpairs.get(4) # returns data from ETH-DFI Pool
48 |
49 | For more information check the :ref:`Ocean index` section.
50 |
51 | .. _instruction quickstart wallet:
52 |
53 | Setup a wallet and get the first address
54 | ----------------------------------------
55 |
56 | Here is an example how to create a new wallet with a newly generated mnemonic seed and how to
57 | retrieve the first bech32 address from it:
58 |
59 | >>> from defichain import Wallet
60 | >>> from defichain.networks import DefichainMainnet
61 | >>> from defichain.hdwallet.utils import generate_mnemonic
62 | >>> wallet = Wallet(DefichainMainnet)
63 | >>> mnemonic = generate_mnemonic()
64 | wisdom path obscure scrub travel vessel boring solar truth original quiz letter exhibit spy point mail else entire involve announce vault outer mirror rug
65 | >>> wallet.from_mnemonic(mnemonic)
66 | >>> wallet.bech32_address()
67 | df1q95vyvvu05sgpaem7w8lwufxwnzdchwk9xr7j0y
68 |
69 |
70 | For more information check the :ref:`HDWallet index` section.
71 |
--------------------------------------------------------------------------------
/defichain/libs/base58.py:
--------------------------------------------------------------------------------
1 | from hashlib import sha256
2 | from hashlib import sha3_256
3 | import six
4 |
5 |
6 | __base58_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
7 | __base58_alphabet_bytes = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
8 | __base58_radix = len(__base58_alphabet)
9 |
10 |
11 | def checksum_encode(address, crypto="eth"):
12 | out = ""
13 | keccak = sha3_256.keccak_256()
14 | addr = address.lower().replace("0x", "") if crypto == "eth" else address.lower().replace("xdc", "")
15 | keccak.update(addr.encode("ascii"))
16 | hash_addr = keccak.hexdigest()
17 | for i, c in enumerate(addr):
18 | if int(hash_addr[i], 16) >= 8:
19 | out += c.upper()
20 | else:
21 | out += c
22 | return ("0x" + out) if crypto == "eth" else ("xdc" + out)
23 |
24 |
25 | def string_to_int(data):
26 | val = 0
27 |
28 | if type(data) == str:
29 | data = bytearray(data)
30 |
31 | for (i, c) in enumerate(data[::-1]):
32 | val += (256 ** i) * c
33 | return val
34 |
35 |
36 | def ensure_string(data):
37 | if isinstance(data, six.binary_type):
38 | return data.decode("utf-8")
39 | elif not isinstance(data, six.string_types):
40 | raise ValueError("Invalid value for string")
41 | return data
42 |
43 |
44 | def encode(data):
45 | enc = ""
46 | val = string_to_int(data)
47 | while val >= __base58_radix:
48 | val, mod = divmod(val, __base58_radix)
49 | enc = __base58_alphabet[mod] + enc
50 | if val:
51 | enc = __base58_alphabet[val] + enc
52 |
53 | n = len(data) - len(data.lstrip(b"\0"))
54 | return __base58_alphabet[0] * n + enc
55 |
56 |
57 | def check_encode(raw):
58 | chk = sha256(sha256(raw).digest()).digest()[:4]
59 | return encode(raw + chk)
60 |
61 |
62 | def decode(data):
63 | if bytes != str:
64 | data = bytes(data, "ascii")
65 |
66 | val = 0
67 | prefix = 0
68 | for c in data:
69 | val = (val * __base58_radix) + __base58_alphabet_bytes.find(c)
70 | if val == 0:
71 | prefix += 1
72 |
73 | dec = bytearray()
74 | while val > 0:
75 | val, mod = divmod(val, 256)
76 | dec.append(mod)
77 |
78 | dec.extend(bytearray(prefix))
79 |
80 | return bytes(dec[::-1])
81 |
82 |
83 | def check_decode(enc):
84 | dec = decode(enc)
85 | raw, chk = dec[:-4], dec[-4:]
86 | if chk != sha256(sha256(raw).digest()).digest()[:4]:
87 | raise ValueError("base58 decoding checksum error")
88 | else:
89 | return raw
90 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/transactions.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Transactions.ts
2 |
3 | class Transactions:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def get(self, id: str) -> {}:
8 | """
9 | Get a Transaction
10 |
11 | :param id: (required) id of transaction to query
12 | :type id: str
13 | :return: (json string) {id: str, order: int, block: {hash: str, height: int, time: int,
14 | medianTime: int}, txid: str, hash: str, version: int, size: int, vSize: int,
15 | weight: int, lockTime: int, vinCount: int, voutCount: int, totalVoutValue: str}
16 |
17 | :example:
18 |
19 | >>> ocean.transactions.get("8d654cdaeba4633aa08e46f1aa258aae7234e89945145f61bc1bd5b342df1069")
20 | """
21 | return self._ocean._conn.get(f"transactions/{id}")
22 |
23 | def getVins(self, txid: str, size: int = 30, next: str = None) -> {}:
24 | """
25 | Get a list of vins of a Transaction
26 |
27 | :param txid: (required) txid of the transaction
28 | :type txid: str
29 | :param size: (optional) size to query
30 | :type size: int
31 | :param next: (optional) next token for next slice of vin
32 | :type next: str
33 | :return: (json string) {id: str, txid: str, coinbase: str, vout: {id: str, txid: str, n: int,
34 | value: str, tokenId: int, script: {hex: str}}, script: {hex: str}, txInWitness: str[],
35 | sequence: str}
36 |
37 | :example:
38 |
39 | >>> ocean.transactions.getVins("8d654cdaeba4633aa08e46f1aa258aae7234e89945145f61bc1bd5b342df1069")
40 | """
41 | return self._ocean._conn.get(f"transactions/{txid}/vins", size=size, next=next)
42 |
43 | def getVouts(self, txid: str, size: int = 30, next: str = None) -> {}:
44 | """
45 | Get a list of vouts of a Transaction
46 |
47 | :param txid: (required) txid of the transaction
48 | :type txid: str
49 | :param size: (optional) size to query
50 | :type size: int
51 | :param next: (optional) next token for next slice of vout
52 | :type next: str
53 | :return: (json string) {id: str, txid: str, n: int, value: str, tokenId: int,
54 | script: {hex: str, type: str}}
55 |
56 | :example:
57 |
58 | >>> ocean.transactions.getVouts("8d654cdaeba4633aa08e46f1aa258aae7234e89945145f61bc1bd5b342df1069")
59 | """
60 | return self._ocean._conn.get(f"transactions/{txid}/vouts", size=size, next=next)
61 |
--------------------------------------------------------------------------------
/defichain/transactions/address/bech32address.py:
--------------------------------------------------------------------------------
1 | from abc import ABC
2 | from typing import Any
3 | import binascii
4 |
5 | from defichain.exceptions.transactions import AddressError
6 | from defichain.libs import bech32
7 | from defichain.transactions.constants import CHARSET, CHARSET_BASE
8 | from .baseaddress import BaseAddress
9 |
10 |
11 | class Bech32Address(BaseAddress, ABC):
12 | @staticmethod
13 | def _is_bech32address(address: str) -> bool:
14 | bech32decode = bech32.bech32_decode(address)
15 | if not bech32decode[0]:
16 | raise AddressError(f"The given address: {address} is not a valid bech32 address")
17 | return True
18 |
19 | @staticmethod
20 | def _is_scriptPublicKey(scriptPublicKey: str) -> bool:
21 | if not (scriptPublicKey[0:4] == "0014" and len(scriptPublicKey) == 44):
22 | raise AddressError(f"The given script public key: {scriptPublicKey} is not valid")
23 | return True
24 |
25 | @staticmethod
26 | def decode(address: str) -> str:
27 | data = reversed(address[4:-6])
28 | result = '%x' % sum([CHARSET.find(c) * CHARSET_BASE ** i for i, c in enumerate(data)])
29 |
30 | while len(result) < 40:
31 | result = "0" + result
32 | return result
33 |
34 | @staticmethod
35 | def encode(network: Any, data: str) -> str:
36 | data = "0014" + data
37 | binary = binascii.unhexlify(data)
38 | version = binary[0] - 0x50 if binary[0] else 0
39 | program = binary[2:]
40 | return bech32.encode(network.SEGWIT_ADDRESS.HRP, version, program)
41 |
42 | @staticmethod
43 | def scriptPublicKey_to_address(network: Any, scriptPublicKey: str) -> str:
44 | if scriptPublicKey[0:4] == "0014":
45 | return Bech32Address.encode(network, scriptPublicKey[4:])
46 |
47 | @staticmethod
48 | def verify(address: str) -> bool:
49 | return Bech32Address._is_bech32address(address)
50 |
51 | def __init__(self, network: Any, address: str):
52 | super().__init__(network)
53 | self._address = None
54 | self.set_address(address)
55 |
56 | # Get Information
57 | def get_address(self) -> str:
58 | return self._address
59 |
60 | # Set Information
61 | def set_address(self, address: str) -> None:
62 | self.verify(address)
63 | self._address = address
64 |
65 | def set_scriptPublicKey(self, scriptPublicKey: str) -> None:
66 | self._is_scriptPublicKey(scriptPublicKey)
67 | self.set_address(self.scriptPublicKey_to_address(self.get_network(), scriptPublicKey))
68 |
--------------------------------------------------------------------------------
/tests/transactions/defitx/test_pool.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.networks import DefichainMainnet
4 | from defichain.transactions.defitx import DefiTx, PoolSwap, CompositeSwap, AddPoolLiquidity, RemovePoolLiquidity
5 | from . import Addresses, TestPool
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_poolswap(): # 01
10 | poolswap: PoolSwap = PoolSwap(addressFrom=TestPool.addressFrom, tokenFrom=TestPool.tokenFrom,
11 | amountFrom=TestPool.amountFrom, addressTo=TestPool.addressTo,
12 | tokenTo=TestPool.tokenTo, maxPrice=TestPool.maxPrice)
13 |
14 | assert poolswap.serialize() == TestPool.poolswap_serialized
15 |
16 | assert DefiTx.deserialize(DefichainMainnet, TestPool.poolswap_serialized).serialize() == \
17 | TestPool.poolswap_serialized
18 |
19 |
20 | @pytest.mark.transactions
21 | def test_compositeswap(): # 02
22 | compositeswap: CompositeSwap = CompositeSwap(addressFrom=TestPool.addressFrom, tokenFrom=TestPool.tokenFrom,
23 | amountFrom=TestPool.amountFrom, addressTo=TestPool.addressTo,
24 | tokenTo=TestPool.tokenTo2, maxPrice=TestPool.maxPrice,
25 | pools=TestPool.pools)
26 |
27 | assert compositeswap.serialize() == TestPool.compositeswap_serialized
28 |
29 | assert DefiTx.deserialize(DefichainMainnet, TestPool.compositeswap_serialized).serialize() == \
30 | TestPool.compositeswap_serialized
31 |
32 |
33 | @pytest.mark.transactions
34 | def test_addpoolliquidity(): # 03
35 | addpoolliquidity: AddPoolLiquidity = AddPoolLiquidity(addressAmount=TestPool.addressAmount,
36 | shareAddress=Addresses.P2WPKH)
37 |
38 | assert addpoolliquidity.serialize() == TestPool.addpoolliquidity_serialized
39 |
40 | assert DefiTx.deserialize(DefichainMainnet, TestPool.addpoolliquidity_serialized).serialize() == \
41 | TestPool.addpoolliquidity_serialized
42 |
43 |
44 | @pytest.mark.transactions
45 | def test_removepoolliquidity(): # 04
46 | removepoolliquidity: RemovePoolLiquidity = RemovePoolLiquidity(addressFrom=Addresses.P2WPKH,
47 | amount=TestPool.removeAmount)
48 |
49 | assert removepoolliquidity.serialize() == TestPool.removepoolliquidity_serialized
50 |
51 | assert DefiTx.deserialize(DefichainMainnet, TestPool.removepoolliquidity_serialized).serialize() == \
52 | TestPool.removepoolliquidity_serialized
53 |
--------------------------------------------------------------------------------
/defichain/ocean/connection.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | from defichain.logger import Logger
4 | from defichain.ocean.OceanErrorHandler import OceanErrorHandler
5 |
6 |
7 | class Connection:
8 | def __init__(self, url, logger: Logger):
9 | self._url = url
10 | self._session = requests.Session()
11 | self._headers = {'content-type': 'application/json'}
12 | self._logger = logger
13 |
14 | def get(self, data, size=None, next=None):
15 | if "?" in data:
16 | sep = "&"
17 | else:
18 | sep = "?"
19 |
20 | url = self._url + data
21 | if size is not None and next is not None:
22 | url += f"{sep}size={size}&next={next}"
23 | elif size is not None:
24 | url += f"{sep}size={size}"
25 | elif next is not None:
26 | url += f"{sep}next={next}"
27 |
28 | # Logging of Ocean get request url
29 | if self._logger:
30 | if self._logger.log_level == "input" or self._logger.log_level == "all":
31 | self._logger.input("OceanInput", f"Get request url: {url}")
32 |
33 | response = requests.get(url)
34 | OceanErrorHandler(response, self._logger) # Handle Exceptions
35 |
36 | result = json.loads(response.text)
37 |
38 | # Logging of Ocean get request result
39 | if self._logger:
40 | if self._logger.log_level == "output" or self._logger.log_level == "all":
41 | self._logger.output("OceanOutput", f"Result of get request: {result}")
42 |
43 | return result
44 |
45 | def post(self, method, params):
46 | if method == "rawtx/send" or method == "rawtx/test":
47 | payload = params
48 | else:
49 | payload = json.dumps({"params": list(params), "jsonrpc": "2.0"})
50 |
51 | # Logging of Ocean post request
52 | if self._logger:
53 | if self._logger.log_level == "input" or self._logger.log_level == "all":
54 | self._logger.input("OceanInput", f"Post request: {self._url + method, self._headers, payload}")
55 |
56 | response = self._session.post(self._url + method, headers=self._headers, data=payload)
57 | OceanErrorHandler(response, self._logger) # Handle Exceptions
58 |
59 | result = response.json()
60 |
61 | # Logging of Ocean get requests result
62 | if self._logger:
63 | if self._logger.log_level == "output" or self._logger.log_level == "all":
64 | self._logger.output("OceanOutput", f"Result of post request: {result}")
65 |
66 | return result
67 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/stats.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Stats.ts
2 |
3 | class Stats:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def get(self) -> {}: # 01
8 | """
9 | Get stats of DeFi Blockchain
10 |
11 | :return: (json string) {count: {blocks: int, tokens: int, prices: int, masternodes: int}, tvl: {total: float,
12 | dex: float, loan: float, masternodes: float}, burned: {total: float, address: float, fee: int,
13 | auction: float, payback: float, emission: float}, price: {usd: float, usdt: float},
14 | masternodes: {locked: [{ weeks: int, tvl: float, count: int}]}, emission: {total: float,
15 | masternode: float, dex: float, community: float, anchor: float, burned: float},
16 | loan: {count: {schemes: int, loanTokens: int, collateralTokens: int, openVaults: int,
17 | openAuctions: int}, value: {collateral: float, loan: float}}, blockchain: {difficulty: float},
18 | net: {version: int, subversion: str, protocolversion: int}}
19 |
20 | :example:
21 |
22 | >>> ocean.stats.get()
23 | """
24 | return self._ocean._conn.get("stats")
25 |
26 | def getRewardDistribution(self) -> {}:
27 | """
28 | Get reward distribution of DeFi Blockchain
29 |
30 | :return: (json string) {masternode: int, community: int, anchor: int, liquidity: int, loan: int, options: int, unallocated: int}
31 |
32 | :example:
33 |
34 | >>> ocean.stats.getRewardDistribution()
35 | """
36 | return self._ocean._conn.get("stats/rewards/distribution")
37 |
38 | def getSupply(self) -> {}: # 02
39 | """
40 | Get supply of DeFi Blockchain
41 |
42 | :return: (json string) {max: float, total: float, burned: float, circulating: float}
43 |
44 | :example:
45 |
46 | >>> ocean.stats.getSupply()
47 | """
48 | return self._ocean._conn.get("stats/supply")
49 |
50 | def getBurn(self) -> {}: # 03
51 | """
52 | Get burn info of DeFi Blockchain
53 |
54 | :return: (json string) {address: str, amount: str, tokens: str[], feeburn: float, emissionburn: float,
55 | auctionburn: float, paybackburn: float, paybackburntokens: str[], dexfeetokens: str[],
56 | dfipaybackfee: float, dfipaybacktokens: str[], paybackfees: str[], paybacktokens: str[],
57 | dfip2203: str[], dfip2206f: str[]}
58 |
59 | :example:
60 |
61 | >>> ocean.stats.getBurn()
62 | """
63 | return self._ocean._conn.get("stats/burn")
64 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/blocks.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Blocks.ts
2 |
3 | class Blocks:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def list(self, size: int = 30, next: str = None) -> {}: # 01
8 | """
9 | Returns a list of blocks
10 |
11 | :param size: (optional) size to query
12 | :type size: int
13 | :param next: next token for next slice of blocks
14 | :type next: (optional) str
15 | :return: (json string) {id: str, hash: str, previousHash: str, height: int, version: int, time: int,
16 | medianTime: int, transactionCount: int, difficulty: float, masternode: str, minter: str,
17 | minterBlockCount: int, reward: str, stakeModifier: str, merkleroot: str, size: int,
18 | sizeStripped: int, weight: int}
19 |
20 | :example:
21 |
22 | >>> ocean.blocks.list()
23 | """
24 | return self._ocean._conn.get("blocks", size=size, next=next)
25 |
26 | def get(self, id: str) -> {}: # 02
27 | """
28 | Returns the specified block
29 |
30 | :param id: (required) id as hash or height of the block
31 | :type id: str
32 | :return: (json string) {id: str, hash: str, previousHash: str, height: int, version: int, time: int,
33 | medianTime: int, transactionCount: int, difficulty: float, masternode: str, minter: str,
34 | minterBlockCount: int, reward: str, stakeModifier: str, merkleroot: str, size: int,
35 | sizeStripped: int, weight: int}
36 |
37 | :example:
38 |
39 | >>> ocean.blocks.get(0)
40 | """
41 | return self._ocean._conn.get(f"blocks/{id}")
42 |
43 | def getTransactions(self, hash: str, size: int = 30, next: str = None) -> {}: # 03
44 | """
45 | Gets all transactions within a block
46 |
47 | :param hash: (required) hash of the block
48 | :type hash: str
49 | :param size: (optional) size to query
50 | :type size: int
51 | :param next: (optional) next token for next slice of blocks
52 | :type next: str
53 | :return: (json string) {id: str, order: int, block: {hash: str, height: int, time: int,
54 | medianTime: int}, txid: str, hash: str, version: int, size: int, vSize: int,
55 | weight: int, lockTime: int, vinCount: int, voutCount: int, totalVoutValue: str}
56 |
57 | :example:
58 |
59 | >>> ocean.blocks.getTransactions("e5b266f18db7662628ea503eb9f889197f05660981f22c07b1b3b86f14329099")
60 | """
61 | return self._ocean._conn.get(f"blocks/{hash}/transactions", size=size, next=next)
62 |
--------------------------------------------------------------------------------
/defichain/ocean/modules/oracles.py:
--------------------------------------------------------------------------------
1 | # https://github.com/DeFiCh/jellyfish/blob/main/packages/whale-api-client/src/api/Prices.ts
2 |
3 | class Oracles:
4 | def __init__(self, ocean):
5 | self._ocean = ocean
6 |
7 | def list(self, size: int = 30, next: str = None) -> {}: # 01
8 | """
9 | Get a list of Oracles
10 |
11 | :param size: (optional) for number of records per page
12 | :type size: int
13 | :param next: (optional) offset for the next page
14 | :type next: str
15 | :return: (json string) {id: str, weightage: int, ownerAddress: str, priceFeeds: [{token: str, currency: str}],
16 | block: {hash: str, height: int, time: int, medianTime: int}}
17 |
18 | :example:
19 |
20 | >>> ocean.oracles.list()
21 | """
22 | return self._ocean._conn.get("oracles", size=size, next=next)
23 |
24 | def getPriceFeed(self, oracleId: str, token: str, currency: str, size: int = 30, next: str = None) -> {}: # 02
25 | """
26 | Get price feed
27 |
28 | :param oracleId: (required) oracleId identifier for an Oracle
29 | :type oracleId: str
30 | :param token: (required) token symbol as part of the price feed pair
31 | :type token: str
32 | :param currency: (required) currency fiat currency part of the price feed pair
33 | :type currency: str
34 | :param size: (optional) for number of records per page
35 | :type size: int
36 | :param next: (optional) offset for the next page
37 | :type next: str
38 | :return: (json string) {id: str, key: str, sort: str, token: str, currency: str, oracleId: str,
39 | txid: str, time: int, amount: str, block: {hash: str, height: int, time: int,
40 | medianTime: int}}
41 |
42 | :example:
43 |
44 | >>> ocean.oracles.getPriceFeed('f95b8a0ef321bcd310a9cc57b90d74fa4423895448678fbf8487807a125a08ef', "GOLD", "USD")
45 | """
46 | key = f"{token}-{currency}"
47 | return self._ocean._conn.get(f"oracles/{oracleId}/{key}/feed", size=size, next=next)
48 |
49 | def getOracleByAddress(self, address: str) -> {}: # 03
50 | """
51 | Get oracle by address
52 |
53 | :param address: (required) address owner address for an Oracle
54 | :type address: str
55 | :return: (json string) {id: str, weightage: int, ownerAddress: str, priceFeeds: [{token: str, currency: str}],
56 | block: {hash: str, height: int, time: int, medianTime: int}}
57 |
58 | :example:
59 |
60 | >>> ocean.oracles.getOracleByAddress("df1q8cz47rwefsxme29sstumepw374gzeu025gqcy4")
61 | """
62 | return self._ocean._conn.get(f"oracles/{address}")
63 |
--------------------------------------------------------------------------------
/tests/transactions/defitx/test_loans.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from defichain.networks import DefichainMainnet
4 | from defichain.transactions.defitx import DefiTx, TakeLoan, PaybackLoan
5 | from . import Addresses, TestLoans
6 |
7 |
8 | @pytest.mark.transactions
9 | def test_takeloan(): # 01
10 | takeloan_p2pkh: TakeLoan = TakeLoan(vaultId=TestLoans.vaultId, addressTo=Addresses.P2PKH, amounts=TestLoans.amounts)
11 | takeloan_p2sh: TakeLoan = TakeLoan(vaultId=TestLoans.vaultId, addressTo=Addresses.P2SH, amounts=TestLoans.amounts)
12 | takeloan_p2wpkh: TakeLoan = TakeLoan(vaultId=TestLoans.vaultId, addressTo=Addresses.P2WPKH,
13 | amounts=TestLoans.amounts)
14 |
15 | assert takeloan_p2pkh.serialize() == TestLoans.takeloan_p2pkh_serialized
16 | assert takeloan_p2sh.serialize() == TestLoans.takeloan_p2sh_serialized
17 | assert takeloan_p2wpkh.serialize() == TestLoans.takeloan_p2wpkh_serialized
18 |
19 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.takeloan_p2pkh_serialized).serialize() == \
20 | TestLoans.takeloan_p2pkh_serialized
21 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.takeloan_p2sh_serialized).serialize() == \
22 | TestLoans.takeloan_p2sh_serialized
23 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.takeloan_p2wpkh_serialized).serialize() == \
24 | TestLoans.takeloan_p2wpkh_serialized
25 |
26 |
27 | @pytest.mark.transactions
28 | def test_paybackloan(): # 02
29 | paybackloan_p2pkh: PaybackLoan = PaybackLoan(vaultId=TestLoans.vaultId, addressFrom=Addresses.P2PKH,
30 | amounts=TestLoans.amounts)
31 | paybackloan_p2sh: PaybackLoan = PaybackLoan(vaultId=TestLoans.vaultId, addressFrom=Addresses.P2SH,
32 | amounts=TestLoans.amounts)
33 | paybackloan_p2wpkh: PaybackLoan = PaybackLoan(vaultId=TestLoans.vaultId, addressFrom=Addresses.P2WPKH,
34 | amounts=TestLoans.amounts)
35 |
36 | assert paybackloan_p2pkh.serialize() == TestLoans.paybackloan_p2pkh_serialized
37 | assert paybackloan_p2sh.serialize() == TestLoans.paybackloan_p2sh_serialized
38 | assert paybackloan_p2wpkh.serialize() == TestLoans.paybackloan_p2wpkh_serialized
39 |
40 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.paybackloan_p2pkh_serialized).serialize() == \
41 | TestLoans.paybackloan_p2pkh_serialized
42 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.paybackloan_p2sh_serialized).serialize() == \
43 | TestLoans.paybackloan_p2sh_serialized
44 | assert DefiTx.deserialize(DefichainMainnet, TestLoans.paybackloan_p2wpkh_serialized).serialize() == \
45 | TestLoans.paybackloan_p2wpkh_serialized
46 |
--------------------------------------------------------------------------------
/defichain/transactions/address/p2sh.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 |
3 | from defichain.networks import Network
4 | from defichain.transactions.constants import AddressTypes, OPCodes
5 | from defichain.transactions.keys import PrivateKey, PublicKey
6 | from .base58address import Base58Address
7 | from .script import Script
8 |
9 |
10 | class P2SH(Base58Address): # Pay to Script Hash
11 |
12 | @staticmethod
13 | def from_publicKey(network: Any, publicKey: str) -> "P2SH":
14 | """
15 | Generates a P2SH address object from the given public key
16 |
17 | :param network: (required) The network in witch the public key should be used
18 | :type network: Network
19 | :param publicKey: (required) public key
20 | :type publicKey: str
21 | :return: P2SH - returns the P2SH address object
22 | """
23 | return P2SH(network, PublicKey(network, publicKey).p2sh_address())
24 |
25 | @staticmethod
26 | def from_privateKey(network: Any, privateKey: str) -> "P2SH":
27 | """
28 | Generates a P2SH address object from the given private key
29 |
30 | :param network: (required) The network in witch the private key should be used
31 | :type network: Network or DefichainRegtest
32 | :param privateKey: (required) private key
33 | :type privateKey: str
34 | :return: P2SH - returns the P2SH address object
35 | """
36 | return P2SH(network, PrivateKey(network, privateKey).p2sh_address())
37 |
38 | @staticmethod
39 | def from_scriptPublicKey(network: Any, scriptPublicKey: str) -> "P2SH":
40 | """
41 | Generates a P2SH address object from the given script private key
42 |
43 | :param network: (required) The network in witch the script public key should be used
44 | :type network: Network
45 | :param scriptPublicKey: (required) script public key
46 | :type scriptPublicKey: str
47 | :return: P2SH - returns the P2SH address object
48 | """
49 | return P2SH(network, Base58Address.scriptPublicKey_to_address(network, scriptPublicKey))
50 |
51 | def __init__(self, network: Any, address: str):
52 | super().__init__(network, address)
53 |
54 | def get_addressType(self) -> str:
55 | return AddressTypes.P2SH
56 |
57 | def get_scriptPublicKey(self) -> str:
58 | return Script.build_script([OPCodes.OP_HASH160, Base58Address.decode(self.get_address())[2:42], OPCodes.OP_EQUAL])
59 |
60 | def get_redeemScript(self) -> str:
61 | return self.get_scriptPublicKey()
62 |
63 | def get_bytes_scriptPublicKey(self) -> bytes:
64 | return bytes.fromhex(self.get_scriptPublicKey())
65 |
66 | def get_bytes_redeemScript(self) -> bytes:
67 | return bytes.fromhex(self.get_redeemScript())
68 |
--------------------------------------------------------------------------------