@ergoblockchain/sage-widget 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import { c as SageActivityResponse, u as SageWidgetOptions, e as SageChatMessage, k as SagePaymentPhase, q as SageQuoteResponse, t as SageVerifyPaymentResponse, r as SageReceiptBundle, l as SagePaymentWidgetOptions } from './types-yv1THHVz.cjs';
2
- export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, m as SagePaymentWidgetStatus, n as SagePremiumPaymentRequired, o as SagePremiumReason, p as SageQuote, s as SageTenantConfig } from './types-yv1THHVz.cjs';
1
+ import { c as SageActivityResponse, y as SageWidgetOptions, e as SageChatMessage, m as SagePaymentPhase, s as SageQuoteResponse, k as SagePaymentIntent, v as SageVerifyPaymentResponse, t as SageReceiptBundle, n as SagePaymentWidgetOptions } from './types-B5V2rsYn.cjs';
2
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, l as SagePaymentNetwork, o as SagePaymentWidgetStatus, p as SagePremiumPaymentRequired, q as SagePremiumReason, r as SageQuote, u as SageTenantConfig, w as SageWalletLaunchResult, x as SageWalletLauncher } from './types-B5V2rsYn.cjs';
3
3
 
4
4
  /**
5
5
  * mountSageFeed — framework-agnostic DOM mount for the Sage activity
@@ -39,6 +39,7 @@ interface MountSagePaymentWidgetHandle {
39
39
  phase: SagePaymentPhase;
40
40
  tier: "free" | "premium" | null;
41
41
  quote: SageQuoteResponse["quote"] | null;
42
+ paymentIntent: SagePaymentIntent | null;
42
43
  receipt: SageVerifyPaymentResponse | null;
43
44
  receiptBundle: SageReceiptBundle | null;
44
45
  error: string | null;
@@ -48,4 +49,4 @@ interface MountSagePaymentWidgetHandle {
48
49
  }
49
50
  declare function mountSagePaymentWidget(target: Element, opts?: SagePaymentWidgetOptions): MountSagePaymentWidgetHandle;
50
51
 
51
- export { type MountSageFeedHandle, type MountSagePaymentWidgetHandle, SageActivityResponse, SageChatMessage, SagePaymentPhase, SagePaymentWidgetOptions, SageQuoteResponse, SageReceiptBundle, SageVerifyPaymentResponse, SageWidgetOptions, mountSageFeed, mountSagePaymentWidget };
52
+ export { type MountSageFeedHandle, type MountSagePaymentWidgetHandle, SageActivityResponse, SageChatMessage, SagePaymentIntent, SagePaymentPhase, SagePaymentWidgetOptions, SageQuoteResponse, SageReceiptBundle, SageVerifyPaymentResponse, SageWidgetOptions, mountSageFeed, mountSagePaymentWidget };
package/dist/vanilla.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as SageActivityResponse, u as SageWidgetOptions, e as SageChatMessage, k as SagePaymentPhase, q as SageQuoteResponse, t as SageVerifyPaymentResponse, r as SageReceiptBundle, l as SagePaymentWidgetOptions } from './types-yv1THHVz.js';
2
- export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, m as SagePaymentWidgetStatus, n as SagePremiumPaymentRequired, o as SagePremiumReason, p as SageQuote, s as SageTenantConfig } from './types-yv1THHVz.js';
1
+ import { c as SageActivityResponse, y as SageWidgetOptions, e as SageChatMessage, m as SagePaymentPhase, s as SageQuoteResponse, k as SagePaymentIntent, v as SageVerifyPaymentResponse, t as SageReceiptBundle, n as SagePaymentWidgetOptions } from './types-B5V2rsYn.js';
2
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType, f as SageChatRole, g as SageChatStreamEvent, h as SageChatStreamResult, i as SageChatTier, j as SagePaymentInstructions, l as SagePaymentNetwork, o as SagePaymentWidgetStatus, p as SagePremiumPaymentRequired, q as SagePremiumReason, r as SageQuote, u as SageTenantConfig, w as SageWalletLaunchResult, x as SageWalletLauncher } from './types-B5V2rsYn.js';
3
3
 
4
4
  /**
5
5
  * mountSageFeed — framework-agnostic DOM mount for the Sage activity
@@ -39,6 +39,7 @@ interface MountSagePaymentWidgetHandle {
39
39
  phase: SagePaymentPhase;
40
40
  tier: "free" | "premium" | null;
41
41
  quote: SageQuoteResponse["quote"] | null;
42
+ paymentIntent: SagePaymentIntent | null;
42
43
  receipt: SageVerifyPaymentResponse | null;
43
44
  receiptBundle: SageReceiptBundle | null;
44
45
  error: string | null;
@@ -48,4 +49,4 @@ interface MountSagePaymentWidgetHandle {
48
49
  }
49
50
  declare function mountSagePaymentWidget(target: Element, opts?: SagePaymentWidgetOptions): MountSagePaymentWidgetHandle;
50
51
 
51
- export { type MountSageFeedHandle, type MountSagePaymentWidgetHandle, SageActivityResponse, SageChatMessage, SagePaymentPhase, SagePaymentWidgetOptions, SageQuoteResponse, SageReceiptBundle, SageVerifyPaymentResponse, SageWidgetOptions, mountSageFeed, mountSagePaymentWidget };
52
+ export { type MountSageFeedHandle, type MountSagePaymentWidgetHandle, SageActivityResponse, SageChatMessage, SagePaymentIntent, SagePaymentPhase, SagePaymentWidgetOptions, SageQuoteResponse, SageReceiptBundle, SageVerifyPaymentResponse, SageWidgetOptions, mountSageFeed, mountSagePaymentWidget };
package/dist/vanilla.js CHANGED
@@ -52,6 +52,28 @@ async function fetchSageReceipt(id, opts = {}) {
52
52
  if (!res.ok) throw new Error(readError(body, `sage receipt ${res.status}`));
53
53
  return body;
54
54
  }
55
+ function createSagePaymentIntent(opts) {
56
+ const base = trimSlash(opts.apiBase ?? DEFAULT_API_BASE);
57
+ return {
58
+ type: "sage.payment_intent.v1",
59
+ network: opts.network ?? "ergo-testnet",
60
+ createdAt: opts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
61
+ question: opts.question,
62
+ ...opts.tenant?.id || opts.tenant?.label ? { tenant: { id: opts.tenant.id, label: opts.tenant.label } } : {},
63
+ quote: opts.quote,
64
+ amountErg: opts.quote.price,
65
+ receiverAddress: opts.quote.receiverAddress,
66
+ reserveBoxId: opts.quote.reserveBoxId,
67
+ taskHash: opts.quote.taskHash,
68
+ expiresAt: opts.quote.expiresAt,
69
+ deadline: opts.quote.deadline,
70
+ verifyEndpoint: `${base}/api/sage/verify-payment`,
71
+ receiptEndpointTemplate: `${base}/api/sage/receipt/{receiptId}`
72
+ };
73
+ }
74
+ function serializeSagePaymentIntent(intent) {
75
+ return JSON.stringify(intent, null, 2);
76
+ }
55
77
  async function streamSageChat(opts) {
56
78
  const res = await fetch(`${apiBase(opts)}/api/sage/chat`, {
57
79
  method: "POST",
@@ -455,6 +477,7 @@ function mountSagePaymentWidget(target, opts = {}) {
455
477
  let noteBoxId = "";
456
478
  let activeQuestion = "";
457
479
  let quoteResponse = null;
480
+ let paymentIntent = null;
458
481
  let receipt = null;
459
482
  let receiptBundle = null;
460
483
  let error = null;
@@ -470,6 +493,7 @@ function mountSagePaymentWidget(target, opts = {}) {
470
493
  inputValue = "";
471
494
  noteBoxId = "";
472
495
  quoteResponse = null;
496
+ paymentIntent = null;
473
497
  receipt = null;
474
498
  receiptBundle = null;
475
499
  error = null;
@@ -491,6 +515,13 @@ function mountSagePaymentWidget(target, opts = {}) {
491
515
  if (quote.premium) {
492
516
  if (!quote.quote) throw new Error("Sage marked this question premium but did not return a quote.");
493
517
  quoteResponse = quote;
518
+ paymentIntent = createSagePaymentIntent({
519
+ apiBase: apiBase2,
520
+ tenant: opts.tenant,
521
+ question,
522
+ quote: quote.quote
523
+ });
524
+ opts.onPaymentIntent?.(paymentIntent);
494
525
  transition("payment_required");
495
526
  render();
496
527
  return;
@@ -525,6 +556,7 @@ function mountSagePaymentWidget(target, opts = {}) {
525
556
  receipt = verified;
526
557
  opts.onReceipt?.(verified);
527
558
  quoteResponse = null;
559
+ paymentIntent = null;
528
560
  noteBoxId = "";
529
561
  transition("streaming");
530
562
  try {
@@ -575,6 +607,13 @@ function mountSagePaymentWidget(target, opts = {}) {
575
607
  });
576
608
  opts.onQuote?.(quote);
577
609
  quoteResponse = quote;
610
+ paymentIntent = quote.quote ? createSagePaymentIntent({
611
+ apiBase: apiBase2,
612
+ tenant: opts.tenant,
613
+ question: activeQuestion,
614
+ quote: quote.quote
615
+ }) : null;
616
+ if (paymentIntent) opts.onPaymentIntent?.(paymentIntent);
578
617
  transition("payment_required");
579
618
  render();
580
619
  return;
@@ -587,6 +626,21 @@ function mountSagePaymentWidget(target, opts = {}) {
587
626
  transition("idle");
588
627
  render();
589
628
  }
629
+ async function launchWallet() {
630
+ if (!paymentIntent || !opts.walletLauncher || isBusy()) return;
631
+ error = null;
632
+ try {
633
+ const result = await opts.walletLauncher(paymentIntent);
634
+ if (result?.ok === false) {
635
+ throw new Error(result.error ?? "Wallet flow did not produce a Note.");
636
+ }
637
+ if (result?.noteBoxId) noteBoxId = result.noteBoxId;
638
+ } catch (err) {
639
+ error = err instanceof Error ? err.message : "Wallet flow failed.";
640
+ opts.onError?.(err);
641
+ }
642
+ render();
643
+ }
590
644
  function render() {
591
645
  root.innerHTML = "";
592
646
  const header = document.createElement("header");
@@ -691,6 +745,41 @@ function mountSagePaymentWidget(target, opts = {}) {
691
745
  field("Reserve box", quote.reserveBoxId),
692
746
  field("Task hash", quote.taskHash)
693
747
  );
748
+ const testnetWarning = opts.testnetWarning === false ? null : opts.testnetWarning ?? "Testnet proof flow. The widget never signs funds; connect your own reviewed wallet layer before handling real value.";
749
+ if (testnetWarning) {
750
+ const warning = document.createElement("div");
751
+ warning.textContent = testnetWarning;
752
+ applyStyles2(warning, warningStyle);
753
+ panel.appendChild(warning);
754
+ }
755
+ if (opts.showPaymentIntent !== false && paymentIntent) {
756
+ const intent = document.createElement("div");
757
+ applyStyles2(intent, intentStyle);
758
+ const intentTop = document.createElement("div");
759
+ applyStyles2(intentTop, intentHeaderStyle);
760
+ const label2 = document.createElement("strong");
761
+ label2.textContent = "Payment intent";
762
+ const copy = document.createElement("button");
763
+ copy.type = "button";
764
+ copy.textContent = "Copy JSON";
765
+ copy.addEventListener("click", () => copyText(serializeSagePaymentIntent(paymentIntent)));
766
+ applyStyles2(copy, copyButtonStyle);
767
+ intentTop.append(label2, copy);
768
+ const code = document.createElement("code");
769
+ code.textContent = serializeSagePaymentIntent(paymentIntent);
770
+ applyStyles2(code, intentCodeStyle);
771
+ intent.append(intentTop, code);
772
+ panel.appendChild(intent);
773
+ }
774
+ if (opts.walletLauncher && paymentIntent) {
775
+ const wallet = document.createElement("button");
776
+ wallet.type = "button";
777
+ wallet.textContent = opts.paymentInstructions?.walletLauncherLabel ?? "Open wallet flow";
778
+ wallet.disabled = isBusy();
779
+ wallet.addEventListener("click", () => void launchWallet());
780
+ applyStyles2(wallet, secondaryButtonStyle);
781
+ panel.appendChild(wallet);
782
+ }
694
783
  const label = document.createElement("label");
695
784
  label.textContent = opts.paymentInstructions?.noteBoxLabel ?? "Note box id";
696
785
  applyStyles2(label, labelStyle2);
@@ -751,6 +840,7 @@ function mountSagePaymentWidget(target, opts = {}) {
751
840
  phase: next,
752
841
  tier,
753
842
  quote: quoteResponse?.quote ?? null,
843
+ paymentIntent,
754
844
  receipt,
755
845
  receiptBundle,
756
846
  error,
@@ -770,6 +860,7 @@ function mountSagePaymentWidget(target, opts = {}) {
770
860
  phase,
771
861
  tier,
772
862
  quote: quoteResponse?.quote ?? null,
863
+ paymentIntent,
773
864
  receipt,
774
865
  receiptBundle,
775
866
  error,
@@ -949,6 +1040,50 @@ var primaryButtonStyle = {
949
1040
  ...sendButtonStyle,
950
1041
  padding: "10px 12px"
951
1042
  };
1043
+ var secondaryButtonStyle = {
1044
+ border: "1px solid rgba(103,232,249,.28)",
1045
+ background: "rgba(103,232,249,.08)",
1046
+ color: "#cffafe",
1047
+ borderRadius: "6px",
1048
+ padding: "10px 12px",
1049
+ fontWeight: "800",
1050
+ cursor: "pointer"
1051
+ };
1052
+ var warningStyle = {
1053
+ color: "#fde68a",
1054
+ background: "rgba(245,158,11,.1)",
1055
+ border: "1px solid rgba(245,158,11,.24)",
1056
+ borderRadius: "6px",
1057
+ padding: "8px 9px",
1058
+ fontSize: "12px",
1059
+ lineHeight: "1.45"
1060
+ };
1061
+ var intentStyle = {
1062
+ border: "1px solid rgba(255,255,255,.12)",
1063
+ background: "rgba(255,255,255,.04)",
1064
+ borderRadius: "6px",
1065
+ padding: "10px",
1066
+ display: "grid",
1067
+ gap: "8px"
1068
+ };
1069
+ var intentHeaderStyle = {
1070
+ display: "flex",
1071
+ justifyContent: "space-between",
1072
+ alignItems: "center",
1073
+ gap: "8px",
1074
+ color: "#e2e8f0",
1075
+ fontSize: "12px"
1076
+ };
1077
+ var intentCodeStyle = {
1078
+ display: "block",
1079
+ maxHeight: "130px",
1080
+ overflow: "auto",
1081
+ whiteSpace: "pre-wrap",
1082
+ wordBreak: "break-word",
1083
+ color: "#cbd5e1",
1084
+ fontSize: "10px",
1085
+ lineHeight: "1.45"
1086
+ };
952
1087
  var receiptStyle = {
953
1088
  display: "block",
954
1089
  marginTop: "10px",