{"id":13425572,"url":"https://github.com/tinymanorg/tinyman-py-sdk","last_synced_at":"2025-12-24T03:37:54.701Z","repository":{"id":38100395,"uuid":"386620917","full_name":"tinymanorg/tinyman-py-sdk","owner":"tinymanorg","description":"Tinyman Python SDK","archived":false,"fork":false,"pushed_at":"2023-05-18T12:14:08.000Z","size":314,"stargazers_count":118,"open_issues_count":7,"forks_count":51,"subscribers_count":12,"default_branch":"main","last_synced_at":"2024-01-24T04:14:37.983Z","etag":null,"topics":["algorand","sdk","tinyman"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tinymanorg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-07-16T11:58:00.000Z","updated_at":"2024-01-19T17:43:08.000Z","dependencies_parsed_at":"2024-01-03T05:16:30.634Z","dependency_job_id":"0ff9c191-bcd7-44bc-9d41-38419041c5ef","html_url":"https://github.com/tinymanorg/tinyman-py-sdk","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinymanorg%2Ftinyman-py-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinymanorg%2Ftinyman-py-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinymanorg%2Ftinyman-py-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinymanorg%2Ftinyman-py-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tinymanorg","download_url":"https://codeload.github.com/tinymanorg/tinyman-py-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243790927,"owners_count":20348377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorand","sdk","tinyman"],"created_at":"2024-07-31T00:01:14.997Z","updated_at":"2025-12-24T03:37:54.691Z","avatar_url":"https://github.com/tinymanorg.png","language":"Python","readme":"# tinyman-py-sdk\nTinyman Python SDK\n\n\u003cp align=\"left\"\u003e\n\u003cimg src=\"https://visitor-badge.glitch.me/badge?page_id=tinymanorg.tinyman-py-sdk\" /\u003e\n\u003ca href=\"https://github.com/tinymanorg/tinyman-py-sdk/actions/workflows/tests.yml\"\u003e\u003cimg src=\"https://github.com/tinymanorg/tinyman-py-sdk/actions/workflows/tests.yml/badge.svg?branch=main\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Design Goal\nThis SDK is designed for automated interaction with the Tinyman AMM. It will be most useful for developers who wish to create automated trading programs/bots. It may also be useful to create an alternative UI but that is not a design goal of this library.\nIt is designed to be reasonably low level so that pieces can be used in isolation. \n\n## Status\nThis SDK is currently under active early development and should not be considered stable.\n\nThe SDK supports Tinyman V2 and V1.1.\n\n\n## Requirements\n- Python 3.8+\n- py-algorand-sdk 1.10.0+\n\n## Installation\ntinyman-py-sdk is not released on PYPI. It can be installed directly from this repository with pip:\n\n`pip install git+https://github.com/tinymanorg/tinyman-py-sdk.git`\n\n\n## Integration\n\nIf you are integrating your project into Tinyman, you can provide `client_name` while setting up Tinyman Client classes.\nThe client name will be added to the application call transaction's note field. It is recommended and completely optional.\n\n```python\nclient = TinymanV2MainnetClient(..., client_name=\"project name\", ...)\n```\n\n## V2\n\n## Sneak Preview\n\n```python\n# examples/v2/sneak_preview.py\n\nfrom examples.v2.utils import get_algod\nfrom tinyman.v2.client import TinymanV2TestnetClient\n\nalgod = get_algod()\nclient = TinymanV2TestnetClient(algod_client=algod)\n\n# Fetch our two assets of interest\nUSDC = client.fetch_asset(10458941)\nALGO = client.fetch_asset(0)\n\n# Fetch the pool we will work with\npool = client.fetch_pool(USDC, ALGO)\nprint(f\"Pool Info: {pool.info()}\")\n\n# Get a quote for a swap of 1 ALGO to USDC with 1% slippage tolerance\nquote = pool.fetch_fixed_input_swap_quote(amount_in=ALGO(1_000_000), slippage=0.01)\nprint(quote)\nprint(f\"USDC per ALGO: {quote.price}\")\nprint(f\"USDC per ALGO (worst case): {quote.price_with_slippage}\")\n```\n\n## Tutorial\n\nYou can find a tutorial under the `examples/v2/tutorial` folder.\n\nTo run a step use `python \u003cfile_name\u003e` such as `python 01_generate_account.py`.\n\n#### Prerequisites\n1. [Generating an account](examples/v2/tutorial/01_generate_account.py)\n2. [Creating assets](examples/v2/tutorial/02_create_assets.py)\n\n#### Steps\n\n3. [Bootstrapping a pool](examples/v2/tutorial/03_bootstrap_pool.py)\n4. [Adding initial liquidity to the pool](examples/v2/tutorial/04_add_initial_liquidity.py)\n5. [Adding flexible (add two asset with a flexible rate) liquidity to the pool](examples/v2/tutorial/05_add_flexible_liquidity.py)\n6. [Adding single asset (add only one asset) liquidity to the pool](examples/v2/tutorial/06_add_single_asset_liquidity.py)\n7. [Removing liquidity to the pool](examples/v2/tutorial/07_remove_liquidity.py)\n8. [Removing single asset(receive single asset) liquidity to the pool](examples/v2/tutorial/08_single_asset_remove_liquidity.py)\n9. [Swapping fixed-input](examples/v2/tutorial/09_fixed_input_swap.py)\n10. [Swapping fixed-output](examples/v2/tutorial/10_fixed_output_swap.py)\n\n## Example Operations\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eBootstrap\u003c/strong\u003e\u003c/summary\u003e\n\n```python\ntxn_group = pool.prepare_bootstrap_transactions()\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eAdd Liquidity\u003c/strong\u003e\u003c/summary\u003e\n\n#### Initial Add Liquidity\n\n```python\nquote = pool.fetch_initial_add_liquidity_quote(\n    amount_a=\u003cAssetAmount\u003e,\n    amount_b=\u003cAssetAmount\u003e,\n)\ntxn_group = pool.prepare_add_liquidity_transactions_from_quote(quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\n#### Flexible Add Liquidity\n\n```python\nquote = pool.fetch_flexible_add_liquidity_quote(\n    amount_a=\u003cAssetAmount\u003e,\n    amount_b=\u003cAssetAmount\u003e,\n)\ntxn_group = pool.prepare_add_liquidity_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\n#### Single Asset Add Liquidity\n\n```python\nquote = pool.fetch_single_asset_add_liquidity_quote(amount_a=\u003cAssetAmount\u003e)\ntxn_group = pool.prepare_add_liquidity_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eRemove Liquidity\u003c/strong\u003e\u003c/summary\u003e\n\n#### Remove Liquidity\n\n```python\nquote = pool.fetch_remove_liquidity_quote(\n    pool_token_asset_in=\u003cAssetAmount\u003e,\n)\ntxn_group = pool.prepare_remove_liquidity_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\n#### Single Asset Remove Liquidity\n\n```python\nquote = pool.fetch_single_asset_remove_liquidity_quote(\n    pool_token_asset_in=\u003cAssetAmount\u003e,\n    output_asset=\u003cAsset\u003e,\n)\ntxn_group = pool.prepare_remove_liquidity_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSwap\u003c/strong\u003e\u003c/summary\u003e\n\n#### Fixed Input Swap\n\n```python\nquote = pool.fetch_fixed_input_swap_quote(amount_in=\u003cAssetAmount\u003e)\ntxn_group = pool.prepare_swap_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\n#### Fixed Output Swap\n\n```python\nquote = pool.fetch_fixed_output_swap_quote(amount_in=\u003cAssetAmount\u003e)\ntxn_group = pool.prepare_swap_transactions_from_quote(quote=quote)\ntxn_group.sign_with_private_key(\u003cADDRESS\u003e, \u003cPRIVATE_KEY\u003e)\ntxn_info = txn_group.submit(algod, wait=True)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFlash Loan\u003c/strong\u003e\u003c/summary\u003e\n\n1. [Flash Loan: Single Asset](examples/v2/tutorial/11_flash_loan_1_single_asset.py)\n2. [Flash Loan: Multiple Assets](examples/v2/tutorial/12_flash_loan_2_multiple_assets.py)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFlash Swap\u003c/strong\u003e\u003c/summary\u003e\n\n1. [Flash Swap: Pay in other currency](examples/v2/tutorial/13_flash_swap_1_pay_in_other_currency.py)\n2. [Flash Swap: Pay in same currency](examples/v2/tutorial/14_flash_swap_2_pay_in_same_currency.py)\n3. [Flash Swap: Pay in multiple currencies](examples/v2/tutorial/15_flash_swap_3_pay_in_multiple_currencies.py)\n\n\u003c/details\u003e\n\n## V1.1\n\n## Sneak Preview\n\n```python\nfrom tinyman.v1.client import TinymanTestnetClient\nfrom algosdk.v2client.algod import AlgodClient\n\n\nalgod = AlgodClient('\u003cTOKEN\u003e', 'http://localhost:8080', headers={'User-Agent': 'algosdk'})\nclient = TinymanTestnetClient(algod_client=algod)\n\n# Fetch our two assets of interest\nTINYUSDC = client.fetch_asset(21582668)\nALGO = client.fetch_asset(0)\n\n# Fetch the pool we will work with\npool = client.fetch_pool(TINYUSDC, ALGO)\n\n# Get a quote for a swap of 1 ALGO to TINYUSDC with 1% slippage tolerance\nquote = pool.fetch_fixed_input_swap_quote(ALGO(1_000_000), slippage=0.01)\nprint(quote)\nprint(f'TINYUSDC per ALGO: {quote.price}')\nprint(f'TINYUSDC per ALGO (worst case): {quote.price_with_slippage}')\n\n# See the examples for the rest...\n\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eExamples\u003c/strong\u003e\u003c/summary\u003e\n\n### Basic Swapping\n[swapping1.py](examples/v1/swapping1.py)\nThis example demonstrates basic functionality including:\n* retrieving Pool details\n* getting a swap quote\n* preparing swap transactions\n* signing transactions\n* submitting transactions\n* checking excess amounts\n* preparing redeem transactions\n\n[swapping1_less_convenience.py](examples/v1/swapping1_less_convenience.py)\nThis example has exactly the same functionality as [swapping1.py](examples/v1/swapping1.py) but is purposely more verbose, using less convenience functions.\n\n\n### Basic Pooling\n[pooling1.py](examples/v1/pooling1.py)\nThis example demonstrates retrieving the current pool position/share for an address.\n\n### Basic Add Liquidity (Minting)\n[add_liquidity1.py](examples/v1/add_liquidity1.py)\nThis example demonstrates add liquidity to an existing pool.\n\n### Basic Burning\nTODO\n\n\u003c/details\u003e\n\n## Conventions\n\n* Methods starting with `fetch_` all make network requests to fetch current balances/state.\n* Methods of the form `prepare_X_transactions` all return `TransactionGroup` objects (see below).\n* All asset amounts are returned as `AssetAmount` objects which contain an `Asset` and `amount` (`int`).\n* All asset amount inputs are expected as micro units e.g. 1 Algo = 1_000_000 micro units.\n\n## Signing \u0026 Submission\n\nThe SDk separates transaction preparation from signing and submission to leave the developer in full control of how transactions are signed and submitted to the network.\n\n### Preparation\nThe `prepare_X_transactions` methods all return a `TransactionGroup` object. This is a container object containing a list of transaction objects (`.transactions`) and a list for signed transactions (`.signed_transactions`). \n\n```python\ntransaction_group = client.prepare_app_optin_transactions(account['address'])\n```\n\n\n### Signing\nIn most cases some of the transactions have a corresponding entry in `.signed_transactions` because they have been signed by the Pool LogicSig. The remaining transactions should be signed by the 'user'.\n\n\nThe `TransactionGroup` includes a method to do this when signing with a private key:\n\n```python\ntransaction_group.sign_with_private_key(account['address'], account['private_key'])\n```\n\nThis helper method is equivalent to the following:\n```python\nfor i, txn in enumerate(transaction_group.transactions):\n    if txn.sender == account['address']:\n        transaction_group.signed_transactions[i] = txn.sign(account['private_key'])\n```\n\nAny alternative method of signing can be used here following the same pattern. For example using KMD:\n```python\nkmd = algosdk.kmd.KMDClient(KMD_TOKEN, KMD_ADDRESS)\nhandle = kmd.init_wallet_handle(KMD_WALLET_ID, KMD_WALLET_PASSWORD)\nfor i, txn in enumerate(transaction_group.transactions):\n    if txn.sender == account['address']:\n        transaction_group.signed_transactions[i] = kmd.sign_transaction(handle, KMD_WALLET_PASSWORD, txn)\n```\n\nA User account LogicSig can also be used in a similar way or using the `sign_with_logicsig` convenience method:\n```python\ntransaction_group.sign_with_logicsig(logicsig)\n```\n\n### Submission\n\nA `TransactionGroup` containing fully signed transactions can be submitted to the network in either of two ways:\n\nUsing an Algod client:\n\n```python\nalgod = AlgodClient(TOKEN, ADDRESS, headers={'User-Agent': 'algosdk'})\ntxid = algod.send_transactions(transaction_group.signed_transactions)\n```\n\nOr, using the convenience method of the `TinymanClient`:\n\n```python\nresult = client.submit(transaction_group, wait=True)\n```\n\nThis method submits the signed transactions and optionally waits for confirmation.\n\n\n# License\n\ntinyman-py-sdk is licensed under a MIT license except for the exceptions listed below. See the LICENSE file for details.\n\n## Exceptions\n`tinyman/v1/asc.json` is currently unlicensed. It may be used by this SDK but may not be used in any other way or be distributed separately without the express permission of Tinyman.\n","funding_links":[],"categories":["Development \u0026 Tools","Python","Development Tools"],"sub_categories":["Language SDKs \u0026 Tools","Languages"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinymanorg%2Ftinyman-py-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftinymanorg%2Ftinyman-py-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinymanorg%2Ftinyman-py-sdk/lists"}