@omen.foundation/game-sdk 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +58 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +58 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -140,15 +140,58 @@ var OAuthFlow = class {
|
|
|
140
140
|
const storageKey = `omenx_oauth_callback_${state}`;
|
|
141
141
|
const stored = localStorage.getItem(storageKey);
|
|
142
142
|
if (pollCount % 10 === 0) {
|
|
143
|
-
console.log("[OAuthFlow] Polling localStorage
|
|
143
|
+
console.log("[OAuthFlow] \u{1F50D} Polling localStorage...", {
|
|
144
|
+
key: storageKey,
|
|
145
|
+
keyPreview: storageKey.substring(0, 50) + "...",
|
|
146
|
+
found: !!stored,
|
|
147
|
+
pollCount,
|
|
148
|
+
state,
|
|
149
|
+
statePreview: state.substring(0, 20) + "..."
|
|
150
|
+
});
|
|
151
|
+
if (pollCount === 10) {
|
|
152
|
+
const allKeys = Object.keys(localStorage).filter((k) => k.startsWith("omenx_oauth_callback_"));
|
|
153
|
+
console.log("[OAuthFlow] \u{1F50D} Found localStorage keys:", {
|
|
154
|
+
count: allKeys.length,
|
|
155
|
+
keys: allKeys,
|
|
156
|
+
lookingFor: storageKey,
|
|
157
|
+
lookingForPreview: storageKey.substring(0, 50) + "..."
|
|
158
|
+
});
|
|
159
|
+
for (const key of allKeys) {
|
|
160
|
+
const storedData = localStorage.getItem(key);
|
|
161
|
+
if (storedData) {
|
|
162
|
+
try {
|
|
163
|
+
const data = JSON.parse(storedData);
|
|
164
|
+
console.log("[OAuthFlow] \u{1F50D} Checking stored key:", {
|
|
165
|
+
key: key.substring(0, 50) + "...",
|
|
166
|
+
storedState: data.state,
|
|
167
|
+
expectedState: state,
|
|
168
|
+
statesMatch: data.state === state,
|
|
169
|
+
hasCode: !!data.code
|
|
170
|
+
});
|
|
171
|
+
} catch (e) {
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
144
176
|
}
|
|
145
177
|
if (stored) {
|
|
146
178
|
try {
|
|
147
179
|
const data = JSON.parse(stored);
|
|
180
|
+
console.log("[OAuthFlow] \u2705 Found stored data!", {
|
|
181
|
+
hasCode: !!data.code,
|
|
182
|
+
hasState: !!data.state,
|
|
183
|
+
stateMatch: data.state === state,
|
|
184
|
+
storedState: data.state?.substring(0, 10) + "...",
|
|
185
|
+
expectedState: state.substring(0, 10) + "..."
|
|
186
|
+
});
|
|
148
187
|
if (data.code && data.state === state) {
|
|
149
188
|
const age = Date.now() - (data.timestamp || 0);
|
|
150
189
|
if (age < 3e4) {
|
|
151
|
-
console.log("[OAuthFlow] \u2705
|
|
190
|
+
console.log("[OAuthFlow] \u2705\u2705\u2705 Processing OAuth callback from localStorage!", {
|
|
191
|
+
age: `${age}ms`,
|
|
192
|
+
hasCode: !!data.code,
|
|
193
|
+
codePreview: data.code.substring(0, 10) + "..."
|
|
194
|
+
});
|
|
152
195
|
clearInterval(pollInterval);
|
|
153
196
|
storageListener(new StorageEvent("storage", {
|
|
154
197
|
key: storageKey,
|
|
@@ -156,12 +199,18 @@ var OAuthFlow = class {
|
|
|
156
199
|
storageArea: localStorage
|
|
157
200
|
}));
|
|
158
201
|
} else {
|
|
159
|
-
console.warn("[OAuthFlow] Callback data too old, removing:", { age: `${age}ms` });
|
|
202
|
+
console.warn("[OAuthFlow] \u26A0\uFE0F Callback data too old, removing:", { age: `${age}ms` });
|
|
160
203
|
localStorage.removeItem(storageKey);
|
|
161
204
|
}
|
|
205
|
+
} else {
|
|
206
|
+
console.warn("[OAuthFlow] \u26A0\uFE0F State mismatch!", {
|
|
207
|
+
storedState: data.state?.substring(0, 20),
|
|
208
|
+
expectedState: state.substring(0, 20),
|
|
209
|
+
statesMatch: data.state === state
|
|
210
|
+
});
|
|
162
211
|
}
|
|
163
212
|
} catch (error) {
|
|
164
|
-
console.error("[OAuthFlow] Error parsing localStorage callback:", error);
|
|
213
|
+
console.error("[OAuthFlow] \u274C Error parsing localStorage callback:", error, { stored });
|
|
165
214
|
}
|
|
166
215
|
}
|
|
167
216
|
}, 100);
|
|
@@ -201,10 +250,13 @@ var OAuthFlow = class {
|
|
|
201
250
|
broadcastChannel = null;
|
|
202
251
|
}
|
|
203
252
|
console.log("[OAuthFlow] \u{1F50D} Starting OAuth flow, listening for callback...", {
|
|
204
|
-
state
|
|
253
|
+
state,
|
|
254
|
+
statePreview: state.substring(0, 20) + "...",
|
|
255
|
+
stateLength: state.length,
|
|
205
256
|
hasOpener: !!window.opener,
|
|
206
257
|
polling: true,
|
|
207
|
-
broadcastChannel: true
|
|
258
|
+
broadcastChannel: true,
|
|
259
|
+
expectedKey: `omenx_oauth_callback_${state}`
|
|
208
260
|
});
|
|
209
261
|
let messageReceived = false;
|
|
210
262
|
const originalMessageListener = messageListener;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":";;;AAGA,eAAsB,YAAA,GAAyE;AAE7F,EAAA,MAAM,YAAA,GAAe,qBAAqB,GAAG,CAAA;AAG7C,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,YAAY,CAAA;AACtC,EAAA,MAAM,aAAA,GAAgB,gBAAgB,IAAI,CAAA;AAE1C,EAAA,OAAO,EAAE,cAAc,aAAA,EAAc;AACvC;AAKA,SAAS,qBAAqB,MAAA,EAAwB;AACpD,EAAA,MAAM,OAAA,GAAU,oEAAA;AAChB,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,MAAM,CAAA;AACnC,EAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAA,IAAA,KAAQ,OAAA,CAAQ,IAAA,GAAO,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC1E;AAKA,SAAS,gBAAgB,MAAA,EAA6B;AACpD,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,YAAA,CAAa,GAAG,IAAI,UAAA,CAAW,MAAM,CAAC,CAAC,CAAA;AAClE,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AACxE;AAKA,eAAe,OAAO,OAAA,EAAuC;AAC3D,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AACnC,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,CAAA;AAC7C;;;ACxBO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,OAAA,EAAqC;AAEtD,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,IAAA,CAAK,aAAA,EAAc;AAGlD,IAAA,IAAI,aAAA;AACJ,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI,OAAA,CAAQ,eAAe,KAAA,EAAO;AAChC,MAAA,MAAM,IAAA,GAAO,MAAM,YAAA,EAAa;AAChC,MAAA,aAAA,GAAgB,IAAA,CAAK,aAAA;AACrB,MAAA,YAAA,GAAe,IAAA,CAAK,YAAA;AAEpB,MAAA,cAAA,CAAe,OAAA,CAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAA,EAAI,YAAY,CAAA;AAAA,IAC5D;AAEA,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AAEtC,MAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,QACjC,SAAA,EAAW,KAAK,MAAA,CAAO,MAAA;AAAA,QACvB,cAAc,OAAA,CAAQ,WAAA;AAAA,QACtB,aAAA,EAAe,MAAA;AAAA,QACf;AAAA,OACD,CAAA;AAED,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,MAAA,CAAO,MAAA,CAAO,kBAAkB,aAAa,CAAA;AAC7C,QAAA,MAAA,CAAO,MAAA,CAAO,yBAAyB,MAAM,CAAA;AAAA,MAC/C;AAEA,MAAA,MAAM,OAAA,GAAU,GAAG,IAAA,CAAK,MAAA,CAAO,iBAAiB,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAA;AAGrE,MAAA,MAAM,QAAQ,MAAA,CAAO,IAAA;AAAA,QACnB,OAAA;AAAA,QACA,sBAAA;AAAA,QACA,4BAAA,IAAgC,MAAA,CAAO,MAAA,CAAO,KAAA,GAAQ,CAAA,GAAI,OAAO,OAAA,IAAW,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,GAAA;AAAA,OACzG;AAEA,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,iEAAiE,CAAA;AACzF,QAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAK,CAAA;AAC3B,QAAA,MAAA,CAAO,KAAK,CAAA;AACZ,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,eAAA,GAAkB,OAAO,KAAA,KAAwB;AAIrD,QAAA,IAAI;AAEF,UAAA,MAAM,aAAA,GAAgB,OAAO,QAAA,CAAS,MAAA;AACtC,UAAA,IAAI,KAAA,CAAM,WAAW,aAAA,EAAe;AAElC,YAAA;AAAA,UACF;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAEA,QAAA,IAAI,KAAA,CAAM,IAAA,EAAM,IAAA,KAAS,kBAAA,EAAoB;AAC3C,UAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AACrD,UAAA,KAAA,CAAM,KAAA,EAAM;AAEZ,UAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,aAAA,KAAkB,KAAA,CAAM,IAAA;AAG7C,UAAA,IAAI,kBAAkB,KAAA,EAAO;AAC3B,YAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,gDAAgD,CAAA;AACxE,YAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAK,CAAA;AAC3B,YAAA,MAAA,CAAO,KAAK,CAAA;AACZ,YAAA;AAAA,UACF;AAGA,UAAA,MAAM,kBAAA,GAAqB,cAAA,CAAe,OAAA,CAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AACvE,UAAA,IAAI,kBAAA,EAAoB;AACtB,YAAA,cAAA,CAAe,UAAA,CAAW,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AAC/C,YAAA,YAAA,GAAe,kBAAA;AAAA,UACjB;AAEA,UAAA,IAAI;AAEF,YAAA,MAAM,gBAAgB,MAAM,IAAA,CAAK,qBAAqB,IAAA,EAAM,OAAA,CAAQ,aAAa,YAAY,CAAA;AAC7F,YAAA,MAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,aAAa,CAAA;AAC/C,YAAA,OAAA,CAAQ,aAAa,CAAA;AAAA,UACvB,SAAS,KAAA,EAAO;AACd,YAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAc,CAAA;AACpC,YAAA,MAAA,CAAO,KAAK,CAAA;AAAA,UACd;AAAA,QACF;AAAA,MACF,CAAA;AAEA,MAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,eAAe,CAAA;AAIlD,MAAA,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAwB;AAC/C,QAAA,IAAI,CAAC,MAAM,GAAA,IAAO,CAAC,MAAM,GAAA,CAAI,UAAA,CAAW,uBAAuB,CAAA,EAAG;AAChE,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,GAAA,CAAI,OAAA,CAAQ,yBAAyB,EAAE,CAAA;AACnE,QAAA,IAAI,kBAAkB,KAAA,EAAO;AAC3B,UAAA;AAAA,QACF;AAEA,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,YAAY,IAAI,CAAA;AAC9C,UAAA,IAAI,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,KAAU,KAAA,EAAO;AACrC,YAAA,OAAA,CAAQ,IAAI,2DAA2D,CAAA;AACvE,YAAA,eAAA,GAAkB,IAAA;AAClB,YAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AACrD,YAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,sBAAsB,CAAA;AAG5D,YAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAgB,GAAI,IAAA;AAGlC,YAAA,MAAM,kBAAA,GAAqB,cAAA,CAAe,OAAA,CAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AACvE,YAAA,IAAIA,aAAAA;AACJ,YAAA,IAAI,kBAAA,EAAoB;AACtB,cAAA,cAAA,CAAe,UAAA,CAAW,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AAC/C,cAAAA,aAAAA,GAAe,kBAAA;AAAA,YACjB;AAGA,YAAA,IAAA,CAAK,oBAAA,CAAqB,iBAAiB,OAAA,CAAQ,WAAA,EAAaA,aAAY,CAAA,CACzE,IAAA,CAAK,OAAO,aAAA,KAAkB;AAC7B,cAAA,MAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,aAAa,CAAA;AAC/C,cAAA,OAAA,CAAQ,aAAa,CAAA;AAAA,YACvB,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,cAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAc,CAAA;AACpC,cAAA,MAAA,CAAO,KAAK,CAAA;AAAA,YACd,CAAC,CAAA;AAGH,YAAA,YAAA,CAAa,UAAA,CAAW,MAAM,GAAI,CAAA;AAAA,UACpC;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,KAAA,CAAM,uDAAuD,KAAK,CAAA;AAAA,QAC5E;AAAA,MACF,CAAA;AAEA,MAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,eAAe,CAAA;AAIlD,MAAA,IAAI,SAAA,GAAY,CAAA;AAChB,MAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,QAAA,SAAA,EAAA;AACA,QAAA,MAAM,UAAA,GAAa,wBAAwB,KAAK,CAAA,CAAA;AAChD,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA;AAE9C,QAAA,IAAI,SAAA,GAAY,OAAO,CAAA,EAAG;AAExB,UAAA,OAAA,CAAQ,GAAA,CAAI,kDAAA,EAAoD,EAAE,GAAA,EAAK,UAAA,EAAY,OAAO,CAAC,CAAC,MAAA,EAAQ,SAAA,EAAW,CAAA;AAAA,QACjH;AAEA,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC9B,YAAA,IAAI,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,KAAU,KAAA,EAAO;AACrC,cAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,EAAI,IAAK,KAAK,SAAA,IAAa,CAAA,CAAA;AAC5C,cAAA,IAAI,MAAM,GAAA,EAAO;AACf,gBAAA,OAAA,CAAQ,GAAA,CAAI,0DAAA,EAAuD,EAAE,GAAA,EAAK,CAAA,EAAG,GAAG,CAAA,EAAA,CAAA,EAAM,OAAA,EAAS,CAAC,CAAC,IAAA,CAAK,IAAA,EAAM,CAAA;AAE5G,gBAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,gBAAA,eAAA,CAAgB,IAAI,aAAa,SAAA,EAAW;AAAA,kBAC1C,GAAA,EAAK,UAAA;AAAA,kBACL,QAAA,EAAU,MAAA;AAAA,kBACV,WAAA,EAAa;AAAA,iBACd,CAAC,CAAA;AAAA,cACJ,CAAA,MAAO;AACL,gBAAA,OAAA,CAAQ,KAAK,8CAAA,EAAgD,EAAE,KAAK,CAAA,EAAG,GAAG,MAAM,CAAA;AAChF,gBAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAAA,cACpC;AAAA,YACF;AAAA,UACF,SAAS,KAAA,EAAO;AACd,YAAA,OAAA,CAAQ,KAAA,CAAM,oDAAoD,KAAK,CAAA;AAAA,UACzE;AAAA,QACF;AAAA,MACF,GAAG,GAAG,CAAA;AAGN,MAAA,IAAI,gBAAA,GAA4C,IAAA;AAChD,MAAA,IAAI;AACF,QAAA,gBAAA,GAAmB,IAAI,iBAAiB,aAAa,CAAA;AACrD,QAAA,MAAM,iBAAA,GAAoB,CAAC,KAAA,KAAwB;AACjD,UAAA,IAAI,MAAM,IAAA,EAAM,IAAA,KAAS,sBAAsB,KAAA,CAAM,IAAA,EAAM,UAAU,KAAA,EAAO;AAC1E,YAAA,OAAA,CAAQ,IAAI,6DAAwD,CAAA;AACpE,YAAA,eAAA,GAAkB,IAAA;AAClB,YAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,YAAA,IAAI,gBAAA,EAAkB;AACpB,cAAA,gBAAA,CAAiB,SAAA,GAAY,IAAA;AAC7B,cAAA,gBAAA,CAAiB,KAAA,EAAM;AAAA,YACzB;AACA,YAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,sBAAsB,CAAA;AAC5D,YAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AAErD,YAAA,MAAM,EAAE,IAAA,EAAM,iBAAA,EAAkB,GAAI,KAAA,CAAM,IAAA;AAC1C,YAAA,MAAM,kBAAA,GAAqB,cAAA,CAAe,OAAA,CAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AACvE,YAAA,IAAIA,aAAAA;AACJ,YAAA,IAAI,kBAAA,EAAoB;AACtB,cAAA,cAAA,CAAe,UAAA,CAAW,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AAC/C,cAAAA,aAAAA,GAAe,kBAAA;AAAA,YACjB;AAEA,YAAA,IAAA,CAAK,oBAAA,CAAqB,mBAAmB,OAAA,CAAQ,WAAA,EAAaA,aAAY,CAAA,CAC3E,IAAA,CAAK,OAAO,aAAA,KAAkB;AAC7B,cAAA,MAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,aAAa,CAAA;AAC/C,cAAA,OAAA,CAAQ,aAAa,CAAA;AAAA,YACvB,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,cAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAc,CAAA;AACpC,cAAA,MAAA,CAAO,KAAK,CAAA;AAAA,YACd,CAAC,CAAA;AAAA,UACL;AAAA,QACF,CAAA;AAEA,QAAA,gBAAA,CAAiB,SAAA,GAAY,iBAAA;AAAA,MAG/B,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,IAAA,CAAK,+CAA+C,KAAK,CAAA;AACjE,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AAGA,MAAA,OAAA,CAAQ,IAAI,sEAAA,EAAiE;AAAA,QAC3E,KAAA,EAAO,KAAA,CAAM,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAAA,QAChC,SAAA,EAAW,CAAC,CAAC,MAAA,CAAO,MAAA;AAAA,QACpB,OAAA,EAAS,IAAA;AAAA,QACT,gBAAA,EAAkB;AAAA,OACnB,CAAA;AAID,MAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,MAAA,MAAM,uBAAA,GAA0B,eAAA;AAChC,MAAA,MAAM,sBAAA,GAAyB,OAAO,KAAA,KAAwB;AAC5D,QAAA,eAAA,GAAkB,IAAA;AAElB,QAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,QAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AACrD,QAAA,MAAM,wBAAwB,KAAK,CAAA;AAAA,MACrC,CAAA;AACA,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AACrD,MAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,sBAAsB,CAAA;AASzD,MAAA,MAAM,wBAAwB,MAAe;AAC3C,QAAA,IAAI;AAEF,UAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,YAAA,OAAO,KAAA;AAAA,UACT;AAIA,UAAA,IAAI;AAEF,YAAA,MAAM,CAAA,GAAI,MAAM,QAAA,CAAS,IAAA;AAEzB,YAAA,OAAO,IAAA;AAAA,UACT,SAAS,CAAA,EAAG;AAGV,YAAA,OAAO,KAAA;AAAA,UACT;AAAA,QACF,SAAS,CAAA,EAAG;AAEV,UAAA,OAAO,KAAA;AAAA,QACT;AAAA,MACF,CAAA;AAEA,MAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AAEpC,QAAA,IAAI,eAAA,EAAiB;AACnB,UAAA;AAAA,QACF;AAGA,QAAA,IAAI,uBAAsB,EAAG;AAC3B,UAAA,aAAA,CAAc,WAAW,CAAA;AACzB,UAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,UAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,sBAAsB,CAAA;AAC5D,UAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,eAAe,CAAA;AACrD,UAAA,IAAI,gBAAA,EAAkB;AACpB,YAAA,gBAAA,CAAiB,SAAA,GAAY,IAAA;AAC7B,YAAA,gBAAA,CAAiB,KAAA,EAAM;AAAA,UACzB;AAEA,UAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,YAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,+BAA+B,CAAA;AACvD,YAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAK,CAAA;AAC3B,YAAA,MAAA,CAAO,KAAK,CAAA;AAAA,UACd;AAAA,QACF;AAAA,MACF,GAAG,GAAI,CAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAA,CACZ,IAAA,EACA,WAAA,EACA,YAAA,EAC6B;AAC7B,IAAA,MAAM,IAAA,GAAY;AAAA,MAChB,IAAA;AAAA,MACA,YAAA,EAAc,WAAA;AAAA,MACd,UAAA,EAAY;AAAA,KACd;AAEA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,IACvB;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,aAAA,EAAe;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA;AAAA;AAAA,OAGlB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,KAC1B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK,CAAE,MAAM,OAAO,EAAE,OAAA,EAAS,mCAAA,EAAoC,CAAE,CAAA;AAClG,MAAA,MAAM,IAAI,KAAA,CAAM,KAAA,CAAM,OAAA,IAAW,mCAAmC,CAAA;AAAA,IACtE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAA,GAAwB;AAC9B,IAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,IAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAA,IAAA,KAAQ,KAAK,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,EAC9E;AACF,CAAA;;;AChXO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAAY,MAAA,EAA0B;AAFtC,IAAA,IAAA,CAAQ,eAAA,GAA0D,IAAA;AAGhE,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,GAAa;AAEX,IAAA,IAAA,CAAK,WAAA,EAAY;AAGjB,IAAA,IAAA,CAAK,eAAA,GAAkB,CAAC,KAAA,KAAwB;AAE9C,MAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,QAAA,IAAI;AACF,UAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,YAAY,CAAA;AAClD,UAAA,IAAI,KAAA,CAAM,MAAA,KAAW,SAAA,CAAU,MAAA,EAAQ;AACrC,YAAA;AAAA,UACF;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAGA,MAAA,IAAI,KAAA,CAAM,IAAA,EAAM,IAAA,KAAS,YAAA,EAAc;AACrC,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAG5B,QAAA,IAAI,QAAA,CAAS,MAAA,KAAW,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ;AAC1C,UAAA,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,MAAA,EAAS,QAAA,CAAS,MAAM,CAAA,CAAE,CAAC,CAAA;AAC3G,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,EAAI,GAAK,IAAI,EAAA,GAAK,GAAA;AAC9C,QAAA,IAAI,QAAA,CAAS,YAAY,cAAA,EAAgB;AACvC,UAAA,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAA;AACpD,UAAA;AAAA,QACF;AAEA,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,eAAe,CAAA;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAA,GAAoB;AAC1B,IAAA,IAAI,MAAA,CAAO,WAAW,MAAA,EAAQ;AAE5B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,IAAgB,GAAA;AACjD,IAAA,MAAA,CAAO,MAAA,CAAO,WAAA;AAAA,MACZ;AAAA,QACE,IAAA,EAAM,oBAAA;AAAA,QACN,MAAA,EAAQ,KAAK,MAAA,CAAO;AAAA,OACtB;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,IAAA,CAAK,eAAe,CAAA;AAC1D,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,IACzB;AAAA,EACF;AACF,CAAA;;;ACzFO,IAAM,eAAN,MAAmB;AAAA,EAGxB,WAAA,CAAY,mBAA2B,aAAA,EAAe;AACpD,IAAA,IAAA,CAAK,gBAAA,GAAmB,gBAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAAU,QAAA,EAAoB,YAAA,EAAsB,SAAA,EAAyB;AAC3E,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,GAAG,IAAA,CAAK,gBAAgB,QAAQ,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAC7E,MAAA,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,iBAAiB,YAAY,CAAA;AAC1E,MAAA,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,UAAA,CAAA,EAAc,MAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAK,SAAA,GAAY,GAAK,CAAC,CAAA;AAAA,IACpG,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,6CAA6C,KAAK,CAAA;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,GAAiC;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,IAAA,CAAM,CAAA;AAClE,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,IAC1B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,gDAAgD,KAAK,CAAA;AAClE,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAAiC;AAC/B,IAAA,IAAI;AACF,MAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,aAAA,CAAe,CAAA;AAAA,IACrE,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,oDAAoD,KAAK,CAAA;AACtE,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAqB;AACnB,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,IAAA,CAAM,CAAA;AACtD,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,aAAA,CAAe,CAAA;AAC/D,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,UAAA,CAAY,CAAA;AAAA,IAC9D,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,2CAA2C,KAAK,CAAA;AAAA,IAC/D;AAAA,EACF;AACF,CAAA;;;AChDO,IAAM,eAAN,MAAmB;AAAA,EAOxB,YAAY,MAAA,EAA4B;AAJxC,IAAA,IAAA,CAAQ,UAAA,GAAgC,IAAA;AAExC,IAAA,IAAA,CAAQ,eAAA,GAAmC,IAAA;AAIzC,IAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,6BAAA;AACxC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,UAAA;AAAA,MACA,iBAAA,EAAmB,MAAA,CAAO,iBAAA,IAAqB,CAAA,EAAG,UAAU,CAAA,mBAAA,CAAA;AAAA,MAC5D,aAAA,EAAe,MAAA,CAAO,aAAA,IAAiB,CAAA,EAAG,UAAU,CAAA,eAAA,CAAA;AAAA,MACpD,MAAA,EAAQ,MAAA,CAAO,MAAA,KAAW,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MACjC,WAAA,EAAa,OAAO,WAAA,KAAgB,CAAC,UAAU,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA,CAAA;AAAA,MAC7F,QAAA,EAAU,MAAA,CAAO,QAAA,KAAa,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MACrC,gBAAA,EAAkB,OAAO,gBAAA,KAAqB,KAAA;AAAA,MAC9C,YAAA,EAAc,OAAO,YAAA,IAAgB,EAAA;AAAA,MACrC,gBAAA,EAAkB,OAAO,gBAAA,IAAoB;AAAA,KAC/C;AAGA,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,YAAA,CAAa,IAAA,CAAK,OAAO,gBAAgB,CAAA;AACjE,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,CAAU;AAAA,MAC7B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,iBAAA,EAAmB,KAAK,MAAA,CAAO,iBAAA;AAAA,MAC/B,aAAA,EAAe,KAAK,MAAA,CAAO,aAAA;AAAA,MAC3B,UAAA,EAAY,KAAK,MAAA,CAAO,UAAA;AAAA,MACxB,eAAA,EAAiB,IAAA,CAAK,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAAA,MACnD,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,KACtB,CAAA;AAED,IAAA,IAAI,IAAA,CAAK,OAAO,gBAAA,EAAkB;AAChC,MAAA,IAAA,CAAK,UAAA,GAAa,IAAI,UAAA,CAAW;AAAA,QAC/B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,QACpB,YAAA,EAAc,IAAA,CAAK,MAAA,CAAO,YAAA,IAAgB,MAAA;AAAA,QAC1C,MAAA,EAAQ,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AAAA,QACrC,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,OACtB,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAA,GAAsB;AAE1B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,aAAA,EAAc;AACnD,IAAA,IAAI,UAAA,EAAY;AAEd,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,SAAA,GAAa,IAAA,GAAO,GAAA;AACjD,MAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,EAAW;AAC1B,QAAA,IAAA,CAAK,eAAA,GAAkB,UAAA;AACvB,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,UAAU,CAAA;AAC7B,QAAA;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,YAAA,CAAa,eAAA,EAAgB;AACvD,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,CAAK,mBAAmB,YAAY,CAAA;AAC1C,YAAA;AAAA,UACF,SAAS,KAAA,EAAO;AAEd,YAAA,IAAA,CAAK,aAAa,YAAA,EAAa;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,gBAAA,IAAoB,IAAA,CAAK,eAAe,IAAA,EAAM;AAC5D,MAAA,IAAA,CAAK,WAAW,IAAA,EAAK;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,OAAA,EAA0C;AAC3D,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,OAAO,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAA+B;AAC7B,IAAA,OAAO,IAAA,CAAK,eAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAA2B;AACzB,IAAA,OAAO,KAAK,eAAA,KAAoB,IAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,GAAwB;AAE5B,IAAA,IAAI,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACrC,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,QAAQ,kBAAA,EAAoB;AAAA,UACrC,MAAA,EAAQ,MAAA;AAAA,UACR,IAAA,EAAM,EAAE,KAAA,EAAO,IAAA,CAAK,gBAAgB,WAAA,EAAY;AAAA,UAChD,WAAA,EAAa;AAAA;AAAA,SACd,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AAEd,QAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,KAAK,CAAA;AAAA,MAC3D;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,IAAA,IAAA,CAAK,aAAa,YAAA,EAAa;AAC/B,IAAA,IAAA,CAAK,OAAO,QAAA,EAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAsB;AAC/E,IAAA,MAAM,MAAM,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GAClC,QAAA,GACA,GAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG,SAAS,UAAA,CAAW,GAAG,IAAI,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA,CAAA;AAEpF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,GAAG,OAAA,CAAQ;AAAA,KACb;AAGA,IAAA,IAAI,OAAA,CAAQ,WAAA,KAAgB,KAAA,IAAS,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACtE,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,gBAAgB,WAAW,CAAA,CAAA;AAAA,IACvE;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,MAC1B;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,MAAA,KAAW,KAAA,EAAO;AAC5C,MAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,YAAY,CAAA;AAG9C,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,IAAA,CAAK,eAAA,EAAiB;AACnD,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,YAAA,CAAa,eAAA,EAAgB;AACvD,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,mBAAmB,YAAY,CAAA;AAE1C,UAAA,IAAI,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACrC,YAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,gBAAgB,WAAW,CAAA,CAAA;AACrE,YAAA,OAAO,MAAM,GAAA,EAAK,EAAE,GAAG,YAAA,EAAc,SAAS,CAAA;AAAA,UAChD;AAAA,QACF,SAAS,KAAA,EAAO;AAEd,UAAA,MAAM,KAAK,MAAA,EAAO;AAClB,UAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAoB,aAAA,EAAkD;AAClF,IAAA,MAAM,QAAA,GAAqB;AAAA,MACzB,aAAa,aAAA,CAAc,YAAA;AAAA,MAC3B,aAAA,EAAe,cAAc,IAAA,CAAK,aAAA;AAAA,MAClC,MAAA,EAAQ,cAAc,IAAA,CAAK,MAAA;AAAA,MAC3B,WAAA,EAAa,cAAc,IAAA,CAAK,WAAA;AAAA,MAChC,cAAA,EAAgB,cAAc,IAAA,CAAK,cAAA;AAAA,MACnC,KAAA,EAAO,cAAc,IAAA,CAAK,KAAA;AAAA,MAC1B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAGA,IAAA,IAAA,CAAK,aAAa,SAAA,CAAU,QAAA,EAAU,aAAA,CAAc,aAAA,EAAe,cAAc,UAAU,CAAA;AAG3F,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,QAAA,EAA0B;AAE/C,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,EAAI,GAAK,IAAI,EAAA,GAAK,GAAA;AAC9C,IAAA,IAAI,QAAA,CAAS,YAAY,cAAA,EAAgB;AACvC,MAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAA;AACtD,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAmB,YAAA,EAAqC;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,aAAA,EAAe;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,UAAA,EAAY,eAAA;AAAA,QACZ,aAAA,EAAe;AAAA,OAChB;AAAA,KACF,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,aAAA,GAAoC,MAAM,QAAA,CAAS,IAAA,EAAK;AAC9D,IAAA,MAAM,IAAA,CAAK,oBAAoB,aAAa,CAAA;AAAA,EAC9C;AACF;;;ACzOO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,UAAA,EAAY,OAAO,UAAA,IAAc;AAAA,KACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAsB;AAC/E,IAAA,MAAM,MAAM,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GAClC,QAAA,GACA,GAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG,SAAS,UAAA,CAAW,GAAG,IAAI,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA,CAAA;AAEpF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,eAAA,EAAiB,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACtC,GAAG,OAAA,CAAQ;AAAA,KACb;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,MAC1B;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,MAAA,KAAW,KAAA,EAAO;AAC5C,MAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,YAAY,CAAA;AAE9C,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,YAAY,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,eAAe,CAAA;AACnE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,QAAA,CAAS,MAAM,IAAI,QAAA,CAAS,UAAU,CAAA,GAAA,EAAM,SAAS,CAAA,CAAE,CAAA;AAAA,IAC7F;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,GAA4B;AAChC,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,cAAc,EAAE,WAAA,EAAa,OAAO,CAAA;AACxE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,GAA8B;AAClC,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAa,CAAA;AACjD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAA,CAAkB,MAAA,EAAgB,OAAA,EAA+B;AACrE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAe,MAAM,CAAA,kBAAA,EAAqB,OAAO,CAAA,CAAE,CAAA;AACvF,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,CACJ,MAAA,EACA,OAAA,EACA,OAAA,EAKc;AACd,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB,EAAE,SAAS,CAAA;AAC9C,IAAA,IAAI,SAAS,QAAA,EAAU,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,QAAQ,QAAQ,CAAA;AACjE,IAAA,IAAI,SAAS,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,QAAA,EAAU,QAAQ,MAAM,CAAA;AAC3D,IAAA,IAAI,OAAA,EAAS,OAAO,MAAA,CAAO,MAAA,CAAO,SAAS,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAA;AAEnE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,YAAA,EAAe,MAAM,CAAA,MAAA,EAAS,MAAA,CAAO,QAAA,EAAU,CAAA,CAAE,CAAA;AACrF,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,MAAA,EASJ;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB;AAAA,MACnD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,MAAA;AAAA,MACN,OAAA,EAAS,OAAO,cAAA,GAAiB;AAAA,QAC/B,mBAAmB,MAAA,CAAO;AAAA,OAC5B,GAAI;AAAA,KACL,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,MAAA,EAA8B;AAClD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,0BAAA,EAA6B,MAAM,CAAA,CAAE,CAAA;AACzE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,MAAA,EAA8B;AACjD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,yBAAA,EAA4B,MAAM,CAAA,CAAE,CAAA;AACxE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,MAAA,EAIE;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB;AAAA,MACnD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,KAAA,EAIF;AAChB,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,KAAA;AAAM,KACf,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAA,CACJ,OAAA,EACA,QAAA,EAMc;AACd,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,OAAO,CAAA,SAAA,CAAA,EAAa;AAAA,MAClE,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,OAAA,EAA+B;AAC3C,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,OAAO,CAAA,CAAA,EAAI;AAAA,MACzD,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,QAAA,EAAkC;AACpD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,QAAA;AAAS,KAClB,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,MAAA,EAGA;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB;AAAA,MAC1D,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AACF","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (pollCount % 10 === 0) {\r\n // Log every 1 second (10 * 100ms) for debugging\r\n console.log('[OAuthFlow] Polling localStorage for callback...', { key: storageKey, found: !!stored, pollCount });\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout (increased from 10s)\r\n console.log('[OAuthFlow] ✅ Found OAuth callback in localStorage!', { age: `${age}ms`, hasCode: !!data.code });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state.substring(0, 10) + '...',\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] 🔍 Polling localStorage...', { \r\n key: storageKey, \r\n keyPreview: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n state: state,\r\n statePreview: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Also check for ANY omenx_oauth_callback keys (debugging)\r\n if (pollCount === 10) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] 🔍 Found localStorage keys:', { \r\n count: allKeys.length,\r\n keys: allKeys,\r\n lookingFor: storageKey,\r\n lookingForPreview: storageKey.substring(0, 50) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] 🔍 Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state,\r\n expectedState: state,\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code\r\n });\r\n } catch (e) {\r\n // Ignore parse errors\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n console.log('[OAuthFlow] ✅ Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 10) + '...',\r\n expectedState: state.substring(0, 10) + '...'\r\n });\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] ✅✅✅ Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...'\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] ⚠️ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n console.warn('[OAuthFlow] ⚠️ State mismatch!', {\r\n storedState: data.state?.substring(0, 20),\r\n expectedState: state.substring(0, 20),\r\n statesMatch: data.state === state\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] ❌ Error parsing localStorage callback:', error, { stored });\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -138,15 +138,58 @@ var OAuthFlow = class {
|
|
|
138
138
|
const storageKey = `omenx_oauth_callback_${state}`;
|
|
139
139
|
const stored = localStorage.getItem(storageKey);
|
|
140
140
|
if (pollCount % 10 === 0) {
|
|
141
|
-
console.log("[OAuthFlow] Polling localStorage
|
|
141
|
+
console.log("[OAuthFlow] \u{1F50D} Polling localStorage...", {
|
|
142
|
+
key: storageKey,
|
|
143
|
+
keyPreview: storageKey.substring(0, 50) + "...",
|
|
144
|
+
found: !!stored,
|
|
145
|
+
pollCount,
|
|
146
|
+
state,
|
|
147
|
+
statePreview: state.substring(0, 20) + "..."
|
|
148
|
+
});
|
|
149
|
+
if (pollCount === 10) {
|
|
150
|
+
const allKeys = Object.keys(localStorage).filter((k) => k.startsWith("omenx_oauth_callback_"));
|
|
151
|
+
console.log("[OAuthFlow] \u{1F50D} Found localStorage keys:", {
|
|
152
|
+
count: allKeys.length,
|
|
153
|
+
keys: allKeys,
|
|
154
|
+
lookingFor: storageKey,
|
|
155
|
+
lookingForPreview: storageKey.substring(0, 50) + "..."
|
|
156
|
+
});
|
|
157
|
+
for (const key of allKeys) {
|
|
158
|
+
const storedData = localStorage.getItem(key);
|
|
159
|
+
if (storedData) {
|
|
160
|
+
try {
|
|
161
|
+
const data = JSON.parse(storedData);
|
|
162
|
+
console.log("[OAuthFlow] \u{1F50D} Checking stored key:", {
|
|
163
|
+
key: key.substring(0, 50) + "...",
|
|
164
|
+
storedState: data.state,
|
|
165
|
+
expectedState: state,
|
|
166
|
+
statesMatch: data.state === state,
|
|
167
|
+
hasCode: !!data.code
|
|
168
|
+
});
|
|
169
|
+
} catch (e) {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
142
174
|
}
|
|
143
175
|
if (stored) {
|
|
144
176
|
try {
|
|
145
177
|
const data = JSON.parse(stored);
|
|
178
|
+
console.log("[OAuthFlow] \u2705 Found stored data!", {
|
|
179
|
+
hasCode: !!data.code,
|
|
180
|
+
hasState: !!data.state,
|
|
181
|
+
stateMatch: data.state === state,
|
|
182
|
+
storedState: data.state?.substring(0, 10) + "...",
|
|
183
|
+
expectedState: state.substring(0, 10) + "..."
|
|
184
|
+
});
|
|
146
185
|
if (data.code && data.state === state) {
|
|
147
186
|
const age = Date.now() - (data.timestamp || 0);
|
|
148
187
|
if (age < 3e4) {
|
|
149
|
-
console.log("[OAuthFlow] \u2705
|
|
188
|
+
console.log("[OAuthFlow] \u2705\u2705\u2705 Processing OAuth callback from localStorage!", {
|
|
189
|
+
age: `${age}ms`,
|
|
190
|
+
hasCode: !!data.code,
|
|
191
|
+
codePreview: data.code.substring(0, 10) + "..."
|
|
192
|
+
});
|
|
150
193
|
clearInterval(pollInterval);
|
|
151
194
|
storageListener(new StorageEvent("storage", {
|
|
152
195
|
key: storageKey,
|
|
@@ -154,12 +197,18 @@ var OAuthFlow = class {
|
|
|
154
197
|
storageArea: localStorage
|
|
155
198
|
}));
|
|
156
199
|
} else {
|
|
157
|
-
console.warn("[OAuthFlow] Callback data too old, removing:", { age: `${age}ms` });
|
|
200
|
+
console.warn("[OAuthFlow] \u26A0\uFE0F Callback data too old, removing:", { age: `${age}ms` });
|
|
158
201
|
localStorage.removeItem(storageKey);
|
|
159
202
|
}
|
|
203
|
+
} else {
|
|
204
|
+
console.warn("[OAuthFlow] \u26A0\uFE0F State mismatch!", {
|
|
205
|
+
storedState: data.state?.substring(0, 20),
|
|
206
|
+
expectedState: state.substring(0, 20),
|
|
207
|
+
statesMatch: data.state === state
|
|
208
|
+
});
|
|
160
209
|
}
|
|
161
210
|
} catch (error) {
|
|
162
|
-
console.error("[OAuthFlow] Error parsing localStorage callback:", error);
|
|
211
|
+
console.error("[OAuthFlow] \u274C Error parsing localStorage callback:", error, { stored });
|
|
163
212
|
}
|
|
164
213
|
}
|
|
165
214
|
}, 100);
|
|
@@ -199,10 +248,13 @@ var OAuthFlow = class {
|
|
|
199
248
|
broadcastChannel = null;
|
|
200
249
|
}
|
|
201
250
|
console.log("[OAuthFlow] \u{1F50D} Starting OAuth flow, listening for callback...", {
|
|
202
|
-
state
|
|
251
|
+
state,
|
|
252
|
+
statePreview: state.substring(0, 20) + "...",
|
|
253
|
+
stateLength: state.length,
|
|
203
254
|
hasOpener: !!window.opener,
|
|
204
255
|
polling: true,
|
|
205
|
-
broadcastChannel: true
|
|
256
|
+
broadcastChannel: true,
|
|
257
|
+
expectedKey: `omenx_oauth_callback_${state}`
|
|
206
258
|
});
|
|
207
259
|
let messageReceived = false;
|
|
208
260
|
const originalMessageListener = messageListener;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (pollCount % 10 === 0) {\r\n // Log every 1 second (10 * 100ms) for debugging\r\n console.log('[OAuthFlow] Polling localStorage for callback...', { key: storageKey, found: !!stored, pollCount });\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout (increased from 10s)\r\n console.log('[OAuthFlow] ✅ Found OAuth callback in localStorage!', { age: `${age}ms`, hasCode: !!data.code });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state.substring(0, 10) + '...',\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] 🔍 Polling localStorage...', { \r\n key: storageKey, \r\n keyPreview: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n state: state,\r\n statePreview: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Also check for ANY omenx_oauth_callback keys (debugging)\r\n if (pollCount === 10) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] 🔍 Found localStorage keys:', { \r\n count: allKeys.length,\r\n keys: allKeys,\r\n lookingFor: storageKey,\r\n lookingForPreview: storageKey.substring(0, 50) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] 🔍 Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state,\r\n expectedState: state,\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code\r\n });\r\n } catch (e) {\r\n // Ignore parse errors\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n console.log('[OAuthFlow] ✅ Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 10) + '...',\r\n expectedState: state.substring(0, 10) + '...'\r\n });\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] ✅✅✅ Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...'\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] ⚠️ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n console.warn('[OAuthFlow] ⚠️ State mismatch!', {\r\n storedState: data.state?.substring(0, 20),\r\n expectedState: state.substring(0, 20),\r\n statesMatch: data.state === state\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] ❌ Error parsing localStorage callback:', error, { stored });\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED