Tutorial: watch a price and swap¶
A common agentic pattern: watch a price and act when it crosses a line. This builds a small, safe polling loop that buys once the spot price of an AMM token drops below a threshold, then stops. It's deliberately simple — the point is the shape, with the guardrails in the right places.
Testnet first
Run this on testnet with a dedicated wallet until it behaves exactly as you expect. It places a real swap when the condition is met.
The script¶
import time
from decimal import Decimal
from primedelta import PrimeDelta, SwapSide, AccountStatus
RPC = "https://chain.testnet.primedelta.io"
SYMBOL = "AMMT1"
BUY_BELOW = Decimal("9.50") # spot price threshold
SPEND = Decimal("10") # dUSD to spend when it triggers
MAX_TRADE_USD = Decimal("25") # your cap
SLIPPAGE_BPS = 100
POLL_SECONDS = 15
pd = PrimeDelta(private_key="0x…", web3_provider_url=RPC, network="testnet")
pd.login()
if pd.get_account_status() != AccountStatus.DID_MINTED:
raise SystemExit("wallet has no minted DID — verify it first")
if SPEND > MAX_TRADE_USD:
raise SystemExit(f"{SPEND} dUSD exceeds your cap of {MAX_TRADE_USD}")
print(f"watching {SYMBOL}; will buy {SPEND} dUSD when spot < {BUY_BELOW}")
while True:
try:
price = pd.spot_price(SYMBOL)
except Exception as exc: # transient RPC / pricing hiccup
print("price check failed, retrying:", exc)
time.sleep(POLL_SECONDS)
continue
print(f"spot {SYMBOL} = {price}")
if price < BUY_BELOW:
quote = pd.quote_swap(SYMBOL, SwapSide.STABLECOIN_TO_STOCK, SPEND)
min_out = pd.min_out_from_quote(quote, slippage_bps=SLIPPAGE_BPS)
tx = pd.swap_exact_input(
SYMBOL, SwapSide.STABLECOIN_TO_STOCK,
amount_in=SPEND, min_amount_out=min_out,
)
print("bought — tx:", tx)
break # one-shot: stop after the fill
time.sleep(POLL_SECONDS)
Why it's shaped this way¶
- The checks that don't change are done once, up front — login, the DID gate, and your cap. No point re-checking them every tick.
- The price read is wrapped in
try/exceptso a transient RPC blip retries instead of crashing the loop. Only pricing is retried; a real trade failure should stop you. - The trade still quotes fresh at the moment it fires and derives a positive
min_amount_out— the threshold decides whether to trade, the quote decides the floor. - It's one-shot (
breakafter the fill). A loop that keeps buying needs a real budget and a daily cap — see below.
Turning it into a budgeted loop¶
If you want it to keep running, don't rely on a counter — track spend and stop at a daily budget:
spent_today = Decimal("0")
DAILY_BUDGET = Decimal("100")
# inside the loop, before swapping:
if spent_today + SPEND > DAILY_BUDGET:
print("daily budget reached — stopping")
break
# after a successful swap:
spent_today += SPEND
When you run this through the MCP server instead of a raw script, the server enforces PRIMEDELTA_MCP_MAX_DAILY_USD for you — off the model — so the budget can't be bypassed. See What the guardrails do.
Don't do this¶
- No zero minimum-out, ever — a watcher that fires on a price move is exactly when a bad floor gets sandwiched.
- Don't poll a tokenized stock's spot price — oracle stocks have no AMM spot; use the oracle price and check market hours.
- Don't hammer the RPC — 10–30s polling is plenty; tighter loops just add load and rate-limit risk.
Back to the guarded swap · SDK reference