Remembers what is in your bank so you can look at it from anywhere — in whichever bank window you already use, not a window of its own.
For World of Warcraft 1.12 clients: Turtle WoW, Ravencraft, and vanilla private servers generally. Nothing in it is server specific.
Download the zip from Releases, extract it into
World of Warcraft/Interface/AddOns/
so that you end up with Interface/AddOns/Stash/Stash.toc, and restart the
game. No dependencies.
Visit a bank once so there is something to remember, then click the minimap
button (or /stash) from anywhere.
Bank contents are only readable while you are standing at a bank, so Stash records them whenever the bank window opens, changes and closes. That part is unremarkable.
The interesting part is how the copy gets shown. Instead of drawing a custom frame, Stash wraps the container and inventory API:
GetContainerNumSlots GetInventoryItemTexture
GetContainerItemInfo GetInventoryItemLink
GetContainerItemLink GetInventoryItemCount
GetContainerItemCooldown GetInventoryItemCooldown
GetNumBankSlots IsInventoryItemLockedWhile the cached view is open, those functions answer from the cache for bank
containers only — container -1 and bank bags 5 to 10. Everything else
falls straight through untouched.
Blizzard's BankFrame reads exactly those functions, so it renders the cache
without knowing this addon exists. So does any other bag addon that asks the
same questions, which is the point: you keep whichever bag UI you already use.
The wrappers check a flag rather than being installed and removed, so they are inert when the view is closed and an error can never strand the game answering from stale data.
Drawing the slots is not enough to explain them. GameTooltip:SetBagItem and
GameTooltip:SetInventoryItem resolve the slot inside the client, so they
never reach the Lua functions above and come up empty away from the bank. Both
are therefore replaced too, and build the tooltip from the stored item link when
the slot is a cached bank slot. That covers Blizzard's bank buttons, Bagnon
(which calls SetInventoryItem for bank slots), and anything else going through
the normal calls.
The link has to be in the client's item cache for the tooltip to fill in — an item the client has never seen this session may come up bare. That is a vanilla limitation, not something the addon can work around.
Two more details worth knowing:
- Hiding
BankFramenormally callsCloseBankFrame(), which talks to a bank you are not standing at. That is swallowed while the cached view is up. - Opening a real bank immediately drops the cached view, so you never see a copy in front of the live window.
Showing Blizzard's BankFrame is only right when that is what you see at a real
bank. A backend describes somebody else's bank window, and the highest
priority one that is actually loaded wins:
| Backend | Window | Notes |
|---|---|---|
bagnon |
Bagnon's Banknon | Bagnon keeps its own bank cache and shows that; Stash just opens it |
blizzard |
BankFrame |
the fallback, and correct for bag addons that replace the bags but not the bank |
EngInventory has no bank window at all — it replaces the bags and leaves the
bank to Blizzard — so blizzard is what its users see at a real bank too, and
what Stash opens.
/stash ui shows what is available, /stash ui <name> pins one, /stash ui auto goes back to picking automatically.
A backend that keeps its own cache gets the API diversion switched off while it is in use, so the screen only ever has one source of truth on it.
Adding one for another bag addon is a few lines — see the header of
backends.lua.
| minimap button, left click | your cached bank |
| minimap button, right click | the cached guild bank |
| drag the button | move it around the minimap |
| Command | Effect |
|---|---|
/stash |
show your cached bank |
/stash bank <name> |
show another character's cached bank |
/stash guild |
show the cached guild bank |
/stash list |
what is cached |
/stash ui |
choose which bank window to open |
/stash probe |
report this client's guild bank support |
/stash reset |
wipe the cache |
The cache is account-wide per realm, so alts you have banked on are available
through /stash bank <name>.
Vanilla 1.12 has no guild bank — it arrived in patch 2.3 — so whether this
one exists is a property of the client, not something that can be assumed.
Everything guild bank related is feature detected at load against the standard
API and stays completely dormant when it is missing. Run /stash probe to see
what your client actually exposes.
Where the API is present, the flow mirrors the player bank: tabs are queried and
cached while the guild bank window is open (one tab at a time, since the server
rate limits those requests), then replayed through Blizzard's GuildBankFrame
by diverting GetGuildBankItemInfo and friends the same way.
Stash.viewing -- character being shown, nil when the view is closed
Stash.offline -- true while the API is being diverted to the cache
Stash.backend -- the backend showing it
Stash.gboffline -- same for the guild bank
table.insert(Stash.callbacks, function(state, name) end) -- "open" / "close"
Stash:RegisterBackend({ ... }) -- add a bank windowRepainting on open is only needed if your frame caches item data itself; if it
reads the container API on demand it already works.
| File | |
|---|---|
core.lua |
saved variables, shared helpers, slash commands |
cache.lua |
captures the bank on open, change and close |
shim.lua |
the container/inventory API wrappers |
tooltip.lua |
the same for GameTooltip, which resolves slots in the client |
backends.lua |
the bank windows that can be opened, and picking between them |
viewer.lua |
turns the cached view on and off |
guildbank.lua |
the same for the guild bank, if the client has one |
minimap.lua |
the button |
Vanilla enumerates an addon's files when the client starts. /reload re-runs
the list it already has, so an edited file comes back but a newly added one
stays missing — the addon then runs half-loaded.
So after an update that adds a file, exit to desktop and start the game again. Stash checks its own modules at login and says so if any are missing, and falls back to the default bank window rather than erroring.
Everything it calls is stock 1.12 client and FrameXML — the container and
inventory getters, BankButtonIDToInvSlotID, ContainerIDToInventoryID, the
BankFrame* widgets, GameTooltip:Set*. No SuperWoW, no nampower, no server
specific API, no addon dependencies. So it runs on any 1.12 client.
It will not work on Classic Era (1.14+), which dropped the this/event
handler model and moved containers to C_Container. TBC and WotLK clients
would likely need little more than a ## Interface bump, but that is untested.
The guild bank half is feature detected at runtime and stays dormant on clients without one — see above.
- Only the bank is cached. Bags and equipped items are live anyway.
- The copy is as fresh as your last visit; nothing updates it from a distance.
- Items cannot be moved in the cached view — it is a picture, not the bank.
- The bank buttons are painted directly rather than through
BankFrameItemButton_Update, which does not exist on every 1.12 derived client. Everything else in FrameXML is called only when present.
MIT — see LICENSE.