Grand Exchange API
Access and manage Grand Exchange offers for buying and selling items.
Core Functions
offers
grand_exchange:offers() -> table
Returns all Grand Exchange offers (slots 0-7 for members, 0-2 for free-to-play).
Returns:
table- Array of GrandExchangeOffer objects
Example:
local all_offers = grand_exchange:offers()
logger:info("Total offers: " .. #all_offers)
for _, offer in ipairs(all_offers) do
if offer:valid() and not offer:is_available() then
logger:info("Slot " .. offer:index() .. ": " .. offer:name())
end
end
offer
grand_exchange:offer(index: number) -> GrandExchangeOffer?
Gets a specific offer by slot index.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
index | number | Yes | Slot index (0-7 for members, 0-2 for free-to-play) |
Returns:
GrandExchangeOffer?- The offer at the specified slot, or nil if invalid
Example:
local offer = grand_exchange:offer(0)
if offer and offer:valid() then
logger:info("Slot 0: " .. offer:name())
end
opened
grand_exchange:opened() -> boolean
Checks if the Grand Exchange interface is open.
Returns:
boolean- True if the Grand Exchange interface is visible
Example:
if grand_exchange:opened() then
logger:info("Grand Exchange is open")
end
open
grand_exchange:open() -> boolean
Opens the Grand Exchange interface by finding and interacting with a Grand Exchange Clerk. If no clerk is nearby, automatically navigates to the GE area using available teleports (Ring of Wealth, etc.).
Returns:
boolean- True if the interface was opened successfully
Example:
if not grand_exchange:opened() then
if grand_exchange:open() then
logger:info("Grand Exchange opened successfully")
else
logger:warn("Failed to open Grand Exchange")
end
end
close
grand_exchange:close() -> boolean
Closes the Grand Exchange interface.
Returns:
boolean- True if the interface was closed successfully
Example:
if grand_exchange:opened() then
grand_exchange:close()
end
available_slot
grand_exchange:available_slot() -> GrandExchangeOffer?
Gets the first available (empty) offer slot.
Returns:
GrandExchangeOffer?- The first empty slot, or nil if all slots are full
Example:
local slot = grand_exchange:available_slot()
if slot then
logger:info("Empty slot found: " .. slot:index())
else
logger:warn("All slots are full")
end
active_offers
grand_exchange:active_offers() -> table
Gets all active (in progress) offers.
Returns:
table- Array of GrandExchangeOffer objects that are currently in progress
Example:
local active = grand_exchange:active_offers()
logger:info("Active offers: " .. #active)
for _, offer in ipairs(active) do
local progress = offer:current_quantity() .. "/" .. offer:total_quantity()
logger:info("Active: " .. offer:name() .. " (" .. progress .. ")")
end
completed_offers
grand_exchange:completed_offers() -> table
Gets all completed offers ready to collect.
Returns:
table- Array of GrandExchangeOffer objects that are complete
Example:
local completed = grand_exchange:completed_offers()
logger:info("Completed offers: " .. #completed)
for _, offer in ipairs(completed) do
logger:info("Ready to collect: " .. offer:name())
end
aborted_offers
grand_exchange:aborted_offers() -> table
Gets all aborted/cancelled offers.
Returns:
table- Array of GrandExchangeOffer objects that were aborted
Example:
local aborted = grand_exchange:aborted_offers()
for _, offer in ipairs(aborted) do
logger:info("Aborted: " .. offer:name())
end
has_completed_offers
grand_exchange:has_completed_offers() -> boolean
Checks if there are any completed or aborted offers ready to collect.
Returns:
boolean- True if there are offers ready to collect
Example:
if grand_exchange:has_completed_offers() then
logger:info("Collecting completed offers...")
grand_exchange:collect_all_to_bank()
end
view_offer
grand_exchange:view_offer(index: number) -> boolean
Opens the details view for an offer.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
index | number | Yes | Slot index (0-7) |
Returns:
boolean- True if the offer details were opened successfully
Example:
local offer = grand_exchange:offer(0)
if offer and offer:is_in_progress() then
grand_exchange:view_offer(0)
end
abort_offer
grand_exchange:abort_offer(index: number) -> boolean
Aborts/cancels an offer.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
index | number | Yes | Slot index (0-7) |
Returns:
boolean- True if the offer was aborted successfully
Example:
local offer = grand_exchange:offer(0)
if offer and offer:is_in_progress() then
logger:info("Aborting offer: " .. offer:name())
grand_exchange:abort_offer(0)
end
collect_offer
grand_exchange:collect_offer(index: number) -> boolean
Collects items from a completed or aborted offer to inventory.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
index | number | Yes | Slot index (0-7) |
Returns:
boolean- True if the offer was collected successfully
Example:
local offer = grand_exchange:offer(0)
if offer and offer:is_complete() then
logger:info("Collecting: " .. offer:name())
grand_exchange:collect_offer(0)
end
buy
grand_exchange:buy(filter: ItemFilter, opts: table) -> GrandExchangeOffer?
Buys an item from the Grand Exchange using item definition filters. Automatically opens the interface, searches for the item, sets quantity and price, and confirms the offer.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | ItemFilter or table | Yes | Item filter to find the item to buy (e.g., {id = 440} or {name = "Iron ore"}) |
opts | table | Yes | Options table with amount (number) - The quantity to buy, and price (number) - The price per item in gp |
Options (opts table):
amount(number) - The quantity to buyprice(number) - The price per item in gp
Returns:
GrandExchangeOffer?- The offer slot if successful, nil otherwise
Example:
-- Buy 1000 iron ore at 200 gp each using item ID filter
local offer = grand_exchange:buy({id = 440}, {amount = 1000, price = 200})
if offer then
logger:info("Buy offer placed in slot " .. offer:index())
else
logger:warn("Failed to place buy offer")
end
-- Buy using item name filter
local offer = grand_exchange:buy({name = "Iron ore"}, {amount = 1000, price = 200})
sell
grand_exchange:sell(filter: ItemFilter, opts: table) -> GrandExchangeOffer?
Sells an item to the Grand Exchange using item filters. The item must be in your inventory. Automatically opens the interface, finds the item in inventory, sets quantity and price, and confirms the offer.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | ItemFilter or table | Yes | Item filter to find the item to sell (e.g., {id = 440} or {name = "Iron ore"}) |
opts | table | Yes | Options table with amount (number, optional) - The quantity to sell (default: sell all), price (number, optional) - The price per item in gp (default: use guide price), and price_reduction_percent (number, optional) - Price reduction percentage from guide price (e.g., 5.0 = 5% reduction) |
Options (opts table):
amount(number, optional) - The quantity to sell (default: sell all)price(number, optional) - The price per item in gp (default: use guide price)price_reduction_percent(number, optional) - Price reduction percentage from guide price (e.g., 5.0 = 5% reduction)
Returns:
GrandExchangeOffer?- The offer slot if successful, nil otherwise
Example:
-- Sell 1000 iron ore at 200 gp each using item ID filter
local offer = grand_exchange:sell({id = 440}, {amount = 1000, price = 200})
if offer then
logger:info("Sell offer placed in slot " .. offer:index())
else
logger:warn("Failed to place sell offer")
end
-- Sell using item name filter with price reduction
local offer = grand_exchange:sell({name = "Iron ore"}, {price_reduction_percent = 5.0})
collect_all_to_inventory
grand_exchange:collect_all_to_inventory() -> boolean
Collects all completed and aborted offers to inventory.
Returns:
boolean- True if collection was successful
Example:
if grand_exchange:has_completed_offers() then
logger:info("Collecting all offers to inventory...")
grand_exchange:collect_all_to_inventory()
end
collect_all_to_bank
grand_exchange:collect_all_to_bank() -> boolean
Collects all completed and aborted offers directly to bank.
Returns:
boolean- True if collection was successful
Example:
if grand_exchange:has_completed_offers() then
logger:info("Collecting all offers to bank...")
grand_exchange:collect_all_to_bank()
end
sell_all
grand_exchange:sell_all(items: table) -> boolean
Sells items matching filters in a loop. For each item:
- Finds the first matching item from inventory (uses same ItemFilter as inventory API)
- Collects to bank if any completed offers
- Waits if all slots are full
- Sells item with specified amount and price
- Continues until no more items match
- Waits for all placed offers to complete at the end
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
items | table | Yes | An array of tables, each with filter (ItemFilter) and optional opts table |
Options (opts table):
amount(number, optional) - Quantity to sell per item (default: sell all)price(number, optional) - Fixed price per item (default: use guide price)price_reduction_percent(number, optional) - Price reduction percentage from guide price (e.g., 5.0 = 5% reduction)
Returns:
boolean- True if all items were processed successfully
Example:
-- Sell multiple item types
grand_exchange:sell_all({
{
filter = {name = "Iron ore"},
opts = {amount = 1000, price = 200}
},
{
filter = {name = "Coal"},
opts = {price_reduction_percent = 3.0}
},
{
filter = {id = 440} -- Iron ore by ID
}
})
-- Sell a single item type (still use array)
grand_exchange:sell_all({
{
filter = {name_contains = "ore"},
opts = {
price_reduction_percent = 5.0 -- Sell at 5% below guide price
}
}
})
Common Patterns
Basic Buy and Sell
-- Open Grand Exchange
if not grand_exchange:opened() then
grand_exchange:open()
wait:until(function() return grand_exchange:opened() end, 3000)
end
-- Buy items
local buy_offer = grand_exchange:buy({id = 440}, {amount = 1000, price = 200}) -- Iron ore
if buy_offer then
logger:info("Buy offer placed in slot " .. buy_offer:index())
end
-- Sell items (must be in inventory)
local sell_offer = grand_exchange:sell({id = 453}, {amount = 500, price = 300}) -- Coal
if sell_offer then
logger:info("Sell offer placed in slot " .. sell_offer:index())
end
Monitoring All Offers
local function check_all_offers()
local offers = grand_exchange:offers()
for _, offer in ipairs(offers) do
if offer:valid() then
if offer:is_available() then
logger:info("Slot " .. offer:index() .. ": [Empty]")
elseif offer:is_complete() then
logger:info("Slot " .. offer:index() .. ": " .. offer:name() .. " - COMPLETE")
elseif offer:is_in_progress() then
local current = offer:current_quantity()
local total = offer:total_quantity()
local percent = math.floor((current / total) * 100)
logger:info("Slot " .. offer:index() .. ": " .. offer:name() .. " - " .. percent .. "%")
end
end
end
end
check_all_offers()
Auto-Collect Completed Offers
local function auto_collect()
if grand_exchange:has_completed_offers() then
logger:info("Collecting completed offers...")
-- Collect to bank (recommended for large quantities)
if grand_exchange:collect_all_to_bank() then
logger:info("All offers collected to bank")
else
logger:warn("Failed to collect offers")
end
end
end
-- Run periodically
while script_running() do
auto_collect()
sleep(5000) -- Check every 5 seconds
end
Wait for Offer Completion
local function wait_for_offer_completion(offer_index, timeout_ms)
local start = os.time()
timeout_ms = timeout_ms or 300000 -- Default 5 minutes
while (os.time() - start) * 1000 < timeout_ms do
local offer = grand_exchange:offer(offer_index)
if not offer or not offer:valid() then
logger:warn("Offer became invalid")
return false
end
if offer:is_complete() then
logger:info("Offer completed!")
return true
end
if offer:is_aborted() then
logger:warn("Offer was cancelled")
return false
end
sleep(1000) -- Check every second
end
logger:warn("Offer timed out")
return false
end
-- Place offer and wait
local offer = grand_exchange:buy({id = 440}, {amount = 1000, price = 200})
if offer then
wait_for_offer_completion(offer:index(), 300000)
end
Bulk Selling with Filters
-- Sell all ores at 5% below guide price
grand_exchange:sell_all({
{
filter = {name_contains = "ore"},
opts = {
price_reduction_percent = 5.0
}
}
})
-- Sell multiple specific items
grand_exchange:sell_all({
{
filter = {name = "Iron ore"},
opts = {amount = 1000}
},
{
filter = {name = "Coal"},
opts = {amount = 500}
},
{
filter = {id = 447}, -- Mithril ore
opts = {price = 500}
}
})
Managing Full Slots
local function wait_for_slot(timeout_ms)
timeout_ms = timeout_ms or 30000 -- Default 30 seconds
local start = os.time()
while (os.time() - start) * 1000 < timeout_ms do
if grand_exchange:available_slot() then
return true
end
sleep(1000)
end
return false
end
-- Check before placing offer
if not grand_exchange:available_slot() then
logger:info("All slots full, waiting...")
if wait_for_slot(30000) then
logger:info("Slot available!")
else
logger:warn("Timeout waiting for slot")
end
end
Abort Slow Offers
local function abort_slow_offers(min_progress_percent)
min_progress_percent = min_progress_percent or 10
local active = grand_exchange:active_offers()
for _, offer in ipairs(active) do
local current = offer:current_quantity()
local total = offer:total_quantity()
local percent = (current / total) * 100
if percent < min_progress_percent then
logger:info("Aborting slow offer: " .. offer:name() .. " (" .. percent .. "%)")
grand_exchange:abort_offer(offer:index())
sleep(600)
end
end
end
-- Abort offers with less than 10% progress
abort_slow_offers(10)
Complete Trading Loop
local function trade_loop()
-- 1. Collect any completed offers
if grand_exchange:has_completed_offers() then
grand_exchange:collect_all_to_bank()
end
-- 2. Check for available slot
if not grand_exchange:available_slot() then
logger:info("All slots full, waiting...")
return
end
-- 3. Open GE if needed
if not grand_exchange:opened() then
grand_exchange:open()
wait:until(function() return grand_exchange:opened() end, 3000)
end
-- 4. Place buy offer
local offer = grand_exchange:buy({id = 440}, {amount = 1000, price = 200})
if offer then
logger:info("Buy offer placed in slot " .. offer:index())
end
end
while script_running() do
trade_loop()
sleep(10000) -- Run every 10 seconds
end
GrandExchangeOffer Methods
Each GrandExchangeOffer object has methods to access offer properties:
-
Basic Info
index()→ numberitem_id()→ numbername()→ stringunit_price()→ numbertotal_quantity()→ numbercurrent_quantity()→ number
-
State Checks
valid()→ booleanis_available()→ booleanis_sell()→ booleanis_in_progress()→ booleanis_complete()→ booleanis_aborted()→ booleanstate()→ string
See GrandExchangeOffer type documentation for complete method list.
Related APIs
- GrandExchangeOffer Type - Offer object documentation
- Inventory API - Inventory management
- Bank API - Bank management