@zendfi/sdk 0.6.0 → 0.7.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.
package/dist/index.js CHANGED
@@ -1041,6 +1041,7 @@ __export(index_exports, {
1041
1041
  WalletConnector: () => WalletConnector,
1042
1042
  WebhookError: () => WebhookError,
1043
1043
  ZendFiClient: () => ZendFiClient,
1044
+ ZendFiEmbeddedCheckout: () => ZendFiEmbeddedCheckout,
1044
1045
  ZendFiError: () => ZendFiError2,
1045
1046
  ZendFiSessionKeyManager: () => ZendFiSessionKeyManager,
1046
1047
  asAgentKeyId: () => asAgentKeyId,
@@ -1525,7 +1526,7 @@ function createInterceptors() {
1525
1526
  };
1526
1527
  }
1527
1528
 
1528
- // src/api/agent.ts
1529
+ // src/aip/agent.ts
1529
1530
  function normalizeArrayResponse(response, key) {
1530
1531
  if (Array.isArray(response)) {
1531
1532
  return response;
@@ -1793,7 +1794,7 @@ var AgentAPI = class {
1793
1794
  }
1794
1795
  };
1795
1796
 
1796
- // src/api/intents.ts
1797
+ // src/aip/intents.ts
1797
1798
  var PaymentIntentsAPI = class {
1798
1799
  constructor(request) {
1799
1800
  this.request = request;
@@ -1956,7 +1957,7 @@ var PaymentIntentsAPI = class {
1956
1957
  }
1957
1958
  };
1958
1959
 
1959
- // src/api/pricing.ts
1960
+ // src/aip/pricing.ts
1960
1961
  var PricingAPI = class {
1961
1962
  constructor(request) {
1962
1963
  this.request = request;
@@ -2093,7 +2094,7 @@ var PricingAPI = class {
2093
2094
  }
2094
2095
  };
2095
2096
 
2096
- // src/api/autonomy.ts
2097
+ // src/aip/autonomy.ts
2097
2098
  var AutonomyAPI = class {
2098
2099
  constructor(request) {
2099
2100
  this.request = request;
@@ -2305,7 +2306,7 @@ var AutonomyAPI = class {
2305
2306
  }
2306
2307
  };
2307
2308
 
2308
- // src/api/smart-payments.ts
2309
+ // src/aip/smart-payments.ts
2309
2310
  var SmartPaymentsAPI = class {
2310
2311
  constructor(request) {
2311
2312
  this.request = request;
@@ -2410,7 +2411,7 @@ var SmartPaymentsAPI = class {
2410
2411
  }
2411
2412
  };
2412
2413
 
2413
- // src/api/session-keys.ts
2414
+ // src/aip/session-keys.ts
2414
2415
  var SessionKeysAPI = class {
2415
2416
  constructor(request) {
2416
2417
  this.request = request;
@@ -3490,6 +3491,677 @@ function verifyWebhookSignature(payload, signature, secret) {
3490
3491
  });
3491
3492
  }
3492
3493
 
3494
+ // src/embedded-checkout.ts
3495
+ var ZendFiEmbeddedCheckout = class {
3496
+ config;
3497
+ container = null;
3498
+ checkoutData = null;
3499
+ pollInterval = null;
3500
+ mounted = false;
3501
+ constructor(config) {
3502
+ this.config = {
3503
+ linkCode: config.linkCode || "",
3504
+ paymentId: config.paymentId || "",
3505
+ containerId: config.containerId,
3506
+ mode: config.mode || "test",
3507
+ apiUrl: config.apiUrl || this.getDefaultApiUrl(),
3508
+ onSuccess: config.onSuccess || (() => {
3509
+ }),
3510
+ onError: config.onError || (() => {
3511
+ }),
3512
+ onLoad: config.onLoad || (() => {
3513
+ }),
3514
+ theme: config.theme || {},
3515
+ allowCustomAmount: config.allowCustomAmount || false,
3516
+ paymentMethods: config.paymentMethods || {
3517
+ walletConnect: true,
3518
+ qrCode: true,
3519
+ solanaWallet: true
3520
+ }
3521
+ };
3522
+ if (!this.config.linkCode && !this.config.paymentId) {
3523
+ throw new Error("Either linkCode or paymentId must be provided");
3524
+ }
3525
+ }
3526
+ getDefaultApiUrl() {
3527
+ if (typeof window !== "undefined" && window.location.hostname === "localhost") {
3528
+ return "http://localhost:8080";
3529
+ }
3530
+ return "https://api.zendfi.tech";
3531
+ }
3532
+ /**
3533
+ * Mount the checkout to the DOM
3534
+ */
3535
+ async mount() {
3536
+ if (this.mounted) {
3537
+ console.warn("Checkout is already mounted");
3538
+ return;
3539
+ }
3540
+ this.container = document.getElementById(this.config.containerId);
3541
+ if (!this.container) {
3542
+ throw new Error(`Container element #${this.config.containerId} not found`);
3543
+ }
3544
+ try {
3545
+ this.renderLoading();
3546
+ await this.loadDependencies();
3547
+ await this.fetchCheckoutData();
3548
+ this.render();
3549
+ this.startPaymentPolling();
3550
+ this.mounted = true;
3551
+ this.config.onLoad();
3552
+ } catch (error) {
3553
+ const err = error;
3554
+ this.config.onError({
3555
+ code: "MOUNT_ERROR",
3556
+ message: err.message,
3557
+ details: error
3558
+ });
3559
+ this.renderError(err.message);
3560
+ }
3561
+ }
3562
+ /**
3563
+ * Unmount and cleanup
3564
+ */
3565
+ unmount() {
3566
+ if (this.pollInterval) {
3567
+ clearInterval(this.pollInterval);
3568
+ this.pollInterval = null;
3569
+ }
3570
+ if (this.container) {
3571
+ this.container.innerHTML = "";
3572
+ }
3573
+ this.mounted = false;
3574
+ }
3575
+ /**
3576
+ * Fetch checkout data from API
3577
+ */
3578
+ async fetchCheckoutData() {
3579
+ let endpoint;
3580
+ let method;
3581
+ if (this.config.linkCode) {
3582
+ endpoint = `/api/v1/payment-links/${this.config.linkCode}/pay`;
3583
+ method = "POST";
3584
+ } else {
3585
+ endpoint = `/api/v1/payments/${this.config.paymentId}/checkout-data`;
3586
+ method = "GET";
3587
+ }
3588
+ const response = await fetch(`${this.config.apiUrl}${endpoint}`, {
3589
+ method,
3590
+ headers: {
3591
+ "Content-Type": "application/json"
3592
+ }
3593
+ });
3594
+ if (!response.ok) {
3595
+ throw new Error(`Failed to fetch checkout data: ${response.statusText}`);
3596
+ }
3597
+ this.checkoutData = await response.json();
3598
+ }
3599
+ /**
3600
+ * Poll for payment confirmation
3601
+ */
3602
+ startPaymentPolling() {
3603
+ this.pollInterval = setInterval(async () => {
3604
+ if (!this.checkoutData) return;
3605
+ try {
3606
+ const response = await fetch(
3607
+ `${this.config.apiUrl}/api/v1/payments/${this.checkoutData.payment_id}/status`,
3608
+ {
3609
+ method: "GET",
3610
+ headers: {
3611
+ "Content-Type": "application/json"
3612
+ }
3613
+ }
3614
+ );
3615
+ if (response.ok) {
3616
+ const data = await response.json();
3617
+ if (data.status === "confirmed") {
3618
+ this.handlePaymentSuccess(data);
3619
+ } else if (data.status === "failed") {
3620
+ this.handlePaymentFailure(data);
3621
+ } else if (data.status === "expired") {
3622
+ this.handlePaymentExpired();
3623
+ }
3624
+ }
3625
+ } catch (error) {
3626
+ console.error("Payment status check failed:", error);
3627
+ }
3628
+ }, 3e3);
3629
+ }
3630
+ /**
3631
+ * Handle successful payment
3632
+ */
3633
+ handlePaymentSuccess(data) {
3634
+ if (this.pollInterval) {
3635
+ clearInterval(this.pollInterval);
3636
+ this.pollInterval = null;
3637
+ }
3638
+ this.config.onSuccess({
3639
+ paymentId: data.id,
3640
+ transactionSignature: data.transaction_signature,
3641
+ amount: data.amount_usd || data.amount,
3642
+ token: data.payment_token,
3643
+ merchantName: this.checkoutData?.merchant_name || "Merchant"
3644
+ });
3645
+ this.renderSuccess();
3646
+ }
3647
+ /**
3648
+ * Handle payment failure
3649
+ */
3650
+ handlePaymentFailure(data) {
3651
+ if (this.pollInterval) {
3652
+ clearInterval(this.pollInterval);
3653
+ this.pollInterval = null;
3654
+ }
3655
+ this.config.onError({
3656
+ code: "PAYMENT_FAILED",
3657
+ message: "Payment failed",
3658
+ details: data
3659
+ });
3660
+ this.renderError("Payment failed. Please try again.");
3661
+ }
3662
+ /**
3663
+ * Handle payment expiration
3664
+ */
3665
+ handlePaymentExpired() {
3666
+ if (this.pollInterval) {
3667
+ clearInterval(this.pollInterval);
3668
+ this.pollInterval = null;
3669
+ }
3670
+ this.config.onError({
3671
+ code: "PAYMENT_EXPIRED",
3672
+ message: "Payment link has expired"
3673
+ });
3674
+ this.renderError("This payment link has expired.");
3675
+ }
3676
+ /**
3677
+ * Render loading state
3678
+ */
3679
+ renderLoading() {
3680
+ if (!this.container) return;
3681
+ this.container.innerHTML = `
3682
+ <div class="zendfi-checkout-loading" style="${this.getLoadingStyles()}">
3683
+ <div class="zendfi-spinner" style="${this.getSpinnerStyles()}"></div>
3684
+ <p style="margin-top: 16px; color: #666;">Loading checkout...</p>
3685
+ </div>
3686
+ `;
3687
+ }
3688
+ /**
3689
+ * Render the main checkout UI
3690
+ */
3691
+ render() {
3692
+ if (!this.container || !this.checkoutData) return;
3693
+ const theme = this.getComputedTheme();
3694
+ this.container.innerHTML = `
3695
+ <div class="zendfi-embedded-checkout" style="${this.getCheckoutContainerStyles(theme)}">
3696
+ ${this.renderHeader()}
3697
+ ${this.renderPaymentInfo()}
3698
+ ${this.renderPaymentMethods()}
3699
+ ${this.renderFooter()}
3700
+ </div>
3701
+ `;
3702
+ this.attachEventListeners();
3703
+ this.injectStyles();
3704
+ }
3705
+ /**
3706
+ * Render header section
3707
+ */
3708
+ renderHeader() {
3709
+ if (!this.checkoutData) return "";
3710
+ return `
3711
+ <div class="zendfi-checkout-header" style="padding: 24px; border-bottom: 1px solid #e5e7eb;">
3712
+ <h2 style="margin: 0; font-size: 24px; font-weight: 600; color: ${this.config.theme.textColor || "#1f2937"};">
3713
+ Pay ${this.checkoutData.merchant_name}
3714
+ </h2>
3715
+ ${this.checkoutData.description ? `
3716
+ <p style="margin: 8px 0 0 0; color: #6b7280; font-size: 14px;">
3717
+ ${this.checkoutData.description}
3718
+ </p>
3719
+ ` : ""}
3720
+ </div>
3721
+ `;
3722
+ }
3723
+ /**
3724
+ * Render payment information
3725
+ */
3726
+ renderPaymentInfo() {
3727
+ if (!this.checkoutData) return "";
3728
+ return `
3729
+ <div class="zendfi-payment-info" style="padding: 24px; background: #f9fafb;">
3730
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
3731
+ <span style="font-size: 14px; color: #6b7280;">Amount</span>
3732
+ <span style="font-size: 24px; font-weight: 700; color: #1f2937;">
3733
+ $${this.checkoutData.amount_usd.toFixed(2)} ${this.checkoutData.token}
3734
+ </span>
3735
+ </div>
3736
+
3737
+ ${this.checkoutData.allow_custom_amount ? this.renderCustomAmountInput() : ""}
3738
+
3739
+ <div style="display: flex; justify-content: space-between; align-items: center; padding: 12px; background: white; border-radius: 8px; margin-top: 12px;">
3740
+ <span style="font-size: 12px; color: #6b7280;">Network</span>
3741
+ <span style="font-size: 12px; font-weight: 600; color: #1f2937; text-transform: uppercase;">
3742
+ ${this.checkoutData.solana_network}
3743
+ </span>
3744
+ </div>
3745
+ </div>
3746
+ `;
3747
+ }
3748
+ /**
3749
+ * Render custom amount input (Pay What You Want)
3750
+ */
3751
+ renderCustomAmountInput() {
3752
+ if (!this.checkoutData) return "";
3753
+ return `
3754
+ <div style="margin-top: 16px;">
3755
+ <label style="display: block; font-size: 14px; color: #6b7280; margin-bottom: 8px;">
3756
+ Custom Amount (Optional)
3757
+ </label>
3758
+ <input
3759
+ type="number"
3760
+ id="zendfi-custom-amount"
3761
+ placeholder="${this.checkoutData.suggested_amount || this.checkoutData.amount_usd}"
3762
+ min="${this.checkoutData.minimum_amount || 0}"
3763
+ ${this.checkoutData.maximum_amount ? `max="${this.checkoutData.maximum_amount}"` : ""}
3764
+ step="0.01"
3765
+ style="width: 100%; padding: 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 16px;"
3766
+ />
3767
+ ${this.checkoutData.minimum_amount ? `
3768
+ <p style="font-size: 12px; color: #6b7280; margin-top: 4px;">
3769
+ Minimum: $${this.checkoutData.minimum_amount}
3770
+ </p>
3771
+ ` : ""}
3772
+ </div>
3773
+ `;
3774
+ }
3775
+ /**
3776
+ * Render payment methods
3777
+ */
3778
+ renderPaymentMethods() {
3779
+ if (!this.checkoutData) return "";
3780
+ return `
3781
+ <div class="zendfi-payment-methods" style="padding: 24px;">
3782
+ <h3 style="margin: 0 0 16px 0; font-size: 16px; font-weight: 600; color: #1f2937;">
3783
+ Payment Methods
3784
+ </h3>
3785
+
3786
+ ${this.config.paymentMethods.qrCode ? this.renderQRCodeMethod() : ""}
3787
+ ${this.config.paymentMethods.solanaWallet ? this.renderWalletMethod() : ""}
3788
+ ${this.config.paymentMethods.walletConnect ? this.renderWalletConnectMethod() : ""}
3789
+ </div>
3790
+ `;
3791
+ }
3792
+ /**
3793
+ * Render QR code payment method
3794
+ */
3795
+ renderQRCodeMethod() {
3796
+ if (!this.checkoutData) return "";
3797
+ return `
3798
+ <div class="zendfi-payment-method" style="padding: 16px; border: 1px solid #e5e7eb; border-radius: 12px; margin-bottom: 16px;">
3799
+ <div style="text-align: center;">
3800
+ <p style="font-size: 14px; color: #6b7280; margin-bottom: 16px;">
3801
+ Scan with Solana wallet
3802
+ </p>
3803
+ <div id="zendfi-qr-container" style="display: flex; justify-content: center; margin-bottom: 16px;">
3804
+ <canvas id="zendfi-qr-code"></canvas>
3805
+ </div>
3806
+ <button
3807
+ id="zendfi-copy-address"
3808
+ style="padding: 10px 20px; background: #f3f4f6; border: 1px solid #d1d5db; border-radius: 8px; cursor: pointer; font-size: 14px; color: #374151; transition: all 0.2s;"
3809
+ onmouseover="this.style.background='#e5e7eb'"
3810
+ onmouseout="this.style.background='#f3f4f6'"
3811
+ >
3812
+ \u{1F4CB} Copy Address
3813
+ </button>
3814
+ </div>
3815
+ </div>
3816
+ `;
3817
+ }
3818
+ /**
3819
+ * Render browser wallet method
3820
+ */
3821
+ renderWalletMethod() {
3822
+ return `
3823
+ <div class="zendfi-payment-method" style="margin-bottom: 16px;">
3824
+ <button
3825
+ id="zendfi-connect-wallet"
3826
+ style="width: 100%; padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);"
3827
+ onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 12px rgba(0, 0, 0, 0.15)';"
3828
+ onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 6px rgba(0, 0, 0, 0.1)';"
3829
+ >
3830
+ \u{1F517} Connect Wallet
3831
+ </button>
3832
+ </div>
3833
+ `;
3834
+ }
3835
+ /**
3836
+ * Render WalletConnect method
3837
+ */
3838
+ renderWalletConnectMethod() {
3839
+ return `
3840
+ <div class="zendfi-payment-method">
3841
+ <button
3842
+ id="zendfi-wallet-connect"
3843
+ style="width: 100%; padding: 16px; background: white; color: #1f2937; border: 2px solid #e5e7eb; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s;"
3844
+ onmouseover="this.style.borderColor='#667eea'; this.style.background='#f9fafb';"
3845
+ onmouseout="this.style.borderColor='#e5e7eb'; this.style.background='white';"
3846
+ >
3847
+ \u{1F4F1} WalletConnect
3848
+ </button>
3849
+ </div>
3850
+ `;
3851
+ }
3852
+ /**
3853
+ * Render footer
3854
+ */
3855
+ renderFooter() {
3856
+ return `
3857
+ <div class="zendfi-checkout-footer" style="padding: 16px 24px; border-top: 1px solid #e5e7eb; text-align: center;">
3858
+ <p style="margin: 0; font-size: 12px; color: #9ca3af;">
3859
+ Powered by <a href="https://zendfi.tech" target="_blank" style="color: #667eea; text-decoration: none; font-weight: 600;">ZendFi</a>
3860
+ </p>
3861
+ </div>
3862
+ `;
3863
+ }
3864
+ /**
3865
+ * Render success state
3866
+ */
3867
+ renderSuccess() {
3868
+ if (!this.container) return;
3869
+ this.container.innerHTML = `
3870
+ <div class="zendfi-checkout-success" style="${this.getSuccessStyles()}">
3871
+ <div style="font-size: 64px; margin-bottom: 16px;">\u2705</div>
3872
+ <h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600; color: #059669;">
3873
+ Payment Successful!
3874
+ </h3>
3875
+ <p style="margin: 0; color: #6b7280; font-size: 14px;">
3876
+ Your payment has been confirmed on the blockchain.
3877
+ </p>
3878
+ </div>
3879
+ `;
3880
+ }
3881
+ /**
3882
+ * Render error state
3883
+ */
3884
+ renderError(message) {
3885
+ if (!this.container) return;
3886
+ this.container.innerHTML = `
3887
+ <div class="zendfi-checkout-error" style="${this.getErrorStyles()}">
3888
+ <div style="font-size: 64px; margin-bottom: 16px;">\u274C</div>
3889
+ <h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600; color: #dc2626;">
3890
+ Payment Failed
3891
+ </h3>
3892
+ <p style="margin: 0; color: #6b7280; font-size: 14px;">
3893
+ ${message}
3894
+ </p>
3895
+ </div>
3896
+ `;
3897
+ }
3898
+ /**
3899
+ * Attach event listeners to interactive elements
3900
+ */
3901
+ attachEventListeners() {
3902
+ const qrCanvas = document.getElementById("zendfi-qr-code");
3903
+ if (qrCanvas && this.checkoutData) {
3904
+ this.generateQRCode(qrCanvas, this.checkoutData.qr_code);
3905
+ }
3906
+ const copyBtn = document.getElementById("zendfi-copy-address");
3907
+ if (copyBtn && this.checkoutData) {
3908
+ copyBtn.addEventListener("click", () => {
3909
+ navigator.clipboard.writeText(this.checkoutData.wallet_address);
3910
+ copyBtn.textContent = "\u2713 Copied!";
3911
+ setTimeout(() => {
3912
+ copyBtn.textContent = "\u{1F4CB} Copy Address";
3913
+ }, 2e3);
3914
+ });
3915
+ }
3916
+ const connectBtn = document.getElementById("zendfi-connect-wallet");
3917
+ if (connectBtn) {
3918
+ connectBtn.addEventListener("click", () => this.handleWalletConnect());
3919
+ }
3920
+ const walletConnectBtn = document.getElementById("zendfi-wallet-connect");
3921
+ if (walletConnectBtn) {
3922
+ walletConnectBtn.addEventListener("click", () => this.handleWalletConnectScan());
3923
+ }
3924
+ }
3925
+ /**
3926
+ * Handle wallet connection and payment
3927
+ */
3928
+ async handleWalletConnect() {
3929
+ try {
3930
+ const provider = window.solana;
3931
+ if (!provider) {
3932
+ alert("No Solana wallet found. Please install Phantom, Solflare, or another Solana wallet.");
3933
+ return;
3934
+ }
3935
+ const connectBtn = document.getElementById("zendfi-connect-wallet");
3936
+ if (connectBtn) {
3937
+ connectBtn.textContent = "\u{1F504} Connecting...";
3938
+ connectBtn.disabled = true;
3939
+ }
3940
+ await provider.connect();
3941
+ const publicKey = provider.publicKey.toString();
3942
+ if (connectBtn) {
3943
+ connectBtn.textContent = "\u{1F528} Building transaction...";
3944
+ }
3945
+ const response = await fetch(
3946
+ `${this.config.apiUrl}/api/v1/payments/${this.checkoutData.payment_id}/build-transaction`,
3947
+ {
3948
+ method: "POST",
3949
+ headers: { "Content-Type": "application/json" },
3950
+ body: JSON.stringify({
3951
+ payer_wallet: publicKey,
3952
+ prefer_gasless: true
3953
+ })
3954
+ }
3955
+ );
3956
+ if (!response.ok) {
3957
+ throw new Error("Failed to build transaction");
3958
+ }
3959
+ const { transaction: transactionBase64, is_gasless } = await response.json();
3960
+ if (connectBtn) {
3961
+ connectBtn.textContent = "\u270D\uFE0F Sign transaction...";
3962
+ }
3963
+ const solanaWeb3 = window.solanaWeb3;
3964
+ const transactionBuffer = Uint8Array.from(atob(transactionBase64), (c) => c.charCodeAt(0));
3965
+ const transaction = solanaWeb3.Transaction.from(transactionBuffer);
3966
+ const signedTransaction = await provider.signTransaction(transaction);
3967
+ if (connectBtn) {
3968
+ connectBtn.textContent = "\u{1F4E1} Submitting...";
3969
+ }
3970
+ if (is_gasless) {
3971
+ const serialized = signedTransaction.serialize();
3972
+ const signedBase64 = btoa(String.fromCharCode(...serialized));
3973
+ const submitResponse = await fetch(
3974
+ `${this.config.apiUrl}/api/v1/payments/${this.checkoutData.payment_id}/submit-gasless-transaction`,
3975
+ {
3976
+ method: "POST",
3977
+ headers: { "Content-Type": "application/json" },
3978
+ body: JSON.stringify({
3979
+ signed_transaction: signedBase64
3980
+ })
3981
+ }
3982
+ );
3983
+ if (!submitResponse.ok) {
3984
+ const errorData = await submitResponse.json().catch(() => ({}));
3985
+ throw new Error(errorData.error || "Failed to submit gasless transaction");
3986
+ }
3987
+ } else {
3988
+ const signature = signedTransaction.signature?.toString();
3989
+ if (!signature) {
3990
+ throw new Error("Transaction signature missing");
3991
+ }
3992
+ const submitResponse = await fetch(
3993
+ `${this.config.apiUrl}/api/v1/payments/${this.checkoutData.payment_id}/submit-transaction`,
3994
+ {
3995
+ method: "POST",
3996
+ headers: { "Content-Type": "application/json" },
3997
+ body: JSON.stringify({
3998
+ transaction_signature: signature
3999
+ })
4000
+ }
4001
+ );
4002
+ if (!submitResponse.ok) {
4003
+ const errorData = await submitResponse.json().catch(() => ({}));
4004
+ throw new Error(errorData.error || "Failed to submit transaction");
4005
+ }
4006
+ }
4007
+ if (connectBtn) {
4008
+ connectBtn.textContent = "\u23F3 Confirming...";
4009
+ }
4010
+ } catch (error) {
4011
+ console.error("Wallet connection error:", error);
4012
+ const connectBtn = document.getElementById("zendfi-connect-wallet");
4013
+ if (connectBtn) {
4014
+ connectBtn.textContent = "\u{1F517} Connect Wallet";
4015
+ connectBtn.disabled = false;
4016
+ }
4017
+ this.config.onError({
4018
+ code: "WALLET_ERROR",
4019
+ message: error instanceof Error ? error.message : "Wallet connection failed",
4020
+ details: error
4021
+ });
4022
+ alert(`Payment failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4023
+ }
4024
+ }
4025
+ /**
4026
+ * Handle mobile wallet connection via Solana Pay deep link
4027
+ */
4028
+ handleWalletConnectScan() {
4029
+ if (!this.checkoutData) return;
4030
+ const solanaPayUrl = `solana:${this.checkoutData.wallet_address}?amount=${this.checkoutData.amount_usd}&spl-token=${this.checkoutData.token}&reference=${this.checkoutData.payment_id}&label=${encodeURIComponent(this.checkoutData.merchant_name)}&message=${encodeURIComponent(this.checkoutData.description || "Payment")}`;
4031
+ if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
4032
+ window.location.href = solanaPayUrl;
4033
+ } else {
4034
+ navigator.clipboard.writeText(solanaPayUrl).then(() => {
4035
+ alert("Solana Pay link copied! Open it on your mobile wallet or scan the QR code above.");
4036
+ }).catch(() => {
4037
+ alert("Solana Pay URL: " + solanaPayUrl);
4038
+ });
4039
+ }
4040
+ }
4041
+ /**
4042
+ * Generate QR code on canvas using QRious library
4043
+ */
4044
+ generateQRCode(canvas, data) {
4045
+ try {
4046
+ const QRious = window.QRious;
4047
+ if (!QRious) {
4048
+ console.error("QRious library not loaded");
4049
+ return;
4050
+ }
4051
+ new QRious({
4052
+ element: canvas,
4053
+ value: data,
4054
+ size: 256,
4055
+ level: "M"
4056
+ });
4057
+ } catch (error) {
4058
+ console.error("Failed to generate QR code:", error);
4059
+ }
4060
+ }
4061
+ /**
4062
+ * Inject custom styles
4063
+ */
4064
+ injectStyles() {
4065
+ const styleId = "zendfi-embedded-styles";
4066
+ if (document.getElementById(styleId)) return;
4067
+ const style = document.createElement("style");
4068
+ style.id = styleId;
4069
+ style.textContent = `
4070
+ .zendfi-embedded-checkout * {
4071
+ box-sizing: border-box;
4072
+ }
4073
+
4074
+ @keyframes zendfi-spin {
4075
+ to { transform: rotate(360deg); }
4076
+ }
4077
+ `;
4078
+ document.head.appendChild(style);
4079
+ }
4080
+ /**
4081
+ * Load external dependencies (QR code library, Solana web3.js)
4082
+ */
4083
+ async loadDependencies() {
4084
+ if (!window.QRious) {
4085
+ await this.loadScript("https://cdn.jsdelivr.net/npm/qrious@4/dist/qrious.min.js");
4086
+ }
4087
+ if (!window.solanaWeb3) {
4088
+ await this.loadScript("https://unpkg.com/@solana/web3.js@1.95.2/lib/index.iife.min.js");
4089
+ }
4090
+ }
4091
+ /**
4092
+ * Load external script
4093
+ */
4094
+ loadScript(src) {
4095
+ return new Promise((resolve, reject) => {
4096
+ if (document.querySelector(`script[src="${src}"]`)) {
4097
+ resolve();
4098
+ return;
4099
+ }
4100
+ const script = document.createElement("script");
4101
+ script.src = src;
4102
+ script.onload = () => resolve();
4103
+ script.onerror = () => reject(new Error(`Failed to load ${src}`));
4104
+ document.head.appendChild(script);
4105
+ });
4106
+ }
4107
+ /**
4108
+ * Get computed theme with defaults
4109
+ */
4110
+ getComputedTheme() {
4111
+ return {
4112
+ primaryColor: this.config.theme.primaryColor || "#667eea",
4113
+ backgroundColor: this.config.theme.backgroundColor || "#ffffff",
4114
+ borderRadius: this.config.theme.borderRadius || "16px",
4115
+ fontFamily: this.config.theme.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
4116
+ textColor: this.config.theme.textColor || "#1f2937",
4117
+ buttonStyle: this.config.theme.buttonStyle || "solid"
4118
+ };
4119
+ }
4120
+ /**
4121
+ * Style helpers
4122
+ */
4123
+ getCheckoutContainerStyles(theme) {
4124
+ return `
4125
+ font-family: ${theme.fontFamily};
4126
+ background: ${theme.backgroundColor};
4127
+ border-radius: ${theme.borderRadius};
4128
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
4129
+ overflow: hidden;
4130
+ max-width: 500px;
4131
+ margin: 0 auto;
4132
+ `.replace(/\s+/g, " ").trim();
4133
+ }
4134
+ getLoadingStyles() {
4135
+ return `
4136
+ display: flex;
4137
+ flex-direction: column;
4138
+ align-items: center;
4139
+ justify-content: center;
4140
+ padding: 80px 24px;
4141
+ text-align: center;
4142
+ `.replace(/\s+/g, " ").trim();
4143
+ }
4144
+ getSpinnerStyles() {
4145
+ return `
4146
+ width: 40px;
4147
+ height: 40px;
4148
+ border: 4px solid #f3f4f6;
4149
+ border-top-color: #667eea;
4150
+ border-radius: 50%;
4151
+ animation: zendfi-spin 0.8s linear infinite;
4152
+ `.replace(/\s+/g, " ").trim();
4153
+ }
4154
+ getSuccessStyles() {
4155
+ return this.getLoadingStyles();
4156
+ }
4157
+ getErrorStyles() {
4158
+ return this.getLoadingStyles();
4159
+ }
4160
+ };
4161
+ if (typeof window !== "undefined") {
4162
+ window.ZendFiEmbeddedCheckout = ZendFiEmbeddedCheckout;
4163
+ }
4164
+
3493
4165
  // src/device-bound-session-keys.ts
3494
4166
  init_device_bound_crypto();
3495
4167
  var import_web32 = require("@solana/web3.js");
@@ -6267,6 +6939,7 @@ var PerformanceMonitor = class {
6267
6939
  WalletConnector,
6268
6940
  WebhookError,
6269
6941
  ZendFiClient,
6942
+ ZendFiEmbeddedCheckout,
6270
6943
  ZendFiError,
6271
6944
  ZendFiSessionKeyManager,
6272
6945
  asAgentKeyId,