kaleido-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. kaleido_sdk-0.1.0/.gitignore +120 -0
  2. kaleido_sdk-0.1.0/PKG-INFO +83 -0
  3. kaleido_sdk-0.1.0/README.md +52 -0
  4. kaleido_sdk-0.1.0/examples/01_hello.py +65 -0
  5. kaleido_sdk-0.1.0/examples/02_get_quote.py +104 -0
  6. kaleido_sdk-0.1.0/examples/03_websocket.py +102 -0
  7. kaleido_sdk-0.1.0/examples/04_create_swap_order.py +120 -0
  8. kaleido_sdk-0.1.0/examples/05_quote_logging_demo.py +100 -0
  9. kaleido_sdk-0.1.0/examples/06_multi_route_streaming.py +102 -0
  10. kaleido_sdk-0.1.0/examples/07_swap_demo.py +77 -0
  11. kaleido_sdk-0.1.0/examples/08_advanced_market_data.py +79 -0
  12. kaleido_sdk-0.1.0/examples/09_error_handling.py +110 -0
  13. kaleido_sdk-0.1.0/kaleido_sdk/__init__.py +260 -0
  14. kaleido_sdk-0.1.0/kaleido_sdk/_generated/__init__.py +9 -0
  15. kaleido_sdk-0.1.0/kaleido_sdk/_generated/api_types.py +1190 -0
  16. kaleido_sdk-0.1.0/kaleido_sdk/_generated/node_types.py +1138 -0
  17. kaleido_sdk-0.1.0/kaleido_sdk/_http_client.py +267 -0
  18. kaleido_sdk-0.1.0/kaleido_sdk/_logging.py +46 -0
  19. kaleido_sdk-0.1.0/kaleido_sdk/_maker_client.py +720 -0
  20. kaleido_sdk-0.1.0/kaleido_sdk/_rln_client.py +740 -0
  21. kaleido_sdk-0.1.0/kaleido_sdk/_utils/__init__.py +23 -0
  22. kaleido_sdk-0.1.0/kaleido_sdk/_utils/precision.py +241 -0
  23. kaleido_sdk-0.1.0/kaleido_sdk/_ws_client.py +494 -0
  24. kaleido_sdk-0.1.0/kaleido_sdk/client.py +243 -0
  25. kaleido_sdk-0.1.0/kaleido_sdk/errors.py +241 -0
  26. kaleido_sdk-0.1.0/kaleido_sdk/py.typed +0 -0
  27. kaleido_sdk-0.1.0/kaleido_sdk/rln/__init__.py +255 -0
  28. kaleido_sdk-0.1.0/kaleido_sdk/types.py +181 -0
  29. kaleido_sdk-0.1.0/pyproject.toml +86 -0
  30. kaleido_sdk-0.1.0/tests/__init__.py +1 -0
  31. kaleido_sdk-0.1.0/tests/conftest.py +55 -0
  32. kaleido_sdk-0.1.0/tests/integration/test_maker_client.py +439 -0
  33. kaleido_sdk-0.1.0/tests/integration/test_rln_client.py +391 -0
  34. kaleido_sdk-0.1.0/tests/integration/test_websocket_client.py +23 -0
  35. kaleido_sdk-0.1.0/tests/unit/test_client.py +258 -0
  36. kaleido_sdk-0.1.0/tests/unit/test_errors.py +204 -0
  37. kaleido_sdk-0.1.0/tests/unit/test_precision.py +148 -0
  38. kaleido_sdk-0.1.0/tests/unit/test_websocket.py +95 -0
  39. kaleido_sdk-0.1.0/tests/utils.py +77 -0
  40. kaleido_sdk-0.1.0/uv.lock +1026 -0
@@ -0,0 +1,120 @@
1
+ target/
2
+
3
+ # Node.js
4
+ node_modules/
5
+
6
+ # TypeScript SDK build artifacts
7
+ typescript-sdk/dist/
8
+ typescript-sdk/coverage/
9
+ typescript-sdk/*.js
10
+ typescript-sdk/*.js.map
11
+ typescript-sdk/*.d.ts
12
+ !typescript-sdk/jest.config.js
13
+ !typescript-sdk/.eslintrc.js
14
+
15
+ # NAPI-RS build artifacts (Node.js native modules)
16
+ *.node
17
+ !node_modules/**/*.node
18
+
19
+ # Lock files - only pnpm is used
20
+ package-lock.json
21
+ npm-shrinkwrap.json
22
+
23
+
24
+ # Package.json filtering
25
+ package-lock.json
26
+ !crates/*/package.json
27
+
28
+ # Python
29
+ __pycache__/
30
+ *.py[cod]
31
+ *$py.class
32
+
33
+ # C extensions
34
+ *.so
35
+
36
+ # Distribution / packaging
37
+ .Python
38
+ build/
39
+ develop-eggs/
40
+ dist/
41
+ downloads/
42
+ eggs/
43
+ .eggs/
44
+ lib/
45
+ lib64/
46
+ !typescript/packages/*/src/lib/
47
+ parts/
48
+ sdist/
49
+ var/
50
+ wheels/
51
+ *.egg-info/
52
+ .installed.cfg
53
+ *.egg
54
+
55
+ # Unit test / coverage reports
56
+ htmlcov/
57
+ .tox/
58
+ .nox/
59
+ .coverage
60
+ .coverage.*
61
+ .cache
62
+ nosetests.xml
63
+ coverage.xml
64
+ test-results.xml
65
+ *.cover
66
+ *.py,cover
67
+ .hypothesis/
68
+ .pytest_cache/
69
+
70
+ # Environments
71
+ .env
72
+ .venv
73
+ env/
74
+ venv/
75
+ ENV/
76
+ env.bak/
77
+ venv.bak/
78
+
79
+ # IDE specific files
80
+ .idea/
81
+ .vscode/
82
+ *.swp
83
+ *.swo
84
+ .DS_Store
85
+
86
+ # Jupyter Notebook
87
+ .ipynb_checkpoints
88
+
89
+ # mypy
90
+ .mypy_cache/
91
+ .dmypy.json
92
+ dmypy.json
93
+
94
+ # Ruff
95
+ .ruff_cache/
96
+
97
+ # Rope project settings
98
+ .ropeproject
99
+
100
+ # mkdocs documentation
101
+ /site
102
+
103
+ # Sphinx documentation
104
+ docs/_build/
105
+
106
+ # pyenv
107
+ .python-version
108
+
109
+ # Log files
110
+ *.log
111
+ *.log.*
112
+ logs/
113
+ log/
114
+
115
+ *.pyc
116
+ __pycache__/
117
+ *.DS_Store
118
+
119
+ # Generated spec snapshots
120
+ specs/backup/
@@ -0,0 +1,83 @@
1
+ Metadata-Version: 2.4
2
+ Name: kaleido-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the Kaleidoswap protocol - Trade RGB assets on Lightning Network
5
+ Project-URL: Homepage, https://kaleidoswap.com
6
+ Project-URL: Documentation, https://docs.kaleidoswap.com
7
+ Project-URL: Repository, https://github.com/kaleidoswap/kaleido-sdk
8
+ Author-email: Kaleidoswap <dev@kaleidoswap.com>
9
+ License-Expression: MIT
10
+ Keywords: bitcoin,lightning,rgb,sdk,swap,trading
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic[email]>=2.0
24
+ Requires-Dist: websockets>=12.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: datamodel-code-generator[ruff]>=0.54.0; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Kaleidoswap Python SDK
33
+
34
+ [![pypi package](https://img.shields.io/pypi/v/kaleido-sdk?label=pypi%20package)](https://pypi.org/project/kaleido-sdk/)
35
+
36
+ Python SDK for trading RGB assets on the Lightning Network via the Kaleidoswap protocol.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install kaleido-sdk
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ The SDK exposes two sub-clients depending on what you need:
47
+
48
+ | Sub-client | Config key | What it does |
49
+ |---|---|---|
50
+ | `client.maker` | `base_url` | Kaleidoswap market API — assets, quotes, swap orders, LSP |
51
+ | `client.rln` | `node_url` | Your RGB Lightning Node — wallet, channels, payments, RGB assets |
52
+
53
+ ```python
54
+ from kaleido_sdk import KaleidoClient
55
+
56
+ # Zero-config — defaults to regtest
57
+ client = KaleidoClient.create()
58
+ assets = await client.maker.list_assets()
59
+
60
+ # Maker API only
61
+ client = KaleidoClient.create(base_url="https://api.kaleidoswap.com")
62
+ assets = await client.maker.list_assets()
63
+
64
+ # Node only (base_url still defaults to regtest)
65
+ client = KaleidoClient.create(node_url="http://localhost:3001")
66
+ info = await client.rln.get_node_info()
67
+
68
+ # Both together
69
+ client = KaleidoClient.create(
70
+ base_url="https://api.kaleidoswap.com",
71
+ node_url="http://localhost:3001",
72
+ )
73
+ pairs = await client.maker.list_pairs()
74
+ channels = await client.rln.list_channels()
75
+ ```
76
+
77
+ ## Documentation
78
+
79
+ Full usage guide, API reference, and examples at **https://docs.kaleidoswap.com/sdk/introduction**
80
+
81
+ ## License
82
+
83
+ MIT
@@ -0,0 +1,52 @@
1
+ # Kaleidoswap Python SDK
2
+
3
+ [![pypi package](https://img.shields.io/pypi/v/kaleido-sdk?label=pypi%20package)](https://pypi.org/project/kaleido-sdk/)
4
+
5
+ Python SDK for trading RGB assets on the Lightning Network via the Kaleidoswap protocol.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install kaleido-sdk
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ The SDK exposes two sub-clients depending on what you need:
16
+
17
+ | Sub-client | Config key | What it does |
18
+ |---|---|---|
19
+ | `client.maker` | `base_url` | Kaleidoswap market API — assets, quotes, swap orders, LSP |
20
+ | `client.rln` | `node_url` | Your RGB Lightning Node — wallet, channels, payments, RGB assets |
21
+
22
+ ```python
23
+ from kaleido_sdk import KaleidoClient
24
+
25
+ # Zero-config — defaults to regtest
26
+ client = KaleidoClient.create()
27
+ assets = await client.maker.list_assets()
28
+
29
+ # Maker API only
30
+ client = KaleidoClient.create(base_url="https://api.kaleidoswap.com")
31
+ assets = await client.maker.list_assets()
32
+
33
+ # Node only (base_url still defaults to regtest)
34
+ client = KaleidoClient.create(node_url="http://localhost:3001")
35
+ info = await client.rln.get_node_info()
36
+
37
+ # Both together
38
+ client = KaleidoClient.create(
39
+ base_url="https://api.kaleidoswap.com",
40
+ node_url="http://localhost:3001",
41
+ )
42
+ pairs = await client.maker.list_pairs()
43
+ channels = await client.rln.list_channels()
44
+ ```
45
+
46
+ ## Documentation
47
+
48
+ Full usage guide, API reference, and examples at **https://docs.kaleidoswap.com/sdk/introduction**
49
+
50
+ ## License
51
+
52
+ MIT
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example 01: Hello Kaleidoswap
4
+
5
+ Basic example showing how to create a client and list assets.
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ import os
11
+
12
+ from kaleido_sdk import KaleidoClient, get_sdk_name, get_version
13
+
14
+ API_URL = os.getenv("KALEIDO_API_URL", "https://api.staging.kaleidoswap.com")
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Logging setup (application's responsibility — the SDK never does this)
18
+ # ---------------------------------------------------------------------------
19
+ # Show all SDK log levels. Change to logging.INFO or logging.WARNING to reduce noise.
20
+ logging.basicConfig(
21
+ level=logging.DEBUG,
22
+ format="%(asctime)s [%(levelname)-8s] %(name)s — %(message)s",
23
+ datefmt="%H:%M:%S",
24
+ )
25
+ # Optionally silence the HTTP sub-logger if you only care about higher-level events:
26
+ # logging.getLogger("kaleido_sdk.http").setLevel(logging.WARNING)
27
+
28
+
29
+ async def main() -> None:
30
+ """Main entry point."""
31
+ # Print SDK info
32
+ print(f"{get_sdk_name()} v{get_version()}")
33
+ print("-" * 40)
34
+
35
+ # Create client — log_level tells the SDK which records to emit
36
+ client = KaleidoClient.create(
37
+ base_url=API_URL,
38
+ log_level=logging.DEBUG,
39
+ )
40
+
41
+ # List available assets
42
+ print("\nFetching assets...")
43
+ assets_response = await client.maker.list_assets()
44
+
45
+ print(f"\nFound {assets_response.total} assets:")
46
+ for asset in assets_response.assets[:5]:
47
+ print(f" - {asset.ticker}: {asset.name} (precision: {asset.precision})")
48
+
49
+ if assets_response.total > 5:
50
+ print(f" ... and {assets_response.total - 5} more")
51
+
52
+ # List trading pairs
53
+ print("\nFetching trading pairs...")
54
+ pairs_response = await client.maker.list_pairs()
55
+
56
+ print(f"\nFound {pairs_response.total} pairs:")
57
+ for pair in pairs_response.pairs[:5]:
58
+ print(f" - {pair.base.ticker}/{pair.quote.ticker}")
59
+
60
+ if pairs_response.total > 5:
61
+ print(f" ... and {pairs_response.total - 5} more")
62
+
63
+
64
+ if __name__ == "__main__":
65
+ asyncio.run(main())
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example 02: Get Quote
4
+
5
+ Example showing how to get a quote for a swap.
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ import os
11
+
12
+ from kaleido_sdk import (
13
+ KaleidoClient,
14
+ Layer,
15
+ PairQuoteRequest,
16
+ SwapLegInput,
17
+ to_display_units,
18
+ to_smallest_units,
19
+ )
20
+
21
+ API_URL = os.getenv("KALEIDO_API_URL", "https://api.staging.kaleidoswap.com")
22
+
23
+ # ---------------------------------------------------------------------------
24
+ # Logging setup (application's responsibility — the SDK never does this)
25
+ # ---------------------------------------------------------------------------
26
+ logging.basicConfig(
27
+ level=logging.DEBUG,
28
+ format="%(asctime)s [%(levelname)-8s] %(name)s — %(message)s",
29
+ datefmt="%H:%M:%S",
30
+ )
31
+
32
+
33
+ async def main() -> None:
34
+ """Main entry point."""
35
+ client = KaleidoClient.create(
36
+ base_url=API_URL,
37
+ log_level=logging.DEBUG,
38
+ )
39
+
40
+ # Discover trading pairs
41
+ print("Fetching available pairs...")
42
+ pairs = await client.maker.list_pairs()
43
+
44
+ if not pairs.pairs:
45
+ print("No trading pairs available")
46
+ return
47
+
48
+ pair = pairs.pairs[0]
49
+ print(f"\nUsing pair: {pair.base.ticker}/{pair.quote.ticker}")
50
+ print(f" Base precision: {pair.base.precision}")
51
+ print(f" Quote precision: {pair.quote.precision}")
52
+
53
+ if pair.routes:
54
+ print(" Available routes:")
55
+ for route in pair.routes:
56
+ print(f" - {route.from_layer} -> {route.to_layer}")
57
+
58
+ # Get a quote for 0.001 BTC
59
+ amount = 0.001
60
+ amount_raw = to_smallest_units(amount, pair.base.precision)
61
+
62
+ print(f"\nGetting quote for {amount} {pair.base.ticker}...")
63
+ print(f" (raw amount: {amount_raw})")
64
+
65
+ if pair.routes:
66
+ from_layer = Layer(pair.routes[0].from_layer)
67
+ to_layer = Layer(pair.routes[0].to_layer)
68
+ else:
69
+ from_layer = Layer.BTC_LN
70
+ to_layer = Layer.RGB_LN
71
+
72
+ quote_request = PairQuoteRequest(
73
+ from_asset=SwapLegInput(
74
+ asset_id=pair.base.ticker,
75
+ layer=from_layer,
76
+ amount=amount_raw,
77
+ ),
78
+ to_asset=SwapLegInput(
79
+ asset_id=pair.quote.ticker,
80
+ layer=to_layer,
81
+ ),
82
+ )
83
+
84
+ try:
85
+ quote = await client.maker.get_quote(quote_request)
86
+
87
+ from_display = to_display_units(quote.from_asset.amount, quote.from_asset.precision)
88
+ to_display = to_display_units(quote.to_asset.amount, quote.to_asset.precision)
89
+
90
+ print("\nQuote received:")
91
+ print(f" RFQ ID: {quote.rfq_id}")
92
+ print(f" From: {from_display} {quote.from_asset.ticker}")
93
+ print(f" To: {to_display} {quote.to_asset.ticker}")
94
+ print(f" Price: {quote.price}")
95
+ print(f" Fee: {quote.fee.final_fee} {quote.fee.fee_asset}")
96
+ print(f" Expires at: {quote.expires_at}")
97
+
98
+ except Exception as e:
99
+ print(f"\nError getting quote: {e}")
100
+ print("(This is expected if the pair doesn't support the requested route)")
101
+
102
+
103
+ if __name__ == "__main__":
104
+ asyncio.run(main())
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example 03: WebSocket Streaming
4
+
5
+ Example showing how to stream real-time quotes via WebSocket.
6
+ The SDK automatically requests quotes at a configurable interval.
7
+ """
8
+
9
+ import asyncio
10
+ import logging
11
+ import os
12
+
13
+ from kaleido_sdk import KaleidoClient, Layer
14
+
15
+ API_URL = os.getenv("KALEIDO_API_URL", "https://api.staging.kaleidoswap.com")
16
+ WS_URL = os.getenv("KALEIDO_WS_URL", "wss://api.staging.kaleidoswap.com/api/v1/market/ws")
17
+
18
+ # ---------------------------------------------------------------------------
19
+ # Logging setup (application's responsibility — the SDK never does this)
20
+ # ---------------------------------------------------------------------------
21
+ # DEBUG shows every WS message, HTTP request, ping, reconnect, etc.
22
+ # Switch to logging.INFO to see only meaningful lifecycle events.
23
+ logging.basicConfig(
24
+ level=logging.DEBUG,
25
+ format="%(asctime)s [%(levelname)-8s] %(name)s — %(message)s",
26
+ datefmt="%H:%M:%S",
27
+ )
28
+
29
+
30
+ async def main() -> None:
31
+ """Main entry point."""
32
+ client = KaleidoClient.create(
33
+ base_url=API_URL,
34
+ log_level=logging.DEBUG,
35
+ )
36
+
37
+ # Enable WebSocket
38
+ ws = client.maker.enable_websocket(WS_URL)
39
+
40
+ quotes_received = 0
41
+ max_quotes = 5
42
+
43
+ def on_quote(quote: dict) -> None:
44
+ nonlocal quotes_received
45
+ quotes_received += 1
46
+
47
+ from_asset = quote.get("from_asset", {})
48
+ to_asset = quote.get("to_asset", {})
49
+
50
+ print(f"\nQuote #{quotes_received}:")
51
+ print(
52
+ f" From: {from_asset.get('amount')} {from_asset.get('ticker')} ({from_asset.get('layer')})"
53
+ )
54
+ print(f" To: {to_asset.get('amount')} {to_asset.get('ticker')} ({to_asset.get('layer')})")
55
+ print(f" Price: {quote.get('price')}")
56
+ print(f" RFQ ID: {quote.get('rfq_id')}")
57
+
58
+ ws.on("connected", lambda: print("Connected to WebSocket!"))
59
+ ws.on("disconnected", lambda: print("Disconnected from WebSocket"))
60
+ ws.on("error", lambda e: print(f"WebSocket error: {e}"))
61
+
62
+ try:
63
+ print("Finding available routes...")
64
+ routes = await client.maker.get_available_routes("BTC", "USDT")
65
+
66
+ if not routes:
67
+ print("No routes found for BTC/USDT")
68
+ return
69
+
70
+ print(f"Found {len(routes)} routes:")
71
+ for route in routes:
72
+ print(f" - {route.from_layer} -> {route.to_layer}")
73
+
74
+ print("\nStreaming quotes for BTC/USDT (automatically requests every 2 seconds)...")
75
+
76
+ # Start streaming - quotes are automatically requested every 2 seconds
77
+ stop = await client.maker.stream_quotes(
78
+ from_asset="BTC",
79
+ to_asset="USDT",
80
+ from_amount=100000,
81
+ from_layer=Layer(routes[0].from_layer),
82
+ to_layer=Layer(routes[0].to_layer),
83
+ on_update=on_quote,
84
+ poll_interval=2.0, # Request new quotes every 2 seconds
85
+ )
86
+
87
+ # Wait for quotes to arrive via callback
88
+ while quotes_received < max_quotes:
89
+ await asyncio.sleep(0.5)
90
+
91
+ # Stop streaming and disconnect
92
+ stop()
93
+ ws.disconnect()
94
+ print(f"\nReceived {quotes_received} quotes. Done!")
95
+
96
+ except Exception as e:
97
+ print(f"\nError: {e}")
98
+ print("(WebSocket streaming requires a working WebSocket endpoint)")
99
+
100
+
101
+ if __name__ == "__main__":
102
+ asyncio.run(main())
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example 04: Create Swap Order
4
+
5
+ Test-backed swap-order flow:
6
+ 1. Find the RGB asset ID for USDT
7
+ 2. Get a fresh quote for USDT(RGB_LN) -> BTC(BTC_L1)
8
+ 3. Ask the local node for a valid BTC receiver address
9
+ 4. Create a swap order
10
+ """
11
+
12
+ import asyncio
13
+ import logging
14
+ import os
15
+
16
+ from kaleido_sdk import (
17
+ CreateSwapOrderRequest,
18
+ KaleidoClient,
19
+ Layer,
20
+ PairQuoteRequest,
21
+ ReceiverAddress,
22
+ ReceiverAddressFormat,
23
+ SwapLegInput,
24
+ )
25
+
26
+ API_URL = os.getenv("KALEIDO_API_URL", "https://api.staging.kaleidoswap.com")
27
+ NODE_URL = os.getenv("KALEIDO_NODE_URL", "http://localhost:3001")
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # Logging setup (application's responsibility — the SDK never does this)
31
+ # ---------------------------------------------------------------------------
32
+ logging.basicConfig(
33
+ level=logging.DEBUG,
34
+ format="%(asctime)s [%(levelname)-8s] %(name)s — %(message)s",
35
+ datefmt="%H:%M:%S",
36
+ )
37
+
38
+
39
+ async def main() -> None:
40
+ """Main entry point."""
41
+ client = KaleidoClient.create(
42
+ base_url=API_URL,
43
+ log_level=logging.DEBUG,
44
+ )
45
+ node_client = KaleidoClient.create(
46
+ base_url=API_URL,
47
+ node_url=NODE_URL,
48
+ log_level=logging.DEBUG,
49
+ )
50
+
51
+ print(f"Maker API: {API_URL}")
52
+ print(f"Node URL: {NODE_URL}")
53
+ print("-" * 40)
54
+
55
+ print("\nFetching assets...")
56
+ assets = await client.maker.list_assets()
57
+ usdt_asset = next((asset for asset in assets.assets if asset.ticker == "USDT"), None)
58
+ if usdt_asset is None:
59
+ print("USDT asset not found in maker asset list")
60
+ return
61
+
62
+ protocol_ids = usdt_asset.protocol_ids or {}
63
+ rgb_asset_id = protocol_ids.get("RGB")
64
+ if rgb_asset_id is None:
65
+ print("USDT RGB asset id not found in protocol_ids")
66
+ return
67
+
68
+ print(f"Using RGB asset id for USDT: {rgb_asset_id}")
69
+
70
+ print("\nRequesting quote for USDT(RGB_LN) -> BTC(BTC_L1)...")
71
+ quote = await client.maker.get_quote(
72
+ PairQuoteRequest(
73
+ from_asset=SwapLegInput(
74
+ asset_id=rgb_asset_id,
75
+ layer=Layer.RGB_LN,
76
+ amount=1_000_000,
77
+ ),
78
+ to_asset=SwapLegInput(
79
+ asset_id="BTC",
80
+ layer=Layer.BTC_L1,
81
+ ),
82
+ )
83
+ )
84
+
85
+ print(f"RFQ ID: {quote.rfq_id}")
86
+ print(f"From: {quote.from_asset.amount} {quote.from_asset.ticker}")
87
+ print(f"To: {quote.to_asset.amount} {quote.to_asset.ticker}")
88
+
89
+ print("\nFetching a valid BTC address from the local node...")
90
+ address_response = await node_client.rln.get_address()
91
+ receiver_address = address_response.address
92
+ print(f"Receiver address: {receiver_address}")
93
+
94
+ order_request = CreateSwapOrderRequest(
95
+ rfq_id=quote.rfq_id,
96
+ from_asset=quote.from_asset,
97
+ to_asset=quote.to_asset,
98
+ receiver_address=ReceiverAddress(
99
+ address=receiver_address,
100
+ format=ReceiverAddressFormat.BTC_ADDRESS,
101
+ ),
102
+ min_onchain_conf=1,
103
+ refund_address=receiver_address,
104
+ email="test@example.com",
105
+ )
106
+
107
+ print("\nCreating swap order...")
108
+ order = await client.maker.create_swap_order(order_request)
109
+
110
+ print("\nOrder created:")
111
+ print(f" Order ID: {order.id}")
112
+ print(f" RFQ ID: {order.rfq_id}")
113
+ print(f" Status: {order.status}")
114
+ if order.deposit_address is not None:
115
+ print(f" Deposit address: {order.deposit_address.address}")
116
+ print(f" Deposit format: {order.deposit_address.format}")
117
+
118
+
119
+ if __name__ == "__main__":
120
+ asyncio.run(main())