Flipping Utilities is a Runelite plugin that aids over 50,000 players in making investing more profitable and enjoyable. It calculates your profits in real time, keeps a richly detailed log of your trading activity, lets you quickly input optimal prices according to your margin checks with just a key press, and a lot more!
old repo: https://github.com/Belieal/flipping-utilities
Join the community on discord at https://discord.gg/GDqVgMH26s, it's one of the largest trading related communities for OSRS!
Our discord also offers access to various powerful tools such as item dump alerts allowing you to buy items at greatly deflated prices and a lot more!
The plugin is divided into three tabs: the slots tab, flipping tab and statistics tab.
This tab displays info most relevant to you when actively flipping
The item cards are highly customizable, allowing you to pick what information to show in which section.
This tab records your trading history, down to every single individual offer you made.
The item cards can be expanded
The trade history for each item can be expanded to see the offers:
And the flips:
Sometimes, flips aren't straightforward selling and buying of the same item - they involve combining several items into one or transforming an item into another. For accurately capturing the profits for these complicated trades, you can create a "recipe flip".
Go to your offers for an item in the stats tab. If there is a recipe for that item, a recipe flip button will be present on the offer card. Click it and select the appropriate recipe
adjust the inputs and outputs if necessary, then combine
view your recipe flips in the "recipes" tab of the stats tab
Slot timers help you figure out when you should cancel an offer. They show you how long it has been since the offer was last active.
The price and quantity help you set up your offers quickly!
Flip on mobile and have untracked trades? Just pop open your ge history and easily add untracked trades
Quickly lookup your favorited items just by typing "1" in the ge search!
This section will talk about the purpose of various parts of the codebase, specifically the folders.
controller/
startUp
method, which is run on client startup. Each of these classes handles a specific
responsibility of the plugin. For example, the NewOfferEventPipelineHandler
is responsible for consuming new offer
events and adding it to the data structures that model a user's trade history. The classes are used via the FlippingPlugin
calling their methods. For example, when the FlippingPlugin gets an offer event in the onGrandExchangeOfferChanged
method it calls newOfferEventPipelineHandler.onGrandExchangeOfferChanged(newOffer);
.
Much of the logic in these controller classes used to live in the FlippingPlugin class but was moved out as the
FlippingPlugin class had become huge and was doing too many things.model/
db/
ui/
jobs/
utilities/
This section will give an example of how the plugin actually runs and what happens during its lifetime. Much more detail can be added to this section, which I will hopefully get to sometime...
The starting point to this plugin is the FlippingPlugin class. On Runelite startup, the Runelite code will create an
instance of the FlippingPlugin class and then call its startUp()
method.
The FlippingPlugin does three main things on startup (all in the startUp()
method):
Now things have been setup properly, and the UI has been drawn and populated with the user's previously saved data from disk.
During the lifetime of the Runelite Client (between startup and shutdown), there are primarily three ways the plugin does work
onGrandExchangeOfferChanged
on the FlippingPlugin class and passing that method a GrandExchangeOfferChanged
object.
It knows to do this because of method naming conventions. You don't have to define a method to handle every possible
type of Runelite event, just the ones your plugin should care about.The Runelite client will tell the plugin when it's shutting down and will allow it to execute some code before
that happens. This occurs in onClientShutdown
in the FlippingPlugin class. Not much happens other than saving
user data to disk and cancelling any background jobs that were running.
This section describes how the plugin models users' trade history. The main model classes used to do this are: AccountData, FlippingItem, HistoryManager, and OfferEvent.
When you go to .runelite/flipping/<username>.json
and open it, you will see the JSON version of an AccountData
object. Each of the user's osrs accounts get their own AccountData object, each of which is stored in a file
of the format .runelite/flipping/<account_username>.json
.
AccountData objects are created from the JSON in those files on client startup (or created on account login if they have no previously saved data for that account). As the user makes trades, deletes trades via the UI, and so on, the AccountData object for the correct account is mutated. Then, on account logout or client shutdown, it is turned back into JSON and saved into the same file it was loaded from (or creates a new file if there was no previously saved data).
The AccountData object's most important field is List<FlippingItem> trades
. This field contains FlippingItem objects.
FlippingItem objects have an itemId (every runescape item has a unique number to identify it) and represents the trade history
for that item on that account. So, for example, if you flipped dragon claws on an account, you would have one and only one
FlippingItem in that account's AccountData object that holds all the buy and sell offers you have ever made for dragon
claws on that account.
The FlippingItem stores all the offers for that item in the HistoryManager history
field. Put simply, a HistoryManager
is just a list of OfferEvent. An OfferEvent represents a buy and sell offer in which some amount of an
item bought or sold. It has various fields like price, quantity, etc.
I mentioned above that handling RL events that reflect a state of change in the game is one of the main responsibilities of the code. The most important event is the GrandExchangeOfferChanged event which we convert into an OfferEvent and send to various components to consume (such as the HistoryManager which adds it to an account's trade history) and eventually persist to disk.
GrandExchangeOfferChanged are sent to the plugin in strange ways that need elaboration, which i've done here https://docs.google.com/document/d/1o-nHpUV8Gp3nRQSt2LiRlYVqRcPSiycFfWlM0IFgytI/edit?usp=sharing.
All icons were either made by Belieal or downloaded from the creators on www.flaticon.com below.
If you notice any bugs or have any suggestions, let us know by making an issue or PM us on Discord @ gamersriseup#4026 or Anyny0#4452! I'm also happy to answer any questions that you may have. :)