dpx-sdk 0.1.0__py3-none-any.whl

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.
dpx_sdk/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ from .client import DPX, DPXError
2
+ from .types import QuoteResult, SettlementResult, OracleStatus, EsgScore
3
+
4
+ __all__ = ["DPX", "DPXError", "QuoteResult", "SettlementResult", "OracleStatus", "EsgScore"]
5
+ __version__ = "0.1.0"
dpx_sdk/client.py ADDED
@@ -0,0 +1,162 @@
1
+ """
2
+ DPX Python SDK — thin async client over the DPX REST + Settlement Agent APIs.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import httpx
8
+ from typing import Optional
9
+
10
+ from .types import QuoteResult, SettlementResult, OracleStatus, EsgScore
11
+
12
+ STABILITY_URL = "https://stability.untitledfinancial.com"
13
+ ESG_URL = "https://esg.untitledfinancial.com"
14
+ AGENT_URL = "https://agent.untitledfinancial.com"
15
+ COMPLIANCE_URL = "https://compliance.untitledfinancial.com"
16
+ DEFAULT_TIMEOUT = 20.0
17
+
18
+
19
+ class DPXError(Exception):
20
+ def __init__(self, message: str, status_code: Optional[int] = None):
21
+ super().__init__(message)
22
+ self.status_code = status_code
23
+
24
+
25
+ class DPX:
26
+ """
27
+ Synchronous DPX client.
28
+
29
+ Usage:
30
+ from dpx_sdk import DPX
31
+ dpx = DPX()
32
+ quote = dpx.quote(amount_usd=500_000, has_fx=True, esg_score=75)
33
+ result = dpx.settle(
34
+ amount=500_000,
35
+ source_currency="USD",
36
+ destination_currency="EUR",
37
+ recipient_address="0x...",
38
+ sandbox=True,
39
+ )
40
+ """
41
+
42
+ def __init__(self, timeout: float = DEFAULT_TIMEOUT):
43
+ self._client = httpx.Client(
44
+ timeout=timeout,
45
+ headers={"User-Agent": "dpx-sdk-python/0.1.0"},
46
+ )
47
+
48
+ def _get(self, url: str, params: Optional[dict] = None) -> dict:
49
+ r = self._client.get(url, params=params)
50
+ if not r.is_success:
51
+ raise DPXError(f"HTTP {r.status_code}: {r.text[:200]}", r.status_code)
52
+ return r.json()
53
+
54
+ def _post(self, url: str, body: dict) -> dict:
55
+ r = self._client.post(url, json=body)
56
+ if not r.is_success:
57
+ raise DPXError(f"HTTP {r.status_code}: {r.text[:200]}", r.status_code)
58
+ return r.json()
59
+
60
+ def quote(
61
+ self,
62
+ amount_usd: float,
63
+ has_fx: bool = True,
64
+ esg_score: float = 75,
65
+ monthly_volume_usd: Optional[float] = None,
66
+ ) -> QuoteResult:
67
+ params: dict = {"amountUsd": amount_usd, "hasFx": str(has_fx).lower(), "esgScore": int(esg_score)}
68
+ if monthly_volume_usd is not None:
69
+ params["monthlyVolumeUsd"] = monthly_volume_usd
70
+ d = self._get(f"{AGENT_URL}/quote", params)
71
+ fees = d.get("fees", {})
72
+ total = fees.get("total", {})
73
+ return QuoteResult(
74
+ quote_id=d.get("quoteId", ""),
75
+ amount_usd=d.get("amountUsd", amount_usd),
76
+ net_amount_usd=d.get("netAmountUsd", 0.0),
77
+ total_fee_pct=total.get("pct", 0.0),
78
+ total_fee_usd=total.get("usd", 0.0),
79
+ oracle_status=d.get("oracleStatus", ""),
80
+ oracle_score=d.get("oracleScore", 0.0),
81
+ tier=d.get("tier", ""),
82
+ expires_at=d.get("expiresAt", ""),
83
+ reasoning=d.get("reasoning", ""),
84
+ raw=d,
85
+ )
86
+
87
+ def oracle_status(self) -> OracleStatus:
88
+ d = self._get(f"{STABILITY_URL}/reliability")
89
+ return OracleStatus(
90
+ status=d.get("status", ""),
91
+ score=float(d.get("stabilityScore", d.get("score", 0))),
92
+ recommendation=d.get("recommendation", ""),
93
+ peg_deviation=float(d.get("pegDeviation", 0)),
94
+ outlook=d.get("outlook", ""),
95
+ reasoning=d.get("reasoning", d.get("briefing", "")),
96
+ timestamp=d.get("timestamp", ""),
97
+ raw=d,
98
+ )
99
+
100
+ def esg_score(self, address: Optional[str] = None) -> EsgScore:
101
+ path = f"/esg-score/{address}" if address else "/esg-score"
102
+ d = self._get(f"{ESG_URL}{path}")
103
+ return EsgScore(
104
+ address=d.get("address", address or "default"),
105
+ esg_score=float(d.get("esgScore", d.get("score", 0))),
106
+ environmental=float(d.get("environmental", 0)),
107
+ social=float(d.get("social", 0)),
108
+ governance=float(d.get("governance", 0)),
109
+ fee_pct=float(d.get("feePct", 0)),
110
+ tier=d.get("tier", ""),
111
+ updated_at=d.get("updatedAt", ""),
112
+ raw=d,
113
+ )
114
+
115
+ def settle(
116
+ self,
117
+ amount: float,
118
+ source_currency: str,
119
+ destination_currency: str,
120
+ recipient_address: str,
121
+ purpose: str = "vendor-payment",
122
+ reference_id: Optional[str] = None,
123
+ quote_id: Optional[str] = None,
124
+ sandbox: bool = True,
125
+ ) -> SettlementResult:
126
+ body: dict = {
127
+ "amount": amount,
128
+ "sourceCurrency": source_currency,
129
+ "destinationCurrency": destination_currency,
130
+ "recipientAddress": recipient_address,
131
+ "purpose": purpose,
132
+ "sandbox": sandbox,
133
+ }
134
+ if reference_id:
135
+ body["referenceId"] = reference_id
136
+ if quote_id:
137
+ body["quoteId"] = quote_id
138
+ d = self._post(f"{AGENT_URL}/settle", body)
139
+ result = d.get("result", d)
140
+ return SettlementResult(
141
+ settlement_id=result.get("settlementId", ""),
142
+ status=result.get("status", ""),
143
+ tx_hash=result.get("txHash"),
144
+ net_amount=float(result.get("netAmount", 0)),
145
+ fees_total=float(result.get("feesTotal", 0)),
146
+ oracle_status=result.get("oracleStatus", ""),
147
+ reasoning=result.get("reasoning", ""),
148
+ timestamp=result.get("timestamp", ""),
149
+ raw=d,
150
+ )
151
+
152
+ def screen(self, address: str) -> dict:
153
+ return self._get(f"{COMPLIANCE_URL}/screen", {"address": address})
154
+
155
+ def close(self):
156
+ self._client.close()
157
+
158
+ def __enter__(self):
159
+ return self
160
+
161
+ def __exit__(self, *_):
162
+ self.close()
@@ -0,0 +1,12 @@
1
+ from .langchain import DPXToolkit, DPXQuoteTool, DPXSettleTool, DPXOracleTool, DPXEsgTool, DPXComplianceTool
2
+ from .llamaindex import DPXToolSpec
3
+
4
+ __all__ = [
5
+ "DPXToolkit",
6
+ "DPXQuoteTool",
7
+ "DPXSettleTool",
8
+ "DPXOracleTool",
9
+ "DPXEsgTool",
10
+ "DPXComplianceTool",
11
+ "DPXToolSpec",
12
+ ]
@@ -0,0 +1,239 @@
1
+ """
2
+ DPX LangChain Toolkit
3
+
4
+ Usage:
5
+ from dpx_sdk.tools import DPXToolkit
6
+ from langchain.agents import initialize_agent, AgentType
7
+ from langchain_openai import ChatOpenAI # or any LLM
8
+
9
+ tools = DPXToolkit().get_tools()
10
+ agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
11
+ agent.run("Get a quote for sending $500K USD to EUR and check oracle stability")
12
+
13
+ Published to LangChain Hub: untitledfinancial/dpx-toolkit
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from typing import Optional, Type, List
20
+
21
+ try:
22
+ from langchain.tools import BaseTool
23
+ from langchain.tools import BaseToolkit
24
+ from langchain_core.tools import BaseTool as CoreBaseTool
25
+ from pydantic import BaseModel, Field
26
+ _LANGCHAIN_AVAILABLE = True
27
+ except ImportError:
28
+ _LANGCHAIN_AVAILABLE = False
29
+ BaseTool = object # type: ignore
30
+ BaseToolkit = object # type: ignore
31
+ BaseModel = object # type: ignore
32
+ Field = lambda *a, **kw: None # type: ignore
33
+
34
+ from ..client import DPX
35
+
36
+
37
+ def _require_langchain():
38
+ if not _LANGCHAIN_AVAILABLE:
39
+ raise ImportError("Install langchain: pip install langchain langchain-core")
40
+
41
+
42
+ # ── Input schemas ──────────────────────────────────────────────────────────────
43
+
44
+ if _LANGCHAIN_AVAILABLE:
45
+ class QuoteInput(BaseModel):
46
+ amount_usd: float = Field(description="Settlement amount in USD")
47
+ has_fx: bool = Field(default=True, description="True if cross-currency (adds FX fee)")
48
+ esg_score: float = Field(default=75, description="Counterparty ESG score 0–100")
49
+
50
+ class SettleInput(BaseModel):
51
+ amount: float = Field(description="Settlement amount")
52
+ source_currency: str = Field(description="Source currency: USD, EUR, GBP, USDC, EURC")
53
+ destination_currency: str = Field(description="Destination currency: USD, EUR, GBP, USDC, EURC")
54
+ recipient_address: str = Field(description="On-chain recipient wallet address (0x...)")
55
+ purpose: str = Field(default="vendor-payment", description="Payment purpose")
56
+ sandbox: bool = Field(default=True, description="Sandbox mode — set False for live execution")
57
+
58
+ class EsgInput(BaseModel):
59
+ address: Optional[str] = Field(default=None, description="Wallet address (0x...). Omit for protocol default.")
60
+
61
+ class ComplianceInput(BaseModel):
62
+ address: str = Field(description="Wallet address or entity name to screen")
63
+
64
+
65
+ # ── Tools ──────────────────────────────────────────────────────────────────────
66
+
67
+ class DPXQuoteTool(BaseTool):
68
+ """Get a binding settlement fee quote from DPX."""
69
+ name: str = "dpx_quote"
70
+ description: str = (
71
+ "Get a binding fee quote for a DPX cross-border settlement. "
72
+ "Returns all-in rate, fee breakdown, net amount, oracle status, and AI reasoning. "
73
+ "Quote is valid for 300 seconds. Always call before dpx_settle."
74
+ )
75
+ args_schema: Type[BaseModel] = QuoteInput if _LANGCHAIN_AVAILABLE else object # type: ignore
76
+
77
+ def _run(self, amount_usd: float, has_fx: bool = True, esg_score: float = 75) -> str:
78
+ _require_langchain()
79
+ with DPX() as dpx:
80
+ q = dpx.quote(amount_usd=amount_usd, has_fx=has_fx, esg_score=esg_score)
81
+ return json.dumps({
82
+ "quote_id": q.quote_id,
83
+ "amount_usd": q.amount_usd,
84
+ "net_amount_usd": q.net_amount_usd,
85
+ "total_fee_pct": q.total_fee_pct,
86
+ "total_fee_usd": q.total_fee_usd,
87
+ "oracle_status": q.oracle_status,
88
+ "tier": q.tier,
89
+ "expires_at": q.expires_at,
90
+ "reasoning": q.reasoning,
91
+ }, indent=2)
92
+
93
+ async def _arun(self, *args, **kwargs) -> str:
94
+ return self._run(*args, **kwargs)
95
+
96
+
97
+ class DPXSettleTool(BaseTool):
98
+ """Execute a cross-border settlement through DPX."""
99
+ name: str = "dpx_settle"
100
+ description: str = (
101
+ "Execute a DPX cross-border or domestic settlement. "
102
+ "Checks oracle conditions, runs ESG scoring and compliance checks, "
103
+ "then executes on-chain (or returns sandbox result if sandbox=True). "
104
+ "Returns settlement ID, tx hash, net amount, fees, and AI reasoning. "
105
+ "Default sandbox=True — set False only for live execution with explicit user confirmation."
106
+ )
107
+ args_schema: Type[BaseModel] = SettleInput if _LANGCHAIN_AVAILABLE else object # type: ignore
108
+
109
+ def _run(
110
+ self,
111
+ amount: float,
112
+ source_currency: str,
113
+ destination_currency: str,
114
+ recipient_address: str,
115
+ purpose: str = "vendor-payment",
116
+ sandbox: bool = True,
117
+ ) -> str:
118
+ _require_langchain()
119
+ with DPX() as dpx:
120
+ r = dpx.settle(
121
+ amount=amount,
122
+ source_currency=source_currency,
123
+ destination_currency=destination_currency,
124
+ recipient_address=recipient_address,
125
+ purpose=purpose,
126
+ sandbox=sandbox,
127
+ )
128
+ return json.dumps({
129
+ "settlement_id": r.settlement_id,
130
+ "status": r.status,
131
+ "tx_hash": r.tx_hash,
132
+ "net_amount": r.net_amount,
133
+ "fees_total": r.fees_total,
134
+ "oracle_status": r.oracle_status,
135
+ "reasoning": r.reasoning,
136
+ "timestamp": r.timestamp,
137
+ }, indent=2)
138
+
139
+ async def _arun(self, *args, **kwargs) -> str:
140
+ return self._run(*args, **kwargs)
141
+
142
+
143
+ class DPXOracleTool(BaseTool):
144
+ """Check live macro stability before a settlement."""
145
+ name: str = "dpx_oracle_status"
146
+ description: str = (
147
+ "Get live macro stability assessment from the DPX Stability Oracle. "
148
+ "Returns stability score (0–100), status (STABLE/CAUTION/UNSTABLE), "
149
+ "recommendation (PROCEED/CAUTION/HOLD), peg deviation in bps, and AI reasoning. "
150
+ "Call before large settlements — UNSTABLE status means hold."
151
+ )
152
+
153
+ def _run(self) -> str:
154
+ _require_langchain()
155
+ with DPX() as dpx:
156
+ o = dpx.oracle_status()
157
+ return json.dumps({
158
+ "status": o.status,
159
+ "score": o.score,
160
+ "recommendation": o.recommendation,
161
+ "peg_deviation_bps": o.peg_deviation,
162
+ "outlook": o.outlook,
163
+ "reasoning": o.reasoning,
164
+ }, indent=2)
165
+
166
+ async def _arun(self) -> str:
167
+ return self._run()
168
+
169
+
170
+ class DPXEsgTool(BaseTool):
171
+ """Score a counterparty wallet for ESG risk."""
172
+ name: str = "dpx_esg_score"
173
+ description: str = (
174
+ "Get the ESG counterparty risk score for a wallet address. "
175
+ "Required for EU SFDR Principal Adverse Impact reporting and CSRD disclosure. "
176
+ "Returns E/S/G sub-scores, composite score (0–100), and the fee adjustment "
177
+ "this score produces at settlement. Updated hourly."
178
+ )
179
+ args_schema: Type[BaseModel] = EsgInput if _LANGCHAIN_AVAILABLE else object # type: ignore
180
+
181
+ def _run(self, address: Optional[str] = None) -> str:
182
+ _require_langchain()
183
+ with DPX() as dpx:
184
+ e = dpx.esg_score(address=address)
185
+ return json.dumps({
186
+ "address": e.address,
187
+ "esg_score": e.esg_score,
188
+ "environmental": e.environmental,
189
+ "social": e.social,
190
+ "governance": e.governance,
191
+ "fee_pct": e.fee_pct,
192
+ "tier": e.tier,
193
+ }, indent=2)
194
+
195
+ async def _arun(self, *args, **kwargs) -> str:
196
+ return self._run(*args, **kwargs)
197
+
198
+
199
+ class DPXComplianceTool(BaseTool):
200
+ """Screen a counterparty through DPX AML/FATF compliance oracle."""
201
+ name: str = "dpx_compliance_screen"
202
+ description: str = (
203
+ "Screen a wallet address or entity through the DPX Compliance Oracle. "
204
+ "Runs FATF R16 Travel Rule, AML behavioural analysis (z-score anomaly + "
205
+ "graph risk), sanctions screening (OFAC SDN), MiCA, and GENIUS Act checks. "
206
+ "Returns APPROVED / FLAGGED / BLOCKED with full reasoning. "
207
+ "Call before every settlement for FATF Travel Rule compliance."
208
+ )
209
+ args_schema: Type[BaseModel] = ComplianceInput if _LANGCHAIN_AVAILABLE else object # type: ignore
210
+
211
+ def _run(self, address: str) -> str:
212
+ _require_langchain()
213
+ with DPX() as dpx:
214
+ return json.dumps(dpx.screen(address), indent=2)
215
+
216
+ async def _arun(self, *args, **kwargs) -> str:
217
+ return self._run(*args, **kwargs)
218
+
219
+
220
+ # ── Toolkit ────────────────────────────────────────────────────────────────────
221
+
222
+ class DPXToolkit(BaseToolkit):
223
+ """
224
+ DPX LangChain Toolkit — full settlement lifecycle as LangChain tools.
225
+
226
+ Provides: dpx_quote, dpx_settle, dpx_oracle_status, dpx_esg_score, dpx_compliance_screen
227
+
228
+ LangChain Hub: untitledfinancial/dpx-toolkit
229
+ """
230
+
231
+ def get_tools(self) -> List[BaseTool]:
232
+ _require_langchain()
233
+ return [
234
+ DPXOracleTool(),
235
+ DPXEsgTool(),
236
+ DPXComplianceTool(),
237
+ DPXQuoteTool(),
238
+ DPXSettleTool(),
239
+ ]
@@ -0,0 +1,201 @@
1
+ """
2
+ DPX LlamaIndex ToolSpec
3
+
4
+ Usage:
5
+ from dpx_sdk.tools import DPXToolSpec
6
+ from llama_index.agent.openai import OpenAIAgent # or any agent
7
+
8
+ dpx_spec = DPXToolSpec()
9
+ tools = dpx_spec.to_tool_list()
10
+ agent = OpenAIAgent.from_tools(tools, verbose=True)
11
+ agent.chat("Get a quote for $1M USD to EUR and check oracle stability")
12
+
13
+ LlamaIndex Hub: untitledfinancial/dpx-tool-spec
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from typing import Optional
20
+
21
+ try:
22
+ from llama_index.core.tools import FunctionTool
23
+ from llama_index.core.tools.tool_spec.base import BaseToolSpec
24
+ _LLAMA_AVAILABLE = True
25
+ except ImportError:
26
+ try:
27
+ from llama_index.tools import FunctionTool
28
+ from llama_index.tools.tool_spec.base import BaseToolSpec
29
+ _LLAMA_AVAILABLE = True
30
+ except ImportError:
31
+ _LLAMA_AVAILABLE = False
32
+ BaseToolSpec = object # type: ignore
33
+
34
+ from ..client import DPX
35
+
36
+
37
+ def _require_llama():
38
+ if not _LLAMA_AVAILABLE:
39
+ raise ImportError("Install llama-index: pip install llama-index-core")
40
+
41
+
42
+ class DPXToolSpec(BaseToolSpec):
43
+ """
44
+ DPX ToolSpec for LlamaIndex agents.
45
+
46
+ Exposes the full DPX settlement lifecycle:
47
+ - get_settlement_quote — Binding fee quote
48
+ - execute_settlement — Cross-border settlement execution
49
+ - get_oracle_status — Macro stability assessment
50
+ - get_esg_score — ESG counterparty scoring
51
+ - screen_compliance — FATF/AML/sanctions screening
52
+ """
53
+
54
+ spec_functions = [
55
+ "get_settlement_quote",
56
+ "execute_settlement",
57
+ "get_oracle_status",
58
+ "get_esg_score",
59
+ "screen_compliance",
60
+ ]
61
+
62
+ def get_settlement_quote(
63
+ self,
64
+ amount_usd: float,
65
+ has_fx: bool = True,
66
+ esg_score: float = 75,
67
+ ) -> str:
68
+ """
69
+ Get a binding fee quote for a DPX settlement.
70
+
71
+ Args:
72
+ amount_usd: Settlement amount in USD.
73
+ has_fx: True if cross-currency (adds FX fee). Default True.
74
+ esg_score: Counterparty ESG score 0–100. Default 75.
75
+
76
+ Returns:
77
+ JSON string with quote_id, net_amount_usd, fee breakdown,
78
+ oracle_status, tier, and AI reasoning. Quote valid 300 seconds.
79
+ """
80
+ _require_llama()
81
+ with DPX() as dpx:
82
+ q = dpx.quote(amount_usd=amount_usd, has_fx=has_fx, esg_score=esg_score)
83
+ return json.dumps({
84
+ "quote_id": q.quote_id,
85
+ "amount_usd": q.amount_usd,
86
+ "net_amount_usd": q.net_amount_usd,
87
+ "total_fee_pct": q.total_fee_pct,
88
+ "total_fee_usd": q.total_fee_usd,
89
+ "oracle_status": q.oracle_status,
90
+ "tier": q.tier,
91
+ "expires_at": q.expires_at,
92
+ "reasoning": q.reasoning,
93
+ }, indent=2)
94
+
95
+ def execute_settlement(
96
+ self,
97
+ amount: float,
98
+ source_currency: str,
99
+ destination_currency: str,
100
+ recipient_address: str,
101
+ purpose: str = "vendor-payment",
102
+ sandbox: bool = True,
103
+ ) -> str:
104
+ """
105
+ Execute a DPX cross-border or domestic settlement.
106
+
107
+ Args:
108
+ amount: Settlement amount.
109
+ source_currency: USD, EUR, GBP, USDC, or EURC.
110
+ destination_currency: USD, EUR, GBP, USDC, or EURC.
111
+ recipient_address: On-chain recipient wallet address (0x...).
112
+ purpose: vendor-payment, intercompany, payroll, or treasury.
113
+ sandbox: If True (default), returns calculations without on-chain execution.
114
+ Set False only for live execution with explicit user confirmation.
115
+
116
+ Returns:
117
+ JSON string with settlement_id, status, tx_hash, net_amount, fees, and reasoning.
118
+ """
119
+ _require_llama()
120
+ with DPX() as dpx:
121
+ r = dpx.settle(
122
+ amount=amount,
123
+ source_currency=source_currency,
124
+ destination_currency=destination_currency,
125
+ recipient_address=recipient_address,
126
+ purpose=purpose,
127
+ sandbox=sandbox,
128
+ )
129
+ return json.dumps({
130
+ "settlement_id": r.settlement_id,
131
+ "status": r.status,
132
+ "tx_hash": r.tx_hash,
133
+ "net_amount": r.net_amount,
134
+ "fees_total": r.fees_total,
135
+ "oracle_status": r.oracle_status,
136
+ "reasoning": r.reasoning,
137
+ "timestamp": r.timestamp,
138
+ }, indent=2)
139
+
140
+ def get_oracle_status(self) -> str:
141
+ """
142
+ Get live macro stability assessment from the DPX Stability Oracle.
143
+
144
+ Returns stability score (0–100), status (STABLE/CAUTION/UNSTABLE),
145
+ recommendation (PROCEED/CAUTION/HOLD), peg deviation in bps, outlook,
146
+ and AI reasoning. UNSTABLE means hold large settlements.
147
+ """
148
+ _require_llama()
149
+ with DPX() as dpx:
150
+ o = dpx.oracle_status()
151
+ return json.dumps({
152
+ "status": o.status,
153
+ "score": o.score,
154
+ "recommendation": o.recommendation,
155
+ "peg_deviation_bps": o.peg_deviation,
156
+ "outlook": o.outlook,
157
+ "reasoning": o.reasoning,
158
+ }, indent=2)
159
+
160
+ def get_esg_score(self, address: Optional[str] = None) -> str:
161
+ """
162
+ Get the ESG counterparty risk score for a wallet address.
163
+
164
+ Args:
165
+ address: Wallet address (0x...). Omit for protocol default score.
166
+
167
+ Returns:
168
+ JSON string with composite ESG score (0–100), E/S/G sub-scores,
169
+ settlement fee adjustment, and tier. Updated hourly from 6 institutional
170
+ sources: World Bank, IMF, OECD, UN, SEC, ClimateMonitor.
171
+ Required for EU SFDR PAI reporting and CSRD disclosure.
172
+ """
173
+ _require_llama()
174
+ with DPX() as dpx:
175
+ e = dpx.esg_score(address=address)
176
+ return json.dumps({
177
+ "address": e.address,
178
+ "esg_score": e.esg_score,
179
+ "environmental": e.environmental,
180
+ "social": e.social,
181
+ "governance": e.governance,
182
+ "fee_pct": e.fee_pct,
183
+ "tier": e.tier,
184
+ }, indent=2)
185
+
186
+ def screen_compliance(self, address: str) -> str:
187
+ """
188
+ Screen a counterparty through the DPX Compliance Oracle.
189
+
190
+ Args:
191
+ address: Wallet address or entity name to screen.
192
+
193
+ Returns:
194
+ JSON string with compliance decision (APPROVED/FLAGGED/BLOCKED),
195
+ FATF R16 Travel Rule status, AML signals, sanctions check,
196
+ MiCA and GENIUS Act attestations, and full reasoning.
197
+ Call before every settlement for FATF Travel Rule compliance.
198
+ """
199
+ _require_llama()
200
+ with DPX() as dpx:
201
+ return json.dumps(dpx.screen(address), indent=2)
dpx_sdk/types.py ADDED
@@ -0,0 +1,61 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class FeeComponent:
7
+ pct: float
8
+ usd: float
9
+
10
+
11
+ @dataclass
12
+ class QuoteResult:
13
+ quote_id: str
14
+ amount_usd: float
15
+ net_amount_usd: float
16
+ total_fee_pct: float
17
+ total_fee_usd: float
18
+ oracle_status: str
19
+ oracle_score: float
20
+ tier: str
21
+ expires_at: str
22
+ reasoning: str
23
+ raw: dict = field(default_factory=dict)
24
+
25
+
26
+ @dataclass
27
+ class SettlementResult:
28
+ settlement_id: str
29
+ status: str # executed | sandbox | held | failed
30
+ tx_hash: Optional[str]
31
+ net_amount: float
32
+ fees_total: float
33
+ oracle_status: str
34
+ reasoning: str
35
+ timestamp: str
36
+ raw: dict = field(default_factory=dict)
37
+
38
+
39
+ @dataclass
40
+ class OracleStatus:
41
+ status: str # STABLE | CAUTION | UNSTABLE
42
+ score: float
43
+ recommendation: str # PROCEED | CAUTION | HOLD
44
+ peg_deviation: float
45
+ outlook: str
46
+ reasoning: str
47
+ timestamp: str
48
+ raw: dict = field(default_factory=dict)
49
+
50
+
51
+ @dataclass
52
+ class EsgScore:
53
+ address: str
54
+ esg_score: float
55
+ environmental: float
56
+ social: float
57
+ governance: float
58
+ fee_pct: float
59
+ tier: str
60
+ updated_at: str
61
+ raw: dict = field(default_factory=dict)
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.4
2
+ Name: dpx-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the DPX Protocol — compliance-grade stablecoin settlement rail with LangChain and LlamaIndex toolkits
5
+ Project-URL: Homepage, https://untitledfinancial.com
6
+ Project-URL: Documentation, https://docs.untitledfinancial.com
7
+ Project-URL: Repository, https://github.com/untitledfinancial/dpx-mcp
8
+ License: BUSL-1.1
9
+ Requires-Python: >=3.9
10
+ Requires-Dist: httpx>=0.27.0
11
+ Provides-Extra: all
12
+ Requires-Dist: langchain-core>=0.2.0; extra == 'all'
13
+ Requires-Dist: langchain>=0.2.0; extra == 'all'
14
+ Requires-Dist: llama-index-core>=0.10.0; extra == 'all'
15
+ Requires-Dist: pydantic>=2.0; extra == 'all'
16
+ Provides-Extra: langchain
17
+ Requires-Dist: langchain-core>=0.2.0; extra == 'langchain'
18
+ Requires-Dist: langchain>=0.2.0; extra == 'langchain'
19
+ Requires-Dist: pydantic>=2.0; extra == 'langchain'
20
+ Provides-Extra: llamaindex
21
+ Requires-Dist: llama-index-core>=0.10.0; extra == 'llamaindex'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # dpx-sdk
25
+
26
+ Python SDK for [DPX Protocol](https://untitledfinancial.com) — compliance-grade stablecoin settlement rail with native LangChain and LlamaIndex toolkits.
27
+
28
+ ```bash
29
+ pip install dpx-sdk # core client
30
+ pip install "dpx-sdk[langchain]" # + LangChain toolkit
31
+ pip install "dpx-sdk[llamaindex]" # + LlamaIndex ToolSpec
32
+ pip install "dpx-sdk[all]" # everything
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ ```python
38
+ from dpx_sdk import DPX
39
+
40
+ with DPX() as dpx:
41
+ # Check oracle before settling
42
+ oracle = dpx.oracle_status()
43
+ print(oracle.status, oracle.recommendation) # STABLE PROCEED
44
+
45
+ # Get a binding quote
46
+ quote = dpx.quote(amount_usd=500_000, has_fx=True, esg_score=75)
47
+ print(f"Net: ${quote.net_amount_usd:,.2f} Fee: {quote.total_fee_pct:.3f}%")
48
+
49
+ # Execute in sandbox (safe default)
50
+ result = dpx.settle(
51
+ amount=500_000,
52
+ source_currency="USD",
53
+ destination_currency="EUR",
54
+ recipient_address="0xYourRecipientAddress",
55
+ sandbox=True, # set False for live execution
56
+ )
57
+ print(result.status, result.settlement_id)
58
+ ```
59
+
60
+ ## LangChain
61
+
62
+ ```python
63
+ from dpx_sdk.tools import DPXToolkit
64
+ from langchain.agents import initialize_agent, AgentType
65
+ from langchain_openai import ChatOpenAI
66
+
67
+ tools = DPXToolkit().get_tools()
68
+ agent = initialize_agent(tools, ChatOpenAI(), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
69
+ agent.run("Check oracle stability, get a quote for $1M USD→EUR, and screen the counterparty 0x123...")
70
+ ```
71
+
72
+ Available tools: `dpx_oracle_status` · `dpx_esg_score` · `dpx_compliance_screen` · `dpx_quote` · `dpx_settle`
73
+
74
+ **LangChain Hub:** `untitledfinancial/dpx-toolkit`
75
+
76
+ ## LlamaIndex
77
+
78
+ ```python
79
+ from dpx_sdk.tools import DPXToolSpec
80
+ from llama_index.agent.openai import OpenAIAgent
81
+
82
+ tools = DPXToolSpec().to_tool_list()
83
+ agent = OpenAIAgent.from_tools(tools, verbose=True)
84
+ agent.chat("Get a quote for $500K USD to EUR and execute in sandbox mode")
85
+ ```
86
+
87
+ Available functions: `get_settlement_quote` · `execute_settlement` · `get_oracle_status` · `get_esg_score` · `screen_compliance`
88
+
89
+ **LlamaIndex Hub:** `untitledfinancial/dpx-tool-spec`
90
+
91
+ ## MCP (Claude / Cursor)
92
+
93
+ ```bash
94
+ npx @untitledfinancial/dpx-mcp
95
+ ```
96
+
97
+ 32 MCP tools for Claude Desktop and Cursor. [Setup →](https://docs.untitledfinancial.com/integrations/mcp)
98
+
99
+ ## Links
100
+
101
+ - [Documentation](https://docs.untitledfinancial.com)
102
+ - [MCP on Smithery](https://smithery.ai/server/@untitledfinancial/dpx-mcp)
103
+ - [npm package](https://www.npmjs.com/package/@untitledfinancial/dpx-mcp)
104
+ - [Contracts on Base mainnet](https://base.blockscout.com/address/0xe333551E18ef0471A71d7e8e761212766aa5AD4f)
@@ -0,0 +1,9 @@
1
+ dpx_sdk/__init__.py,sha256=x7jKK0dYRs24Fzr_xIDqHGejafqsYXt9L0BfjqBNVtc,223
2
+ dpx_sdk/client.py,sha256=Lq7qQW6OkooAlS5DmldCLEzAbeo_Ribgj9ipGJXbTCM,5587
3
+ dpx_sdk/types.py,sha256=5JNanNtglsUnSKiy0-wQQBeA56nrfHK-7Kv1F1zqlNA,1232
4
+ dpx_sdk/tools/__init__.py,sha256=oIUGq4HTGjm0ortRNu18AaFs7PZwX_Z90lOQwc39ZnM,302
5
+ dpx_sdk/tools/langchain.py,sha256=TwYdDZ6QroJWbBvO8_LwgKKCYI1-WFuKMLBZ0FJZzoA,9441
6
+ dpx_sdk/tools/llamaindex.py,sha256=Tzu4Dj6g54eM-45DjGBdilcRHQswBxLtVaC9DI5lpnA,6839
7
+ dpx_sdk-0.1.0.dist-info/METADATA,sha256=Eh4MtKn6JlDngMIInPiWyD77vhjS5-wCh5ZJTemYrDM,3632
8
+ dpx_sdk-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ dpx_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any