@nibgate/sdk 0.2.1 → 0.2.4

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/nibgate.js CHANGED
@@ -142,7 +142,6 @@ var Nibgate = (() => {
142
142
  createOnchainRating: () => createOnchainRating,
143
143
  createTransferCheckout: () => createTransferCheckout,
144
144
  createWalletCheckout: () => createWalletCheckout,
145
- gate: () => gate,
146
145
  mountRatingUI: () => mountRatingUI,
147
146
  nibgate: () => nibgate,
148
147
  normalizeAccessPolicy: () => normalizeAccessPolicy,
@@ -216,6 +215,24 @@ var Nibgate = (() => {
216
215
  mode: UNLOCK_MODES.includes(mode) ? mode : "one_time"
217
216
  };
218
217
  }
218
+ function browserEnv() {
219
+ return typeof window !== "undefined" ? window : null;
220
+ }
221
+ function metaContent(name) {
222
+ const win = browserEnv();
223
+ if (!win) return "";
224
+ const selector = `meta[name="${name}"], meta[property="${name}"]`;
225
+ const node = win.document.querySelector(selector);
226
+ return node ? node.getAttribute("content") || "" : "";
227
+ }
228
+ function autoDeriveUrl(path) {
229
+ const win = browserEnv();
230
+ if (!win || !path) return void 0;
231
+ return `${win.location.origin}${path.startsWith("/") ? path : "/" + path}`;
232
+ }
233
+ function autoDeriveImage() {
234
+ return metaContent("og:image") || void 0;
235
+ }
219
236
  function normalizeResource(resource = {}) {
220
237
  const input = typeof resource === "string" ? { id: resource } : resource || {};
221
238
  const {
@@ -230,6 +247,8 @@ var Nibgate = (() => {
230
247
  authorHandle,
231
248
  ...v1Input
232
249
  } = input;
250
+ const path = input.path || input.route || void 0;
251
+ const url = input.url || autoDeriveUrl(path) || void 0;
233
252
  return {
234
253
  ...v1Input,
235
254
  id: String(input.id || input.contentId || input.slug || "").trim(),
@@ -239,9 +258,9 @@ var Nibgate = (() => {
239
258
  paymentRail: normalizePaymentRail(input.paymentRail || input.paymentMode || input.rail),
240
259
  recipient: input.recipient || input.receiver || input.receiverAddress || input.payTo || input.creatorWallet || void 0,
241
260
  payTo: input.payTo || input.recipient || input.receiver || input.receiverAddress || input.creatorWallet || void 0,
242
- path: input.path || input.route || void 0,
243
- url: input.url || void 0,
244
- imageUrl: input.imageUrl || input.image || void 0,
261
+ path,
262
+ url,
263
+ imageUrl: input.imageUrl || input.image || autoDeriveImage() || void 0,
245
264
  tags: input.tags || void 0,
246
265
  access: normalizeAccessPolicy(input.access),
247
266
  unlock: normalizeUnlockPolicy(input.unlock),
@@ -281,7 +300,7 @@ var Nibgate = (() => {
281
300
  }
282
301
  if (isPaidResource(normalized)) {
283
302
  if (!hasValue(normalized.price)) errors.push("Paid content requires price.");
284
- if (!hasValue(normalized.recipient || normalized.payTo)) errors.push("Paid content requires recipient/payTo wallet.");
303
+ if (!hasValue(normalized.recipient || normalized.payTo)) warnings.push("Paid content should include recipient/payTo (server value from 402 challenge is used for actual payment).");
285
304
  }
286
305
  const score = Math.max(0, 100 - errors.length * 20 - warnings.length * 8);
287
306
  return {
@@ -293,31 +312,6 @@ var Nibgate = (() => {
293
312
  };
294
313
  }
295
314
 
296
- // src/core/rating.js
297
- function normalizeRating(input = {}) {
298
- const value = typeof input === "number" ? input : input.rating ?? input.stars ?? input.ratingValue ?? input.score;
299
- const numeric = Number.parseFloat(value);
300
- const ratingValue = Number.isFinite(numeric) ? Math.max(1, Math.min(50, numeric <= 5 ? Math.round(numeric * 10) : Math.round(numeric))) : null;
301
- return {
302
- ...input,
303
- rating: ratingValue ? ratingValue / 10 : void 0,
304
- ratingValue: ratingValue || void 0
305
- };
306
- }
307
- function ratingMessage(resource, rating = {}, options = {}) {
308
- const normalized = normalizeResource(resource);
309
- const normalizedRating = normalizeRating(rating);
310
- const value = normalizedRating.ratingValue || 0;
311
- return [
312
- "Nibgate content rating",
313
- `site:${options.siteDomain || options.domain || normalized.siteDomain || normalized.domain || ""}`,
314
- `content:${normalized.externalId || normalized.id}`,
315
- `url:${normalized.url || options.url || ""}`,
316
- `rating:${value}`,
317
- "I confirm this rating is tied to my unlock/payment proof."
318
- ].join("\n");
319
- }
320
-
321
315
  // src/browser/env.js
322
316
  function browserWindow() {
323
317
  return typeof window === "undefined" ? null : window;
@@ -435,241 +429,14 @@ var Nibgate = (() => {
435
429
  }
436
430
  }
437
431
 
438
- // src/browser/index.js
439
- init_json();
440
-
441
- // src/browser/reputation.js
442
- var RATE_CONTENT_SELECTOR = "0xc62fad09";
443
- var ZERO_HASH = `0x${"0".repeat(64)}`;
444
- var NIBGATE_CONTENT_HASH_NAMESPACE = "nibgate:content:v1";
445
- var NIBGATE_REPUTATION_CHAIN_ID = 5042002;
446
- var NIBGATE_REPUTATION_CHAIN_NAME = "Arc Testnet";
447
- var NIBGATE_REPUTATION_RPC_URL = "https://rpc.testnet.arc.network";
448
- var NIBGATE_REPUTATION_CONTRACT = "0x9f27fd62e75f86a3c7addfdba443aab1f930e281";
449
- var NIBGATE_REPUTATION_ABI = [
450
- {
451
- type: "function",
452
- name: "rateContent",
453
- stateMutability: "nonpayable",
454
- inputs: [
455
- { name: "contentId", type: "bytes32" },
456
- { name: "rating", type: "uint8" },
457
- { name: "reviewHash", type: "bytes32" },
458
- { name: "unlockRef", type: "string" }
459
- ],
460
- outputs: []
461
- }
462
- ];
463
- function stripHex(value = "") {
464
- return String(value || "").replace(/^0x/i, "").toLowerCase();
465
- }
466
- function wordRight(hex = "") {
467
- const clean = stripHex(hex);
468
- if (clean.length > 64) throw new Error("ABI word is too long.");
469
- return clean.padEnd(64, "0");
470
- }
471
- function numberWord(value = 0) {
472
- return Number(value || 0).toString(16).padStart(64, "0");
473
- }
474
- function utf8Hex(value = "") {
475
- return Array.from(new TextEncoder().encode(String(value || ""))).map((byte) => byte.toString(16).padStart(2, "0")).join("");
476
- }
477
- function encodeString(value = "") {
478
- const hex = utf8Hex(value);
479
- const byteLength = hex.length / 2;
480
- const paddedLength = Math.ceil(byteLength / 32) * 64;
481
- return numberWord(byteLength) + hex.padEnd(paddedLength, "0");
482
- }
483
- function encodeRateContent({ contentId, ratingValue, reviewHash, unlockRef }) {
484
- return RATE_CONTENT_SELECTOR + wordRight(contentId) + numberWord(ratingValue) + wordRight(reviewHash || ZERO_HASH) + numberWord(128) + encodeString(unlockRef || "");
485
- }
486
- function contentRatingHash(_resource, options = {}) {
487
- const contentId = options.contentId || options.contentHash;
488
- if (!contentId) {
489
- throw new Error("contentId/contentHash is required. Use the Nibgate backend prepare endpoint or pass a known content hash.");
490
- }
491
- return contentId;
492
- }
493
- function reviewTextHash(review = "") {
494
- if (!review) return ZERO_HASH;
495
- throw new Error("Text review hashing is not available in direct-browser mode. Pass reviewHash from your app/backend.");
496
- }
497
- async function prepareOnchainRating(resource, options = {}) {
498
- if (options.contentId || options.contentHash) return { contentId: options.contentId || options.contentHash };
499
- const prepareUrl = options.prepareUrl || options.indexUrl?.replace(/\/index$/, "/prepare");
500
- if (!prepareUrl) throw new Error("contentId/contentHash or prepareUrl is required for onchain rating.");
501
- const response = await fetch(prepareUrl, {
502
- method: "POST",
503
- headers: { "content-type": "application/json", ...options.indexHeaders || {} },
504
- body: JSON.stringify({
505
- siteId: options.siteId,
506
- token: options.token,
507
- resource,
508
- url: resource.url,
509
- path: resource.path
510
- })
511
- });
512
- const payload = await response.json().catch(() => ({}));
513
- if (!response.ok || !payload.contentHash) throw new Error(payload.error || "Could not prepare Nibgate onchain rating.");
514
- return payload;
515
- }
516
- async function rateContentOnchain(resource, options = {}) {
517
- const normalized = normalizeResource(resource);
518
- const rating = normalizeRating(options.rating ?? options.stars ?? options);
519
- if (!rating.ratingValue) throw new Error("Rating must be between 0.1 and 5 stars.");
520
- const provider = options.provider || globalThis?.ethereum;
521
- if (!provider?.request) throw new Error("Connect an EVM wallet to rate this content onchain.");
522
- const contractAddress = options.contractAddress || options.reputationContract || NIBGATE_REPUTATION_CONTRACT;
523
- if (!contractAddress) throw new Error("Nibgate reputation contract address is not configured.");
524
- const accounts = await provider.request({ method: "eth_requestAccounts" });
525
- const walletAddress = Array.isArray(accounts) ? accounts[0] || "" : "";
526
- if (!walletAddress) throw new Error("No wallet account selected.");
527
- const prepared = await prepareOnchainRating(normalized, options);
528
- const contentId = prepared.contentHash || prepared.contentId || contentRatingHash(normalized, options);
529
- const reviewHash = options.reviewHash || ZERO_HASH;
530
- const unlockRef = String(options.unlockRef || options.paymentId || options.txHash || "");
531
- const data = encodeRateContent({ contentId, ratingValue: rating.ratingValue, reviewHash, unlockRef });
532
- const txHash = await provider.request({
533
- method: "eth_sendTransaction",
534
- params: [{
535
- from: walletAddress,
536
- to: contractAddress,
537
- data
538
- }]
539
- });
540
- const payload = payloadWithResource(normalized, {
541
- rating: rating.rating,
542
- ratingValue: rating.ratingValue,
543
- walletAddress,
544
- txHash,
545
- contentHash: contentId,
546
- reviewHash,
547
- proofType: "onchain_pending",
548
- proof: unlockRef,
549
- paymentId: options.paymentId,
550
- actor: options.actor || "human"
551
- });
552
- emit("content_rating", payload);
553
- if (options.indexUrl) {
554
- await fetch(options.indexUrl, {
555
- method: "POST",
556
- headers: { "content-type": "application/json", ...options.indexHeaders || {} },
557
- body: JSON.stringify({
558
- siteId: options.siteId,
559
- token: options.token,
560
- txHash,
561
- resource: normalized,
562
- url: normalized.url,
563
- path: normalized.path,
564
- actor: options.actor || "human"
565
- })
566
- }).catch(() => null);
567
- }
568
- return { txHash, walletAddress, contentId, ratingValue: rating.ratingValue, reviewHash };
569
- }
570
-
571
- // src/browser/transfer.js
572
- function createTransferCheckout(resource, options = {}) {
573
- const normalized = normalizeResource({ ...resource, paymentRail: "transfer" });
574
- const sendTransfer = options.sendTransfer || options.transfer;
575
- if (typeof sendTransfer !== "function") {
576
- throw new Error("createTransferCheckout requires sendTransfer({ resource, recipient, amount, currency, network }) and a server verifyTransfer hook.");
577
- }
578
- return {
579
- resource: normalized,
580
- async pay(input = {}) {
581
- const recipient = normalized.recipient || normalized.payTo;
582
- const amount = String(normalized.price || normalized.amount || "0");
583
- const currency = normalized.currency || "USDC";
584
- const network = options.network || input.challenge?.accepts?.[0]?.network || "eip155:5042002";
585
- const result = await sendTransfer({ resource: normalized, recipient, amount, currency, network, challenge: input.challenge });
586
- const txHash = result?.txHash || result?.hash || result?.transactionHash || result?.paymentId || "";
587
- if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
588
- return {
589
- paymentSignature: txHash,
590
- signature: txHash,
591
- memo: result.memo || "",
592
- metadata: {
593
- paymentProvider: "direct-transfer",
594
- paymentId: txHash,
595
- txHash,
596
- recipient,
597
- amount: Number(amount),
598
- currency,
599
- network,
600
- ...result.metadata || result
601
- }
602
- };
603
- }
604
- };
605
- }
606
- async function payWithTransfer(resource, options = {}) {
607
- const checkout = options.checkout || createTransferCheckout(resource, options).pay;
608
- const result = await checkout({ resource: normalizeResource(resource), challenge: options.challenge || null });
609
- const txHash = result?.metadata?.txHash || result?.txHash || result?.paymentSignature || result?.signature || "";
610
- if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
611
- return checkResourceAccess(resource, {
612
- ...options,
613
- headers: {
614
- ...options.headers || {},
615
- "x-nibgate-transfer-tx": txHash
616
- },
617
- payment: result.metadata || { paymentProvider: "direct-transfer", txHash, paymentId: txHash }
618
- });
619
- }
620
-
621
- // src/core/settings.js
622
- var NIBGATE_CONTENT_SETTING_FIELDS = [
623
- { name: "publishToNibgate", label: "Publish to Nibgate discovery", type: "boolean", defaultValue: true },
624
- { name: "type", label: "Content type", type: "select", options: CONTENT_TYPES, defaultValue: "article" },
625
- { name: "humanAccess", label: "Human access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
626
- { name: "agentAccess", label: "Agent access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
627
- { name: "unlockMode", label: "Unlock mode", type: "select", options: UNLOCK_MODES, defaultValue: "one_time" },
628
- { name: "paymentRail", label: "Payment rail", type: "select", options: PAYMENT_RAILS, defaultValue: "gateway" },
629
- { name: "price", label: "Price", type: "text", defaultValue: "0.005" },
630
- { name: "currency", label: "Currency", type: "text", defaultValue: "USDC" },
631
- { name: "recipient", label: "Recipient wallet", type: "wallet", defaultValue: "" },
632
- { name: "ratingsEnabled", label: "Enable ratings", type: "boolean", defaultValue: true },
633
- { name: "license", label: "License / terms", type: "textarea", defaultValue: "" }
634
- ];
635
- function createNibgateContentSettings(input = {}) {
636
- const access = normalizeAccessPolicy(input.access || {
637
- humans: input.humanAccess,
638
- agents: input.agentAccess
639
- });
640
- const unlock = normalizeUnlockPolicy(input.unlock || input.unlockMode || "one_time");
641
- return {
642
- publishToNibgate: input.publishToNibgate ?? input.publishedToNibgate ?? true,
643
- type: normalizeContentType(input.type || input.contentType || "article"),
644
- humanAccess: access.humans,
645
- agentAccess: access.agents,
646
- unlockMode: unlock.mode,
647
- paymentRail: normalizePaymentRail(input.paymentRail || input.paymentMode || input.rail),
648
- price: String(input.price ?? input.amount ?? "0.005"),
649
- currency: input.currency || "USDC",
650
- recipient: input.recipient || input.payTo || input.receiverAddress || input.creatorWallet || "",
651
- ratingsEnabled: input.ratingsEnabled ?? input.enableRatings ?? input.reputation?.ratingsEnabled ?? true,
652
- license: input.license || input.terms || ""
653
- };
654
- }
655
- function settingsToAccessPolicy(settings = {}) {
656
- return normalizeAccessPolicy({
657
- humans: settings.humanAccess,
658
- agents: settings.agentAccess
659
- });
660
- }
661
- function settingsToUnlockPolicy(settings = {}) {
662
- return normalizeUnlockPolicy(settings.unlockMode || settings.unlock || "one_time");
663
- }
664
-
665
- // src/browser/index.js
666
- async function createCircleGatewayBrowserAdapter2(options = {}) {
667
- const gateway = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
668
- return gateway.createCircleGatewayBrowserAdapter(options);
432
+ // src/browser/gate.js
433
+ var defaultClient = null;
434
+ function setDefaultClient(client) {
435
+ defaultClient = client;
669
436
  }
670
437
  function createGate(resource, options = {}) {
671
438
  const normalized = normalizeResource(resource);
672
- const client = options.client || nibgate;
439
+ const client = options.client || defaultClient;
673
440
  return {
674
441
  resource: normalized,
675
442
  content(extra = {}) {
@@ -713,18 +480,11 @@ var Nibgate = (() => {
713
480
  }
714
481
  };
715
482
  }
716
- function rateResource(resource, rating = {}, extra = {}) {
717
- const normalized = normalizeResource(resource);
718
- const normalizedRating = normalizeRating(rating);
719
- const payload = {
720
- ...extra,
721
- ...normalizedRating,
722
- ratingMessage: extra.ratingMessage || rating.message || rating.ratingMessage || ratingMessage(normalized, normalizedRating, extra),
723
- ratingSignature: extra.ratingSignature || rating.signature || rating.ratingSignature || void 0,
724
- resource: normalized
725
- };
726
- return emit("content_rating", payload);
727
- }
483
+
484
+ // src/browser/access.js
485
+ init_json();
486
+
487
+ // src/browser/track.js
728
488
  function trackResourcePage(resource, options = {}) {
729
489
  const item = createGate(resource, options.gateOptions || {});
730
490
  const validation = validateResourceMetadata(item.resource, options.validation || {});
@@ -740,6 +500,29 @@ var Nibgate = (() => {
740
500
  });
741
501
  return item;
742
502
  }
503
+ function setupResourcePage(resource, options = {}) {
504
+ const item = trackResourcePage(resource, options);
505
+ const win = browserWindow();
506
+ if (!win) return item;
507
+ const button = typeof options.button === "string" ? win.document.querySelector(options.button) : options.button;
508
+ const statusElement = typeof options.status === "string" ? win.document.querySelector(options.status) : options.status;
509
+ const setStatus = options.onStatus || ((message) => {
510
+ if (statusElement) statusElement.textContent = message || "";
511
+ });
512
+ if (button) {
513
+ button.addEventListener("click", async () => {
514
+ button.disabled = true;
515
+ try {
516
+ await checkResourceAccess(resource, { ...options, onStatus: setStatus });
517
+ } finally {
518
+ button.disabled = false;
519
+ }
520
+ });
521
+ }
522
+ return item;
523
+ }
524
+
525
+ // src/browser/access.js
743
526
  async function checkResourceAccess(resource, options = {}) {
744
527
  const item = createGate(resource, options.gateOptions || {});
745
528
  const accessPath = options.accessPath || item.resource.accessPath || "/api/nibgate/access";
@@ -761,12 +544,11 @@ var Nibgate = (() => {
761
544
  item.track("payment_challenge_returned", { source: options.source, challenge: payload, resource: item.resource });
762
545
  status(options.challengeMessage || "Payment challenge returned. Continue with checkout.");
763
546
  if (typeof options.createPaymentSignature === "function" || typeof options.checkout === "function") {
764
- const paymentResult = await payWithPaymentSignature(resource, {
547
+ return payWithPaymentSignature(resource, {
765
548
  ...options,
766
549
  challenge: payload,
767
550
  paymentRequiredHeader: response.headers.get("PAYMENT-REQUIRED") || response.headers.get("payment-required") || ""
768
551
  });
769
- return paymentResult;
770
552
  }
771
553
  if (options.autoPay && options.payPath) {
772
554
  const paymentResult = await payAndUnlockResource(resource, options);
@@ -856,6 +638,42 @@ var Nibgate = (() => {
856
638
  status(options.paymentSuccessMessage || "Payment verified. Content unlocked.");
857
639
  return { ok: true, status: response.status, payload, payment, resource: item.resource, response };
858
640
  }
641
+ async function payAndUnlockResource(resource, options = {}) {
642
+ const item = createGate(resource, options.gateOptions || {});
643
+ const payPath = options.payPath || item.resource.payPath || "/api/nibgate/pay";
644
+ const status = typeof options.onStatus === "function" ? options.onStatus : () => {
645
+ };
646
+ status(options.paymentMessage || "Starting payment...");
647
+ item.unlockStarted({ source: options.source, paymentProvider: options.paymentProvider || "circle-gateway" });
648
+ const response = await fetch(payPath, {
649
+ method: options.payMethod || "POST",
650
+ headers: {
651
+ accept: "application/json",
652
+ "content-type": "application/json",
653
+ ...options.payHeaders || {}
654
+ },
655
+ body: JSON.stringify({ resource: item.resource, ...options.payPayload || {} })
656
+ });
657
+ const payload = await response.json().catch(() => ({}));
658
+ if (!response.ok || !payload.ok) {
659
+ item.track("payment_failed", { source: options.source, status: response.status, error: payload.error || "Payment failed", detail: payload.detail || "" });
660
+ status(payload.detail || payload.error || options.paymentErrorMessage || "Payment failed.");
661
+ return { ok: false, status: response.status, payload, resource: item.resource, response };
662
+ }
663
+ const payment = payload.payment || {
664
+ paymentProvider: options.paymentProvider || "circle-gateway",
665
+ paymentId: payload.paymentId || `nibgate_payment_${Date.now()}`,
666
+ amount: Number(item.resource.price || 0),
667
+ revenue: Number(item.resource.price || 0),
668
+ currency: item.resource.currency || "USDC"
669
+ };
670
+ storePaymentProof(item.resource, payload.unlockProof);
671
+ item.markUnlocked(payment);
672
+ status(options.paymentSuccessMessage || "Payment verified. Content unlocked.");
673
+ return { ok: true, status: response.status, payload, payment, resource: item.resource, response };
674
+ }
675
+
676
+ // src/browser/checkout.js
859
677
  function setElementText(target, message) {
860
678
  const win = browserWindow();
861
679
  if (!target || !win) return;
@@ -899,12 +717,40 @@ var Nibgate = (() => {
899
717
  if (element) element.addEventListener("click", () => unlock().catch((error) => status(error.message || "Checkout failed.")));
900
718
  return { unlock };
901
719
  }
720
+ return { resource: normalized, unlock, mount };
721
+ }
722
+
723
+ // src/core/rating.js
724
+ function normalizeRating(input = {}) {
725
+ const value = typeof input === "number" ? input : input.rating ?? input.stars ?? input.ratingValue ?? input.score;
726
+ const numeric = Number.parseFloat(value);
727
+ const ratingValue = Number.isFinite(numeric) ? Math.max(1, Math.min(50, numeric <= 5 ? Math.round(numeric * 10) : Math.round(numeric))) : null;
902
728
  return {
903
- resource: normalized,
904
- unlock,
905
- mount
729
+ ...input,
730
+ rating: ratingValue ? ratingValue / 10 : void 0,
731
+ ratingValue: ratingValue || void 0
906
732
  };
907
733
  }
734
+ function ratingMessage(resource, rating = {}, options = {}) {
735
+ const normalized = normalizeResource(resource);
736
+ const normalizedRating = normalizeRating(rating);
737
+ const value = normalizedRating.ratingValue || 0;
738
+ return [
739
+ "Nibgate content rating",
740
+ `site:${options.siteDomain || options.domain || normalized.siteDomain || normalized.domain || ""}`,
741
+ `content:${normalized.externalId || normalized.id}`,
742
+ `url:${normalized.url || options.url || ""}`,
743
+ `rating:${value}`,
744
+ "I confirm this rating is tied to my unlock/payment proof."
745
+ ].join("\n");
746
+ }
747
+
748
+ // src/browser/evm-gateway.js
749
+ init_json();
750
+ async function createCircleGatewayBrowserAdapter2(options = {}) {
751
+ const gateway = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
752
+ return gateway.createCircleGatewayBrowserAdapter(options);
753
+ }
908
754
  function createEvmGatewayUnlock(resource, options = {}) {
909
755
  const item = createGate(resource, options.gateOptions || {});
910
756
  const win = browserWindow();
@@ -976,10 +822,7 @@ var Nibgate = (() => {
976
822
  const evm = provider();
977
823
  if (evm?.request && walletAddress) {
978
824
  try {
979
- await evm.request({
980
- method: "wallet_revokePermissions",
981
- params: [{ eth_accounts: {} }]
982
- });
825
+ await evm.request({ method: "wallet_revokePermissions", params: [{ eth_accounts: {} }] });
983
826
  } catch (_error) {
984
827
  }
985
828
  }
@@ -999,10 +842,7 @@ var Nibgate = (() => {
999
842
  network,
1000
843
  signer: {
1001
844
  address: walletAddress,
1002
- signTypedData: (typedData) => evm.request({
1003
- method: "eth_signTypedData_v4",
1004
- params: [walletAddress, stringifyJson(typedData)]
1005
- })
845
+ signTypedData: (typedData) => evm.request({ method: "eth_signTypedData_v4", params: [walletAddress, stringifyJson(typedData)] })
1006
846
  },
1007
847
  clientModule: options.circleClientModule,
1008
848
  clientModuleUrl: options.circleClientModuleUrl
@@ -1054,18 +894,162 @@ var Nibgate = (() => {
1054
894
  renderWallet();
1055
895
  setUnlocked(false);
1056
896
  }
1057
- function mount() {
1058
- connectButton?.addEventListener?.("click", () => connect().catch((error) => setStatus(error?.message || "Could not connect wallet.")));
1059
- disconnectButton?.addEventListener?.("click", () => disconnect().catch((error) => setStatus(error?.message || "Could not disconnect wallet.")));
1060
- unlockButton?.addEventListener?.("click", () => unlock());
1061
- clearButton?.addEventListener?.("click", clear);
1062
- hydrate();
1063
- trackResourcePage(item.resource, { source });
1064
- return controller;
897
+ function mount() {
898
+ connectButton?.addEventListener?.("click", () => connect().catch((error) => setStatus(error?.message || "Could not connect wallet.")));
899
+ disconnectButton?.addEventListener?.("click", () => disconnect().catch((error) => setStatus(error?.message || "Could not disconnect wallet.")));
900
+ unlockButton?.addEventListener?.("click", () => unlock());
901
+ clearButton?.addEventListener?.("click", clear);
902
+ hydrate();
903
+ trackResourcePage(item.resource, { source });
904
+ return controller;
905
+ }
906
+ const controller = { resource: item.resource, connect, disconnect, unlock, clear, hydrate, mount, getWalletAddress: () => walletAddress };
907
+ if (options.autoMount !== false) mount();
908
+ return controller;
909
+ }
910
+
911
+ // src/browser/reputation.js
912
+ var RATE_CONTENT_SELECTOR = "0xc62fad09";
913
+ var ZERO_HASH = `0x${"0".repeat(64)}`;
914
+ var NIBGATE_CONTENT_HASH_NAMESPACE = "nibgate:content:v1";
915
+ var NIBGATE_REPUTATION_CHAIN_ID = 5042002;
916
+ var NIBGATE_REPUTATION_CHAIN_NAME = "Arc Testnet";
917
+ var NIBGATE_REPUTATION_RPC_URL = "https://rpc.testnet.arc.network";
918
+ var NIBGATE_REPUTATION_CONTRACT = "0x9f27fd62e75f86a3c7addfdba443aab1f930e281";
919
+ var NIBGATE_REPUTATION_ABI = [
920
+ {
921
+ type: "function",
922
+ name: "rateContent",
923
+ stateMutability: "nonpayable",
924
+ inputs: [
925
+ { name: "contentId", type: "bytes32" },
926
+ { name: "rating", type: "uint8" },
927
+ { name: "reviewHash", type: "bytes32" },
928
+ { name: "unlockRef", type: "string" }
929
+ ],
930
+ outputs: []
931
+ }
932
+ ];
933
+ function stripHex(value = "") {
934
+ return String(value || "").replace(/^0x/i, "").toLowerCase();
935
+ }
936
+ function wordRight(hex = "") {
937
+ const clean = stripHex(hex);
938
+ if (clean.length > 64) throw new Error("ABI word is too long.");
939
+ return clean.padEnd(64, "0");
940
+ }
941
+ function numberWord(value = 0) {
942
+ return Number(value || 0).toString(16).padStart(64, "0");
943
+ }
944
+ function utf8Hex(value = "") {
945
+ return Array.from(new TextEncoder().encode(String(value || ""))).map((byte) => byte.toString(16).padStart(2, "0")).join("");
946
+ }
947
+ function encodeString(value = "") {
948
+ const hex = utf8Hex(value);
949
+ const byteLength = hex.length / 2;
950
+ const paddedLength = Math.ceil(byteLength / 32) * 64;
951
+ return numberWord(byteLength) + hex.padEnd(paddedLength, "0");
952
+ }
953
+ function encodeRateContent({ contentId, ratingValue, reviewHash, unlockRef }) {
954
+ return RATE_CONTENT_SELECTOR + wordRight(contentId) + numberWord(ratingValue) + wordRight(reviewHash || ZERO_HASH) + numberWord(128) + encodeString(unlockRef || "");
955
+ }
956
+ function contentRatingHash(_resource, options = {}) {
957
+ const contentId = options.contentId || options.contentHash;
958
+ if (!contentId) {
959
+ throw new Error("contentId/contentHash is required. Use the Nibgate backend prepare endpoint or pass a known content hash.");
960
+ }
961
+ return contentId;
962
+ }
963
+ function reviewTextHash(review = "") {
964
+ if (!review) return ZERO_HASH;
965
+ throw new Error("Text review hashing is not available in direct-browser mode. Pass reviewHash from your app/backend.");
966
+ }
967
+ async function prepareOnchainRating(resource, options = {}) {
968
+ if (options.contentId || options.contentHash) return { contentId: options.contentId || options.contentHash };
969
+ const prepareUrl = options.prepareUrl || options.indexUrl?.replace(/\/index$/, "/prepare");
970
+ if (!prepareUrl) throw new Error("contentId/contentHash or prepareUrl is required for onchain rating.");
971
+ const response = await fetch(prepareUrl, {
972
+ method: "POST",
973
+ headers: { "content-type": "application/json", ...options.indexHeaders || {} },
974
+ body: JSON.stringify({
975
+ siteId: options.siteId,
976
+ token: options.token,
977
+ resource,
978
+ url: resource.url,
979
+ path: resource.path
980
+ })
981
+ });
982
+ const payload = await response.json().catch(() => ({}));
983
+ if (!response.ok || !payload.contentHash) throw new Error(payload.error || "Could not prepare Nibgate onchain rating.");
984
+ return payload;
985
+ }
986
+ async function rateContentOnchain(resource, options = {}) {
987
+ const normalized = normalizeResource(resource);
988
+ const rating = normalizeRating(options.rating ?? options.stars ?? options);
989
+ if (!rating.ratingValue) throw new Error("Rating must be between 0.1 and 5 stars.");
990
+ const provider = options.provider || globalThis?.ethereum;
991
+ if (!provider?.request) throw new Error("Connect an EVM wallet to rate this content onchain.");
992
+ const contractAddress = options.contractAddress || options.reputationContract || NIBGATE_REPUTATION_CONTRACT;
993
+ if (!contractAddress) throw new Error("Nibgate reputation contract address is not configured.");
994
+ const accounts = await provider.request({ method: "eth_requestAccounts" });
995
+ const walletAddress = Array.isArray(accounts) ? accounts[0] || "" : "";
996
+ if (!walletAddress) throw new Error("No wallet account selected.");
997
+ const prepared = await prepareOnchainRating(normalized, options);
998
+ const contentId = prepared.contentHash || prepared.contentId || contentRatingHash(normalized, options);
999
+ const reviewHash = options.reviewHash || ZERO_HASH;
1000
+ const unlockRef = String(options.unlockRef || options.paymentId || options.txHash || "");
1001
+ const data = encodeRateContent({ contentId, ratingValue: rating.ratingValue, reviewHash, unlockRef });
1002
+ const txHash = await provider.request({
1003
+ method: "eth_sendTransaction",
1004
+ params: [{
1005
+ from: walletAddress,
1006
+ to: contractAddress,
1007
+ data
1008
+ }]
1009
+ });
1010
+ const payload = payloadWithResource(normalized, {
1011
+ rating: rating.rating,
1012
+ ratingValue: rating.ratingValue,
1013
+ walletAddress,
1014
+ txHash,
1015
+ contentHash: contentId,
1016
+ reviewHash,
1017
+ proofType: "onchain_pending",
1018
+ proof: unlockRef,
1019
+ paymentId: options.paymentId,
1020
+ actor: options.actor || "human"
1021
+ });
1022
+ emit("content_rating", payload);
1023
+ if (options.indexUrl) {
1024
+ await fetch(options.indexUrl, {
1025
+ method: "POST",
1026
+ headers: { "content-type": "application/json", ...options.indexHeaders || {} },
1027
+ body: JSON.stringify({
1028
+ siteId: options.siteId,
1029
+ token: options.token,
1030
+ txHash,
1031
+ resource: normalized,
1032
+ url: normalized.url,
1033
+ path: normalized.path,
1034
+ actor: options.actor || "human"
1035
+ })
1036
+ }).catch(() => null);
1065
1037
  }
1066
- const controller = { resource: item.resource, connect, disconnect, unlock, clear, hydrate, mount, getWalletAddress: () => walletAddress };
1067
- if (options.autoMount !== false) mount();
1068
- return controller;
1038
+ return { txHash, walletAddress, contentId, ratingValue: rating.ratingValue, reviewHash };
1039
+ }
1040
+
1041
+ // src/browser/rating-ui.js
1042
+ function rateResource(resource, rating = {}, extra = {}) {
1043
+ const normalized = normalizeResource(resource);
1044
+ const normalizedRating = normalizeRating(rating);
1045
+ const payload = {
1046
+ ...extra,
1047
+ ...normalizedRating,
1048
+ ratingMessage: extra.ratingMessage || rating.message || rating.ratingMessage || ratingMessage(normalized, normalizedRating, extra),
1049
+ ratingSignature: extra.ratingSignature || rating.signature || rating.ratingSignature || void 0,
1050
+ resource: normalized
1051
+ };
1052
+ return emit("content_rating", payload);
1069
1053
  }
1070
1054
  function createOnchainRating(resource, options = {}) {
1071
1055
  const item = createGate(resource, options.gateOptions || {});
@@ -1111,14 +1095,7 @@ var Nibgate = (() => {
1111
1095
  const paymentId = input.paymentId || options.paymentId || (typeof options.getPaymentId === "function" ? options.getPaymentId() : payment?.paymentId);
1112
1096
  const unlockRef = input.unlockRef || options.unlockRef || (typeof options.getUnlockRef === "function" ? options.getUnlockRef() : null) || paymentId || payment?.txHash || payment?.transactionHash || "";
1113
1097
  setStatus(options.pendingMessage || "Send the onchain rating transaction...");
1114
- const result = await rateContentOnchain(item.resource, {
1115
- ...options,
1116
- ...input,
1117
- rating,
1118
- paymentId,
1119
- unlockRef,
1120
- source
1121
- });
1098
+ const result = await rateContentOnchain(item.resource, { ...options, ...input, rating, paymentId, unlockRef, source });
1122
1099
  setStatus(options.successMessage || "Rating sent to Nibgate reputation.");
1123
1100
  if (typeof options.onRated === "function") options.onRated(result);
1124
1101
  return result;
@@ -1169,7 +1146,7 @@ var Nibgate = (() => {
1169
1146
  btn.addEventListener("click", () => {
1170
1147
  selectedRating = value;
1171
1148
  starButtons.forEach((b, i) => b.style.color = i < value ? "#f5b342" : "#ccc");
1172
- rate(item.resource, { rating: value }).catch(() => {
1149
+ rateResource(item.resource, { rating: value }).catch(() => {
1173
1150
  });
1174
1151
  });
1175
1152
  container.appendChild(btn);
@@ -1187,71 +1164,60 @@ var Nibgate = (() => {
1187
1164
  selectedRating = value;
1188
1165
  starButtons.forEach((b, i) => b.style.color = i < value ? "#f5b342" : "#ccc");
1189
1166
  }
1167
+ return { resource: item.resource, container, setRating, rate };
1168
+ }
1169
+
1170
+ // src/browser/transfer.js
1171
+ function createTransferCheckout(resource, options = {}) {
1172
+ const normalized = normalizeResource({ ...resource, paymentRail: "transfer" });
1173
+ const sendTransfer = options.sendTransfer || options.transfer;
1174
+ if (typeof sendTransfer !== "function") {
1175
+ throw new Error("createTransferCheckout requires sendTransfer({ resource, recipient, amount, currency, network }) and a server verifyTransfer hook.");
1176
+ }
1190
1177
  return {
1191
- resource: item.resource,
1192
- container,
1193
- setRating,
1194
- rate
1178
+ resource: normalized,
1179
+ async pay(input = {}) {
1180
+ const recipient = normalized.recipient || normalized.payTo;
1181
+ const amount = String(normalized.price || normalized.amount || "0");
1182
+ const currency = normalized.currency || "USDC";
1183
+ const network = options.network || input.challenge?.accepts?.[0]?.network || "eip155:5042002";
1184
+ const result = await sendTransfer({ resource: normalized, recipient, amount, currency, network, challenge: input.challenge });
1185
+ const txHash = result?.txHash || result?.hash || result?.transactionHash || result?.paymentId || "";
1186
+ if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
1187
+ return {
1188
+ paymentSignature: txHash,
1189
+ signature: txHash,
1190
+ memo: result.memo || "",
1191
+ metadata: {
1192
+ paymentProvider: "direct-transfer",
1193
+ paymentId: txHash,
1194
+ txHash,
1195
+ recipient,
1196
+ amount: Number(amount),
1197
+ currency,
1198
+ network,
1199
+ ...result.metadata || result
1200
+ }
1201
+ };
1202
+ }
1195
1203
  };
1196
1204
  }
1197
- async function payAndUnlockResource(resource, options = {}) {
1198
- const item = createGate(resource, options.gateOptions || {});
1199
- const payPath = options.payPath || item.resource.payPath || "/api/nibgate/pay";
1200
- const status = typeof options.onStatus === "function" ? options.onStatus : () => {
1201
- };
1202
- status(options.paymentMessage || "Starting payment...");
1203
- item.unlockStarted({ source: options.source, paymentProvider: options.paymentProvider || "circle-gateway" });
1204
- const response = await fetch(payPath, {
1205
- method: options.payMethod || "POST",
1205
+ async function payWithTransfer(resource, options = {}) {
1206
+ const checkout = options.checkout || createTransferCheckout(resource, options).pay;
1207
+ const result = await checkout({ resource: normalizeResource(resource), challenge: options.challenge || null });
1208
+ const txHash = result?.metadata?.txHash || result?.txHash || result?.paymentSignature || result?.signature || "";
1209
+ if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
1210
+ return checkResourceAccess(resource, {
1211
+ ...options,
1206
1212
  headers: {
1207
- accept: "application/json",
1208
- "content-type": "application/json",
1209
- ...options.payHeaders || {}
1213
+ ...options.headers || {},
1214
+ "x-nibgate-transfer-tx": txHash
1210
1215
  },
1211
- body: JSON.stringify({
1212
- resource: item.resource,
1213
- ...options.payPayload || {}
1214
- })
1215
- });
1216
- const payload = await response.json().catch(() => ({}));
1217
- if (!response.ok || !payload.success) {
1218
- item.track("payment_failed", { source: options.source, status: response.status, error: payload.error || "Payment failed", detail: payload.detail || "" });
1219
- status(payload.detail || payload.error || options.paymentErrorMessage || "Payment failed.");
1220
- return { ok: false, status: response.status, payload, resource: item.resource, response };
1221
- }
1222
- const payment = payload.payment || {
1223
- paymentProvider: options.paymentProvider || "circle-gateway",
1224
- paymentId: payload.paymentId || `nibgate_payment_${Date.now()}`,
1225
- amount: Number(item.resource.price || 0),
1226
- revenue: Number(item.resource.price || 0),
1227
- currency: item.resource.currency || "USDC"
1228
- };
1229
- storePaymentProof(item.resource, payload.unlockProof);
1230
- item.markUnlocked(payment);
1231
- status(options.paymentSuccessMessage || "Payment verified. Content unlocked.");
1232
- return { ok: true, status: response.status, payload, payment, resource: item.resource, response };
1233
- }
1234
- function setupResourcePage(resource, options = {}) {
1235
- const item = trackResourcePage(resource, options);
1236
- const win = browserWindow();
1237
- if (!win) return item;
1238
- const button = typeof options.button === "string" ? win.document.querySelector(options.button) : options.button;
1239
- const statusElement = typeof options.status === "string" ? win.document.querySelector(options.status) : options.status;
1240
- const setStatus = options.onStatus || ((message) => {
1241
- if (statusElement) statusElement.textContent = message || "";
1216
+ payment: result.metadata || { paymentProvider: "direct-transfer", txHash, paymentId: txHash }
1242
1217
  });
1243
- if (button) {
1244
- button.addEventListener("click", async () => {
1245
- button.disabled = true;
1246
- try {
1247
- await checkResourceAccess(resource, { ...options, onStatus: setStatus });
1248
- } finally {
1249
- button.disabled = false;
1250
- }
1251
- });
1252
- }
1253
- return item;
1254
1218
  }
1219
+
1220
+ // src/browser/client.js
1255
1221
  function createNibgate(defaults = {}) {
1256
1222
  const defaultResource = defaults.resource ? normalizeResource(defaults.resource) : null;
1257
1223
  function resourceWithDefaults(resource = {}) {
@@ -1333,7 +1299,51 @@ var Nibgate = (() => {
1333
1299
  };
1334
1300
  }
1335
1301
  var nibgate = createNibgate();
1336
- var gate = createGate;
1302
+ setDefaultClient(nibgate);
1303
+
1304
+ // src/core/settings.js
1305
+ var NIBGATE_CONTENT_SETTING_FIELDS = [
1306
+ { name: "publishToNibgate", label: "Publish to Nibgate discovery", type: "boolean", defaultValue: true },
1307
+ { name: "type", label: "Content type", type: "select", options: CONTENT_TYPES, defaultValue: "article" },
1308
+ { name: "humanAccess", label: "Human access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
1309
+ { name: "agentAccess", label: "Agent access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
1310
+ { name: "unlockMode", label: "Unlock mode", type: "select", options: UNLOCK_MODES, defaultValue: "one_time" },
1311
+ { name: "paymentRail", label: "Payment rail", type: "select", options: PAYMENT_RAILS, defaultValue: "gateway" },
1312
+ { name: "price", label: "Price", type: "text", defaultValue: "0.005" },
1313
+ { name: "currency", label: "Currency", type: "text", defaultValue: "USDC" },
1314
+ { name: "recipient", label: "Recipient wallet", type: "wallet", defaultValue: "" },
1315
+ { name: "ratingsEnabled", label: "Enable ratings", type: "boolean", defaultValue: true },
1316
+ { name: "license", label: "License / terms", type: "textarea", defaultValue: "" }
1317
+ ];
1318
+ function createNibgateContentSettings(input = {}) {
1319
+ const access = normalizeAccessPolicy(input.access || {
1320
+ humans: input.humanAccess,
1321
+ agents: input.agentAccess
1322
+ });
1323
+ const unlock = normalizeUnlockPolicy(input.unlock || input.unlockMode || "one_time");
1324
+ return {
1325
+ publishToNibgate: input.publishToNibgate ?? input.publishedToNibgate ?? true,
1326
+ type: normalizeContentType(input.type || input.contentType || "article"),
1327
+ humanAccess: access.humans,
1328
+ agentAccess: access.agents,
1329
+ unlockMode: unlock.mode,
1330
+ paymentRail: normalizePaymentRail(input.paymentRail || input.paymentMode || input.rail),
1331
+ price: String(input.price ?? input.amount ?? "0.005"),
1332
+ currency: input.currency || "USDC",
1333
+ recipient: input.recipient || input.payTo || input.receiverAddress || input.creatorWallet || "",
1334
+ ratingsEnabled: input.ratingsEnabled ?? input.enableRatings ?? input.reputation?.ratingsEnabled ?? true,
1335
+ license: input.license || input.terms || ""
1336
+ };
1337
+ }
1338
+ function settingsToAccessPolicy(settings = {}) {
1339
+ return normalizeAccessPolicy({
1340
+ humans: settings.humanAccess,
1341
+ agents: settings.agentAccess
1342
+ });
1343
+ }
1344
+ function settingsToUnlockPolicy(settings = {}) {
1345
+ return normalizeUnlockPolicy(settings.unlockMode || settings.unlock || "one_time");
1346
+ }
1337
1347
  return __toCommonJS(index_exports);
1338
1348
  })();
1339
1349
  //# sourceMappingURL=nibgate.js.map