@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/SKILL.md +145 -10
- package/dist/nibgate.js +376 -366
- package/dist/nibgate.js.map +4 -4
- package/dist/nibgate.min.js +2 -2
- package/dist/nibgate.min.js.map +4 -4
- package/package.json +6 -3
- package/src/browser/access.js +168 -0
- package/src/browser/checkout.js +53 -0
- package/src/browser/client.js +97 -0
- package/src/browser/evm-gateway.js +180 -0
- package/src/browser/gate.js +63 -0
- package/src/browser/index.js +9 -770
- package/src/browser/rating-ui.js +161 -0
- package/src/browser/track.js +45 -0
- package/src/core/resource.js +29 -4
- package/src/server/access.js +14 -29
- package/src/server/admin-page.html +168 -0
- package/src/server/admin.js +18 -180
- package/src/server/gateway.js +8 -3
- package/src/server/hub.js +1 -1
- package/src/server/webhooks.js +2 -2
- package/src/server/runtime.js +0 -39
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
|
|
243
|
-
url
|
|
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))
|
|
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/
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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 ||
|
|
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
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
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
|
-
|
|
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
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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
|
-
|
|
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:
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
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
|
|
1198
|
-
const
|
|
1199
|
-
const
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
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
|
-
|
|
1208
|
-
"
|
|
1209
|
-
...options.payHeaders || {}
|
|
1213
|
+
...options.headers || {},
|
|
1214
|
+
"x-nibgate-transfer-tx": txHash
|
|
1210
1215
|
},
|
|
1211
|
-
|
|
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
|
-
|
|
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
|