Module documentation
Everything a Rug Engine module can do. Modules run on Luau in a sandbox and reach the world through one global table called rug.
Getting started
A module is a small script, written in Luau (a dialect of Lua), that the app runs for you. It gets one global table called rug, and that table is the whole world it can touch. There is no io, no os, no require, no file access, and no internet beyond the rug calls. Your Rugplay login is never exposed to the script.
A module has a run mode. Manual runs once when you press Run. Interval runs every few seconds. Continuous stays alive and reacts to live events. Pick the one that fits what you are building.
Every script can read the market and your portfolio. Anything that spends or sends money has to be granted a permission first, and while dry run is on those calls only log what they would have done instead of really doing it.
rug.log("hello from my module")
rug.log("cash on hand:", rug.fmt.money(rug.portfolio.cash()))
The language (Luau)
Modules run on Luau, a fast, sandboxed dialect of Lua. Almost everything you know from Lua works exactly the same: variables, functions, tables, if and for and while, the string and table and math libraries, pcall, ipairs, and so on. If you have written Lua before, you already know how to write a module here.
Luau adds a few nice things you are free to use. continue skips to the next loop pass. Compound assignment works, so you can write count += 1 instead of count = count + 1. And you can add optional type hints like local n: number = 0 if you like them. They are ignored at run time, so they never change what the module does.
A few pieces of newer mainline Lua are not in Luau, so avoid them: there is no // floor division (write math.floor(a / b)), no bitwise operators (& | ~ << >>), no goto, and no string.pack or math.maxinteger. If you paste in older code that uses one of those, the module shows a clear error when you save or test it, so nothing ever breaks silently.
One small thing to know: numbers are all decimals under the hood, so a whole number like 5 prints as "5", never "5.0". Your existing modules keep working, and the rug API in the rest of these docs is exactly the same.
for _, c in ipairs(rug.market.list(10)) do
if c.liquidity < 100 then continue end
rug.log(c.symbol, rug.fmt.money(c.price))
end
Run modes
Manual: the script runs top to bottom once when you hit Run. Good for one-off tools and scans.
Interval: the script runs top to bottom on a timer (you set the seconds). Good for simple repeated checks.
Continuous: the script runs its top level once to register handlers and timers, then stays alive. This is the mode for anything that reacts to events (rug.on.*) or schedules work (rug.every / rug.after). It keeps running in the background, even while you are idle, until you turn it off.
rug.on.newCoin(function(c)
rug.log("a continuous module saw a new coin:", c.symbol)
end)
Events and timers
In a continuous module you register handlers at the top level and the app calls them when things happen. rug.on.newCoin fires when a coin is created, rug.on.trade on live trades, rug.on.notification when Rugplay notifies you, and so on. Each handler gets a table describing what happened.
Keep handlers quick. If a handler blocks for a long time the module can fall behind and miss events (it will log a warning if that happens). For anything time based, do not sleep inside a handler. Instead use rug.every(seconds, fn) or rug.after(seconds, fn), or queue work and act on it from a timer. rug.on.tick fires about every four seconds if you want a steady heartbeat.
rug.on.trade({ minValue = 5000 }, function(t)
rug.log("whale bought", t.coinSymbol)
end)
rug.every(60, function()
rug.log("still watching the feed")
end)
Settings
Settings let the user change how a module behaves without touching the code. Call rug.settings.define at the top with the fields you want, and they show up as a form on the module's page. Read them at runtime with rug.settings.get(key).
This is how the sniper exposes things like spend range and blacklisted creators. Define once, read often.
rug.settings.define({
{ key = "spend", label = "Spend ($)", type = "number", default = 5 },
})
local spend = rug.settings.get("spend")
Permissions
Reading data is always allowed. Anything that moves money or acts on your behalf needs a permission you grant on the module's page: trade (buy and sell), transfer (send cash or coins), create (make coins), gamble (arcade), hopium (prediction bets), social (post comments, block users), and prestige (sell everything to level up).
Declare what your module wants with rug.permissions("trade", "social") so the page can show the user exactly what to allow. If a call needs a permission that was not granted, it fails with a clear message.
rug.permissions("trade", "social")
rug.trade.buy("ELON", 5)
rug.comments.post("ELON", "in")
Dry run
Every module has a dry run switch. While it is on, calls that would spend or send money do not really happen. They log what they would have done so you can watch the logic play out safely. Test run always stays in dry run.
Turn dry run off only when you have watched it behave and you are ready for it to use real funds.
if rug.me.dryRun then
rug.log("dry run is on, this buy is only pretend")
end
rug.trade.buy("ELON", 5)
Saved state
rug.state is a small key to value store that belongs to your module and survives restarts. Use it to remember things between runs: coins you have already seen, a daily spend total, a cooldown timestamp. Values are stored as text. Read with rug.state.get, write with rug.state.set, remove with rug.state.delete. To keep the database healthy, a module can hold up to 512 keys and each value can be up to 64 KiB. Setting past those limits raises an error, so store summaries rather than dumping everything.
local seen = rug.state.get("seen") or ""
if not seen:find("ELON,", 1, true) then
rug.state.set("seen", seen .. "ELON,")
rug.log("first time seeing ELON")
end
Custom panels
A module can show its own data with rug.ui. Declare a panel at the top with rug.ui.panel, then fill it at runtime with rug.ui.append (for a table), rug.ui.set (for stats or text), or rug.ui.clear. Panels show up under the Modules dropdown in the top nav. The sniper uses one to show its recent snipes.
Panels can also take input: give a panel inputs (text, number, boolean, or choice fields) and their values arrive with every button press in rug.on.panelAction as a.values. An input with setting = "someKey" binds the field to that module setting, so editing it on the panel updates the running module immediately. Use rug.ui.update to change a panel's structure while running, and width = "half", order, or section to arrange panels.
rug.ui.panel({ key = "snipes", title = "Recent snipes", type = "table",
columns = {{ key = "symbol", label = "Coin" }} })
rug.ui.append("snipes", { symbol = "ELON" })
Building with blueprints
A blueprint is a module you build by wiring blocks instead of writing Lua. It compiles to the same Lua and runs on the same engine, so it gets the same dry run, settings, permissions, and event system. A Lua module is edited as Lua and a blueprint as a blueprint, never mixed.
## Run modes Picked on the module's page.
- Continuous reacts to triggers and stays alive.
- Period runs on a timer but only inside a window. Its opening block is Active between, where from and to take a daily time (09:00, and it handles overnight) or a date or date-time.
- One time runs once when you press Run. Its opening block is When Run is pressed.
## The seven kinds of block
- Trigger: decides when things run (a new coin, a trade, a price move, a timer, the daily reward, and so on).
- Branch: the conditional. Wire a yes/no condition into it; the green True port runs when it holds, the red False port when it does not. You build the condition out of compare blocks (Less than, Greater than, Equals) fed by values, optionally combined with And/Or/Not. The True and False blocks act on the coin in scope, so they often need nothing wired.
- Loop: runs the blocks under it once per item, either each of your holdings or each coin from a market list.
- Guard: runs the blocks under it only within a limit. Not too often holds a cooldown (overall or per coin); At most N times caps how many times they run (ever or per day). These are the safety rails that stop a bot acting on the same thing over and over.
- Math, logic and values: numbers (add, multiply, percent of, round, random), comparisons (less than, equals, and so on, which give a yes/no), and a Coin value getter that reads one field off a coin. No order wires, only value ports, so you wire them through to build a value or a condition.
- Action: does something. Buy, sell, send, comment, log, notify, wait, remember a value, and more.
- Setting: adds a field to the module's page so the user can tune a value without touching the blueprint.
## The coin in scope The coin in scope is the heart of it. Under a trigger it is the coin from the event; inside a loop it is the current item. Actions that take a coin default to the coin in scope, or you can pin a specific one.
Log, notify, and comment messages are built from parts: hit + text to type a piece, or + value to add a wire-in dot you drag a coin, number, or value onto. Inside a text part the tokens {coin}, {price}, {value}, {amount}, {trader}, {side}, {change}, {marketCap}, {volume}, and {liquidity} still fill in from the coin in scope. Money tokens come out formatted ($1.50K, $0.0000237), percents as +1.23%.
Every live buy, sell, and transfer carries a locked 7-second cooldown from the one before it. It is enforced in the engine, so even raw Lua cannot send orders faster than that. It only ever waits when your own pacing is under 7 seconds, so it is a floor against API abuse, not an extra delay on top of a Wait you already added.
## Wiring values between blocks Blocks that produce values (a trigger, a loop, Find a user, Get coin info) list their outputs at the bottom under a small "gives" label, each a colored chip with a connector dot on the right edge: coin is teal, user is purple, a number is orange, a time is amber, a list is green, text is blue. Numbers, times, and plain text mix freely; a coin, user, or yes/no only fits its own kind, and if you try to wire the wrong one in the editor tells you why.
- Drag an output chip onto a dot of the same color on another block's left edge. A colored line links them and the field reads "from <block>" with no dropdowns.
- Colors only match like to like, so it is hard to wire the wrong thing.
- A coin field left blank uses the coin in scope, or you can type a symbol.
- Keep the producer under the same trigger or loop as the block that uses it, so the value is in scope.
## The In scope panel Pinned to the top left of the canvas, it lists what the selected block can read: every variable wired down from the triggers and loops above it, with its color and source, plus the tokens you can drop into log and notify text. Click any block to update it.
## Three kinds of memory (and when to use each) These look similar but do different jobs. Picking the right one avoids surprises.
- Set a variable / Use a variable: the blueprint's own scratch number. Lives for one run and is forgotten on restart. Use it for a counter or running total inside a single pass, like adding up spend as you loop.
- Remember a value / Recall a value: saved to disk, so it survives restarts. Use it for anything that must outlast a run: a peak price per coin, the last coin you acted on, a daily count that should not reset when the app closes. Build the key from parts (text plus a wired coin) to keep one slot per coin.
- User setting: a knob the user sets on the module page. The blueprint only reads it (drag the setting's value output into an input). Use it for anything you want tunable without editing blocks, like a sell threshold.
- Rule of thumb: counting within one run, use a variable. Must survive a restart, use Remember. The user should control it, use a setting.
## Checking and editing The panel under the canvas lists problems and heads-ups: a trigger with no action, an empty coin field, a value bound to a setting that does not exist, a row out of scope. Fix the errors before you turn dry run off.
- Right click the canvas to search for and drop in any block at that spot.
- Toolbar: add a note, tidy the layout, undo, redo, and zoom.
- Ctrl+C / Ctrl+V copy and paste a block, Ctrl+D duplicates.
- The minimap in the corner jumps you around a big graph. Notes are sticky labels you can drag and resize.
The Dust Cleaner, drawn out. Run order flows left to right along the tops; values wire in from the sides.
ORDER (the white path):
[On a timer 60s] --> [For each holding] --> [Branch]
|-- True --> [Log] --> [Sell all] --> [Wait 7s]
'-- False --> (nothing)
VALUES (the colored wires):
For each holding . coin --> Coin value (liquid) --.
'--> a |
User setting "threshold" -----------------------------> b | Less than (a < b) --> Branch condition
For each holding . coin ----------------------------------------------------------> Sell all . coin
For each holding . coin and . $ value ---------------------------------------------> Log message parts
So: every minute, for each coin you hold, read its liquid value, and if it is under the user's threshold, log it and sell it, pausing 7s between sells.
How the engine works
A short tour of what happens under the hood when your module runs. You do not need any of this to build modules, but it explains why things behave the way they do.
## The sandbox Your script gets one global table, rug, and that is the entire world it can touch. There is no io, no os, no require, no file access, and no way onto the internet except the rug calls. Your Rugplay login is held by the app and never handed to the script. On top of that the engine caps how much memory a module can use and stops any script that runs too long in one go, so a runaway loop cannot freeze the app. Anything that spends or sends money is checked against the permissions you granted and against dry run before it does anything real.
## How a module is run The engine builds your module once and keeps it warm, rather than rebuilding it every time. A continuous module is built once, registers its handlers and timers, then stays alive and reacts. An interval module is built once too, then on each tick it re-runs your script from a clean slate (so leftover values do not pile up between ticks) while your saved rug.state carries over. A manual module is built, run once, and torn down. Keeping the module warm is what makes interval and continuous modules fast and steady.
## The live event feed There is one live feed of market activity (new coins, trades, price moves, transfers, comments, your fills, the daily reward). Every continuous module subscribes to it, and the app fans each event out to all of them. If one of your handlers takes too long, that module can fall behind and miss a few events, and it will log a warning when that happens. This is why the docs push you to keep handlers quick and use timers for slow work.
## How orders are paced Every live buy, sell, and transfer from every module funnels through a single queue with a minimum gap between calls, so no number of modules can hammer the Rugplay API at once. On top of that each module keeps a locked 7-second floor between its own orders. The floor only ever waits when your own pacing is faster than 7 seconds, so it is a guard against abuse, not an extra delay on top of a Wait you already added.
## The lifecycle Editing a running module's settings does not restart it. The new values are handed to the live module on the fly, so queued waits, timers, and in-memory values all survive. Changing the actual blocks or code, or toggling enabled, dry run, or permissions, does restart it, because those change what the module is or is allowed to do. When a module stops, the engine lets it finish the action it is in the middle of, then shuts it down cleanly, so a restart never leaves an old copy and a new copy both trading. And if a module errors over and over with no success in between, the engine stops it for you and logs why, so a broken script cannot spin or spam forever. Turn it back on once you have fixed it.
## Where your data lives Saved state from rug.state lives in the app's local database and belongs to that one module. Settings live on the module's page. Both survive restarts and app updates. Nothing about your modules or your account leaves your machine except the Rugplay calls the modules make.
rug.on.trade({ minValue = 5000 }, function(t)
rug.log("the feed delivered a whale trade:", t.coinSymbol)
end)
rug.every(60, function()
rug.log("still warm, still watching")
end)
Limits and performance
The engine runs with a set of fixed limits, and the app has a Performance page you can tune to your own machine.
## Fixed engine limits These are the same for everyone, on purpose: a module that works on one machine works the same on every machine. You cannot change them, but it helps to know them.
- Each module gets up to 64 MiB of memory and is stopped if a single step runs longer than 15 seconds.
- Every live buy, sell, and transfer keeps a locked 7-second floor.
- Network requests time out after 30 seconds.
- rug.state holds up to 512 keys, 64 KiB per value.
- The app keeps the newest 300 log lines and 2000 runs per module.
- A module that errors 20 times in a row with no success is stopped for you.
## Performance settings (Settings page) These only change your machine, never how a module behaves. Pick a Low, Medium, or Max preset, or set each one:
- Max running modules, and how many holdings scans run at once.
- How often the app polls the live feed and the market.
- How many rows big tables draw, and whether animations are on.
- On Linux, GPU compositing is off by default for stability; a toggle can turn it on if your drivers handle it well.
Low is good for an old laptop; Max is for a fast desktop. The defaults match Medium.
local n = tonumber(rug.state.get("count")) or 0
rug.state.set("count", tostring(n + 1))
rug.log("run number", n + 1)
Module safety and reliability
A module trades with real money, so the engine holds the safety rails itself instead of trusting each script to behave. Knowing what they do helps you read your logs and build modules that stay out of trouble.
## Practice and Live Every module has one Practice/Live switch on its page, and that is the only thing that decides whether it trades for real. In Practice the buy, sell, and transfer calls only log what they would have done. In the script this reads as rug.me.dryRun, so you can branch on it. Do not build your own second practice toggle in settings: it splits the control and gets confusing. Start in Practice, watch the logs, then flip to Live.
## The 7-second floor and the burst brake Every live buy, sell, and transfer keeps a locked 7-second gap, enforced in the host so no script can skip it. On top of that, if more than a handful of live actions ever try to land inside one 20-second window (for example if something releases a backed-up queue at once), the engine trips a burst brake: it stops the module and logs the reason rather than letting it dump a pile of trades. A multi-chunk sell of a large position is paced by the same gap, so big exits take a little while on purpose.
## The handler watchdog Each event or timer handler gets about 20 seconds of its own work before the engine stops it with "this handler ran too long". Time spent waiting on the network or on rug.sleep does not count against that budget, so a handler that legitimately waits on a slow request is fine; only real runaway work (an endless loop) gets cut. A single module step is also capped at 15 seconds and 64 MiB.
## Sleep, wake, and stale work Timers use real wall-clock time, so when your PC sleeps overnight and wakes, anything that came due while it was asleep is due now. The engine spaces those out with the 7-second floor and the burst brake instead of firing them all at once, and a queued action a script considers too old can be skipped. If you schedule buys far in the future, expect them to run shortly after a long sleep, not never.
## Permissions, quarantine, and the warnings tray A module only gets the abilities you grant it: trade, transfer, create, and so on. If an enabled module asks for a permission you have not granted, it does not quietly error in a loop. it does not start, and a warning appears in the tray at the bottom right telling you which permission to grant. Grant it and the module starts on its own. A module that errors 20 times in a row with no success is turned off (quarantined) and shows a warning too, so a broken module cannot run forever.
## Social rate limits Comments and other social actions go through Rugplay's own server limits. Posting the same short comment on every buy, or many comments back to back, gets refused by the server with a rate-limit error. That is the server talking, not a bug in your module. Space comments out, vary the text, or post on only some buys. A failed comment is logged and ignored; it never blocks a trade.
rug.on.newCoin(function(c)
if rug.me.dryRun then rug.log("practice: would buy", c.symbol); return end
rug.trade.buy(c.symbol, 5) -- paced by the 7s floor for you
end)
Logging and identity
Write to the module's output and find out who you are.
rug.log(...)Write a line to the module's output.
rug.log("checking the market", rug.fmt.money(rug.portfolio.cash()))
rug.warn(...)Write a line marked as a warning.
rug.warn("price looks stale, skipping")
rug.error(...)Write a line marked as an error.
rug.error("could not reach the market")
rug.notify(title, body?)Add a notice line to the output.
rug.notify("Bought ELON", "spent $5")
rug.me.usernameYour username.
rug.log("running as", rug.me.username)
rug.me.userIdYour user id.
rug.state.set("owner", rug.me.userId)
rug.me.dryRunTrue while dry run is on.
if rug.me.dryRun then rug.log("just testing") end
rug.me.profile()Your full profile from the server.
local me = rug.me.profile()
rug.log(me.name, rug.fmt.money(me.balance))
Formatting, math, and time
Helpers for money, the bonding curve, and timing.
rug.fmt.money(n)Format a number as money, like "$1.2K".
rug.log(rug.fmt.money(1234.5))
rug.fmt.compact(n)Format a number compactly without the dollar sign.
rug.log(rug.fmt.compact(2500000))
rug.fmt.pct(n)Format a number as a signed percent, like "+4.20%".
rug.log(rug.fmt.pct(4.2))
rug.amm.sellValue(coins, poolCoin, poolBase)What you would pocket for selling coins into a pool, after the 0.3% trading fee.
local c = rug.coin.get("ELON")
local out = rug.amm.sellValue(1000, c.poolCoin, c.poolBase)
rug.amm.sellGross(coins, poolCoin, poolBase)The raw pool output of a sell before the fee. Use for pool math; sellValue is what you keep.
local gross = rug.amm.sellGross(1000, c.poolCoin, c.poolBase)
rug.amm.buyCoins(usd, poolCoin, poolBase)Coins a dollar spend would buy, after the 0.3% fee is skimmed before the swap.
local coins = rug.amm.buyCoins(100, c.poolCoin, c.poolBase)
rug.amm.buyCost(coins, poolCoin, poolBase)The dollar spend needed to receive that many coins, fee included.
local usd = rug.amm.buyCost(1e6, c.poolCoin, c.poolBase)
rug.amm.coinsForCash(netUsd, poolCoin, poolBase)Coins to sell to pocket a target net amount, grossed up for the fee.
local q = rug.amm.coinsForCash(250, c.poolCoin, c.poolBase)
rug.amm.toPrice(target, poolCoin, poolBase)Reach a target price: returns { side = "buy", spend, fee, coins } above spot, { side = "sell", coins, gross, fee, net } below, { side = "none" } at spot. Fee aware both ways.
local plan = rug.amm.toPrice(0.01, c.poolCoin, c.poolBase)
if plan.side == "buy" then rug.log("costs", rug.fmt.money(plan.spend)) end
rug.amm.liquidity(price)The base liquidity implied by a price.
local base = rug.amm.liquidity(0.5)
rug.amm.valueAtPrice(coins, price)What a holding is worth at a given price, after the 0.3% fee.
local worth = rug.amm.valueAtPrice(1000, 0.5)
rug.fees.swapThe trading fee rate (0.003 = 0.3%, both buys and sells). rug.fees.swapKeep is 1 minus that.
local fee = usd * rug.fees.swap
rug.fees.cashTransferThe cash transfer fee rate (0.01 = 1%). Coin transfers are free.
local received = usd * (1 - rug.fees.cashTransfer)
rug.time.now()The current time in milliseconds.
local started = rug.time.now()
rug.time.age(isoString)Seconds since an ISO timestamp, handy with coin.createdAt.
local c = rug.coin.get("ELON")
if rug.time.age(c.createdAt) < 60 then rug.log("brand new") end
rug.time.clock()Seconds into the local day (0 to 86399).
if rug.time.clock() > 9 * 3600 then rug.log("after 9am") end
rug.time.today()Today's local date as yyyy-mm-dd.
rug.log("date", rug.time.today())
rug.time.inRange(from, to)True if now is inside a window. from/to can be a daily time (09:00, handles overnight) or a date / date-time.
if rug.time.inRange("09:00", "17:00") then rug.log("trading hours") end
rug.sleep(seconds)Pause the script. Flushes the output gathered so far first, so logs and trades show before the wait, which is handy for spacing out a loop. Interruptible by turning the module off. Prefer timers over sleeping inside event handlers.
rug.trade.sellAll(h.symbol)
rug.sleep(2)
rug.rand(min, max)A random number between min and max (or 0 and min if you pass one value). Already seeded, so it varies every run. Pair it with rug.sleep for a random cooldown.
rug.sleep(rug.rand(10, 20))
rug.math.round(n, decimals?)Rounds to the given number of decimals (0 by default).
rug.math.round(1.2367, 2) -- 1.24
rug.math.clamp(n, lo, hi)Keeps a number inside a range.
local spend = rug.math.clamp(bet, 5, 100)
rug.math.pct(part, whole)What percent part is of whole (0 if whole is 0).
rug.math.pct(h.value, rug.portfolio.value())
rug.stop()Turn the module off from inside itself.
rug.stop()
Market
Scan and search the coin market.
rug.market.list(limit?)The newest coins.
for _, c in ipairs(rug.market.list(10)) do rug.log(c.symbol) end
rug.market.new(limit?)The newest coins (same as list).
local fresh = rug.market.new(5)
rug.market.top(limit?)Top coins by market cap.
local big = rug.market.top(10)
rug.market.search(text, limit?)Search coins by name or symbol.
local hits = rug.market.search("elon", 5)
rug.market.gainers(n?)Biggest 24h gainers.
for _, c in ipairs(rug.market.gainers(5)) do rug.log(c.symbol, rug.fmt.pct(c.change24h)) end
rug.market.losers(n?)Biggest 24h losers.
local dumps = rug.market.losers(5)
rug.market.movers(n?)Most active by volume.
local active = rug.market.movers(10)
rug.market.query(filter)Filter the top of the market by minMarketCap, maxMarketCap, minVolume, minChange24h, maxChange24h, minPrice, maxPrice, search.
local cheap = rug.market.query({ maxPrice = 0.01, minVolume = 1000 })
rug.market.recentTrades(limit?, minValue?)A one-shot look at the live trade feed.
for _, t in ipairs(rug.market.recentTrades(20, 500)) do rug.log(t.coinSymbol, rug.fmt.money(t.totalValue)) end
Coin
Look up a single coin in detail.
rug.coin.get(symbol)Full detail: price, marketCap, poolCoin, poolBase, liquidity, supply, createdAt, creatorId, creatorName, creatorUsername, creatorImage, tradingUnlocksAt, secondsUntilUnlock, locked, and more.
local c = rug.coin.get("ELON")
rug.log(c.symbol, rug.fmt.money(c.price), "by", c.creatorName)
rug.coin.get(symbol).lockedTrue while a brand new coin is still in its creation lock. secondsUntilUnlock counts down to when anyone can trade. Only the creator can buy or sell before then.
local c = rug.coin.get("ELON")
if c.locked then
rug.log("locked for", c.secondsUntilUnlock, "more seconds")
else
rug.trade.buy("ELON", 5)
end
rug.coin.holders(symbol, limit?)Who holds the coin and how much.
for _, h in ipairs(rug.coin.holders("ELON", 5)) do rug.log(h.username, rug.fmt.pct(h.percentage)) end
rug.coin.candles(symbol, timeframe?)Candlestick data for a timeframe.
local cs = rug.coin.candles("ELON", "1h")
rug.log("candles:", #cs)
rug.coin.chart(symbol, { timeframe?, before? })Paged candles plus volume. before is a millisecond cutoff for older data.
local data = rug.coin.chart("ELON", { timeframe = "1m" })
rug.coin.comments(symbol)The coin's comments.
for _, c in ipairs(rug.coin.comments("ELON")) do rug.log(c.content) end
rug.coin.liquidity(symbol)The coin's base liquidity.
rug.log("liquidity", rug.fmt.money(rug.coin.liquidity("ELON")))
rug.coin.exists(symbol)True if the coin exists.
if rug.coin.exists("ELON") then rug.log("it is real") end
Portfolio
Read your holdings and balance.
rug.portfolio.holdings()All your coin positions.
for _, h in ipairs(rug.portfolio.holdings()) do rug.log(h.symbol, h.quantity) end
rug.portfolio.cash()Your cash balance.
rug.log("cash", rug.fmt.money(rug.portfolio.cash()))
rug.portfolio.value()Your real liquid value if you sold out now, after the 0.3% trading fee.
rug.log("liquid", rug.fmt.money(rug.portfolio.value()))
rug.portfolio.summary()Server totals: cash, coinValue, total, holdings.
local s = rug.portfolio.summary()
rug.log(rug.fmt.money(s.total))
rug.portfolio.coin(symbol)One position, or nil if you do not hold it.
local h = rug.portfolio.coin("ELON")
if h then rug.log("you hold", h.quantity) end
rug.portfolio.filter(fn)Holdings where fn(h) returns true.
local up = rug.portfolio.filter(function(h) return h.change24h > 0 end)
rug.portfolio.where(opts)Holdings matching minLiquid, maxLiquid, minValue, maxValue, minChange24h.
local big = rug.portfolio.where({ minValue = 100 })
Trading
Buy and sell. Needs the trade permission. Honors dry run.
rug.trade.buy(symbol, usd)needs tradereal moneyBuy a dollar amount of a coin.
rug.trade.buy("ELON", 5)
rug.trade.buyCoins(symbol, coins)needs tradereal moneyBuy a specific number of coins.
rug.trade.buyCoins("ELON", 1000)
rug.trade.unthrottle(on?)needs tradeTurn this module's 7s trade gate and burst brake off so trades fire instantly (on defaults to true; pass false to restore). Only affects the module that calls it. The 600ms executor pacer still applies, and this raises the risk of a server-side rate limit on your account.
rug.trade.unthrottle()
rug.trade.sell(symbol, coins, keep?)needs tradereal moneySell a number of coins. Optional keep ($) is a floor: it never sells the holding below that liquid value, and the floor wins over the coin count.
rug.trade.sell("ELON", 500)
rug.trade.sell("ELON", 1e9, 2000) -- dump but keep $2000
rug.trade.sellPercent(symbol, pct, keep?)needs tradereal moneySell a percent of a holding, chunked. Optional keep ($) stops the sell at that liquid value.
rug.trade.sellPercent("ELON", 50)
rug.trade.sellAll(symbol, keep?)needs tradereal moneySell an entire holding, chunked. With keep ($) it sells the position down to that liquid value instead of fully.
rug.trade.sellAll("ELON")
rug.trade.sellAll("ELON", 2000) -- leave $2000
rug.trade.sellWhere(fn, pct)needs tradereal moneySell pct of every holding where fn(h) is true.
rug.trade.sellWhere(function(h) return h.change24h < -20 end, 100)
rug.trade.estimateBuy(symbol, usd)How many coins a buy would get you, without buying. Includes the 0.3% fee.
local coins = rug.trade.estimateBuy("ELON", 5)
rug.trade.estimateSell(symbol, coins)How much a sell would pocket, without selling. Net of the 0.3% fee.
local usd = rug.trade.estimateSell("ELON", 1000)
rug.trade.quoteBuy(symbol, usd)A full buy quote from the live pool: coins, spend, fee, intoPool, avgPrice, newPrice.
local q = rug.trade.quoteBuy("ELON", 100)
rug.log("fee", rug.fmt.money(q.fee), "new price", q.newPrice)
rug.trade.quoteSell(symbol, coins)A full sell quote: gross, fee, net, newPrice.
local q = rug.trade.quoteSell("ELON", 1000)
rug.log("you get", rug.fmt.money(q.net))
Wallet
Move cash and coins. Sends need the transfer permission. Honors dry run.
rug.wallet.send(username, usd)needs transferreal moneySend cash to someone (minimum $10). A 1% fee is taken, so they receive 99% of what you send.
rug.wallet.send("friend", 25)
rug.wallet.sendCoin(username, symbol, coins)needs transferreal moneySend coins to someone. Coin transfers have no fee.
rug.wallet.sendCoin("friend", "ELON", 100)
rug.wallet.transactions(opts?)Your transaction history (limit, type).
local tx = rug.wallet.transactions({ limit = 20 })
rug.wallet.received(limit?)Recent incoming transfers.
for _, t in ipairs(rug.wallet.received(10)) do rug.log(rug.fmt.money(t.amount)) end
Create, rewards, prestige, achievements
Make coins, claim the daily reward, prestige, and achievements.
rug.create.coin({ name, symbol })needs createreal moneyCreate a new coin. Costs about $1,100.
rug.create.coin({ name = "My Coin", symbol = "MINE" })
rug.rewards.status()Your daily reward status.
local r = rug.rewards.status()
if r.canClaim then rug.rewards.claim() end
rug.rewards.claim()Claim the daily reward.
rug.rewards.claim()
rug.prestige.status()Your prestige status.
local p = rug.prestige.status()
rug.log("level", p.level)
rug.prestige.reset()needs prestigereal moneyPrestige: sells everything and bumps your level.
rug.prestige.reset()
rug.achievements.list()All achievements.
for _, a in ipairs(rug.achievements.list()) do rug.log(a.name) end
rug.achievements.unclaimed()Achievements you can still claim.
local left = rug.achievements.unclaimed()
rug.achievements.claim(id?)Claim one achievement, or all unclaimed.
rug.achievements.claim()
Hopium
Prediction markets. Bets need the hopium permission. Honors dry run.
rug.hopium.questions(opts?)Open questions (status, limit).
local qs = rug.hopium.questions({ limit = 10 })
rug.hopium.question(id)One question in detail.
local q = rug.hopium.question(id)
rug.hopium.bet(id, "yes"|"no", amount)needs hopiumreal moneyPlace a bet.
rug.hopium.bet(id, "yes", 50)
rug.hopium.create(text)needs hopiumreal moneyCreate a question (needs a $100k balance).
rug.hopium.create("Will ELON hit $1 today?")
Arcade
Gambling games. They need the gamble permission and honor dry run. Profit and loss is tracked.
rug.arcade.coinflip(amount, "heads"|"tails")needs gamblereal moneyFlip a coin.
local r = rug.arcade.coinflip(10, "heads")
rug.log(r.won and "won" or "lost")
rug.arcade.dice(amount, number)needs gamblereal moneyRoll for a number 1 to 6.
local r = rug.arcade.dice(10, 6)
rug.arcade.slots(amount)needs gamblereal moneySpin the slots.
local r = rug.arcade.slots(10)
rug.arcade.mines.start(bet, mineCount)needs gamblereal moneyStart a mines game (3 to 24 mines).
local g = rug.arcade.mines.start(10, 3)
rug.arcade.mines.reveal(token, tile)needs gamblereal moneyReveal a tile.
rug.arcade.mines.reveal(g.token, 5)
rug.arcade.mines.cashout(token)needs gamblereal moneyCash out a mines game.
rug.arcade.mines.cashout(g.token)
rug.arcade.tower.start(bet, difficulty)needs gamblereal moneyStart a tower game.
local g = rug.arcade.tower.start(10, "easy")
rug.arcade.tower.step(token, tile)needs gamblereal moneyTake a step up the tower.
rug.arcade.tower.step(g.token, 1)
rug.arcade.tower.cashout(token)needs gamblereal moneyCash out a tower game.
rug.arcade.tower.cashout(g.token)
rug.arcade.stats()Your wins, losses, and total played.
local s = rug.arcade.stats()
rug.log("net", rug.fmt.money(s.profit))
Saved state
A small key to value store that survives restarts.
rug.state.get(key)Read a saved value, or nil.
local seen = rug.state.get("seen")
rug.state.set(key, value)Save a value (stored as text).
rug.state.set("seen", "1")
rug.state.all()Every saved key and value.
for k, v in pairs(rug.state.all()) do rug.log(k, v) end
rug.state.delete(key)Remove a saved value.
rug.state.delete("seen")
Settings
Expose options the user can change on the module's page.
rug.permissions(...)Declare the permissions your module needs, like rug.permissions("trade", "social"), so the module page can show exactly what to allow. A call that needs an ungranted permission fails with a clear message.
rug.permissions("trade", "social")
rug.settings.define(fields)Define the settings form. Each field is { key, type (number, text, boolean, choice), label, default, help?, min?, max?, step?, options? }.
rug.settings.define({
{ key = "spend", label = "Spend ($)", type = "number", default = 5 },
})
rug.settings.get(key)Read a setting's current value.
local spend = rug.settings.get("spend")
Custom panels
Show your own tables, stats, or text under the Modules dropdown.
rug.ui.panel(def)Declare a panel at the top: { key, title, type (table, stats, text, buttons), columns?, empty?, buttons?, inputs?, width?, order?, section? }. Table columns are { key, label, format? } where format can be time or money. Inputs are { key, label, type (text, number, boolean, choice), default?, min?, max?, step?, options?, placeholder?, setting? }; their values arrive with every button press, and setting binds the field to one of the module's settings so edits apply live. width can be "half" to sit two panels side by side.
rug.ui.panel({ key = "buy", title = "Quick buy", type = "buttons",
inputs = {{ key = "amount", label = "Spend", type = "number", default = 50 }},
buttons = {{ key = "go", label = "Buy" }} })
rug.ui.update(key, def)Replace a panel's structure at runtime (same def shape as rug.ui.panel). Declaring twice is still ignored; update is the explicit way to change columns, buttons, or inputs while running.
rug.ui.update("buy", { title = "Quick buy (armed)", type = "buttons",
buttons = {{ key = "go", label = "Buy now" }} })
rug.ui.append(key, row, max?)Add a row to a table panel (default keeps 50, cap 500).
rug.ui.append("snipes", { symbol = "ELON" })
rug.ui.set(key, value)Replace a panel's data (a map for stats, a string for text).
rug.ui.set("stats", { bought = 3, spent = 15 })
rug.ui.clear(key)Empty a panel.
rug.ui.clear("snipes")
rug.ui.get(key)Read a panel's stored data back.
local rows = rug.ui.get("snipes")
Events
React to live activity in a continuous module. Register these at the top level.
rug.on.trade(filter?, fn)A live trade. filter: { symbol, minValue, maxValue, type, trader, minAmount, maxAmount }. type is BUY or SELL, trader matches a username or id. The event carries coinSymbol, totalValue, amount, price, type, username, userId.
rug.on.trade({ trader = "whale_guy", type = "BUY" }, function(t)
rug.log(t.username, "bought", t.coinSymbol)
end)
rug.on.newCoin(filter?, fn)A brand new coin. filter: { symbol, creator }. creator matches a creator name or id.
rug.on.newCoin({ creator = "someone" }, function(c)
rug.log("new coin from them:", c.symbol)
end)
rug.on.price(symbol|filter?, fn)Derived from trades. filter: { symbol, below, above } for limit-style triggers.
rug.on.price({ symbol = "ELON", below = 0.001 }, function(p)
rug.log("ELON dipped to", p.price)
end)
rug.on.transfer(fn)An incoming transfer to you.
rug.on.transfer(function(t)
rug.log("got", rug.fmt.money(t.amount))
end)
rug.on.comment(symbolOrFilter?, fn)A new comment on a coin you hold.
rug.on.comment(function(c)
rug.log(c.userUsername, "said", c.content)
end)
rug.on.notification(filter?, fn)A new Rugplay notification, including rugpull alerts on coins you held. Filter by { type }.
rug.on.notification({ type = "RUGPULL" }, function(n)
rug.log("rugpull!", n.title)
end)
rug.on.fill(filter?, fn)One of your own trades completed (symbol, side, amount).
rug.on.fill(function(f)
rug.log("filled", f.side, f.symbol)
end)
rug.on.tick(fn)Fires about every four seconds.
rug.on.tick(function()
rug.log("tick")
end)
rug.on.reward(fn)Fires after your daily reward is claimed. The event has amount, newBalance, streak.
rug.on.reward(function(r)
rug.log("claimed", rug.fmt.money(r.amount), "streak", r.streak)
end)
rug.on.idle(fn)Fires when you go idle or come back. The event has an idle boolean.
rug.on.idle(function(e)
rug.log(e.idle and "went idle" or "back")
end)
rug.on.panelAction(fn)A panel button was pressed. The event has panel and button, the keys you set on rug.ui.panel, plus values with the panel's input fields at press time. Works on continuous and interval modules.
rug.on.panelAction(function(a)
if a.button == "go" then rug.log("buying", a.values.amount) end
end)
rug.await.trade / newCoin / price / transfer / notification / fill(opts?)Wait for one event inline. opts: timeout (seconds, max 40) plus the same filters. Returns the event or nil.
local t = rug.await.trade({ minValue = 1000, timeout = 30 })
if t then rug.log("saw", t.coinSymbol) end
rug.await.comment(symbol, timeout?)Wait for the next comment on a specific coin.
local c = rug.await.comment("ELON", 30)
Timers
Schedule work without blocking. Use these instead of sleeping in a handler.
rug.every(seconds, fn)Run fn on a repeating interval (minimum 1 second).
rug.every(30, function()
rug.log("still here")
end)
rug.after(seconds, fn)Run fn once after a delay.
rug.after(10, function()
rug.log("ten seconds later")
end)
rug.stop()Turn the module off from inside itself.
rug.stop()
Blueprint blocks
The visual blocks you wire together to build a module without writing Lua. See the Building with blueprints guide for how they fit together.
Opening: When Run is pressed / Active betweenThe opening block for a One time blueprint (runs once on Run) or a Period blueprint (runs on a timer inside a from-to window, given as a daily time or a date).
Active between 09:00 and 17:00 -> For each holding -> ...
Producer: Get coin infoFetches a coin and breaks out every field as its own chip: coin, price, mkt cap, 24h %, 24h vol, liquidity, supply, locked? (maroon bool), unlock in seconds, creator, created at. Drag any onto a matching dot.
Get coin info (BTC) --locked?--> Branch (skip the buy while it is still locked)
Producer: Find a userLooks a user up and gives the user (purple) plus net worth, cash, and holdings value (orange). Drag the user chip onto a To user dot, or a number chip onto an amount.
Find a user (whale) --user--> Send cash (To user dot)
Wiring valuesTriggers and loops also list output chips at the bottom (coin, trader, $ value, P/L %, etc.). Drag a chip onto a same-color input dot. Coin is teal, user purple, value orange. A blank coin field uses the coin in scope.
For each holding --coin--> Sell all (coin dot)
Trigger: When a trade happensFires on live trades. Filter by coin, value range, side (buy/sell), and trader. The coin and trader filters each take a single name, a comma list (a whitelist or blacklist), or a wired coin, user, list, or text setting. Output chips: coin, trader, $ value, price, amount, side.
When a trade happens (trader is alice,bob)
-> Buy / Log / Notify ...
Trigger: When a new coin appearsFires on a new coin. Filter by creator, typed or wired from a user or setting.
When a new coin appears -> Buy (the coin in scope)
Trigger: When a price movesFires when a coin hits a price at or below / above your target. The coin box takes a symbol, a comma list, or a wired coin or text setting, and the thresholds take a wired number or setting. Leave the coin blank to watch every coin.
When a price moves (ELON at or below 0.001) -> Buy
Trigger: On a timer / Every few secondsRuns on an interval or about every four seconds. Good for sweeps.
On a timer (60s) -> For each of my holdings -> ...
Trigger: When my trade fillsFires when your own buy or sell completes. Filter to buys only, sells only, or both, and read the side, amount, and coin from its output chips.
When my trade fills (sells only) -> Post a comment "sold {coin}"
Trigger: When I receive moneyFires when someone sends you cash or coins. Filter by kind (cash, coins, or both) and a minimum amount. Output chips: amount, sender, coin, and kind. Wire the sender into Send cash to thank them back.
When I receive money (cash only, at least $50)
-> Send cash (to sender, $5) -> Notify
Trigger: reward / idle / comment / notificationReact to the daily reward (amount, streak), going idle or active (gives a yes/no idle chip you wire into a Branch), a comment (gives the comment text), or a Rugplay notification (gives the title, filter by type).
When I go idle or active --idle--> Branch
True -> Notify "away"
False -> (back)
Branch (True / False)The main conditional. Wire a yes/no condition into it: blocks on the green True port run when it holds, blocks on the red False port run when it does not. Build the condition with a compare block. The True/False blocks act on the coin in scope, so a Sell all under True needs no coin wired.
Coin value (liquid) is less than 1 --yes/no--> Branch
True -> Log -> Sell all
False -> (nothing)
Compare: Less than / At most / Greater than / At least / Equals / Not equalPure yes/no blocks. Wire a value into each side (or type a number), and the result is a yes/no you wire into a Branch or an And/Or. This is how you turn numbers into a decision.
Coin value (price) --value--> Greater than (2) --yes/no--> Branch
Logic: And / Or / NotCombine yes/no conditions. And is yes only when both are; Or when either is; Not flips one. Wire compare blocks into them, then the result into a Branch.
(price > 2) --> And <-- (liquid > 100) --yes/no--> Branch
Coin value (getter)Reads one number from a coin: liquid value, value, price, market cap, 24h change, 24h volume, amount, or P/L %. Wire a coin in (like the coin from For each of my holdings), pick the field, and wire the number into a compare block.
For each holding --coin--> Coin value (liquid) --value--> Less than (1)
Condition: Quick filter (legacy)The older all-in-one condition with a rows grid. Still works, but prefer Branch with compare blocks. Runs its then/else blocks when the rows match or not.
Quick filter P/L % is less than -20 then -> Sell all
Math & values: Add / Subtract / Multiply / Divide / Percent of / Smaller of / Larger of / Round / Random number / Absolute value / Negative / Power / RemainderPure value blocks. Each takes numbers (wired, typed, or both) and gives a result chip you wire onward. No order wires, only value ports. Build any number, like 10% of cash or price times 2.
Get coin info --price--> Multiply (x2) --result--> Buy $
Producer: Count my holdingsAdds up your holdings into one number: how many, total $ value, or total liquid $, optionally only the winning, losing, or dust ones. Wire the result out.
Count my holdings (dust, total liquid $) --result--> Notify
Producer: Wait for a trade / Wait for my trade to fillPause the flow until the next matching trade (filter by coin and minimum value) or one of your own fills, up to a timeout, then offer the details. Best in one-time or timer flows.
Buy $5 -> Wait for my trade to fill -> Log "filled"
Math & values: Join textGlues pieces into one string. Wire numbers, coins, or text into its slots, then wire the text result into a log, notify, comment, or saved value.
Join text ("sold " + amount + " coins") --text--> Write to the log
Producer: My portfolio / My holding of a coinRead your balances (cash, total, coin value, # holdings) or one position (amount, value, price, P/L %) as value chips to wire in.
My portfolio --cash--> Percent of (10) --> Buy $
Remember / Recall a value (persistent, per coin)Remember saves a value to disk so it survives restarts; Recall reads it back. Build the key from parts (text plus a wired coin) to keep one slot per coin, like a peak price per coin. This is how you do trailing stops and dedup. Different from Set a variable, which is forgotten on restart.
Recall (peak: + coin) --> Larger of <- coin price --> Remember (peak: + coin)
Loop: For each of my holdingsRuns the blocks under it once per coin you hold. The holding becomes the coin in scope, with its quantity, value, and cost basis.
For each of my holdings -> Only if P&L % < -20 -> Sell all
Loop: For each coin from the marketRuns the blocks under it once per coin from the top, newest, gainers, losers, or most active list.
For each coin from newest (10) -> Only if market cap < 5000 -> Buy $5
Loop: For each holder of a coinRuns the blocks under it once per holder of a coin, biggest first. Wire a coin in or leave blank for the coin in scope. Gives the holder, coins held, % of supply, and $ value. Good for spotting whales and concentration.
For each holder of PEPE -> Only if % of supply > 20 -> Log a whale
Guard: Not too often / At most N timesGate the blocks under them. Not too often keeps a cooldown (overall or per coin); At most N times caps the count (ever or per day). They remember across restarts via state.
When a trade happens -> Not too often (5 min per coin) -> Buy
Action: Stop the loopEnds the enclosing loop early. Handy after you act on the first match.
For each coin from gainers -> Buy -> Stop the loop
Set a variable / Use a variableA scratch number for one run only, forgotten on restart. The blueprint's own internal value, not a user setting. For something that must survive a restart use Remember a value; for something the user controls use a User setting. Good for counters within one pass.
Set a variable (spent = spent + cost)
Action: Buy / Sell / Sell percent / Sell all / Buy by coin countTrade the coin in scope or a pinned coin. Amounts can be bound to a user setting. Every live buy, sell, and transfer keeps a locked 7-second gap from the one before it, even from raw Lua, so a fast loop cannot abuse the Rugplay API. If you wait 7s or more yourself, the gap adds nothing.
Sell a percent (50) of the coin in scope
Action: Send cash / Send coins / Post comment / Block a userMove funds or interact socially. Build comment text from parts (type text or wire a coin/number/value in). Transfers also keep the locked 7-second gap.
Post comment: [text] watching [wire coin] [text] at [wire price]
Action: Log / Notify (message parts)Write to the output or add a notice. Build the message from a list of parts: + text to type a piece, + value to drop a wire-in dot you drag a coin, number, or value onto. The {coin} style tokens still work inside a text part for the coin in scope.
Log: [text] Cleaning dust: [wire coin] [text] (liquid $ [wire $ value] [text] )
Action: WaitPauses before the next block. Drop it inside a loop so actions run one at a time with a cooldown instead of all at once. Set the optional upper bound to wait a random time in the range. The output so far shows before each wait.
For each holding -> Sell all -> Wait (10 up to 20)
Action: Remember / Forget a value, Claim reward, Create coin, Turn offSave and clear state, claim the daily reward, launch a coin, or stop the module.
Remember a value (key seen, value 1)
Setting: User settingAdds a number, text, on/off, or pick-from-a-list field to the module's page so the user can tune it. Drag the block's value output straight into an amount, a compare, a Branch, or a message. A number gives a value, on/off gives a yes/no, text or a list gives text.
User setting (threshold, number, default 1) --value--> Less than b
Compare text: Text is / is not / contains / is one ofYes/no blocks for words, not numbers. Wire a side, coin symbol, kind, name, or comment in and compare it. Is one of is your blacklist or whitelist: check a value against a comma list you type or wire from a text setting the user edits.
When a trade happens --trader--> Is one of (alice, bob) --yes/no--> Branch
Lists, wireable numbers, and result chipsWhen a trade happens takes a comma list of coins or traders, not just one. Almost every number field accepts a wired value, so a User setting or variable can drive it: a price target, a timeout, a threshold, a timer interval (Every N seconds), a cooldown length, an At most N cap, and a loop's How many. Buy, Sell, Sell all, Claim reward, and Create coin give result chips (coins bought, $ received, amount, the new coin) to wire into a log or a next step.
On a timer (Every <- a setting) -> Buy $5 --coins bought--> Write to the log
Text and MeText is a piece of text you type or wire onward. Me is your own account, to wire into Send cash or to compare a name against yours.
When a trade happens --trader--> Text is <- Me (did I make this trade?)
Time is betweenYes when the clock is inside a window (a daily time like 09:00, overnight aware, or a date). Wire it into a Branch to only act during certain hours.
When a trade happens -> Branch (Time is between 09:00 17:00) -> Buy
Guard: Do onceRuns the blocks under it a single time, then never again. Reset it each day, and track it per coin, so you only act on each coin once a day.
When a new coin appears -> Do once (per coin) -> Buy
Wait for a price / new coin / money in / notification / commentPause the flow until that thing happens or a timeout, then read its details. Best in one-time or timer flows. Pair Wait for a price after a buy to wait for your sell target.
Buy $5 -> Wait for a price (above 0.01) -> Sell all
Bet on a question (Hopium)Places a yes or no bet on a Hopium prediction question by its id. Needs the hopium permission.
On a timer -> Bet on a question (id 42, yes, $10)
Arcade: Coin flip / Dice / SlotsPlays an arcade game for a bet. Gives a won (yes/no) and a payout you can wire onward, so you can build martingale-style flows. Needs the gamble permission.
Coin flip ($10 heads) --won?--> Branch
False -> Set a variable (bet = bet * 2)
Loop: For each recent tradeRuns the blocks under it once per recent live trade, newest first, with a minimum value filter. A one-shot scan, good on a timer. Gives coin, trader, $ value, side.
On a timer -> For each recent trade (at least $5000) -> Log {coin}
Claim achievements / PrestigeClaim achievements claims any you have earned. Prestige sells everything and bumps your level (big and irreversible, needs the prestige permission).
On a timer (daily) -> Claim achievements
Like a commentLikes a comment on a coin by its id. Wire the comment id from the When someone comments trigger.
When someone comments --comment id--> Like a comment
Message formattingWhen you wire a value into a Log, Notify, or Comment part, a small dropdown picks how to show it: plain, $ money, percent, or compact (1.2K). So a wired price can read $0.0000237 instead of a raw number.
Log: [text] sold at [wire price shown as $ money]
Generated from the same catalog the app ships, so this always matches the version you are running.
Social
Comments, other users, and notifications. The actions need the social permission.
rug.comments.post(symbol, text)needs socialPost a comment on a coin.
rug.comments.like(symbol, id)needs socialLike a comment.
rug.comments.unlike(symbol, id)needs socialRemove your like.
rug.user.get(idOrName)Look up a user's profile.
rug.user.search(query, limit?)Search users by name. Best effort, returns matches or nil if the server has no search.
rug.user.coins(idOrName)The coins a user has created.
rug.user.stats(idOrName)A user's totals: portfolio value, holdings, trades, volume.
rug.user.holding(idOrName, symbol)How much of a coin a user holds.
rug.profile.get()Your own profile: name, username, and bio.
rug.profile.setBio(text)needs socialSet your About Me bio (up to 160 characters). Keeps your name and username.
rug.user.block(username)needs socialBlock a user.
rug.user.unblock(username)needs socialUnblock a user.
rug.user.blocked()Your block list.
rug.leaderboard(opts?)The leaderboard. opts can set { type, limit }.
rug.notifications.list()Your notifications.
rug.notifications.unread()Your unread notifications.
rug.notifications.markRead(id?)Mark everything as read, or one notification by id.