@nibgate/sdk 0.2.37 → 0.2.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nibgate/sdk",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
4
4
  "description": "Framework-agnostic browser and server package for creator-owned gated content, unlock events, and receipts.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -259,7 +259,11 @@ export function renderDefaultUnlockUI(container, resource, options = {}) {
259
259
  gwOverlay.addEventListener('click', (e) => { if (e.target === gwOverlay) { gwOverlay.remove(); gwOverlay = null; document.removeEventListener('keydown', onDepKey); } });
260
260
  document.body.appendChild(gwOverlay);
261
261
  document.addEventListener('keydown', onDepKey);
262
- import('./default-ui.js').then(m => m.renderDefaultGatewayWalletUI(modal, options.gatewayOptions || {})).catch(() => {});
262
+ import('./default-ui.js').then(m => m.renderDefaultGatewayWalletUI(modal, {
263
+ address: ctrl.getWalletAddress(),
264
+ gatewayBalanceUrl: options.gatewayBalanceUrl,
265
+ ...(options.gatewayOptions || {}),
266
+ })).catch(() => {});
263
267
  }
264
268
  function onDepKey(e) { if (e.key === 'Escape' && gwOverlay) { gwOverlay.remove(); gwOverlay = null; document.removeEventListener('keydown', onDepKey); } }
265
269
 
@@ -421,9 +425,10 @@ export function renderDefaultGatewayWalletUI(container, options = {}) {
421
425
  <div style="display:flex;gap:12px;margin-bottom:20px">
422
426
  <div data-gw-wallet-card style="flex:1;background:${theme.bg};border:1px solid ${theme.border};border-radius:12px;padding:16px">
423
427
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px">
424
- <div style="font-size:12px;font-weight:600;color:${theme.muted};letter-spacing:.02em">Wallet</div>
425
- <button data-gw-connect style="font-size:12px;font-weight:600;cursor:pointer;border:1px solid ${theme.accent};background:transparent;color:${theme.accent};border-radius:8px;padding:4px 12px;font-family:inherit">Connect</button>
428
+ <div></div>
429
+ <span data-gw-connect-label style="font-size:12px;font-weight:600;color:${theme.accent}">Connected</span>
426
430
  </div>
431
+ <div data-gw-wallet-addr class="nui-mono" style="font-size:13px;color:${theme.muted};margin-bottom:4px"></div>
427
432
  <div data-gw-wallet-balance class="nui-mono" style="font-size:24px;font-weight:700;color:${theme.fg}">—</div>
428
433
  </div>
429
434
  <div style="flex:1;background:${theme.bg};border:1px solid ${theme.border};border-radius:12px;padding:16px">
@@ -442,6 +447,13 @@ export function renderDefaultGatewayWalletUI(container, options = {}) {
442
447
 
443
448
  const formEl = wrap.querySelector('[data-gw-form]');
444
449
  const tabs = wrap.querySelectorAll('[data-tab]');
450
+ const walletAddrEl = wrap.querySelector('[data-gw-wallet-addr]');
451
+ const walletBalEl = wrap.querySelector('[data-gw-wallet-balance]');
452
+ const gwBalEl = wrap.querySelector('[data-gw-balance]');
453
+
454
+ const ARC_RPC = 'https://arc-testnet.drpc.org';
455
+ const USDC = '0x3600000000000000000000000000000000000000';
456
+ const BALANCE_OF = '0x70a08231';
445
457
 
446
458
  function select(btns, t) {
447
459
  btns.forEach(b => {
@@ -451,6 +463,60 @@ export function renderDefaultGatewayWalletUI(container, options = {}) {
451
463
  });
452
464
  }
453
465
 
466
+ const GATEWAY = '0x0077777d7EBA4688BDeF3E311b846F25870A19B9';
467
+ const SEL_APPROVE = '0x095ea7b3';
468
+ const SEL_DEPOSIT = '0x47e7ef24';
469
+
470
+ function parse6(v) {
471
+ const [w = '0', f = ''] = String(v).split('.');
472
+ return BigInt(w + f.padEnd(6, '0').slice(0, 6));
473
+ }
474
+
475
+ function addr32(a) { return '000000000000000000000000' + a.slice(2); }
476
+
477
+ function setTx(msg, ok) {
478
+ const el = formEl.querySelector('[data-gw-tx]');
479
+ if (!el) return;
480
+ el.style.display = 'block';
481
+ el.style.color = ok ? theme.accent : '#dc2626';
482
+ el.textContent = msg;
483
+ }
484
+
485
+ async function doDeposit() {
486
+ if (!window.ethereum) { setTx('No wallet found'); return; }
487
+ const input = formEl.querySelector('[data-gw-deposit-amount]');
488
+ const amt = input?.value;
489
+ if (!amt || Number(amt) <= 0) { setTx('Enter an amount'); return; }
490
+ const btn = formEl.querySelector('[data-gw-deposit]');
491
+ try {
492
+ btn.disabled = true;
493
+ btn.textContent = 'Approving\u2026';
494
+ const accts = await window.ethereum.request({ method: 'eth_accounts' });
495
+ const addr = accts?.[0];
496
+ if (!addr) { setTx('Connect wallet'); btn.disabled = false; btn.textContent = 'Deposit'; return; }
497
+ const amount = parse6(amt).toString(16);
498
+ const approveTx = await window.ethereum.request({
499
+ method: 'eth_sendTransaction',
500
+ params: [{ from: addr, to: USDC, data: SEL_APPROVE + addr32(GATEWAY) + amount.padStart(64, '0') }],
501
+ });
502
+ setTx('Approved: ' + approveTx.slice(0, 10) + '\u2026', true);
503
+ btn.textContent = 'Depositing\u2026';
504
+ const depositTx = await window.ethereum.request({
505
+ method: 'eth_sendTransaction',
506
+ params: [{ from: addr, to: GATEWAY, data: SEL_DEPOSIT + addr32(USDC) + amount.padStart(64, '0') }],
507
+ });
508
+ setTx('Deposited: ' + depositTx.slice(0, 10) + '\u2026', true);
509
+ updateWallet();
510
+ btn.textContent = 'Deposit';
511
+ } catch (e) { setTx(e?.message || 'Deposit failed'); }
512
+ btn.disabled = false;
513
+ btn.textContent = 'Deposit';
514
+ }
515
+
516
+ async function doWithdraw() {
517
+ setTx('Withdraw via admin dashboard', false);
518
+ }
519
+
454
520
  function render(t) {
455
521
  tab = t;
456
522
  select(tabs, t);
@@ -461,6 +527,7 @@ export function renderDefaultGatewayWalletUI(container, options = {}) {
461
527
  <button type="button" data-gw-deposit class="nui-btn nui-btn-primary" style="width:100%;padding:16px 28px;font-size:20px">Deposit</button>
462
528
  <div data-gw-tx class="nui-mono" style="font-size:12px;color:${theme.muted};word-break:break-all;margin-top:12px;display:none"></div>
463
529
  `;
530
+ formEl.querySelector('[data-gw-deposit]')?.addEventListener('click', doDeposit);
464
531
  } else {
465
532
  formEl.innerHTML = `
466
533
  <label class="nui-label">Amount (USDC)</label>
@@ -468,11 +535,63 @@ export function renderDefaultGatewayWalletUI(container, options = {}) {
468
535
  <button type="button" data-gw-withdraw class="nui-btn nui-btn-primary" style="width:100%;padding:16px 28px;font-size:20px">Withdraw to your wallet</button>
469
536
  <div data-gw-tx class="nui-mono" style="font-size:12px;color:${theme.muted};word-break:break-all;margin-top:12px;display:none"></div>
470
537
  `;
538
+ formEl.querySelector('[data-gw-withdraw]')?.addEventListener('click', doWithdraw);
471
539
  }
472
540
  }
473
541
 
542
+ function shortAddress(a) { return a ? a.slice(0, 6) + '...' + a.slice(-4) : ''; }
543
+
544
+ async function updateWallet() {
545
+ if (!window.ethereum) return;
546
+ try {
547
+ const accts = await window.ethereum.request({ method: 'eth_accounts' });
548
+ const addr = Array.isArray(accts) && accts[0] ? accts[0] : null;
549
+ if (addr) {
550
+ walletAddrEl.textContent = shortAddress(addr);
551
+ fetchWalletUsdc(addr);
552
+ fetchGwBal(addr);
553
+ }
554
+ } catch {}
555
+ }
556
+
557
+ async function fetchWalletUsdc(addr) {
558
+ try {
559
+ const r = await fetch(ARC_RPC, {
560
+ method: 'POST',
561
+ headers: { 'Content-Type': 'application/json' },
562
+ body: JSON.stringify({
563
+ jsonrpc: '2.0', method: 'eth_call',
564
+ params: [{ to: USDC, data: BALANCE_OF + addr.slice(2).padStart(64, '0') }, 'latest'],
565
+ id: 1,
566
+ }),
567
+ });
568
+ const d = await r.json();
569
+ const bal = d.result ? parseInt(d.result, 16) / 1e6 : 0;
570
+ walletBalEl.textContent = bal.toFixed(2) + ' USDC';
571
+ } catch { walletBalEl.textContent = '—'; }
572
+ }
573
+
574
+ async function fetchGwBal(addr) {
575
+ if (!options.gatewayBalanceUrl) { gwBalEl.textContent = '—'; return; }
576
+ try {
577
+ const r = await fetch(options.gatewayBalanceUrl, {
578
+ method: 'POST',
579
+ headers: { 'Content-Type': 'application/json' },
580
+ body: JSON.stringify({ address: addr }),
581
+ });
582
+ const data = await r.json();
583
+ gwBalEl.textContent = data?.balance || '0.00 USDC';
584
+ } catch { gwBalEl.textContent = '—'; }
585
+ }
586
+
587
+ if (window.ethereum) {
588
+ window.ethereum.on('accountsChanged', updateWallet);
589
+ }
590
+
474
591
  render('deposit');
475
592
  tabs.forEach(b => b.addEventListener('click', () => render(b.dataset.tab)));
476
593
 
594
+ setTimeout(updateWallet, 100);
595
+
477
596
  return { element: wrap, destroy: () => wrap.remove(), switchTab: render };
478
597
  }