Skip to content

Trade Bridge PT

Lafko edited this page Jun 22, 2026 · 1 revision

← Home


Trade Bridge (extensão de navegador)

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_required e recusa as compras.


1. Como funciona

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-client embutido 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.

2. Instalar a extensão

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.

Chrome / Edge

  1. Descompacte Resources\extension\poefixer-extension-chrome.zip em qualquer pasta (de modo que manifest.json fique na raiz dela). Ou clique em Assisted install… no POEFixer e use o caminho copiado — então pule para o passo 4.
  2. Abra chrome://extensions (Edge: edge://extensions).
  3. Ative o Modo de desenvolvedor (canto superior direito).
  4. Clique em Carregar sem compactação e selecione essa pasta (ou cole o caminho do Assisted install).
  5. 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://extensions e clique em Recarregar no card da extensão para aplicar a nova versão (ou descompacte de novo e use Carregar sem compactação).

Firefox

O Firefox de release só instala extensões assinadas pela Mozilla, então use o carregamento temporário:

  1. Descompacte Resources\extension\poefixer-extension-firefox.zip em qualquer pasta.
  2. Abra about:debugging#/runtime/this-firefox.
  3. Clique em Carregar complemento temporário… e escolha o manifest.json da pasta descompactada.
  4. Ele permanece carregado até você reiniciar o Firefox (repita após reiniciar).
  • Permanente: instale um .xpi assinado pela Mozilla/AMO abrindo-o no Firefox e confirmando o aviso de permissão.

Depois conecte

  1. No POEFixer: Configuration → Trade → Trade data source → Browser extension, anote a Port (padrão 47362) e clique em Start bridge.
  2. 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).
  3. Faça login no site de trade nesse navegador, depois adicione seus Trade Links e pressione Play (veja §3).

3. Como usar

Tudo é controlado pelo POEFixer — o popup da extensão só define a Port de conexão.

  1. No POEFixer: Configuration → Trade → Data source = Browser extension, defina a Port, clique em Start bridge.
  2. No popup da extensão, confirme Host: connected e a mesma Port.
  3. Faça login no site de trade no mesmo navegador.
  4. 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.
  5. 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.
  6. 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.


4. Crie sua própria extensão — Trade Bridge API (PTBP)

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.)

4.1 Handshake

Envie hello primeiro; o host responde welcome.

// client → host
{ "type":"hello", "proto":1, "client":"MyExtension/1.0", "version":"1.1.0", "token":"<optional>" }
// host → client
{ "type":"welcome", "proto":1, "host":"POEFixer", "allowed":true, "paid":false, "ready":false }
  • 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 com entitlement_required.
  • token só é 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":"" } ] }

4.2 Prontidão — whisper only when ready

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.

4.3 Fluxo de compra

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/stashY são as coordenadas do item na loja do vendedor; w/h o 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>}.

4.4 Eventos da etapa de whisper + logs (ext → host)

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_error

Um trade_event também pode carregar o objeto item completo (os mesmos campos de um item de buy_request). teleport_failed = o anúncio do vendedor ainda estava in demand mesmo após um re-whisper forçado; enviado com seu item, o POEFixer o registra em Trade Logs como um Teleport Fail. fetch_error / whisper_failed / in_demand sã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 | error

4.5 Manual buy (host-driven bulk buy)

Quando 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 em itemCount (0 = todos), agrupe por vendedor e compre cada grupo via buy_request (isLastGroup:false).
  • Envie manual_buy_status started no início, progress conforme os grupos terminam, e exatamente um terminal done / cancelled / error.

4.6 Confiabilidade

  • buy_request e trade_event carregam um seq incremental; o host os confirma. Guarde os frames não confirmados e reenvie-os ao reconectar (ordenados por seq).
  • buy_request.id é a chave de idempotência — um id reenviado retorna o buy_result registrado (ou error: duplicate enquanto ainda em andamento). Use um id estável e único por compra.
  • buy_result carrega um seq que você confirma com ack.

4.7 Erros

{ "type":"error", "code":"entitlement_required|not_in_game|busy|duplicate|bad_request|unauthorized|proto_unsupported|outdated_extension", "id":"r-42", "detail":"..." }

4.8 Cliente mínimo (JavaScript)

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 } }));
}

5. Solução de problemas

  • 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; aguarde status.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.

← Home

Clone this wiki locally