@fivenorth/loop-sdk 0.1.3 → 0.3.0

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/README.md CHANGED
@@ -146,7 +146,7 @@ try {
146
146
 
147
147
  # API
148
148
 
149
-
149
+ Coming soon
150
150
 
151
151
  # Development Guide
152
152
 
@@ -158,12 +158,14 @@ To install dependencies:
158
158
  bun install
159
159
  ```
160
160
 
161
- To run:
161
+ To run the dev server, that is also auto re-compile the sdk:
162
162
 
163
163
  ```bash
164
- bun run index.ts
164
+ bun start
165
165
  ```
166
166
 
167
+ Upon doing so you can visit http://localhost:3030/ to see the local demo app, serve in `demo/test.html` and SDK is auto compile so you can actively working and trying out the SDK.
168
+
167
169
  # Publish the package to NPM
168
170
 
169
171
 
package/dist/index.js CHANGED
@@ -2213,16 +2213,18 @@ class Provider {
2213
2213
  connection;
2214
2214
  party_id;
2215
2215
  public_key;
2216
+ email;
2216
2217
  auth_token;
2217
2218
  requests = new Map;
2218
2219
  requestTimeout = 30000;
2219
- constructor({ connection, party_id, public_key, auth_token, requestTimeout }) {
2220
+ constructor({ connection, party_id, public_key, auth_token, email, requestTimeout }) {
2220
2221
  if (!connection) {
2221
2222
  throw new Error("Provider requires a connection object.");
2222
2223
  }
2223
2224
  this.connection = connection;
2224
2225
  this.party_id = party_id;
2225
2226
  this.public_key = public_key;
2227
+ this.email = email;
2226
2228
  this.auth_token = auth_token;
2227
2229
  this.requestTimeout = requestTimeout || 30000;
2228
2230
  }
@@ -2286,15 +2288,18 @@ class LoopSDK {
2286
2288
  appName = "Unknown";
2287
2289
  connection = null;
2288
2290
  provider = null;
2291
+ openMode = "popup";
2292
+ popupWindow = null;
2289
2293
  onAccept = null;
2290
2294
  onReject = null;
2291
2295
  overlay = null;
2292
2296
  ticketId = null;
2293
2297
  constructor() {}
2294
- init({ appName, network, walletUrl, apiUrl, onAccept, onReject }) {
2298
+ init({ appName, network, walletUrl, apiUrl, onAccept, onReject, openMode }) {
2295
2299
  this.appName = appName;
2296
2300
  this.onAccept = onAccept || null;
2297
2301
  this.onReject = onReject || null;
2302
+ this.openMode = openMode ?? "popup";
2298
2303
  this.connection = new Connection({ network, walletUrl, apiUrl });
2299
2304
  }
2300
2305
  async connect() {
@@ -2308,23 +2313,30 @@ class LoopSDK {
2308
2313
  const existingConnectionRaw = localStorage.getItem("loop_connect");
2309
2314
  if (existingConnectionRaw) {
2310
2315
  try {
2311
- const { ticketId, authToken, partyId, publicKey } = JSON.parse(existingConnectionRaw);
2316
+ let canReuseTicket = true;
2317
+ const { ticketId, authToken, partyId, publicKey, email } = JSON.parse(existingConnectionRaw);
2312
2318
  if (authToken && partyId && publicKey) {
2313
2319
  try {
2314
2320
  const verifiedAccount = await this.connection.verifySession(authToken);
2315
2321
  if (verifiedAccount.party_id === partyId) {
2316
- this.provider = new Provider({ connection: this.connection, party_id: partyId, auth_token: authToken, public_key: publicKey });
2322
+ this.provider = new Provider({ connection: this.connection, party_id: partyId, auth_token: authToken, public_key: publicKey, email });
2317
2323
  this.onAccept?.(this.provider);
2318
2324
  if (ticketId) {
2319
2325
  this.connection.connectWebSocket(ticketId, this.handleWebSocketMessage.bind(this));
2320
2326
  }
2321
2327
  return;
2328
+ } else {
2329
+ console.warn("[LoopSDK] Sttored partyId does not march verified account. Clearing cached session.");
2330
+ canReuseTicket = false;
2331
+ localStorage.removeItem("loop_connect");
2322
2332
  }
2323
2333
  } catch (err) {
2324
2334
  console.error("Auto-login failed, token is invalid. Starting new connection.", err);
2335
+ canReuseTicket = false;
2336
+ localStorage.removeItem("loop_connect");
2325
2337
  }
2326
2338
  }
2327
- if (ticketId) {
2339
+ if (ticketId && canReuseTicket) {
2328
2340
  this.ticketId = ticketId;
2329
2341
  const connectUrl = `${this.connection.walletUrl}/.connect/?ticketId=${ticketId}`;
2330
2342
  this.showQrCode(connectUrl);
@@ -2351,10 +2363,12 @@ class LoopSDK {
2351
2363
  }
2352
2364
  handleWebSocketMessage(event) {
2353
2365
  const message = JSON.parse(event.data);
2366
+ console.log("[LoopSDK] WS message received:", message);
2354
2367
  if (message.type === "handshake_accept" /* HANDSHAKE_ACCEPT */) {
2355
- const { authToken, partyId, publicKey } = message.payload || {};
2368
+ console.log("[LoopSDK] Entering HANDSHAKE_ACCEPT flow");
2369
+ const { authToken, partyId, publicKey, email } = message.payload || {};
2356
2370
  if (authToken && partyId && publicKey) {
2357
- this.provider = new Provider({ connection: this.connection, party_id: partyId, auth_token: authToken, public_key: publicKey });
2371
+ this.provider = new Provider({ connection: this.connection, party_id: partyId, auth_token: authToken, public_key: publicKey, email });
2358
2372
  const connectionInfoRaw = localStorage.getItem("loop_connect");
2359
2373
  if (connectionInfoRaw) {
2360
2374
  try {
@@ -2362,24 +2376,59 @@ class LoopSDK {
2362
2376
  connectionInfo.authToken = authToken;
2363
2377
  connectionInfo.partyId = partyId;
2364
2378
  connectionInfo.publicKey = publicKey;
2379
+ connectionInfo.email = email;
2365
2380
  localStorage.setItem("loop_connect", JSON.stringify(connectionInfo));
2366
2381
  this.onAccept?.(this.provider);
2367
2382
  this.hideQrCode();
2368
2383
  this.connection?.connectWebSocket(connectionInfo.ticketId, this.handleWebSocketMessage.bind(this));
2384
+ console.log("[LoopSDK] HANDSHAKE_ACCEPT: closing popup (if exists)");
2385
+ if (this.popupWindow && !this.popupWindow.closed) {
2386
+ this.popupWindow.close();
2387
+ }
2388
+ this.popupWindow = null;
2369
2389
  } catch (error) {
2370
2390
  console.error("Failed to update local storage with auth token.", error);
2371
2391
  }
2372
2392
  }
2373
2393
  }
2374
2394
  } else if (message.type === "handshake_reject" /* HANDSHAKE_REJECT */) {
2395
+ console.log("[LoopSDK] Entering HANDSHAKE_REJECT flow");
2375
2396
  localStorage.removeItem("loop_connect");
2376
2397
  this.connection?.ws?.close();
2377
2398
  this.onReject?.();
2378
2399
  this.hideQrCode();
2400
+ console.log("[LoopSDK] HANDSHAKE_REJECT: closing popup (if exists)");
2401
+ if (this.popupWindow && !this.popupWindow.closed) {
2402
+ this.popupWindow.close();
2403
+ }
2404
+ this.popupWindow = null;
2379
2405
  } else if (this.provider) {
2380
2406
  this.provider.handleResponse(message);
2381
2407
  }
2382
2408
  }
2409
+ openWallet(url) {
2410
+ if (typeof window === "undefined") {
2411
+ return;
2412
+ }
2413
+ if (this.openMode === "popup") {
2414
+ const width = 480;
2415
+ const height = 720;
2416
+ const left = (window.innerWidth - width) / 2 + window.screenX;
2417
+ const top = (window.innerWidth - height) / 2 + window.screenY;
2418
+ const features = `width=${width},height=${height},` + `left=${left},top=${top},` + "menubar=no,toolbar=no,location=no," + "resizable=yes,scrollbars=yes,status=no";
2419
+ const popup = window.open(url, "loop-wallet", features);
2420
+ if (!popup) {
2421
+ window.open(url, "_blank", "noopener,noreferrer");
2422
+ return;
2423
+ }
2424
+ this.popupWindow = popup;
2425
+ try {
2426
+ popup.focus();
2427
+ } catch {}
2428
+ return;
2429
+ }
2430
+ window.open(url, "_blank", "noopener,noreferrer");
2431
+ }
2383
2432
  showQrCode(url) {
2384
2433
  if (typeof window === "undefined" || typeof document === "undefined") {
2385
2434
  return;
@@ -2409,7 +2458,10 @@ class LoopSDK {
2409
2458
  link.textContent = "Or click here to connect";
2410
2459
  link.style.color = "white";
2411
2460
  link.style.marginTop = "20px";
2412
- link.target = "_blank";
2461
+ link.onclick = (e) => {
2462
+ e.preventDefault();
2463
+ this.openWallet(url);
2464
+ };
2413
2465
  overlay.appendChild(link);
2414
2466
  overlay.onclick = (e) => {
2415
2467
  if (e.target === overlay) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fivenorth/loop-sdk",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "author": "hello@fivenorth.io",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",