Skip to content

Trade Bridge JA

Lafko edited this page Jun 22, 2026 · 1 revision

← Home


Trade Bridge (ブラウザ拡張機能)

Trade Bridge は、トレードサイト関連の作業 (live 検索、fetch、whisper) をすべてブラウザ拡張機能に任せ、POEFixer はゲーム内での購入だけを担当する仕組みです。これによりトレードサイトのトラフィックは実際のブラウザセッション内で完結し、cookie のコピーも cf_clearance の手間も不要になります。さらに、将来の「POEFixer を別の PC で動かす」モードの基盤にもなります。

無料の公式拡張機能 を使うことも、下記のドキュメント化されたプロトコルに沿って 自作 することもできます。

Trade Bridge を利用するには、POEFixer ライセンスに Trade 機能が含まれている必要があります。サーバー側で Trade が有料に設定されている場合は有効なキーが必要です。無料設定なら誰でも利用できます。権限がない場合、ブリッジは entitlement_required を返し、購入を拒否します。


1. 仕組み

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
  • 拡張機能 はトレードサイトに触れるすべてを担います。
  • POEFixer はゲームクライアント内のすべてを担い、拡張機能が接続するためのローカル WebSocket サーバー (Trade Bridge) を公開します。
  • このモードでは POEFixer 内蔵の tls-client は使われず、トレードサイト関連のコントロール (Connections、Trade Cookies、Force teleport、In-demand、Rate limiting) は拡張機能側へ移り、POEFixer 内では非表示/無効になります。

2. 拡張機能のインストール

拡張機能は POEFixer に同梱されています。POEFixer フォルダ内の 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

完全に無音のワンクリックインストールはできません。ブラウザは仕様として、プログラムによる拡張機能インストールをブロックします。自分のブラウザ用のファイルを解凍し、一度だけ読み込みます。POEFixer の Assisted install… ボタン (Configuration → Trade) は Chrome/Edge 向けの作業を代行します。解凍済みの chrome\ フォルダのパスをクリップボードにコピーし、このガイドを開くので、解凍を省略できます。

Chrome / Edge

  1. Resources\extension\poefixer-extension-chrome.zip を任意のフォルダに 解凍 します (manifest.json がその最上位に来るように)。または POEFixer で Assisted install… をクリックし、コピーされたパスを使います。その場合は手順 4 へ進んでください。
  2. chrome://extensions を開きます (Edge: edge://extensions)。
  3. デベロッパーモード を有効にします (右上)。
  4. パッケージ化されていない拡張機能を読み込む をクリックし、そのフォルダを選択します (または Assisted install のパスを貼り付けます)。
  5. 拡張機能のアイコンがツールバーに表示されます。再起動後も読み込まれたままになります。

POEFixer の更新後は同梱の拡張機能も更新されます。chrome://extensions を開き、拡張機能カードの 再読み込み をクリックして新しいバージョンを反映してください (または再度解凍して「パッケージ化されていない拡張機能を読み込む」を実行)。

Firefox

リリース版 Firefox は Mozilla 署名済みの拡張機能しかインストールできないため、一時的な読み込みを使います:

  1. Resources\extension\poefixer-extension-firefox.zip を任意のフォルダに 解凍 します。
  2. about:debugging#/runtime/this-firefox を開きます。
  3. 一時的なアドオンを読み込む… をクリックし、解凍したフォルダの manifest.json を選びます。
  4. Firefox を再起動するまで読み込まれたままになります (再起動後はやり直してください)。
  • 恒久的にする場合: Mozilla/AMO 署名済みの .xpi を Firefox で開き、権限の確認に同意してインストールします。

その後の接続

  1. POEFixer で: Configuration → Trade → Trade data source → Browser extension を選び、Port (デフォルト 47362) を確認して Start bridge をクリックします。
  2. 拡張機能のポップアップで 同じ Port を設定します。Host: connected と表示され、POEFixer 側のステータスが になり、拡張機能の名前と実際のバージョンが表示されます。例: "Extension connected (PoeFixerExt/1.1.2)" (バージョンは拡張機能のマニフェストから取得され、古い拡張機能はここで警告されます)。
  3. そのブラウザでトレードサイトにログインし、Trade Links を追加して Play を押します (§3 参照)。

3. 使い方

すべての操作は POEFixer から制御します。拡張機能のポップアップでは接続用の Port を設定するだけです。

  1. POEFixer で: Configuration → Trade → Data source = Browser extension を選び、Port を設定して Start bridge をクリックします。
  2. 拡張機能のポップアップで Host: connected と同じ Port を確認します。
  3. 同じブラウザでトレードサイトにログインします。
  4. POEFixer の Trade Links (Connections タブ) に trade2 の検索 URL を追加して Play を押します。検索が拡張機能へ送られ、そこで実行されます。Stop で削除されます。
  5. POEFixer (Configuration → Trade) で動作を設定します: Force teleportItem is in demand → teleport anywayRate limiting。POEFixer がこれらを拡張機能へ送り、拡張機能は従うだけです。
  6. リスティングが一致すると、拡張機能が whisper を送り、POEFixer がゲーム内で購入します。拡張機能のすべての活動は POEFixer の Logs に表示されます (カテゴリ Trade)。

信頼性の高い live フィード (自動): アクティブな検索ごとに、拡張機能はトレードページへの ピン留めされたバックグラウンドタブを開き、live WebSocket を そのページ内で 接続します (正しい Origin + セッション cookie — サイト自体と同じ動作です)。トレードサイトにログインしたままにするだけで、Live Search を手動で開く必要はありません。Trade Link は live WS が確立するまで Connecting…、確立後は Live と表示します。そのピン留めタブを閉じると検索が停止します。

Manual Buy (検索結果を今すぐまとめ買い): live リスティングを待つ代わりに、任意の Trade Link の Shopping Cart アイコンを押すと即座にまとめ買いできます。拡張機能はその検索で最も安い一致リスティングを取得し (設定した item count まで、そのリンクの currency filters に従う)、出品者ごとにグループ化し、POEFixer を通じてそれぞれ whisper + 購入します。同じ spend limitsauto-stash を適用し、最後に一度だけ hideout へ戻ります。Manual Buy と live 検索 (Play) は排他的です。Manual Buy を始める前に live 検索を停止し、その逆も同様にしてください。カートボタンは拡張機能が接続されているときだけ有効になります。


4. 自作拡張機能 — Trade Bridge API (PTBP)

プロトコルは WebSocket 上の素の JSON です。誰でも実装できます。サーバーは POEFixer が立てます。あなたのクライアントは ws://127.0.0.1:<port> へ接続します (デフォルト 47362、Settings で変更可能)。

ホストは、ライセンスに Trade entitlement がある場合にのみ購入を実行します。そうでなければ {"type":"error","code":"entitlement_required"} を受け取ります。(認証の詳細は意図的にドキュメント化していません。)

4.1 ハンドシェイク

まず hello を送り、ホストが 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 は拡張機能のマニフェストのバージョンです (semver 文字列、例 "1.1.0")。拡張機能が POEFixer の期待するバージョンより古い場合、POEFixer は不一致を検出して live 検索を抑制し、最新の拡張機能を再インストールするまで購入を無効にします。POEFixer は Settings → Trade に警告を表示します。古い状態で購入を試みると {"type":"error","code":"outdated_extension"} を受け取ります。
  • allowed:false → 権限なし (「キーを購入」と扱う)。ホストは購入を entitlement_required で拒否します。
  • token は、ユーザーが POEFixer でペアリングトークンを有効にした場合にのみ必要です (デフォルトはオフ)。

welcome の後 (およびユーザーが POEFixer で何かを変更するたびに)、ホストは config メッセージを送ります。プログラムが唯一の操作面なので、拡張機能はまさにこれらの検索を監視し、この behavior に従う必要があります:

// host → client
{ "type":"config",
  "behavior":{ "forceTeleport":false, "inDemandRetry":true, "rateLimit":true },
  "searches":[ { "realm":"poe2", "league":"Standard", "searchId":"", "note":"" } ] }

4.2 準備完了 — whisper は ready のときだけ

ホストは定期的に status を送ります:

{ "type":"status", "ready":true, "inGame":true, "attached":true, "busy":false }

最後の status.ready === true のときにのみ whisper/teleport しなければなりません。 ready = entitled && attached && in-game && !busy です。ready でないときに whisper すると、取引を進める購入者がいないままキャラクターがテレポートしてしまいます。

4.3 購入フロー

whisper が成功した後 (キャラクターがテレポート中)、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":"..."
    } ] } }

ホストはこれを ack し、必要に応じて進捗を送り、最後に 1 つの結果を送ります:

{ "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 はリスティングの出所となる検索です。ホストはこれを使って購入を正しい Trade Link に紐付けます (省略時は最初のアクティブな検索にフォールバック)。複数検索を正しく扱うために指定してください。
  • stashX/stashY は出品者のショップ内でのアイテムの座標、w/h はそのサイズです。これらがゲーム内のクリックを駆動します。
  • 価格はフラット (currency/amount、上記のとおり) でも、ネスト ("price":{"currency","amount"}) でも送れます。ホストは両方を受け付けます。
  • hideoutToken はログ用にのみ運ばれます (whisper にはすでに使用済みです)。
  • buy_result必ず ack してください: {"type":"ack","ackSeq":<buy_result.seq>} を送ります。

4.4 whisper 段階のイベント + ログ (ext → host)

whisper 段階の結果 (POEFixer のログを完全に保つため):

{ "type":"trade_event", "seq":8, "stage":"whisper", "outcome":"in_demand", "itemId":"...", "detail":"" }
// outcome ∈ in_demand | whisper_failed | teleport_failed | fetch_error

trade_event は完全な item オブジェクト (buy_request のアイテムと同じフィールド) を含むこともあります。teleport_failed = 強制的な再 whisper の後でも出品者のリスティングがまだ in demand だったことを意味します。item 付きで送られると、POEFixer はそれを Trade LogsTeleport Fail として記録します。fetch_error / whisper_failed / in_demand は情報用で、一般の Logs (カテゴリ Trade) に送られます。

自分の活動を POEFixer のログへ転送してください (推奨 — 拡張機能のすべてのログはプログラムに表示されるべきです):

{ "type":"log", "level":"info", "message":"" }   // shown in POEFixer Logs (category Trade)

各検索の live-WS の状態を報告し、POEFixer の Trade Link が Connecting…/Live を表示できるようにします:

{ "type":"search_status", "searchId":"", "state":"connected" }   // state ∈ connected | closed | error

4.5 Manual buy (host-driven bulk buy)

ユーザーが Trade Link で Manual Buy (カートアイコン) をクリックすると、ホストは manual_buy を送ります。拡張機能はその検索のワンショットまとめ買いを実行し、ライフサイクル/進捗を manual_buy_status で報告します。出品者ごとの購入は通常の buy_request フロー (§4.3) を isLastGroup:false で使います。ホストは state:"done" を受け取ると、最後の /hideout を一度だけ発火します。

// 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":"" }
  • 検索を解決し、最も安い一致リスティングを取得し、filters を適用し、itemCount で上限を設け (0 = すべて)、出品者ごとにグループ化し、各グループを buy_request (isLastGroup:false) で購入します。
  • 最初に manual_buy_statusstarted を送り、グループ完了ごとに progress を送り、最後にちょうど 1 つの終端 done / cancelled / error を送ります。

4.6 信頼性

  • buy_requesttrade_event は増加する seq を持ち、ホストがそれらを ack します。ack されていないフレームを保持し、再接続時に再送してください (seq 順)。
  • buy_request.id冪等性キー です。再送された id は記録済みの buy_result を返します (または処理中の間は error: duplicate)。購入ごとに安定した一意の id を使ってください。
  • buy_resultあなたが ack する seq を持ちます。

4.7 エラー

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

4.8 最小クライアント (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. トラブルシューティング

  • Host: disconnected — POEFixer が起動していない、ブリッジが開始されていない、またはポートが間違っています。Settings → Trade でブリッジを開始し、ポップアップのポートを一致させてください。
  • entitlement_required — ライセンスに Trade 機能がありません (サーバー側で有料)。
  • not_in_game — POEFixer がアタッチ/ゲーム内になっていません。status.ready を待ってください。
  • Live 検索が発火しない — 同じブラウザでトレードサイトにログインしているか確認してください。拡張機能は検索ごとに専用のピン留めバックグラウンドタブを自動的に開き、そのページ内で live WebSocket を実行します。Trade Link は Connecting…、その後 Live と表示します。Connecting… のまま止まる場合は、ピン留めタブを開いてログイン状態を確認してください。
  • Port in use — Settings → Trade とポップアップでポートを変更し、ブリッジを再起動してください。

← Home

Clone this wiki locally