@nibgate/sdk 0.2.0 → 0.2.2

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,
@@ -293,31 +292,6 @@ var Nibgate = (() => {
293
292
  };
294
293
  }
295
294
 
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
295
  // src/browser/env.js
322
296
  function browserWindow() {
323
297
  return typeof window === "undefined" ? null : window;
@@ -435,241 +409,14 @@ var Nibgate = (() => {
435
409
  }
436
410
  }
437
411
 
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);
412
+ // src/browser/gate.js
413
+ var defaultClient = null;
414
+ function setDefaultClient(client) {
415
+ defaultClient = client;
669
416
  }
670
417
  function createGate(resource, options = {}) {
671
418
  const normalized = normalizeResource(resource);
672
- const client = options.client || nibgate;
419
+ const client = options.client || defaultClient;
673
420
  return {
674
421
  resource: normalized,
675
422
  content(extra = {}) {
@@ -713,18 +460,11 @@ var Nibgate = (() => {
713
460
  }
714
461
  };
715
462
  }
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
- }
463
+
464
+ // src/browser/access.js
465
+ init_json();
466
+
467
+ // src/browser/track.js
728
468
  function trackResourcePage(resource, options = {}) {
729
469
  const item = createGate(resource, options.gateOptions || {});
730
470
  const validation = validateResourceMetadata(item.resource, options.validation || {});
@@ -740,6 +480,29 @@ var Nibgate = (() => {
740
480
  });
741
481
  return item;
742
482
  }
483
+ function setupResourcePage(resource, options = {}) {
484
+ const item = trackResourcePage(resource, options);
485
+ const win = browserWindow();
486
+ if (!win) return item;
487
+ const button = typeof options.button === "string" ? win.document.querySelector(options.button) : options.button;
488
+ const statusElement = typeof options.status === "string" ? win.document.querySelector(options.status) : options.status;
489
+ const setStatus = options.onStatus || ((message) => {
490
+ if (statusElement) statusElement.textContent = message || "";
491
+ });
492
+ if (button) {
493
+ button.addEventListener("click", async () => {
494
+ button.disabled = true;
495
+ try {
496
+ await checkResourceAccess(resource, { ...options, onStatus: setStatus });
497
+ } finally {
498
+ button.disabled = false;
499
+ }
500
+ });
501
+ }
502
+ return item;
503
+ }
504
+
505
+ // src/browser/access.js
743
506
  async function checkResourceAccess(resource, options = {}) {
744
507
  const item = createGate(resource, options.gateOptions || {});
745
508
  const accessPath = options.accessPath || item.resource.accessPath || "/api/nibgate/access";
@@ -761,12 +524,11 @@ var Nibgate = (() => {
761
524
  item.track("payment_challenge_returned", { source: options.source, challenge: payload, resource: item.resource });
762
525
  status(options.challengeMessage || "Payment challenge returned. Continue with checkout.");
763
526
  if (typeof options.createPaymentSignature === "function" || typeof options.checkout === "function") {
764
- const paymentResult = await payWithPaymentSignature(resource, {
527
+ return payWithPaymentSignature(resource, {
765
528
  ...options,
766
529
  challenge: payload,
767
530
  paymentRequiredHeader: response.headers.get("PAYMENT-REQUIRED") || response.headers.get("payment-required") || ""
768
531
  });
769
- return paymentResult;
770
532
  }
771
533
  if (options.autoPay && options.payPath) {
772
534
  const paymentResult = await payAndUnlockResource(resource, options);
@@ -856,6 +618,42 @@ var Nibgate = (() => {
856
618
  status(options.paymentSuccessMessage || "Payment verified. Content unlocked.");
857
619
  return { ok: true, status: response.status, payload, payment, resource: item.resource, response };
858
620
  }
621
+ async function payAndUnlockResource(resource, options = {}) {
622
+ const item = createGate(resource, options.gateOptions || {});
623
+ const payPath = options.payPath || item.resource.payPath || "/api/nibgate/pay";
624
+ const status = typeof options.onStatus === "function" ? options.onStatus : () => {
625
+ };
626
+ status(options.paymentMessage || "Starting payment...");
627
+ item.unlockStarted({ source: options.source, paymentProvider: options.paymentProvider || "circle-gateway" });
628
+ const response = await fetch(payPath, {
629
+ method: options.payMethod || "POST",
630
+ headers: {
631
+ accept: "application/json",
632
+ "content-type": "application/json",
633
+ ...options.payHeaders || {}
634
+ },
635
+ body: JSON.stringify({ resource: item.resource, ...options.payPayload || {} })
636
+ });
637
+ const payload = await response.json().catch(() => ({}));
638
+ if (!response.ok || !payload.ok) {
639
+ item.track("payment_failed", { source: options.source, status: response.status, error: payload.error || "Payment failed", detail: payload.detail || "" });
640
+ status(payload.detail || payload.error || options.paymentErrorMessage || "Payment failed.");
641
+ return { ok: false, status: response.status, payload, resource: item.resource, response };
642
+ }
643
+ const payment = payload.payment || {
644
+ paymentProvider: options.paymentProvider || "circle-gateway",
645
+ paymentId: payload.paymentId || `nibgate_payment_${Date.now()}`,
646
+ amount: Number(item.resource.price || 0),
647
+ revenue: Number(item.resource.price || 0),
648
+ currency: item.resource.currency || "USDC"
649
+ };
650
+ storePaymentProof(item.resource, payload.unlockProof);
651
+ item.markUnlocked(payment);
652
+ status(options.paymentSuccessMessage || "Payment verified. Content unlocked.");
653
+ return { ok: true, status: response.status, payload, payment, resource: item.resource, response };
654
+ }
655
+
656
+ // src/browser/checkout.js
859
657
  function setElementText(target, message) {
860
658
  const win = browserWindow();
861
659
  if (!target || !win) return;
@@ -899,12 +697,40 @@ var Nibgate = (() => {
899
697
  if (element) element.addEventListener("click", () => unlock().catch((error) => status(error.message || "Checkout failed.")));
900
698
  return { unlock };
901
699
  }
700
+ return { resource: normalized, unlock, mount };
701
+ }
702
+
703
+ // src/core/rating.js
704
+ function normalizeRating(input = {}) {
705
+ const value = typeof input === "number" ? input : input.rating ?? input.stars ?? input.ratingValue ?? input.score;
706
+ const numeric = Number.parseFloat(value);
707
+ const ratingValue = Number.isFinite(numeric) ? Math.max(1, Math.min(50, numeric <= 5 ? Math.round(numeric * 10) : Math.round(numeric))) : null;
902
708
  return {
903
- resource: normalized,
904
- unlock,
905
- mount
709
+ ...input,
710
+ rating: ratingValue ? ratingValue / 10 : void 0,
711
+ ratingValue: ratingValue || void 0
906
712
  };
907
713
  }
714
+ function ratingMessage(resource, rating = {}, options = {}) {
715
+ const normalized = normalizeResource(resource);
716
+ const normalizedRating = normalizeRating(rating);
717
+ const value = normalizedRating.ratingValue || 0;
718
+ return [
719
+ "Nibgate content rating",
720
+ `site:${options.siteDomain || options.domain || normalized.siteDomain || normalized.domain || ""}`,
721
+ `content:${normalized.externalId || normalized.id}`,
722
+ `url:${normalized.url || options.url || ""}`,
723
+ `rating:${value}`,
724
+ "I confirm this rating is tied to my unlock/payment proof."
725
+ ].join("\n");
726
+ }
727
+
728
+ // src/browser/evm-gateway.js
729
+ init_json();
730
+ async function createCircleGatewayBrowserAdapter2(options = {}) {
731
+ const gateway = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
732
+ return gateway.createCircleGatewayBrowserAdapter(options);
733
+ }
908
734
  function createEvmGatewayUnlock(resource, options = {}) {
909
735
  const item = createGate(resource, options.gateOptions || {});
910
736
  const win = browserWindow();
@@ -976,10 +802,7 @@ var Nibgate = (() => {
976
802
  const evm = provider();
977
803
  if (evm?.request && walletAddress) {
978
804
  try {
979
- await evm.request({
980
- method: "wallet_revokePermissions",
981
- params: [{ eth_accounts: {} }]
982
- });
805
+ await evm.request({ method: "wallet_revokePermissions", params: [{ eth_accounts: {} }] });
983
806
  } catch (_error) {
984
807
  }
985
808
  }
@@ -999,10 +822,7 @@ var Nibgate = (() => {
999
822
  network,
1000
823
  signer: {
1001
824
  address: walletAddress,
1002
- signTypedData: (typedData) => evm.request({
1003
- method: "eth_signTypedData_v4",
1004
- params: [walletAddress, stringifyJson(typedData)]
1005
- })
825
+ signTypedData: (typedData) => evm.request({ method: "eth_signTypedData_v4", params: [walletAddress, stringifyJson(typedData)] })
1006
826
  },
1007
827
  clientModule: options.circleClientModule,
1008
828
  clientModuleUrl: options.circleClientModuleUrl
@@ -1054,18 +874,162 @@ var Nibgate = (() => {
1054
874
  renderWallet();
1055
875
  setUnlocked(false);
1056
876
  }
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;
877
+ function mount() {
878
+ connectButton?.addEventListener?.("click", () => connect().catch((error) => setStatus(error?.message || "Could not connect wallet.")));
879
+ disconnectButton?.addEventListener?.("click", () => disconnect().catch((error) => setStatus(error?.message || "Could not disconnect wallet.")));
880
+ unlockButton?.addEventListener?.("click", () => unlock());
881
+ clearButton?.addEventListener?.("click", clear);
882
+ hydrate();
883
+ trackResourcePage(item.resource, { source });
884
+ return controller;
885
+ }
886
+ const controller = { resource: item.resource, connect, disconnect, unlock, clear, hydrate, mount, getWalletAddress: () => walletAddress };
887
+ if (options.autoMount !== false) mount();
888
+ return controller;
889
+ }
890
+
891
+ // src/browser/reputation.js
892
+ var RATE_CONTENT_SELECTOR = "0xc62fad09";
893
+ var ZERO_HASH = `0x${"0".repeat(64)}`;
894
+ var NIBGATE_CONTENT_HASH_NAMESPACE = "nibgate:content:v1";
895
+ var NIBGATE_REPUTATION_CHAIN_ID = 5042002;
896
+ var NIBGATE_REPUTATION_CHAIN_NAME = "Arc Testnet";
897
+ var NIBGATE_REPUTATION_RPC_URL = "https://rpc.testnet.arc.network";
898
+ var NIBGATE_REPUTATION_CONTRACT = "0x9f27fd62e75f86a3c7addfdba443aab1f930e281";
899
+ var NIBGATE_REPUTATION_ABI = [
900
+ {
901
+ type: "function",
902
+ name: "rateContent",
903
+ stateMutability: "nonpayable",
904
+ inputs: [
905
+ { name: "contentId", type: "bytes32" },
906
+ { name: "rating", type: "uint8" },
907
+ { name: "reviewHash", type: "bytes32" },
908
+ { name: "unlockRef", type: "string" }
909
+ ],
910
+ outputs: []
911
+ }
912
+ ];
913
+ function stripHex(value = "") {
914
+ return String(value || "").replace(/^0x/i, "").toLowerCase();
915
+ }
916
+ function wordRight(hex = "") {
917
+ const clean = stripHex(hex);
918
+ if (clean.length > 64) throw new Error("ABI word is too long.");
919
+ return clean.padEnd(64, "0");
920
+ }
921
+ function numberWord(value = 0) {
922
+ return Number(value || 0).toString(16).padStart(64, "0");
923
+ }
924
+ function utf8Hex(value = "") {
925
+ return Array.from(new TextEncoder().encode(String(value || ""))).map((byte) => byte.toString(16).padStart(2, "0")).join("");
926
+ }
927
+ function encodeString(value = "") {
928
+ const hex = utf8Hex(value);
929
+ const byteLength = hex.length / 2;
930
+ const paddedLength = Math.ceil(byteLength / 32) * 64;
931
+ return numberWord(byteLength) + hex.padEnd(paddedLength, "0");
932
+ }
933
+ function encodeRateContent({ contentId, ratingValue, reviewHash, unlockRef }) {
934
+ return RATE_CONTENT_SELECTOR + wordRight(contentId) + numberWord(ratingValue) + wordRight(reviewHash || ZERO_HASH) + numberWord(128) + encodeString(unlockRef || "");
935
+ }
936
+ function contentRatingHash(_resource, options = {}) {
937
+ const contentId = options.contentId || options.contentHash;
938
+ if (!contentId) {
939
+ throw new Error("contentId/contentHash is required. Use the Nibgate backend prepare endpoint or pass a known content hash.");
940
+ }
941
+ return contentId;
942
+ }
943
+ function reviewTextHash(review = "") {
944
+ if (!review) return ZERO_HASH;
945
+ throw new Error("Text review hashing is not available in direct-browser mode. Pass reviewHash from your app/backend.");
946
+ }
947
+ async function prepareOnchainRating(resource, options = {}) {
948
+ if (options.contentId || options.contentHash) return { contentId: options.contentId || options.contentHash };
949
+ const prepareUrl = options.prepareUrl || options.indexUrl?.replace(/\/index$/, "/prepare");
950
+ if (!prepareUrl) throw new Error("contentId/contentHash or prepareUrl is required for onchain rating.");
951
+ const response = await fetch(prepareUrl, {
952
+ method: "POST",
953
+ headers: { "content-type": "application/json", ...options.indexHeaders || {} },
954
+ body: JSON.stringify({
955
+ siteId: options.siteId,
956
+ token: options.token,
957
+ resource,
958
+ url: resource.url,
959
+ path: resource.path
960
+ })
961
+ });
962
+ const payload = await response.json().catch(() => ({}));
963
+ if (!response.ok || !payload.contentHash) throw new Error(payload.error || "Could not prepare Nibgate onchain rating.");
964
+ return payload;
965
+ }
966
+ async function rateContentOnchain(resource, options = {}) {
967
+ const normalized = normalizeResource(resource);
968
+ const rating = normalizeRating(options.rating ?? options.stars ?? options);
969
+ if (!rating.ratingValue) throw new Error("Rating must be between 0.1 and 5 stars.");
970
+ const provider = options.provider || globalThis?.ethereum;
971
+ if (!provider?.request) throw new Error("Connect an EVM wallet to rate this content onchain.");
972
+ const contractAddress = options.contractAddress || options.reputationContract || NIBGATE_REPUTATION_CONTRACT;
973
+ if (!contractAddress) throw new Error("Nibgate reputation contract address is not configured.");
974
+ const accounts = await provider.request({ method: "eth_requestAccounts" });
975
+ const walletAddress = Array.isArray(accounts) ? accounts[0] || "" : "";
976
+ if (!walletAddress) throw new Error("No wallet account selected.");
977
+ const prepared = await prepareOnchainRating(normalized, options);
978
+ const contentId = prepared.contentHash || prepared.contentId || contentRatingHash(normalized, options);
979
+ const reviewHash = options.reviewHash || ZERO_HASH;
980
+ const unlockRef = String(options.unlockRef || options.paymentId || options.txHash || "");
981
+ const data = encodeRateContent({ contentId, ratingValue: rating.ratingValue, reviewHash, unlockRef });
982
+ const txHash = await provider.request({
983
+ method: "eth_sendTransaction",
984
+ params: [{
985
+ from: walletAddress,
986
+ to: contractAddress,
987
+ data
988
+ }]
989
+ });
990
+ const payload = payloadWithResource(normalized, {
991
+ rating: rating.rating,
992
+ ratingValue: rating.ratingValue,
993
+ walletAddress,
994
+ txHash,
995
+ contentHash: contentId,
996
+ reviewHash,
997
+ proofType: "onchain_pending",
998
+ proof: unlockRef,
999
+ paymentId: options.paymentId,
1000
+ actor: options.actor || "human"
1001
+ });
1002
+ emit("content_rating", payload);
1003
+ if (options.indexUrl) {
1004
+ await fetch(options.indexUrl, {
1005
+ method: "POST",
1006
+ headers: { "content-type": "application/json", ...options.indexHeaders || {} },
1007
+ body: JSON.stringify({
1008
+ siteId: options.siteId,
1009
+ token: options.token,
1010
+ txHash,
1011
+ resource: normalized,
1012
+ url: normalized.url,
1013
+ path: normalized.path,
1014
+ actor: options.actor || "human"
1015
+ })
1016
+ }).catch(() => null);
1065
1017
  }
1066
- const controller = { resource: item.resource, connect, disconnect, unlock, clear, hydrate, mount, getWalletAddress: () => walletAddress };
1067
- if (options.autoMount !== false) mount();
1068
- return controller;
1018
+ return { txHash, walletAddress, contentId, ratingValue: rating.ratingValue, reviewHash };
1019
+ }
1020
+
1021
+ // src/browser/rating-ui.js
1022
+ function rateResource(resource, rating = {}, extra = {}) {
1023
+ const normalized = normalizeResource(resource);
1024
+ const normalizedRating = normalizeRating(rating);
1025
+ const payload = {
1026
+ ...extra,
1027
+ ...normalizedRating,
1028
+ ratingMessage: extra.ratingMessage || rating.message || rating.ratingMessage || ratingMessage(normalized, normalizedRating, extra),
1029
+ ratingSignature: extra.ratingSignature || rating.signature || rating.ratingSignature || void 0,
1030
+ resource: normalized
1031
+ };
1032
+ return emit("content_rating", payload);
1069
1033
  }
1070
1034
  function createOnchainRating(resource, options = {}) {
1071
1035
  const item = createGate(resource, options.gateOptions || {});
@@ -1111,14 +1075,7 @@ var Nibgate = (() => {
1111
1075
  const paymentId = input.paymentId || options.paymentId || (typeof options.getPaymentId === "function" ? options.getPaymentId() : payment?.paymentId);
1112
1076
  const unlockRef = input.unlockRef || options.unlockRef || (typeof options.getUnlockRef === "function" ? options.getUnlockRef() : null) || paymentId || payment?.txHash || payment?.transactionHash || "";
1113
1077
  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
- });
1078
+ const result = await rateContentOnchain(item.resource, { ...options, ...input, rating, paymentId, unlockRef, source });
1122
1079
  setStatus(options.successMessage || "Rating sent to Nibgate reputation.");
1123
1080
  if (typeof options.onRated === "function") options.onRated(result);
1124
1081
  return result;
@@ -1169,7 +1126,7 @@ var Nibgate = (() => {
1169
1126
  btn.addEventListener("click", () => {
1170
1127
  selectedRating = value;
1171
1128
  starButtons.forEach((b, i) => b.style.color = i < value ? "#f5b342" : "#ccc");
1172
- rate(item.resource, { rating: value }).catch(() => {
1129
+ rateResource(item.resource, { rating: value }).catch(() => {
1173
1130
  });
1174
1131
  });
1175
1132
  container.appendChild(btn);
@@ -1187,71 +1144,60 @@ var Nibgate = (() => {
1187
1144
  selectedRating = value;
1188
1145
  starButtons.forEach((b, i) => b.style.color = i < value ? "#f5b342" : "#ccc");
1189
1146
  }
1147
+ return { resource: item.resource, container, setRating, rate };
1148
+ }
1149
+
1150
+ // src/browser/transfer.js
1151
+ function createTransferCheckout(resource, options = {}) {
1152
+ const normalized = normalizeResource({ ...resource, paymentRail: "transfer" });
1153
+ const sendTransfer = options.sendTransfer || options.transfer;
1154
+ if (typeof sendTransfer !== "function") {
1155
+ throw new Error("createTransferCheckout requires sendTransfer({ resource, recipient, amount, currency, network }) and a server verifyTransfer hook.");
1156
+ }
1190
1157
  return {
1191
- resource: item.resource,
1192
- container,
1193
- setRating,
1194
- rate
1158
+ resource: normalized,
1159
+ async pay(input = {}) {
1160
+ const recipient = normalized.recipient || normalized.payTo;
1161
+ const amount = String(normalized.price || normalized.amount || "0");
1162
+ const currency = normalized.currency || "USDC";
1163
+ const network = options.network || input.challenge?.accepts?.[0]?.network || "eip155:5042002";
1164
+ const result = await sendTransfer({ resource: normalized, recipient, amount, currency, network, challenge: input.challenge });
1165
+ const txHash = result?.txHash || result?.hash || result?.transactionHash || result?.paymentId || "";
1166
+ if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
1167
+ return {
1168
+ paymentSignature: txHash,
1169
+ signature: txHash,
1170
+ memo: result.memo || "",
1171
+ metadata: {
1172
+ paymentProvider: "direct-transfer",
1173
+ paymentId: txHash,
1174
+ txHash,
1175
+ recipient,
1176
+ amount: Number(amount),
1177
+ currency,
1178
+ network,
1179
+ ...result.metadata || result
1180
+ }
1181
+ };
1182
+ }
1195
1183
  };
1196
1184
  }
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",
1185
+ async function payWithTransfer(resource, options = {}) {
1186
+ const checkout = options.checkout || createTransferCheckout(resource, options).pay;
1187
+ const result = await checkout({ resource: normalizeResource(resource), challenge: options.challenge || null });
1188
+ const txHash = result?.metadata?.txHash || result?.txHash || result?.paymentSignature || result?.signature || "";
1189
+ if (!txHash) throw new Error("Transfer checkout did not return a txHash.");
1190
+ return checkResourceAccess(resource, {
1191
+ ...options,
1206
1192
  headers: {
1207
- accept: "application/json",
1208
- "content-type": "application/json",
1209
- ...options.payHeaders || {}
1193
+ ...options.headers || {},
1194
+ "x-nibgate-transfer-tx": txHash
1210
1195
  },
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 || "";
1196
+ payment: result.metadata || { paymentProvider: "direct-transfer", txHash, paymentId: txHash }
1242
1197
  });
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
1198
  }
1199
+
1200
+ // src/browser/client.js
1255
1201
  function createNibgate(defaults = {}) {
1256
1202
  const defaultResource = defaults.resource ? normalizeResource(defaults.resource) : null;
1257
1203
  function resourceWithDefaults(resource = {}) {
@@ -1333,7 +1279,51 @@ var Nibgate = (() => {
1333
1279
  };
1334
1280
  }
1335
1281
  var nibgate = createNibgate();
1336
- var gate = createGate;
1282
+ setDefaultClient(nibgate);
1283
+
1284
+ // src/core/settings.js
1285
+ var NIBGATE_CONTENT_SETTING_FIELDS = [
1286
+ { name: "publishToNibgate", label: "Publish to Nibgate discovery", type: "boolean", defaultValue: true },
1287
+ { name: "type", label: "Content type", type: "select", options: CONTENT_TYPES, defaultValue: "article" },
1288
+ { name: "humanAccess", label: "Human access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
1289
+ { name: "agentAccess", label: "Agent access", type: "select", options: ACCESS_MODES, defaultValue: "paid" },
1290
+ { name: "unlockMode", label: "Unlock mode", type: "select", options: UNLOCK_MODES, defaultValue: "one_time" },
1291
+ { name: "paymentRail", label: "Payment rail", type: "select", options: PAYMENT_RAILS, defaultValue: "gateway" },
1292
+ { name: "price", label: "Price", type: "text", defaultValue: "0.005" },
1293
+ { name: "currency", label: "Currency", type: "text", defaultValue: "USDC" },
1294
+ { name: "recipient", label: "Recipient wallet", type: "wallet", defaultValue: "" },
1295
+ { name: "ratingsEnabled", label: "Enable ratings", type: "boolean", defaultValue: true },
1296
+ { name: "license", label: "License / terms", type: "textarea", defaultValue: "" }
1297
+ ];
1298
+ function createNibgateContentSettings(input = {}) {
1299
+ const access = normalizeAccessPolicy(input.access || {
1300
+ humans: input.humanAccess,
1301
+ agents: input.agentAccess
1302
+ });
1303
+ const unlock = normalizeUnlockPolicy(input.unlock || input.unlockMode || "one_time");
1304
+ return {
1305
+ publishToNibgate: input.publishToNibgate ?? input.publishedToNibgate ?? true,
1306
+ type: normalizeContentType(input.type || input.contentType || "article"),
1307
+ humanAccess: access.humans,
1308
+ agentAccess: access.agents,
1309
+ unlockMode: unlock.mode,
1310
+ paymentRail: normalizePaymentRail(input.paymentRail || input.paymentMode || input.rail),
1311
+ price: String(input.price ?? input.amount ?? "0.005"),
1312
+ currency: input.currency || "USDC",
1313
+ recipient: input.recipient || input.payTo || input.receiverAddress || input.creatorWallet || "",
1314
+ ratingsEnabled: input.ratingsEnabled ?? input.enableRatings ?? input.reputation?.ratingsEnabled ?? true,
1315
+ license: input.license || input.terms || ""
1316
+ };
1317
+ }
1318
+ function settingsToAccessPolicy(settings = {}) {
1319
+ return normalizeAccessPolicy({
1320
+ humans: settings.humanAccess,
1321
+ agents: settings.agentAccess
1322
+ });
1323
+ }
1324
+ function settingsToUnlockPolicy(settings = {}) {
1325
+ return normalizeUnlockPolicy(settings.unlockMode || settings.unlock || "one_time");
1326
+ }
1337
1327
  return __toCommonJS(index_exports);
1338
1328
  })();
1339
1329
  //# sourceMappingURL=nibgate.js.map