@zauthx402/sdk 0.1.5 → 0.1.7

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.
@@ -542,10 +542,14 @@ interface RefundConfig {
542
542
  */
543
543
  signer?: RefundSigner;
544
544
  /**
545
- * Private key for refund transactions (deprecated, use signer)
545
+ * Private key for EVM refund transactions (hex format)
546
546
  * @deprecated Use signer instead
547
547
  */
548
548
  privateKey?: string;
549
+ /**
550
+ * Private key for Solana refund transactions (base58 format)
551
+ */
552
+ solanaPrivateKey?: string;
549
553
  /**
550
554
  * Default network for refunds (can be overridden per-endpoint)
551
555
  * @default 'base'
@@ -743,6 +747,7 @@ interface ResolvedRefundConfig {
743
747
  enabled: boolean;
744
748
  signer?: RefundSigner;
745
749
  privateKey?: string;
750
+ solanaPrivateKey?: string;
746
751
  network: X402Network;
747
752
  triggers: Required<RefundTriggers>;
748
753
  maxRefundUsd: number;
@@ -1010,6 +1015,7 @@ declare class RefundExecutor {
1010
1015
  private monthRefundedCents;
1011
1016
  private lastCapResetDate;
1012
1017
  private lastCapResetMonth;
1018
+ private processedRefundIds;
1013
1019
  constructor(client: ZauthClient, config: ResolvedRefundConfig, debug?: boolean);
1014
1020
  /**
1015
1021
  * Start the WebSocket connection for refund notifications
@@ -1054,7 +1060,7 @@ declare class RefundExecutor {
1054
1060
  */
1055
1061
  private executeEvmRefund;
1056
1062
  /**
1057
- * Execute Solana refund
1063
+ * Execute Solana refund using @solana/kit v2 libraries
1058
1064
  */
1059
1065
  private executeSolanaRefund;
1060
1066
  /**
@@ -542,10 +542,14 @@ interface RefundConfig {
542
542
  */
543
543
  signer?: RefundSigner;
544
544
  /**
545
- * Private key for refund transactions (deprecated, use signer)
545
+ * Private key for EVM refund transactions (hex format)
546
546
  * @deprecated Use signer instead
547
547
  */
548
548
  privateKey?: string;
549
+ /**
550
+ * Private key for Solana refund transactions (base58 format)
551
+ */
552
+ solanaPrivateKey?: string;
549
553
  /**
550
554
  * Default network for refunds (can be overridden per-endpoint)
551
555
  * @default 'base'
@@ -743,6 +747,7 @@ interface ResolvedRefundConfig {
743
747
  enabled: boolean;
744
748
  signer?: RefundSigner;
745
749
  privateKey?: string;
750
+ solanaPrivateKey?: string;
746
751
  network: X402Network;
747
752
  triggers: Required<RefundTriggers>;
748
753
  maxRefundUsd: number;
@@ -1010,6 +1015,7 @@ declare class RefundExecutor {
1010
1015
  private monthRefundedCents;
1011
1016
  private lastCapResetDate;
1012
1017
  private lastCapResetMonth;
1018
+ private processedRefundIds;
1013
1019
  constructor(client: ZauthClient, config: ResolvedRefundConfig, debug?: boolean);
1014
1020
  /**
1015
1021
  * Start the WebSocket connection for refund notifications
@@ -1054,7 +1060,7 @@ declare class RefundExecutor {
1054
1060
  */
1055
1061
  private executeEvmRefund;
1056
1062
  /**
1057
- * Execute Solana refund
1063
+ * Execute Solana refund using @solana/kit v2 libraries
1058
1064
  */
1059
1065
  private executeSolanaRefund;
1060
1066
  /**
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { V as ValidationConfig, a as ValidationResult } from './index-CzB2rK59.mjs';
2
- export { Q as BatchingConfig, K as ConfirmRefundRequest, L as ConfirmRefundResponse, a6 as DEFAULT_CONFIG, W as EndpointRefundConfig, E as EndpointStatus, B as ErrorEvent, F as EventBatch, G as EventSubmitResponse, _ as ExecutedRefund, H as HealthCheckEvent, P as PaymentEvent, I as PendingRefund, J as PendingRefundsResponse, a2 as ProviderMiddlewareConfig, a0 as RefundCondition, S as RefundConfig, $ as RefundError, y as RefundEvent, R as RefundHandler, Y as RefundPollingConfig, A as RefundReason, f as RefundRequest, g as RefundResult, T as RefundSigner, U as RefundTriggers, M as RejectRefundRequest, N as RejectRefundResponse, w as RequestEvent, a5 as ResolvedConfig, a4 as ResolvedRefundConfig, a3 as ResolvedValidationConfig, x as ResponseEvent, a1 as TelemetryConfig, C as ValidationCheck, X as X402Network, p as X402PaymentInfo, n as X402PaymentPayload, j as X402PaymentRequirement, o as X402PaymentResponse, m as X402Response, k as X402ResponseV1, l as X402ResponseV2, h as X402Scheme, i as X402Version, Z as ZauthClient, O as ZauthConfig, D as ZauthEvent, v as ZauthEventBase, d as ZauthMiddlewareOptions, c as createClient, e as createRefundHandler, b as createZauthMiddleware, t as decodePaymentResponse, u as encodePaymentPayload, r as getPaymentRequirements, s as getPriceUsdc, q as parseX402Response, a7 as resolveConfig, z as zauthProvider } from './index-CzB2rK59.mjs';
1
+ import { V as ValidationConfig, a as ValidationResult } from './index-C2FGNEe1.mjs';
2
+ export { Q as BatchingConfig, K as ConfirmRefundRequest, L as ConfirmRefundResponse, a6 as DEFAULT_CONFIG, W as EndpointRefundConfig, E as EndpointStatus, B as ErrorEvent, F as EventBatch, G as EventSubmitResponse, _ as ExecutedRefund, H as HealthCheckEvent, P as PaymentEvent, I as PendingRefund, J as PendingRefundsResponse, a2 as ProviderMiddlewareConfig, a0 as RefundCondition, S as RefundConfig, $ as RefundError, y as RefundEvent, R as RefundHandler, Y as RefundPollingConfig, A as RefundReason, f as RefundRequest, g as RefundResult, T as RefundSigner, U as RefundTriggers, M as RejectRefundRequest, N as RejectRefundResponse, w as RequestEvent, a5 as ResolvedConfig, a4 as ResolvedRefundConfig, a3 as ResolvedValidationConfig, x as ResponseEvent, a1 as TelemetryConfig, C as ValidationCheck, X as X402Network, p as X402PaymentInfo, n as X402PaymentPayload, j as X402PaymentRequirement, o as X402PaymentResponse, m as X402Response, k as X402ResponseV1, l as X402ResponseV2, h as X402Scheme, i as X402Version, Z as ZauthClient, O as ZauthConfig, D as ZauthEvent, v as ZauthEventBase, d as ZauthMiddlewareOptions, c as createClient, e as createRefundHandler, b as createZauthMiddleware, t as decodePaymentResponse, u as encodePaymentPayload, r as getPaymentRequirements, s as getPriceUsdc, q as parseX402Response, a7 as resolveConfig, z as zauthProvider } from './index-C2FGNEe1.mjs';
3
3
  import 'express';
4
4
 
5
5
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { V as ValidationConfig, a as ValidationResult } from './index-CzB2rK59.js';
2
- export { Q as BatchingConfig, K as ConfirmRefundRequest, L as ConfirmRefundResponse, a6 as DEFAULT_CONFIG, W as EndpointRefundConfig, E as EndpointStatus, B as ErrorEvent, F as EventBatch, G as EventSubmitResponse, _ as ExecutedRefund, H as HealthCheckEvent, P as PaymentEvent, I as PendingRefund, J as PendingRefundsResponse, a2 as ProviderMiddlewareConfig, a0 as RefundCondition, S as RefundConfig, $ as RefundError, y as RefundEvent, R as RefundHandler, Y as RefundPollingConfig, A as RefundReason, f as RefundRequest, g as RefundResult, T as RefundSigner, U as RefundTriggers, M as RejectRefundRequest, N as RejectRefundResponse, w as RequestEvent, a5 as ResolvedConfig, a4 as ResolvedRefundConfig, a3 as ResolvedValidationConfig, x as ResponseEvent, a1 as TelemetryConfig, C as ValidationCheck, X as X402Network, p as X402PaymentInfo, n as X402PaymentPayload, j as X402PaymentRequirement, o as X402PaymentResponse, m as X402Response, k as X402ResponseV1, l as X402ResponseV2, h as X402Scheme, i as X402Version, Z as ZauthClient, O as ZauthConfig, D as ZauthEvent, v as ZauthEventBase, d as ZauthMiddlewareOptions, c as createClient, e as createRefundHandler, b as createZauthMiddleware, t as decodePaymentResponse, u as encodePaymentPayload, r as getPaymentRequirements, s as getPriceUsdc, q as parseX402Response, a7 as resolveConfig, z as zauthProvider } from './index-CzB2rK59.js';
1
+ import { V as ValidationConfig, a as ValidationResult } from './index-C2FGNEe1.js';
2
+ export { Q as BatchingConfig, K as ConfirmRefundRequest, L as ConfirmRefundResponse, a6 as DEFAULT_CONFIG, W as EndpointRefundConfig, E as EndpointStatus, B as ErrorEvent, F as EventBatch, G as EventSubmitResponse, _ as ExecutedRefund, H as HealthCheckEvent, P as PaymentEvent, I as PendingRefund, J as PendingRefundsResponse, a2 as ProviderMiddlewareConfig, a0 as RefundCondition, S as RefundConfig, $ as RefundError, y as RefundEvent, R as RefundHandler, Y as RefundPollingConfig, A as RefundReason, f as RefundRequest, g as RefundResult, T as RefundSigner, U as RefundTriggers, M as RejectRefundRequest, N as RejectRefundResponse, w as RequestEvent, a5 as ResolvedConfig, a4 as ResolvedRefundConfig, a3 as ResolvedValidationConfig, x as ResponseEvent, a1 as TelemetryConfig, C as ValidationCheck, X as X402Network, p as X402PaymentInfo, n as X402PaymentPayload, j as X402PaymentRequirement, o as X402PaymentResponse, m as X402Response, k as X402ResponseV1, l as X402ResponseV2, h as X402Scheme, i as X402Version, Z as ZauthClient, O as ZauthConfig, D as ZauthEvent, v as ZauthEventBase, d as ZauthMiddlewareOptions, c as createClient, e as createRefundHandler, b as createZauthMiddleware, t as decodePaymentResponse, u as encodePaymentPayload, r as getPaymentRequirements, s as getPriceUsdc, q as parseX402Response, a7 as resolveConfig, z as zauthProvider } from './index-C2FGNEe1.js';
3
3
  import 'express';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -60,9 +60,9 @@ var require_constants = __commonJS({
60
60
  }
61
61
  });
62
62
 
63
- // ../../node_modules/node-gyp-build/node-gyp-build.js
63
+ // node_modules/node-gyp-build/node-gyp-build.js
64
64
  var require_node_gyp_build = __commonJS({
65
- "../../node_modules/node-gyp-build/node-gyp-build.js"(exports$1, module) {
65
+ "node_modules/node-gyp-build/node-gyp-build.js"(exports$1, module) {
66
66
  var fs = __require("fs");
67
67
  var path = __require("path");
68
68
  var os = __require("os");
@@ -229,9 +229,9 @@ var require_node_gyp_build = __commonJS({
229
229
  }
230
230
  });
231
231
 
232
- // ../../node_modules/node-gyp-build/index.js
232
+ // node_modules/node-gyp-build/index.js
233
233
  var require_node_gyp_build2 = __commonJS({
234
- "../../node_modules/node-gyp-build/index.js"(exports$1, module) {
234
+ "node_modules/node-gyp-build/index.js"(exports$1, module) {
235
235
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
236
236
  if (typeof runtimeRequire.addon === "function") {
237
237
  module.exports = runtimeRequire.addon.bind(runtimeRequire);
@@ -241,9 +241,9 @@ var require_node_gyp_build2 = __commonJS({
241
241
  }
242
242
  });
243
243
 
244
- // ../../node_modules/bufferutil/fallback.js
244
+ // node_modules/bufferutil/fallback.js
245
245
  var require_fallback = __commonJS({
246
- "../../node_modules/bufferutil/fallback.js"(exports$1, module) {
246
+ "node_modules/bufferutil/fallback.js"(exports$1, module) {
247
247
  var mask = (source, mask2, output, offset, length) => {
248
248
  for (var i = 0; i < length; i++) {
249
249
  output[offset + i] = source[i] ^ mask2[i & 3];
@@ -259,9 +259,9 @@ var require_fallback = __commonJS({
259
259
  }
260
260
  });
261
261
 
262
- // ../../node_modules/bufferutil/index.js
262
+ // node_modules/bufferutil/index.js
263
263
  var require_bufferutil = __commonJS({
264
- "../../node_modules/bufferutil/index.js"(exports$1, module) {
264
+ "node_modules/bufferutil/index.js"(exports$1, module) {
265
265
  try {
266
266
  module.exports = require_node_gyp_build2()(__dirname);
267
267
  } catch (e) {
@@ -775,9 +775,9 @@ var require_permessage_deflate = __commonJS({
775
775
  }
776
776
  });
777
777
 
778
- // ../../node_modules/utf-8-validate/fallback.js
778
+ // node_modules/utf-8-validate/fallback.js
779
779
  var require_fallback2 = __commonJS({
780
- "../../node_modules/utf-8-validate/fallback.js"(exports$1, module) {
780
+ "node_modules/utf-8-validate/fallback.js"(exports$1, module) {
781
781
  function isValidUTF8(buf) {
782
782
  const len = buf.length;
783
783
  let i = 0;
@@ -811,9 +811,9 @@ var require_fallback2 = __commonJS({
811
811
  }
812
812
  });
813
813
 
814
- // ../../node_modules/utf-8-validate/index.js
814
+ // node_modules/utf-8-validate/index.js
815
815
  var require_utf_8_validate = __commonJS({
816
- "../../node_modules/utf-8-validate/index.js"(exports$1, module) {
816
+ "node_modules/utf-8-validate/index.js"(exports$1, module) {
817
817
  try {
818
818
  module.exports = require_node_gyp_build2()(__dirname);
819
819
  } catch (e) {
@@ -3933,6 +3933,7 @@ var DEFAULT_CONFIG = {
3933
3933
  refund: {
3934
3934
  enabled: false,
3935
3935
  privateKey: process.env.ZAUTH_REFUND_PRIVATE_KEY,
3936
+ solanaPrivateKey: process.env.ZAUTH_SOLANA_PRIVATE_KEY,
3936
3937
  network: "base",
3937
3938
  triggers: {
3938
3939
  serverError: true,
@@ -3963,6 +3964,7 @@ function resolveConfig(config) {
3963
3964
  enabled: config.refund?.enabled ?? DEFAULT_CONFIG.refund.enabled,
3964
3965
  signer: config.refund?.signer,
3965
3966
  privateKey: config.refund?.privateKey ?? DEFAULT_CONFIG.refund.privateKey,
3967
+ solanaPrivateKey: config.refund?.solanaPrivateKey ?? DEFAULT_CONFIG.refund.solanaPrivateKey,
3966
3968
  network: config.refund?.network ?? DEFAULT_CONFIG.refund.network,
3967
3969
  triggers: {
3968
3970
  ...DEFAULT_CONFIG.refund.triggers,
@@ -4593,17 +4595,68 @@ function decodePaymentHeader(paymentHeader) {
4593
4595
  decoded = paymentHeader;
4594
4596
  }
4595
4597
  const parsed = JSON.parse(decoded);
4596
- const payer = parsed.payload?.authorization?.from || // x402 V2
4598
+ let payer = parsed.payload?.authorization?.from || // x402 V2 EVM
4597
4599
  parsed.payer || parsed.from || parsed.payload?.from || parsed.x?.signature?.address || null;
4600
+ if (!payer && parsed.payload?.transaction) {
4601
+ payer = extractSolanaFeePayer(parsed.payload.transaction);
4602
+ }
4598
4603
  const amount = parsed.payload?.authorization?.value || // x402 V2
4599
4604
  parsed.amount || parsed.payload?.amount || null;
4600
- const network = parsed.payload?.authorization?.network || // x402 V2
4605
+ let network = parsed.payload?.authorization?.network || // x402 V2 EVM
4601
4606
  parsed.network || parsed.payload?.network || null;
4607
+ if (!network && parsed.payload?.transaction && payer) {
4608
+ network = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
4609
+ }
4602
4610
  return { payer, amount, network };
4603
4611
  } catch {
4604
4612
  return null;
4605
4613
  }
4606
4614
  }
4615
+ function extractSolanaFeePayer(base64Transaction) {
4616
+ try {
4617
+ const txBytes = typeof Buffer !== "undefined" ? Buffer.from(base64Transaction, "base64") : Uint8Array.from(atob(base64Transaction), (c) => c.charCodeAt(0));
4618
+ let offset = 0;
4619
+ const numSignatures = txBytes[offset];
4620
+ offset += 1;
4621
+ offset += numSignatures * 64;
4622
+ const firstByte = txBytes[offset];
4623
+ if ((firstByte & 128) !== 0) {
4624
+ offset += 1;
4625
+ }
4626
+ offset += 3;
4627
+ const numAccounts = txBytes[offset];
4628
+ offset += 1;
4629
+ if (numAccounts > 0 && offset + 32 <= txBytes.length) {
4630
+ const feePayerBytes = txBytes.slice(offset, offset + 32);
4631
+ return base58Encode(feePayerBytes);
4632
+ }
4633
+ return null;
4634
+ } catch {
4635
+ return null;
4636
+ }
4637
+ }
4638
+ function base58Encode(bytes) {
4639
+ const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
4640
+ const BASE = 58;
4641
+ let num = BigInt(0);
4642
+ for (const byte of bytes) {
4643
+ num = num * BigInt(256) + BigInt(byte);
4644
+ }
4645
+ let result = "";
4646
+ while (num > 0) {
4647
+ const remainder = Number(num % BigInt(BASE));
4648
+ num = num / BigInt(BASE);
4649
+ result = ALPHABET[remainder] + result;
4650
+ }
4651
+ for (const byte of bytes) {
4652
+ if (byte === 0) {
4653
+ result = "1" + result;
4654
+ } else {
4655
+ break;
4656
+ }
4657
+ }
4658
+ return result || "1";
4659
+ }
4607
4660
  function detectX402Version(body) {
4608
4661
  if (!body || typeof body !== "object") {
4609
4662
  return null;
@@ -4965,6 +5018,8 @@ var RefundExecutor = class {
4965
5018
  // YYYY-MM-DD
4966
5019
  lastCapResetMonth = (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
4967
5020
  // YYYY-MM
5021
+ // Track processed refundIds to prevent double execution within same session
5022
+ processedRefundIds = /* @__PURE__ */ new Set();
4968
5023
  constructor(client, config, debug = false) {
4969
5024
  this.client = client;
4970
5025
  this.config = config;
@@ -5057,6 +5112,11 @@ var RefundExecutor = class {
5057
5112
  case "rejection_ack":
5058
5113
  this.log("Refund rejection acknowledged", { refundId: msg.refundId });
5059
5114
  break;
5115
+ case "executing_ack":
5116
+ if (this.debug) {
5117
+ this.log("Refund executing acknowledged", { refundId: msg.refundId, status: msg.status });
5118
+ }
5119
+ break;
5060
5120
  case "pong":
5061
5121
  break;
5062
5122
  default:
@@ -5071,6 +5131,10 @@ var RefundExecutor = class {
5071
5131
  */
5072
5132
  async processSingleRefund(refund) {
5073
5133
  try {
5134
+ if (this.processedRefundIds.has(refund.id)) {
5135
+ this.log("Refund already processed in this session", { refundId: refund.id });
5136
+ return;
5137
+ }
5074
5138
  const endpointConfig = this.getEndpointConfig(refund.url);
5075
5139
  if (endpointConfig?.enabled === false) {
5076
5140
  this.log("Refunds disabled for endpoint", { url: refund.url });
@@ -5129,8 +5193,13 @@ var RefundExecutor = class {
5129
5193
  return;
5130
5194
  }
5131
5195
  }
5196
+ this.sendMessage({
5197
+ type: "refund_executing",
5198
+ refundId: refund.id
5199
+ });
5132
5200
  const result = await this.executeRefundTx(refund);
5133
5201
  if (result.success) {
5202
+ this.processedRefundIds.add(refund.id);
5134
5203
  this.sendMessage({
5135
5204
  type: "refund_confirmed",
5136
5205
  refundId: refund.id,
@@ -5329,14 +5398,98 @@ var RefundExecutor = class {
5329
5398
  }
5330
5399
  }
5331
5400
  /**
5332
- * Execute Solana refund
5401
+ * Execute Solana refund using @solana/kit v2 libraries
5333
5402
  */
5334
- async executeSolanaRefund(_refund, _amountRaw) {
5335
- return {
5336
- success: false,
5337
- error: "Solana refunds not yet implemented",
5338
- retryable: false
5339
- };
5403
+ async executeSolanaRefund(refund, amountRaw) {
5404
+ try {
5405
+ const solanaPrivateKey = this.config.solanaPrivateKey;
5406
+ if (!solanaPrivateKey) {
5407
+ return {
5408
+ success: false,
5409
+ error: "No Solana private key configured (set ZAUTH_SOLANA_PRIVATE_KEY)",
5410
+ retryable: false
5411
+ };
5412
+ }
5413
+ const { createKeyPairSignerFromPrivateKeyBytes } = await import('@solana/signers');
5414
+ const {
5415
+ createSolanaRpc,
5416
+ address,
5417
+ pipe,
5418
+ createTransactionMessage,
5419
+ setTransactionMessageFeePayer,
5420
+ setTransactionMessageLifetimeUsingBlockhash,
5421
+ appendTransactionMessageInstructions,
5422
+ signTransactionMessageWithSigners,
5423
+ getBase64EncodedWireTransaction
5424
+ } = await import('@solana/kit');
5425
+ const {
5426
+ findAssociatedTokenPda,
5427
+ getTransferInstruction,
5428
+ TOKEN_PROGRAM_ADDRESS
5429
+ } = await import('@solana-program/token');
5430
+ const bs58 = await import('bs58');
5431
+ const USDC_MINT = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
5432
+ const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
5433
+ const rpc = createSolanaRpc(rpcUrl);
5434
+ let signer;
5435
+ try {
5436
+ const secretKey = bs58.default.decode(solanaPrivateKey);
5437
+ const privateKeyBytes = secretKey.slice(0, 32);
5438
+ signer = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes);
5439
+ } catch {
5440
+ return {
5441
+ success: false,
5442
+ error: "Invalid Solana private key format (expected base58)",
5443
+ retryable: false
5444
+ };
5445
+ }
5446
+ const recipientAddress = address(refund.recipientAddress);
5447
+ const [senderAta] = await findAssociatedTokenPda({
5448
+ mint: USDC_MINT,
5449
+ owner: signer.address,
5450
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
5451
+ });
5452
+ const [recipientAta] = await findAssociatedTokenPda({
5453
+ mint: USDC_MINT,
5454
+ owner: recipientAddress,
5455
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
5456
+ });
5457
+ const transferIx = getTransferInstruction({
5458
+ source: senderAta,
5459
+ destination: recipientAta,
5460
+ authority: signer,
5461
+ amount: BigInt(amountRaw)
5462
+ });
5463
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
5464
+ const tx = pipe(
5465
+ createTransactionMessage({ version: 0 }),
5466
+ (tx2) => setTransactionMessageFeePayer(signer.address, tx2),
5467
+ (tx2) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx2),
5468
+ (tx2) => appendTransactionMessageInstructions([transferIx], tx2)
5469
+ );
5470
+ const signedTx = await signTransactionMessageWithSigners(tx);
5471
+ const base64Tx = getBase64EncodedWireTransaction(signedTx);
5472
+ const txSignature = await rpc.sendTransaction(base64Tx, { encoding: "base64" }).send();
5473
+ this.log("Solana refund sent", {
5474
+ txHash: txSignature,
5475
+ to: refund.recipientAddress,
5476
+ amount: amountRaw
5477
+ });
5478
+ return {
5479
+ success: true,
5480
+ txHash: txSignature,
5481
+ amountRaw,
5482
+ gasCostCents: 0
5483
+ // Solana fees are negligible
5484
+ };
5485
+ } catch (error) {
5486
+ this.log("Solana refund failed", { error: error.message });
5487
+ return {
5488
+ success: false,
5489
+ error: error.message,
5490
+ retryable: true
5491
+ };
5492
+ }
5340
5493
  }
5341
5494
  /**
5342
5495
  * Get endpoint-specific config by matching URL patterns
@@ -5376,6 +5529,25 @@ function createZauthMiddleware(options) {
5376
5529
  if (config.debug) {
5377
5530
  console.log("[zauthSDK] Refund executor started");
5378
5531
  }
5532
+ client.updateRefundConfig({
5533
+ enabled: true,
5534
+ maxRefundUsdCents: Math.round((config.refund.maxRefundUsd || 1) * 100),
5535
+ dailyCapCents: config.refund.dailyCapUsd ? Math.round(config.refund.dailyCapUsd * 100) : void 0,
5536
+ monthlyCapCents: config.refund.monthlyCapUsd ? Math.round(config.refund.monthlyCapUsd * 100) : void 0,
5537
+ triggers: {
5538
+ serverError: config.refund.triggers?.serverError ?? true,
5539
+ timeout: config.refund.triggers?.timeout ?? true,
5540
+ emptyResponse: config.refund.triggers?.emptyResponse ?? true,
5541
+ schemaValidation: config.refund.triggers?.schemaValidation ?? false,
5542
+ minMeaningfulness: config.refund.triggers?.minMeaningfulness ?? 0.3
5543
+ }
5544
+ }).then((result) => {
5545
+ if (config.debug) {
5546
+ console.log("[zauthSDK] Refund config registered with server", { success: result.success });
5547
+ }
5548
+ }).catch((err) => {
5549
+ console.error("[zauthSDK] Failed to register refund config:", err.message);
5550
+ });
5379
5551
  }
5380
5552
  function shouldMonitorRoute(req) {
5381
5553
  if (options.shouldMonitor) {