@zauthx402/sdk 0.1.6 → 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.
@@ -58,9 +58,9 @@ var require_constants = __commonJS({
58
58
  }
59
59
  });
60
60
 
61
- // ../../node_modules/node-gyp-build/node-gyp-build.js
61
+ // node_modules/node-gyp-build/node-gyp-build.js
62
62
  var require_node_gyp_build = __commonJS({
63
- "../../node_modules/node-gyp-build/node-gyp-build.js"(exports$1, module) {
63
+ "node_modules/node-gyp-build/node-gyp-build.js"(exports$1, module) {
64
64
  var fs = __require("fs");
65
65
  var path = __require("path");
66
66
  var os = __require("os");
@@ -227,9 +227,9 @@ var require_node_gyp_build = __commonJS({
227
227
  }
228
228
  });
229
229
 
230
- // ../../node_modules/node-gyp-build/index.js
230
+ // node_modules/node-gyp-build/index.js
231
231
  var require_node_gyp_build2 = __commonJS({
232
- "../../node_modules/node-gyp-build/index.js"(exports$1, module) {
232
+ "node_modules/node-gyp-build/index.js"(exports$1, module) {
233
233
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
234
234
  if (typeof runtimeRequire.addon === "function") {
235
235
  module.exports = runtimeRequire.addon.bind(runtimeRequire);
@@ -239,9 +239,9 @@ var require_node_gyp_build2 = __commonJS({
239
239
  }
240
240
  });
241
241
 
242
- // ../../node_modules/bufferutil/fallback.js
242
+ // node_modules/bufferutil/fallback.js
243
243
  var require_fallback = __commonJS({
244
- "../../node_modules/bufferutil/fallback.js"(exports$1, module) {
244
+ "node_modules/bufferutil/fallback.js"(exports$1, module) {
245
245
  var mask = (source, mask2, output, offset, length) => {
246
246
  for (var i = 0; i < length; i++) {
247
247
  output[offset + i] = source[i] ^ mask2[i & 3];
@@ -257,9 +257,9 @@ var require_fallback = __commonJS({
257
257
  }
258
258
  });
259
259
 
260
- // ../../node_modules/bufferutil/index.js
260
+ // node_modules/bufferutil/index.js
261
261
  var require_bufferutil = __commonJS({
262
- "../../node_modules/bufferutil/index.js"(exports$1, module) {
262
+ "node_modules/bufferutil/index.js"(exports$1, module) {
263
263
  try {
264
264
  module.exports = require_node_gyp_build2()(__dirname);
265
265
  } catch (e) {
@@ -773,9 +773,9 @@ var require_permessage_deflate = __commonJS({
773
773
  }
774
774
  });
775
775
 
776
- // ../../node_modules/utf-8-validate/fallback.js
776
+ // node_modules/utf-8-validate/fallback.js
777
777
  var require_fallback2 = __commonJS({
778
- "../../node_modules/utf-8-validate/fallback.js"(exports$1, module) {
778
+ "node_modules/utf-8-validate/fallback.js"(exports$1, module) {
779
779
  function isValidUTF8(buf) {
780
780
  const len = buf.length;
781
781
  let i = 0;
@@ -809,9 +809,9 @@ var require_fallback2 = __commonJS({
809
809
  }
810
810
  });
811
811
 
812
- // ../../node_modules/utf-8-validate/index.js
812
+ // node_modules/utf-8-validate/index.js
813
813
  var require_utf_8_validate = __commonJS({
814
- "../../node_modules/utf-8-validate/index.js"(exports$1, module) {
814
+ "node_modules/utf-8-validate/index.js"(exports$1, module) {
815
815
  try {
816
816
  module.exports = require_node_gyp_build2()(__dirname);
817
817
  } catch (e) {
@@ -3931,6 +3931,7 @@ var DEFAULT_CONFIG = {
3931
3931
  refund: {
3932
3932
  enabled: false,
3933
3933
  privateKey: process.env.ZAUTH_REFUND_PRIVATE_KEY,
3934
+ solanaPrivateKey: process.env.ZAUTH_SOLANA_PRIVATE_KEY,
3934
3935
  network: "base",
3935
3936
  triggers: {
3936
3937
  serverError: true,
@@ -3961,6 +3962,7 @@ function resolveConfig(config) {
3961
3962
  enabled: config.refund?.enabled ?? DEFAULT_CONFIG.refund.enabled,
3962
3963
  signer: config.refund?.signer,
3963
3964
  privateKey: config.refund?.privateKey ?? DEFAULT_CONFIG.refund.privateKey,
3965
+ solanaPrivateKey: config.refund?.solanaPrivateKey ?? DEFAULT_CONFIG.refund.solanaPrivateKey,
3964
3966
  network: config.refund?.network ?? DEFAULT_CONFIG.refund.network,
3965
3967
  triggers: {
3966
3968
  ...DEFAULT_CONFIG.refund.triggers,
@@ -4533,17 +4535,68 @@ function decodePaymentHeader(paymentHeader) {
4533
4535
  decoded = paymentHeader;
4534
4536
  }
4535
4537
  const parsed = JSON.parse(decoded);
4536
- const payer = parsed.payload?.authorization?.from || // x402 V2
4538
+ let payer = parsed.payload?.authorization?.from || // x402 V2 EVM
4537
4539
  parsed.payer || parsed.from || parsed.payload?.from || parsed.x?.signature?.address || null;
4540
+ if (!payer && parsed.payload?.transaction) {
4541
+ payer = extractSolanaFeePayer(parsed.payload.transaction);
4542
+ }
4538
4543
  const amount = parsed.payload?.authorization?.value || // x402 V2
4539
4544
  parsed.amount || parsed.payload?.amount || null;
4540
- const network = parsed.payload?.authorization?.network || // x402 V2
4545
+ let network = parsed.payload?.authorization?.network || // x402 V2 EVM
4541
4546
  parsed.network || parsed.payload?.network || null;
4547
+ if (!network && parsed.payload?.transaction && payer) {
4548
+ network = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
4549
+ }
4542
4550
  return { payer, amount, network };
4543
4551
  } catch {
4544
4552
  return null;
4545
4553
  }
4546
4554
  }
4555
+ function extractSolanaFeePayer(base64Transaction) {
4556
+ try {
4557
+ const txBytes = typeof Buffer !== "undefined" ? Buffer.from(base64Transaction, "base64") : Uint8Array.from(atob(base64Transaction), (c) => c.charCodeAt(0));
4558
+ let offset = 0;
4559
+ const numSignatures = txBytes[offset];
4560
+ offset += 1;
4561
+ offset += numSignatures * 64;
4562
+ const firstByte = txBytes[offset];
4563
+ if ((firstByte & 128) !== 0) {
4564
+ offset += 1;
4565
+ }
4566
+ offset += 3;
4567
+ const numAccounts = txBytes[offset];
4568
+ offset += 1;
4569
+ if (numAccounts > 0 && offset + 32 <= txBytes.length) {
4570
+ const feePayerBytes = txBytes.slice(offset, offset + 32);
4571
+ return base58Encode(feePayerBytes);
4572
+ }
4573
+ return null;
4574
+ } catch {
4575
+ return null;
4576
+ }
4577
+ }
4578
+ function base58Encode(bytes) {
4579
+ const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
4580
+ const BASE = 58;
4581
+ let num = BigInt(0);
4582
+ for (const byte of bytes) {
4583
+ num = num * BigInt(256) + BigInt(byte);
4584
+ }
4585
+ let result = "";
4586
+ while (num > 0) {
4587
+ const remainder = Number(num % BigInt(BASE));
4588
+ num = num / BigInt(BASE);
4589
+ result = ALPHABET[remainder] + result;
4590
+ }
4591
+ for (const byte of bytes) {
4592
+ if (byte === 0) {
4593
+ result = "1" + result;
4594
+ } else {
4595
+ break;
4596
+ }
4597
+ }
4598
+ return result || "1";
4599
+ }
4547
4600
 
4548
4601
  // src/validator.ts
4549
4602
  function validateResponse(body, statusCode, config) {
@@ -5073,14 +5126,98 @@ var RefundExecutor = class {
5073
5126
  }
5074
5127
  }
5075
5128
  /**
5076
- * Execute Solana refund
5129
+ * Execute Solana refund using @solana/kit v2 libraries
5077
5130
  */
5078
- async executeSolanaRefund(_refund, _amountRaw) {
5079
- return {
5080
- success: false,
5081
- error: "Solana refunds not yet implemented",
5082
- retryable: false
5083
- };
5131
+ async executeSolanaRefund(refund, amountRaw) {
5132
+ try {
5133
+ const solanaPrivateKey = this.config.solanaPrivateKey;
5134
+ if (!solanaPrivateKey) {
5135
+ return {
5136
+ success: false,
5137
+ error: "No Solana private key configured (set ZAUTH_SOLANA_PRIVATE_KEY)",
5138
+ retryable: false
5139
+ };
5140
+ }
5141
+ const { createKeyPairSignerFromPrivateKeyBytes } = await import('@solana/signers');
5142
+ const {
5143
+ createSolanaRpc,
5144
+ address,
5145
+ pipe,
5146
+ createTransactionMessage,
5147
+ setTransactionMessageFeePayer,
5148
+ setTransactionMessageLifetimeUsingBlockhash,
5149
+ appendTransactionMessageInstructions,
5150
+ signTransactionMessageWithSigners,
5151
+ getBase64EncodedWireTransaction
5152
+ } = await import('@solana/kit');
5153
+ const {
5154
+ findAssociatedTokenPda,
5155
+ getTransferInstruction,
5156
+ TOKEN_PROGRAM_ADDRESS
5157
+ } = await import('@solana-program/token');
5158
+ const bs58 = await import('bs58');
5159
+ const USDC_MINT = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
5160
+ const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
5161
+ const rpc = createSolanaRpc(rpcUrl);
5162
+ let signer;
5163
+ try {
5164
+ const secretKey = bs58.default.decode(solanaPrivateKey);
5165
+ const privateKeyBytes = secretKey.slice(0, 32);
5166
+ signer = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes);
5167
+ } catch {
5168
+ return {
5169
+ success: false,
5170
+ error: "Invalid Solana private key format (expected base58)",
5171
+ retryable: false
5172
+ };
5173
+ }
5174
+ const recipientAddress = address(refund.recipientAddress);
5175
+ const [senderAta] = await findAssociatedTokenPda({
5176
+ mint: USDC_MINT,
5177
+ owner: signer.address,
5178
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
5179
+ });
5180
+ const [recipientAta] = await findAssociatedTokenPda({
5181
+ mint: USDC_MINT,
5182
+ owner: recipientAddress,
5183
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
5184
+ });
5185
+ const transferIx = getTransferInstruction({
5186
+ source: senderAta,
5187
+ destination: recipientAta,
5188
+ authority: signer,
5189
+ amount: BigInt(amountRaw)
5190
+ });
5191
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
5192
+ const tx = pipe(
5193
+ createTransactionMessage({ version: 0 }),
5194
+ (tx2) => setTransactionMessageFeePayer(signer.address, tx2),
5195
+ (tx2) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx2),
5196
+ (tx2) => appendTransactionMessageInstructions([transferIx], tx2)
5197
+ );
5198
+ const signedTx = await signTransactionMessageWithSigners(tx);
5199
+ const base64Tx = getBase64EncodedWireTransaction(signedTx);
5200
+ const txSignature = await rpc.sendTransaction(base64Tx, { encoding: "base64" }).send();
5201
+ this.log("Solana refund sent", {
5202
+ txHash: txSignature,
5203
+ to: refund.recipientAddress,
5204
+ amount: amountRaw
5205
+ });
5206
+ return {
5207
+ success: true,
5208
+ txHash: txSignature,
5209
+ amountRaw,
5210
+ gasCostCents: 0
5211
+ // Solana fees are negligible
5212
+ };
5213
+ } catch (error) {
5214
+ this.log("Solana refund failed", { error: error.message });
5215
+ return {
5216
+ success: false,
5217
+ error: error.message,
5218
+ retryable: true
5219
+ };
5220
+ }
5084
5221
  }
5085
5222
  /**
5086
5223
  * Get endpoint-specific config by matching URL patterns