SDK reference¶
This page is generated from the primedelta package docstrings at build time, so it can't drift from the installed SDK. For task-oriented walkthroughs, start with the SDK guides.
Client¶
PrimeDelta ¶
PrimeDelta(
private_key: Optional[str] = None,
web3_provider_url: Optional[str] = None,
network: str = "dev",
signer: Optional[Signer] = None,
auto_relogin: bool = True,
on_login: Optional[Callable[[PrimeDelta], None]] = None,
)
craft ¶
Run a trading action WITHOUT broadcasting and return the unsigned
transaction(s) it would have sent, for an external wallet to sign.
Non-custodial flow (per Web3/MCP security guidance): this SDK builds the
calldata but never signs a fund-moving transaction here — the returned
dicts go to the user's own wallet (MetaMask / hardware) to review and
sign. action is any zero-arg callable that would normally send a
transaction::
txs = pd.craft(
lambda: pd.swap_exact_input(
"AMMT1", SwapSide.STABLECOIN_TO_STOCK, Decimal("10"), Decimal("0")
)
)
Each returned dict is {from, to, value, data, chainId}. Gas and
nonce are intentionally omitted for the signing wallet to fill. A
multi-step action (e.g. approve -> swap) returns one dict per
transaction, in send order.
The action still reads the chain and backend to build calldata (pool addresses, allowances, signed prices, deadlines). For oracle-priced instruments the signed price and deadline baked into the calldata expire — sign and broadcast promptly.
Scope: craft captures ON-CHAIN transactions — swap, LP, native
transfer, token approve, and custodial deposit/claim (all go through the
signed send path). Backend REST actions (limit/market orders, withdrawal
requests, order cancels) produce no on-chain tx here and raise
CannotCraft under craft rather than silently executing for real.
Not thread-safe: crafting toggles an instance-level flag, so do not share
one client across threads while a craft is in flight — a concurrent
fund-moving call on the same client would be captured instead of
broadcast. Use a separate client per thread, or don't overlap them.
export_session ¶
Serialize the authenticated session cookies so a caller can persist the
login (e.g. across process restarts) instead of re-running SIWE. Pair with
import_session. Returns an empty list when not logged in.
import_session ¶
Restore a session previously captured with export_session. The session
is not re-validated; a stale one raises NotLoggedIn on the next authed
call, which auto-relogin (when enabled) then retries. Arm auto-relogin so a
stale restore recovers cleanly.
register_ai_account ¶
Register the logged-in wallet as an AI subaccount of main_wallet_address.
Call this from the SUBACCOUNT's session (a fresh wallet); the main account must then confirm it before the subaccount becomes active.
get_pending_ai_agents ¶
List AI subaccounts awaiting this (main) account's confirmation.
confirm_ai_agent ¶
Confirm a pending AI subaccount registered under this main account.
reject_ai_agent ¶
Reject a pending AI subaccount registered under this main account.
verification_url ¶
Return the URL of the web page where the user completes KYC.
Verification (uploading ID, taking a selfie, etc.) is performed in the
web app, not via the SDK. After verification completes there, the
backend marks the account as VERIFIED and the SDK can call
claim_digital_identity() to mint the on-chain DID NFT.
open_verification_page ¶
Open the verification web page in the user's default browser.
Returns the URL that was opened, so callers can fall back to printing
it if webbrowser.open returned False (headless environments).
get_onchain_stablecoin_balance ¶
Read stablecoin balance from chain (bypasses backend indexer lag).
get_onchain_stock_balance ¶
Read a stock token balance from chain (bypasses backend indexer lag).
Useful immediately after a swap when the backend hasn't synced yet.
get_onchain_balances ¶
All on-chain token balances for this wallet in a SINGLE Multicall3 call: dUSD (6 decimals) plus every token the DEX router lists (18 decimals). Returns the held balances (> 0) plus dUSD. Falls back to one read per token when the network has no Multicall3 configured.
tx_status ¶
Look up the mined receipt for a transaction hash.
Returns None if the tx is not yet mined / unknown to the node.
succeeded is False for a reverted (status 0) transaction. The send
methods already block on the receipt and raise on failure, so this is
for polling a hash you hold (e.g. one broadcast externally after
craft, or a hash returned by a prior send).
wrap_del ¶
Wrap native DEL → WDEL by sending msg.value to WDEL.deposit().
The resulting WDEL is an AMM ERC20 — feed it into the regular swap methods using the symbol "WDEL".
prices_stream ¶
Stream real-time price updates.
When logged in, uses the broker's authenticated price stream. When not logged in, uses Pyth Hermes API for public price feeds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
Optional[list[str]]
|
List of stock symbols to stream prices for. Only used when not logged in (Pyth stream). If None, streams all available stocks. |
None
|
Raises:
| Type | Description |
|---|---|
AccountNotVerified
|
If logged in but account is not verified. Use pyth_prices_stream() or verify at https://app.primedelta.io |
pyth_prices_stream ¶
Stream prices from Pyth Hermes API.
This method does not require authentication and can be used when not logged in.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
Optional[list[str]]
|
List of stock symbols to stream prices for. If None, streams all available stocks. |
None
|
swap_token_to_token_exact_input ¶
swap_token_to_token_exact_input(
input_symbol: str,
output_symbol: str,
amount_in: Decimal,
min_amount_out: Decimal,
deadline_seconds: int = 600,
update_fee: int = 0,
) -> str
Trade one non-dUSD token for another (routed through dUSD on chain).
Use for AMM↔AMM, AMM↔stock, and stock↔stock swaps. For dUSD↔token
swaps, use swap_exact_input with SwapSide.
swap_token_to_token_exact_output ¶
swap_token_to_token_exact_output(
input_symbol: str,
output_symbol: str,
amount_out: Decimal,
max_amount_in: Decimal,
deadline_seconds: int = 600,
update_fee: int = 0,
) -> str
Exact-output cross-dex swap. See swap_token_to_token_exact_input.
preview_fees ¶
Preview an AMM (V3) position's currently collectable amounts as
(stock, stablecoin) in human units, via a static collect simulation.
Read-only (no login) but only for positions owned by this wallet — the
NPM gates collect on ownership, so a third party's position_id reverts.
lp_positions ¶
Return all AMM (V3) position NFT token IDs owned by the wallet.
lp_position ¶
Read AMM (V3) position info for a given NFT token ID.
instrument_kind ¶
Classify a tradable symbol as "amm" (a 24/7 Uniswap-V3 AMM pool)
or "oracle" (a price-feed pool, tradable only in US market hours).
Agents should gate oracle-instrument swaps on is_market_open().
min_out_from_quote
staticmethod
¶
Compute a safe min_amount_out from a quote_swap result and a
slippage budget in basis points (default 100 = 1%). Never pass a raw
Decimal("0") to a swap in production — derive the bound from a quote.
halt ¶
Engage the kill switch: every subsequent on-chain send raises
TradingHalted until resume(). Reads are unaffected.
oracle_price ¶
Current signed oracle USD price for an oracle (price-feed) stock — the reference AAPL-class stocks lack an on-chain quote for. Decoded from the same signed update the swap would submit (feedId, price:int64, expo:int32, ... — FIOracle layout), so it is the price the pool values against. Returns None when none is available (e.g. the market is closed).
This is a REFERENCE price, not a fee-adjusted amount-out: the oracle pool applies a dynamic, reserve-dependent fee on top, so budget slippage to cover it when deriving a swap's min_amount_out. Needs a logged-in session.
simulate_swap ¶
simulate_swap(
symbol: str,
side: SwapSide,
amount_in: Decimal,
slippage_bps: int = 100,
) -> SwapSimulation
Paper-trade an exact-input swap without touching account state.
Runs entirely on static reads (the on-chain Quoter) — no allowance,
balance, or signature — so it returns a result before you have approved
or funded anything, and on thin pools where a live trade might revert.
Gives the expected output, a slippage-bounded min_amount_out ready to
pass straight to swap_exact_input, the current spot price, and the
pool fee tier. AMM pools only, like quote_swap.
Signers¶
A signer is the boundary of what the SDK can do on your behalf. See Signing modes for how to choose.
Signer ¶
Bases: Protocol
Wallet seam the SDK signs and broadcasts through.
fills_gas_and_nonce is False for signers where the SDK builds a fully
specified transaction (nonce, gas, gasPrice) and the signer only signs and
broadcasts it, and True for wallet signers that fill nonce/gas and broadcast
themselves (e.g. a browser extension).
KmsSigner ¶
Signer whose key stays inside AWS KMS — only 32-byte digests are sent out.
Requires the optional primedelta[kms] extra (boto3). Pass an existing KMS
client as kms_client, or let the signer build one for region_name.
The key must be an asymmetric secp256k1 signing key (KeySpec ECC_SECG_P256K1,
KeyUsage SIGN_VERIFY).
BrowserSigner ¶
Sign through a browser wallet (MetaMask, …) via a one-shot local bridge.
Each operation opens a single-use page on 127.0.0.1 that discovers the wallet
(EIP-6963), performs eth_requestAccounts / personal_sign /
eth_sendTransaction, and posts the result back over a one-time state token;
the loopback server then shuts down. Pass chain (a wallet_addEthereumChain
params dict) to switch/add the network before signing.
RemoteBrowserSigner ¶
RemoteBrowserSigner(
*,
base_url: str,
deliver: Callable[[str], None],
chain: Optional[dict[str, Any]] = None,
timeout: float = 180.0
)
Sign through the user's own browser wallet reached at a HOSTED HTTPS origin — for a hosted/remote MCP that can't open the user's local browser.
It reuses BrowserSigner's one-shot page and one-time state token, but the
hosting app serves the page from base_url and decides how to send the
user there via the deliver callback (e.g. an MCP url-mode elicitation).
The hosting app must:
- serve GET /sign?state=<token> -> :meth:render_page
- serve POST /result?state=<token> -> :meth:resolve
The URL carries only the opaque token; the tx/message stays server-side.
Non-custodial: no fund-moving key lives here — the user's wallet signs.
Liquidity & swap parameters¶
SwapSide ¶
Bases: str, Enum
PoolType ¶
Bases: str, Enum
SwapSimulation
dataclass
¶
SwapSimulation(
symbol: str,
side: SwapSide,
amount_in: Decimal,
expected_amount_out: Decimal,
min_amount_out: Decimal,
slippage_bps: int,
spot_price: Decimal,
fee_tier: int,
)
AMMAddLiquidity
dataclass
¶
AMMAddLiquidity(
symbol: str,
tick_lower: int,
tick_upper: int,
amount_stock_desired: Decimal,
amount_stablecoin_desired: Decimal,
amount_stock_min: Decimal,
amount_stablecoin_min: Decimal,
)
AMMRemoveLiquidity
dataclass
¶
AMMRemoveLiquidity(
position_id: int,
liquidity: int,
amount_stock_min: Decimal,
amount_stablecoin_min: Decimal,
)
PriceFeedAddLiquidity
dataclass
¶
PriceFeedAddLiquidity(
symbol: str,
liquidity_amount: Decimal,
max_stock_amount: Decimal,
max_stablecoin_amount: Decimal,
)
PriceFeedRemoveLiquidity
dataclass
¶
Exceptions¶
NotLoggedIn ¶
Bases: Exception
AccountNotVerified ¶
Bases: Exception
NotEnoughFunds ¶
Bases: Exception
MarketClosed ¶
MarketClosed(
function_name: str,
reason: str,
tx_hash: Optional[str] = None,
to: Optional[str] = None,
data: Optional[str] = None,
trace: Optional[Any] = None,
)
Bases: TransactionFailed
An oracle/price-feed swap reverted because the signed equity price was stale or absent — the US market is closed (or the price was withheld). A subclass of TransactionFailed, so existing handlers still catch it, but agents can catch it specifically to distinguish 'market closed' from a bug.
TradingHalted ¶
Bases: Exception
Raised when a transaction is attempted while the client's kill switch is
engaged (halt()); call resume() to re-enable.
TransactionFailed ¶
TransactionFailed(
function_name: str,
reason: str,
tx_hash: Optional[str] = None,
to: Optional[str] = None,
data: Optional[str] = None,
trace: Optional[Any] = None,
)
Bases: Exception
A transaction submitted by the SDK reverted or failed to mine.
Attributes:
| Name | Type | Description |
|---|---|---|
function_name |
Solidity function the SDK tried to call. |
|
reason |
Decoded revert reason if available (Error(string) or Panic(uint256)), otherwise the raw return data or original message. |
|
tx_hash |
Hex-encoded tx hash if the transaction was submitted. None when the failure happened during pre-submit gas estimation. |
|
to |
Target contract address (when known) — useful for replay via
|
|
data |
ABI-encoded calldata (when known) — pair with |
|
trace |
Best-effort |
CannotCraft ¶
Bases: Exception
Raised when a backend REST action (limit/market order, withdrawal
request, order cancel) is invoked inside craft. Those actions do not
produce an on-chain transaction the SDK can capture, so crafting cannot
intercept them — calling one would execute it for real.
DigitalIdentityAlreadyClaimed ¶
Bases: Exception
WdelNotConfigured ¶
Bases: Exception
Raised when a DEL/WDEL helper is called on a network whose config has no
wdel address. Add it to networks/<name>.json to enable.
BackendUnavailable ¶
Bases: Exception
The backend could not be reached, or errored transiently — a dropped
connection, a timeout that survived the automatic retries, or a 5xx. Kept
distinct from NotLoggedIn / AuthorizationError / APIError so a caller
(or the MCP layer) can back off and retry rather than crash on a raw
requests traceback.