-
Notifications
You must be signed in to change notification settings - Fork 0
Trade Bridge PT
O Trade Bridge permite que uma extensão de navegador faça todo o trabalho no site de trade (live search, fetch, whisper), enquanto o POEFixer faz apenas a compra dentro do jogo. Assim, todo o tráfego com o site de trade fica dentro da sua sessão real de navegador — sem copiar cookies, sem dor de cabeça com cf_clearance — e é a base para um futuro modo "rodar o POEFixer em outro PC".
Você pode usar a extensão oficial gratuita ou criar a sua própria seguindo o protocolo documentado abaixo.
O Trade Bridge exige que sua licença POEFixer tenha o recurso Trade. Se o Trade estiver configurado como pago no servidor, você precisa de uma chave válida; se for gratuito, qualquer um pode usar. Sem direito de acesso, o bridge responde
entitlement_requirede recusa as compras.
Browser extension POEFixer
live-search WebSocket ─┐
fetch item details │ ws://127.0.0.1:PORT in-game buying:
whisper (teleport) ├─────────────────────► wait teleport → click → verify
(Force teleport, │ buy_request → auto-stash → /hideout
In-demand retry, │ ◄───────────────────── → report result
Rate limiting) ─┘ buy_result
- A extensão controla tudo o que toca o site de trade.
- O POEFixer controla tudo no cliente do jogo e expõe um servidor WebSocket local (o Trade Bridge) ao qual a extensão se conecta.
- Nesse modo, o
tls-clientembutido do POEFixer não é usado, e os controles do site de trade (Connections, Trade Cookies, Force teleport, In-demand, Rate limiting) migram para a extensão e ficam ocultos/desativados no POEFixer.
A extensão vem dentro do POEFixer. Na sua pasta do POEFixer, abra Resources\extension\:
<POEFixer folder>\Resources\extension\
├─ poefixer-extension-chrome.zip ← Chrome / Edge
├─ poefixer-extension-firefox.zip ← Firefox
└─ chrome\ ← unpacked copy used by the "Assisted install" button
Uma instalação totalmente silenciosa em um clique não é possível — os navegadores bloqueiam a instalação programática de extensões por design. Você descompacta o arquivo do seu navegador e o carrega uma vez. O botão Assisted install… do POEFixer (Configuration → Trade) faz a parte do Chrome/Edge por você: copia o caminho da pasta descompactada
chrome\para a área de transferência e abre este guia, para que você possa pular a descompactação.
-
Descompacte
Resources\extension\poefixer-extension-chrome.zipem qualquer pasta (de modo quemanifest.jsonfique na raiz dela). Ou clique em Assisted install… no POEFixer e use o caminho copiado — então pule para o passo 4. - Abra
chrome://extensions(Edge:edge://extensions). - Ative o Modo de desenvolvedor (canto superior direito).
- Clique em Carregar sem compactação e selecione essa pasta (ou cole o caminho do Assisted install).
- O ícone da extensão aparece na barra de ferramentas; ele permanece carregado entre reinicializações.
Após uma atualização do POEFixer, a extensão incluída é renovada — abra
chrome://extensionse clique em Recarregar no card da extensão para aplicar a nova versão (ou descompacte de novo e use Carregar sem compactação).
O Firefox de release só instala extensões assinadas pela Mozilla, então use o carregamento temporário:
-
Descompacte
Resources\extension\poefixer-extension-firefox.zipem qualquer pasta. - Abra
about:debugging#/runtime/this-firefox. - Clique em Carregar complemento temporário… e escolha o
manifest.jsonda pasta descompactada. - Ele permanece carregado até você reiniciar o Firefox (repita após reiniciar).
-
Permanente: instale um
.xpiassinado pela Mozilla/AMO abrindo-o no Firefox e confirmando o aviso de permissão.
- No POEFixer: Configuration → Trade → Trade data source → Browser extension, anote a Port (padrão
47362) e clique em Start bridge. - No popup da extensão, defina a mesma Port — deve aparecer Host: connected, e o status no POEFixer fica verde e mostra o nome e a versão real da extensão, por exemplo "Extension connected (PoeFixerExt/1.1.2)" (a versão vem do manifesto da extensão — uma extensão desatualizada é sinalizada aqui).
- Faça login no site de trade nesse navegador, depois adicione seus Trade Links e pressione Play (veja §3).
Tudo é controlado pelo POEFixer — o popup da extensão só define a Port de conexão.
- No POEFixer: Configuration → Trade → Data source = Browser extension, defina a Port, clique em Start bridge.
- No popup da extensão, confirme Host: connected e a mesma Port.
- Faça login no site de trade no mesmo navegador.
- Em Trade Links (aba Connections) do POEFixer, adicione suas URLs de busca trade2 e pressione Play — a busca é enviada à extensão e roda lá; Stop a remove.
- Defina o comportamento no POEFixer (Configuration → Trade): Force teleport, Item is in demand → teleport anyway, Rate limiting — o POEFixer envia esses ajustes à extensão, que apenas obedece.
- Quando um anúncio corresponde, a extensão faz o whisper e o POEFixer compra no jogo. Toda a atividade da extensão aparece nos Logs do POEFixer (categoria Trade).
Feed ao vivo confiável (automático): para cada busca ativa, a extensão abre uma aba de fundo fixada na página de trade e conecta o WebSocket ao vivo dentro dessa página (Origin correto + seus cookies de sessão — exatamente como o site faz). Basta continuar logado no site de trade; você não abre o Live Search manualmente. O Trade Link mostra Connecting… até o WS ao vivo subir, depois Live. Fechar essa aba fixada interrompe a busca.
Manual Buy (comprar uma busca em lote, agora): em vez de esperar pelos anúncios ao vivo, pressione o ícone de Carrinho de compras em qualquer Trade Link para comprar em lote imediatamente. A extensão busca os anúncios correspondentes mais baratos para aquela busca (até a quantidade de itens que você definir, respeitando os filtros de moeda daquele link), agrupa por vendedor e faz whisper + compra de cada um pelo POEFixer — aplicando os mesmos limites de gasto e auto-stash, com um único retorno ao hideout no final. Manual Buy e live search (Play) são mutuamente exclusivos: pare suas buscas ao vivo antes de iniciar um Manual Buy, e vice-versa. O botão do carrinho só fica habilitado enquanto a extensão estiver conectada.
O protocolo é JSON puro sobre um WebSocket. Qualquer um pode implementá-lo. O POEFixer hospeda o servidor; seu cliente se conecta a ws://127.0.0.1:<port> (padrão 47362, configurável em Settings).
O host só honra compras quando sua licença tem o direito de acesso Trade. Caso contrário, você recebe
{"type":"error","code":"entitlement_required"}. (Os detalhes de autenticação não são documentados de propósito.)
Envie hello primeiro; o host responde welcome.
-
versioné a versão do manifesto da extensão (string semver, ex.:"1.1.0"). Se sua extensão for mais antiga que a versão que o POEFixer espera, ele detecta a divergência, suprime as buscas ao vivo e desativa a compra até você reinstalar a extensão mais recente. O POEFixer mostra um aviso em Settings → Trade. Uma compra tentada enquanto desatualizada recebe{"type":"error","code":"outdated_extension"}. -
allowed:false→ sem direito de acesso (trate como "compre uma chave"); o host rejeitará as compras comentitlement_required. -
tokensó é necessário se o usuário ativou um token de pareamento no POEFixer (desligado por padrão).
Após welcome (e sempre que o usuário mudar qualquer coisa no POEFixer), o host envia uma mensagem config. O programa é a única superfície de controle, então sua extensão deve monitorar exatamente estas buscas e obedecer este comportamento:
// host → client
{ "type":"config",
"behavior":{ "forceTeleport":false, "inDemandRetry":true, "rateLimit":true },
"searches":[ { "realm":"poe2", "league":"Standard", "searchId":"…", "note":"…" } ] }O host envia status periodicamente:
{ "type":"status", "ready":true, "inGame":true, "attached":true, "busy":false }Você DEVE fazer whisper/teleport somente quando o último status.ready === true. ready = entitled && attached && in-game && !busy. Fazer whisper sem estar ready teleporta o personagem sem nenhum comprador conduzindo o trade.
Depois que seu whisper for bem-sucedido (o personagem está se teleportando), envie buy_request:
// client → host
{ "type":"buy_request", "id":"r-42", "seq":7,
"group":{
"searchId":"…", "groupId":"g-9", "isLastGroup":true,
"items":[ {
"itemId":"...", "stashX":3, "stashY":1, "w":1, "h":1,
"currency":"chaos", "amount":50,
"seller":"AccountName", "stashName":"~price 50 chaos",
"name":"...", "typeLine":"...", "baseType":"...", "rarity":"Rare",
"iconUrl":"https://...", "ilvl":82, "corrupted":false, "identified":true,
"explicitMods":[ "..." ], "implicitMods":[ "..." ],
"league":"Standard", "realm":"poe2",
"hideoutToken":"...", "indexedTime":"..."
} ] } }O host confirma com ack, opcionalmente emite progresso e depois um único resultado:
{ "type":"ack", "ackSeq":7 }
{ "type":"buy_progress", "id":"r-42", "phase":"teleporting" }
{ "type":"buy_result", "id":"r-42", "seq":11,
"items":[ { "itemId":"...", "ok":true, "reason":"verified" } ],
"summary":{ "bought":1, "failed":0 } }-
group.searchIdé a busca de onde o anúncio veio; o host o usa para vincular a compra ao Trade Link correto (recorre à primeira busca ativa se omitido). Envie-o para o comportamento correto com múltiplas buscas. -
stashX/stashYsão as coordenadas do item na loja do vendedor;w/ho tamanho dele — esses valores conduzem o clique no jogo. - O preço pode ser enviado de forma plana (
currency/amount, como acima) ou aninhada ("price":{"currency","amount"}) — o host aceita ambos. -
hideoutTokené transportado apenas para logging (você já o usou para o whisper). - Você deve dar ack em cada
buy_result: envie{"type":"ack","ackSeq":<buy_result.seq>}.
Resultados da etapa de whisper (mantêm completos os logs do POEFixer):
{ "type":"trade_event", "seq":8, "stage":"whisper", "outcome":"in_demand", "itemId":"...", "detail":"" }
// outcome ∈ in_demand | whisper_failed | teleport_failed | fetch_errorUm
trade_eventtambém pode carregar o objetoitemcompleto (os mesmos campos de um item debuy_request).teleport_failed= o anúncio do vendedor ainda estava in demand mesmo após um re-whisper forçado; enviado com seuitem, o POEFixer o registra em Trade Logs como um Teleport Fail.fetch_error/whisper_failed/in_demandsão informativos e vão para os Logs gerais (categoria Trade).
Encaminhe sua atividade para o log do POEFixer (recomendado — todos os logs da extensão devem aparecer no programa):
{ "type":"log", "level":"info", "message":"…" } // shown in POEFixer Logs (category Trade)Reporte o estado do WS ao vivo de cada busca para que o Trade Link do POEFixer mostre Connecting…/Live:
{ "type":"search_status", "searchId":"…", "state":"connected" } // state ∈ connected | closed | errorQuando o usuário clica em Manual Buy (o ícone do carrinho) em um Trade Link, o host envia manual_buy; sua extensão executa uma compra em lote única daquela busca e reporta ciclo de vida/progresso com manual_buy_status. As compras por vendedor usam o fluxo comum de buy_request (§4.3) com isLastGroup:false; o host dispara o /hideout final assim que recebe state:"done".
// host → client: start a one-shot bulk buy of one saved search
{ "type":"manual_buy", "id":"mb-…", "seq":12,
"search":{ "realm":"poe2", "league":"Standard", "searchId":"…", "note":"…" },
"itemCount":10, // 0 = all results
"filters":{ "chaos":{ "min":0, "max":0 } } } // currency → {min,max}; 0 = unbounded
// host → client: cancel an in-progress bulk buy
{ "type":"manual_buy_cancel", "id":"mb-…", "seq":13 }
// client → host: lifecycle + progress (ack-tracked like trade_event)
{ "type":"manual_buy_status", "id":"mb-…", "seq":4,
"state":"started|progress|done|cancelled|error",
"processed":3, "bought":2, "failed":1, "total":10, "detail":"" }- Resolva a busca, busque os anúncios correspondentes mais baratos, aplique
filters, limite emitemCount(0 = todos), agrupe por vendedor e compre cada grupo viabuy_request(isLastGroup:false). - Envie
manual_buy_statusstartedno início,progressconforme os grupos terminam, e exatamente um terminaldone/cancelled/error.
-
buy_requestetrade_eventcarregam umseqincremental; o host os confirma. Guarde os frames não confirmados e reenvie-os ao reconectar (ordenados porseq). -
buy_request.idé a chave de idempotência — um id reenviado retorna obuy_resultregistrado (ouerror: duplicateenquanto ainda em andamento). Use um id estável e único por compra. -
buy_resultcarrega umseqque você confirma com ack.
{ "type":"error", "code":"entitlement_required|not_in_game|busy|duplicate|bad_request|unauthorized|proto_unsupported|outdated_extension", "id":"r-42", "detail":"..." }const ws = new WebSocket("ws://127.0.0.1:47362");
let ready = false, seq = 0, behavior = {}, searches = [];
const log = (message) => ws.send(JSON.stringify({ type:"log", level:"info", message }));
ws.onopen = () => ws.send(JSON.stringify({ type:"hello", proto:1, client:"MyExt/1.0", version:"1.1.0" }));
ws.onmessage = (e) => {
const m = JSON.parse(e.data);
if (m.type === "welcome" && !m.allowed) console.warn("Trade entitlement required");
if (m.type === "config") { behavior = m.behavior; searches = m.searches; } // program controls you
if (m.type === "status") ready = m.ready;
if (m.type === "buy_result") ws.send(JSON.stringify({ type:"ack", ackSeq:m.seq }));
};
// monitor `searches`, obey `behavior`; after YOUR whisper succeeds and ready === true:
function buy(items) {
ws.send(JSON.stringify({ type:"buy_request", id:"r-"+Date.now(), seq:++seq,
group:{ groupId:"g", isLastGroup:true, items } }));
}- Host: disconnected — POEFixer não está rodando, o bridge não foi iniciado ou a porta está errada. Inicie o bridge em Settings → Trade; faça a porta coincidir no popup.
-
entitlement_required— sua licença não tem o recurso Trade (pago no servidor). -
not_in_game— o POEFixer não está anexado/no jogo; aguardestatus.ready. - Live search nunca dispara — verifique se você está logado no site de trade no mesmo navegador. A extensão abre automaticamente sua própria aba de fundo fixada por busca e roda o WebSocket ao vivo dentro dessa página; o Trade Link mostra Connecting… e depois Live. Se ficar em Connecting…, abra a aba fixada para conferir se você está logado.
- Port in use — mude a porta em Settings → Trade e no popup, depois reinicie o bridge.