First of all, you wont find any download in this thread. This thread will contain general informations about the trading post from a technically view and how one can utilize those informations to extend or build your very own trading post. Notice though, that this is not a step by step guide. Instead I will only point out the required informations.
In autuum 2012 the GW2CA team reversed the trading post resulting in a small proof of concept extension allowing unlimited buy orders which was quite handy for trading materials. While we never released that very early version only used by a small group of peopel, we always wanted to write a public fully fledged "extended" trading post capable of showing graphs and similiar things. Well, the time ran by and we never were in the mood to continue work. Now totally occupied by implementing GW2CA its clear to us that we will also never find the time to finish this little project, not now and not in the future. Therefore we hope that some interessted developers will read this thread and continue our work. Maybe some day we will see an really cool public TP overhaul.
Here are some screens of this proof of concept extension showing newly added components aswell as modified ones:
What can be done?
With the informations provided in this thread you can either add, change, replace components of the trading post, or write your own complete overhaul. Writing a trading bot is not possible, as selling and taking items is done via ingame packets and not REST requests. This is not covered in this thread.
How the TP works
The TP is actually a simple website also accessable with your browser. In order to buy items or query information REST requests are sent. The GW2 client uses the
framework to render websites. Under the hood Awesomium is an offscreen port of Chromium.Two things are not mentioned yet: In order to access the TP you have to be authenticated, typically done with a cookie holding the session id. This session is created by the portal server on login and can be attached to a character. An unattached session is sufficient to access the TP and can be obtained from
, you wont be able to buy items with that one though.A feature making the TP special is, that through a JS proxy (window.externalHost) the web-client can directly communicate with the game-client in a REST like fashion. Those request will will result in native calls and are used to query informations like gold, gems, xp or the items possed by the character. Due to that, only a subset of the TP will work if you access it with your regular browser, even with an attached session.
Now, lets finally come to the TP itself. The TP uses the
library from Yahoo. This is a very modular framework, quite handy for us, as it allows us to inject our custom modifications in a very simple manner. The JS code of the TP is obfuscated and compressed making it very hard to read. Though by looking on the REST requests and debuging its still possible to get things running. If you really want to write a serious extension I recommend you to rewrite the TP though, as the obfuscated code is a pain in the ass to maintain.Useful tools
Besides the regular disassemblers like OllyDbg and IDA, two tools have proven useful for this project.
The first one to mention is
. Fiddler will capture all your web traffic and allows you to analyze the sites involved and the REST requests sent. Once you get used to it, you will never want to work without it again.The second one is actually well known, the browser
. Now wait, why should Chrome be useful for reversing? The answere is quite simple: Rember me saying that Awesomium is based on Chromium? Well, Awesomium comes with an remote debugging feature allowing you to use the Chrome Developer Tools for the TP. This is very handy for debugging Arenanets original and your own JS code. You have to enable this feature though. The dll I wrote for this purpose has broken long time ago but I will shortly explain what you have to do to enable it. Basically the only thing to be done is to set remote_debugging_port of
. The thing making it a bit tricky is, that you have to modify it in the call to
. The problem: The method is called after hitting launch; at this point (in the launcher) awesomium isnt loaded though. The solution: Patch the actual call to point to your function and call the original method in there. Last but not least, the inspector.pak (contained in the awesomium sdk) must be placed into awesomiums working directory, typically in your temp folder starting with gw2cache-. Well back in autuum 2012, the path of this directory once created hasnt changed, so placing the file once should be enough. After all this has been done, you can start debugging by accessing localhost:debugPort in Chrome.You probably will also find this little website useful to demangle names when you want to set breakpoints:

The concept
Its actually quite easy to build your own TP. Three steps have to be done:
- Redirect requests from the client to your own server
- Fetch the original site from Arenanets servers
- Inject your custom JS code
Code:
---- redirected ----> ------->
GW2 Client Your Server TP Server
<--- modified ------------------- <-------
^
|
|
Custom.js
Redirecting the traffic
This can be done in several ways:
- You can hook the UI code
- You can hook the awesomium methods
- You can change the host file
For both the 1) and the 2) method the best starting point is probably the Awesomium::WebString or Awesomium::WebUrl constructor. Walking up the callstack only by 1 and your in the right method. Pretty easy to reverse as you can simply see the URLs on the stack and in the registers. Just make sure to disable the breakpoints temporaly if you only get trash as Awesomium::WebString is of course used for alot of other stuff too.
The 3) method is probably more stable regarding patches. I dont think that I have to explain here how it is done exactly, simply google it up.
Handling the request
Notice that we used an apache webserver and php. Although you should be able to implement this on any other webserver with any other scripting language you might want to use easily.
The first thing we did was actually setting up a RewriteRule so that every GET requests is handled by a single script called "get.php". Only requests to "authenticate" are handled in a special way.
Code:
RewriteCond %{REQUEST_URI} ^/authenticate
RewriteRule .* authenticate.php
RewriteCond %{REQUEST_METHOD} ^(GET)$
RewriteRule !^(get.php)$ get.php [L]
Code:
<?php
$s = $_GET['session_key'];
$loc = $_GET['source'];
header("HTTP/1.1 303 Redirection");
header("Location:" . $loc);
header("Set-Cookie: s=" . $s);
?>
Code:
$reqURI = $_SERVER['REQUEST_URI'];
$host = $_SERVER['HTTP_HOST'];
$headers = "Cookie: s=" . $_COOKIE['s'] . "\r\n";
if($_SERVER['HTTP_REFERER'] != ""){
$headers = $headers . "Referer: " . str_replace("http://www.our-host.com","https://tradingpost-live.ncplatform.net",$_SERVER['HTTP_REFERER']) . "\r\n";
}
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>$headers
)
);
$context = stream_context_create($opts);
$tpAdr = "https://tradingpost-live.ncplatform.net" . $reqURI;
$raw = file_get_contents($tpAdr,false,$context);
Now we simply check $reqURI whether we have to inject our scripts and after doing so we send the (probably modified) response back to the client.
Injecting the custom scripts
Now this is the point where you probably want to thank god that Arenanet uses YUI. All you have to do is to add an additional <script> tag refering to your custom script. To add it in the right place, you can simply use str_replace:
Code:
$injectionPoint = '<script src="https://d3eye159mg2h6m.cloudfront.net/combo/_/js/_config.1126439568.4.js"></script>'; $yuiInjection = '<script src="http://our-host.com/custom.js"></script>'; $yuiInjection .= $injectionPoint $domInjected = str_replace($injectionPoint,$yuiInjection,$raw); echo $domInjected;
Code:
YUI.add("gw2-template-buy-instant", function(Y) {
var tmpl = Y.Handlebars.template(function(Handlebars, depth0, helpers, partials, data) {
helpers = helpers || Handlebars.helpers;
var buffer = "", stack1, stack2, foundHelper, self = this, functionType = "function", helperMissing = helpers.helperMissing, undef = void 0, escapeExpression = this.escapeExpression;
// Writes a simple header and increases the limit of the input.
// This corrsponds to the first screenshot seen in this thread.
buffer += "<div><h3 class=\"infiny\">Infiny Buy: </h3></div>\r\n";
buffer += "<h5>\r\n ";
// Code to resolve localized strings:
stack1 = "tp.buy.quantity";
foundHelper = helpers.i18n;
stack2 = foundHelper || depth0.i18n;
if (typeof stack2 === functionType) {
stack1 = stack2.call(depth0, stack1, {hash: {}});
}
else if (stack2 === undef) {
stack1 = helperMissing.call(depth0, "i18n", stack1, {hash: {}});
}
else {
stack1 = stack2;
}
buffer += escapeExpression(stack1) + "\r\n <input\r\n type=\"text\"\r\n data-type=\"number\"\r\n class=\"yui3-u infiny-input\"\r\n min=\"1\"\r\n max=\"" + BUY_MAX + "\"\r\n maxlength=\"6\"\r\n placeholder=\"1\"\r\n value=\"1\"\r\n />\r\n</h5>\r\n\r\n<div class=\"total yui3-g\">\r\n <p class=\"yui3-u\">";
// Further tags have been removed for simplicity
return buffer;
});
Y.namespace("GW2.Templates")["buy-instant"] = tmpl; // store the template in a global map
Y.Handlebars.registerPartial("buyInstant", tmpl); // register the template
}, "", {requires: ["handlebars-base"]});
I think the basic principle should be understood now. Copy Arenanets modules, modifiy or re-implement them and your done. By re-registering, yours and not Arenanets modules are loaded.
The "point of injection" is actually the very last import. You might want to search for it in a different manner (as a quick look reveals that the scriptname has changed now) or simply choose another one. Back in autuum I havent found anything about how YUI loads their modules concretly, especially in the case that some are defined multiple times. Therefore, you might want to play with this a bit.
When reversing the js code its always useful to start with the REST requests as the parameters are known and you can then traverse them back. To take a look at them, simply open Fiddler or browse through the gw2spidy src. On ********* you will also find a long discussion regarding the TP.
The Chrome Developer Tools are extremly useful for reversing the obfuscated js as mentioned above and it really worths activating remote debugging, especially if you plan a bigger and serious project.
Oh and you might ask yourself how do I get the original files? Simply intercept the GET request using Fiddler and copy it into your browser. Equipped with a valid session id you can now inspect the TP with Firebug or the Chrome Developer Tools. They even added a nice background (better than the plain white wall they had back then).
A note on overhauls and other concepts
If you want to write a complete overhaul you probably go better by completly focusing on the REST requests, including those sent to the client. There arent too many and its for sure easier to reimplement them instead of working through compressed and obfuscated code.
Besides that, this removes the additonal delay arising from the two GET requests. This could also be omitted by injecting the js files at clientside. For this you probably have to dig into the core of Awesomium though, which is, as far as im am aware of, not public.
Other methods omitting this delay I came up with are to run the server locally, or to intercept the traffic like Fiddler does (it would acutally be possible to write the whole injection based on Fiddlers scripting capabilities, but i guess you dont want your users to run Fiddler
Conclusion
I hope that this thread will give you an quick overview about the TP and how to extent it. Please be kind if I didnt go too much into detail at some points but this thread is already yet quite long and the last time I dealt with this topic was some months ago. Im eager to see some progress on this






