├── 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 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 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 | --------------------------------------------------------------------------------