@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.
- package/dist/{index-CzB2rK59.d.mts → index-C2FGNEe1.d.mts} +8 -2
- package/dist/{index-CzB2rK59.d.ts → index-C2FGNEe1.d.ts} +8 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +193 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +193 -21
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +193 -21
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +193 -21
- package/dist/middleware/index.mjs.map +1 -1
- package/package.json +7 -2
package/dist/index.mjs
CHANGED
|
@@ -58,9 +58,9 @@ var require_constants = __commonJS({
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// node_modules/node-gyp-build/node-gyp-build.js
|
|
62
62
|
var require_node_gyp_build = __commonJS({
|
|
63
|
-
"
|
|
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
|
-
//
|
|
230
|
+
// node_modules/node-gyp-build/index.js
|
|
231
231
|
var require_node_gyp_build2 = __commonJS({
|
|
232
|
-
"
|
|
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
|
-
//
|
|
242
|
+
// node_modules/bufferutil/fallback.js
|
|
243
243
|
var require_fallback = __commonJS({
|
|
244
|
-
"
|
|
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
|
-
//
|
|
260
|
+
// node_modules/bufferutil/index.js
|
|
261
261
|
var require_bufferutil = __commonJS({
|
|
262
|
-
"
|
|
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
|
-
//
|
|
776
|
+
// node_modules/utf-8-validate/fallback.js
|
|
777
777
|
var require_fallback2 = __commonJS({
|
|
778
|
-
"
|
|
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
|
-
//
|
|
812
|
+
// node_modules/utf-8-validate/index.js
|
|
813
813
|
var require_utf_8_validate = __commonJS({
|
|
814
|
-
"
|
|
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,
|
|
@@ -4591,17 +4593,68 @@ function decodePaymentHeader(paymentHeader) {
|
|
|
4591
4593
|
decoded = paymentHeader;
|
|
4592
4594
|
}
|
|
4593
4595
|
const parsed = JSON.parse(decoded);
|
|
4594
|
-
|
|
4596
|
+
let payer = parsed.payload?.authorization?.from || // x402 V2 EVM
|
|
4595
4597
|
parsed.payer || parsed.from || parsed.payload?.from || parsed.x?.signature?.address || null;
|
|
4598
|
+
if (!payer && parsed.payload?.transaction) {
|
|
4599
|
+
payer = extractSolanaFeePayer(parsed.payload.transaction);
|
|
4600
|
+
}
|
|
4596
4601
|
const amount = parsed.payload?.authorization?.value || // x402 V2
|
|
4597
4602
|
parsed.amount || parsed.payload?.amount || null;
|
|
4598
|
-
|
|
4603
|
+
let network = parsed.payload?.authorization?.network || // x402 V2 EVM
|
|
4599
4604
|
parsed.network || parsed.payload?.network || null;
|
|
4605
|
+
if (!network && parsed.payload?.transaction && payer) {
|
|
4606
|
+
network = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
4607
|
+
}
|
|
4600
4608
|
return { payer, amount, network };
|
|
4601
4609
|
} catch {
|
|
4602
4610
|
return null;
|
|
4603
4611
|
}
|
|
4604
4612
|
}
|
|
4613
|
+
function extractSolanaFeePayer(base64Transaction) {
|
|
4614
|
+
try {
|
|
4615
|
+
const txBytes = typeof Buffer !== "undefined" ? Buffer.from(base64Transaction, "base64") : Uint8Array.from(atob(base64Transaction), (c) => c.charCodeAt(0));
|
|
4616
|
+
let offset = 0;
|
|
4617
|
+
const numSignatures = txBytes[offset];
|
|
4618
|
+
offset += 1;
|
|
4619
|
+
offset += numSignatures * 64;
|
|
4620
|
+
const firstByte = txBytes[offset];
|
|
4621
|
+
if ((firstByte & 128) !== 0) {
|
|
4622
|
+
offset += 1;
|
|
4623
|
+
}
|
|
4624
|
+
offset += 3;
|
|
4625
|
+
const numAccounts = txBytes[offset];
|
|
4626
|
+
offset += 1;
|
|
4627
|
+
if (numAccounts > 0 && offset + 32 <= txBytes.length) {
|
|
4628
|
+
const feePayerBytes = txBytes.slice(offset, offset + 32);
|
|
4629
|
+
return base58Encode(feePayerBytes);
|
|
4630
|
+
}
|
|
4631
|
+
return null;
|
|
4632
|
+
} catch {
|
|
4633
|
+
return null;
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
function base58Encode(bytes) {
|
|
4637
|
+
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
4638
|
+
const BASE = 58;
|
|
4639
|
+
let num = BigInt(0);
|
|
4640
|
+
for (const byte of bytes) {
|
|
4641
|
+
num = num * BigInt(256) + BigInt(byte);
|
|
4642
|
+
}
|
|
4643
|
+
let result = "";
|
|
4644
|
+
while (num > 0) {
|
|
4645
|
+
const remainder = Number(num % BigInt(BASE));
|
|
4646
|
+
num = num / BigInt(BASE);
|
|
4647
|
+
result = ALPHABET[remainder] + result;
|
|
4648
|
+
}
|
|
4649
|
+
for (const byte of bytes) {
|
|
4650
|
+
if (byte === 0) {
|
|
4651
|
+
result = "1" + result;
|
|
4652
|
+
} else {
|
|
4653
|
+
break;
|
|
4654
|
+
}
|
|
4655
|
+
}
|
|
4656
|
+
return result || "1";
|
|
4657
|
+
}
|
|
4605
4658
|
function detectX402Version(body) {
|
|
4606
4659
|
if (!body || typeof body !== "object") {
|
|
4607
4660
|
return null;
|
|
@@ -4963,6 +5016,8 @@ var RefundExecutor = class {
|
|
|
4963
5016
|
// YYYY-MM-DD
|
|
4964
5017
|
lastCapResetMonth = (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
4965
5018
|
// YYYY-MM
|
|
5019
|
+
// Track processed refundIds to prevent double execution within same session
|
|
5020
|
+
processedRefundIds = /* @__PURE__ */ new Set();
|
|
4966
5021
|
constructor(client, config, debug = false) {
|
|
4967
5022
|
this.client = client;
|
|
4968
5023
|
this.config = config;
|
|
@@ -5055,6 +5110,11 @@ var RefundExecutor = class {
|
|
|
5055
5110
|
case "rejection_ack":
|
|
5056
5111
|
this.log("Refund rejection acknowledged", { refundId: msg.refundId });
|
|
5057
5112
|
break;
|
|
5113
|
+
case "executing_ack":
|
|
5114
|
+
if (this.debug) {
|
|
5115
|
+
this.log("Refund executing acknowledged", { refundId: msg.refundId, status: msg.status });
|
|
5116
|
+
}
|
|
5117
|
+
break;
|
|
5058
5118
|
case "pong":
|
|
5059
5119
|
break;
|
|
5060
5120
|
default:
|
|
@@ -5069,6 +5129,10 @@ var RefundExecutor = class {
|
|
|
5069
5129
|
*/
|
|
5070
5130
|
async processSingleRefund(refund) {
|
|
5071
5131
|
try {
|
|
5132
|
+
if (this.processedRefundIds.has(refund.id)) {
|
|
5133
|
+
this.log("Refund already processed in this session", { refundId: refund.id });
|
|
5134
|
+
return;
|
|
5135
|
+
}
|
|
5072
5136
|
const endpointConfig = this.getEndpointConfig(refund.url);
|
|
5073
5137
|
if (endpointConfig?.enabled === false) {
|
|
5074
5138
|
this.log("Refunds disabled for endpoint", { url: refund.url });
|
|
@@ -5127,8 +5191,13 @@ var RefundExecutor = class {
|
|
|
5127
5191
|
return;
|
|
5128
5192
|
}
|
|
5129
5193
|
}
|
|
5194
|
+
this.sendMessage({
|
|
5195
|
+
type: "refund_executing",
|
|
5196
|
+
refundId: refund.id
|
|
5197
|
+
});
|
|
5130
5198
|
const result = await this.executeRefundTx(refund);
|
|
5131
5199
|
if (result.success) {
|
|
5200
|
+
this.processedRefundIds.add(refund.id);
|
|
5132
5201
|
this.sendMessage({
|
|
5133
5202
|
type: "refund_confirmed",
|
|
5134
5203
|
refundId: refund.id,
|
|
@@ -5327,14 +5396,98 @@ var RefundExecutor = class {
|
|
|
5327
5396
|
}
|
|
5328
5397
|
}
|
|
5329
5398
|
/**
|
|
5330
|
-
* Execute Solana refund
|
|
5399
|
+
* Execute Solana refund using @solana/kit v2 libraries
|
|
5331
5400
|
*/
|
|
5332
|
-
async executeSolanaRefund(
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5401
|
+
async executeSolanaRefund(refund, amountRaw) {
|
|
5402
|
+
try {
|
|
5403
|
+
const solanaPrivateKey = this.config.solanaPrivateKey;
|
|
5404
|
+
if (!solanaPrivateKey) {
|
|
5405
|
+
return {
|
|
5406
|
+
success: false,
|
|
5407
|
+
error: "No Solana private key configured (set ZAUTH_SOLANA_PRIVATE_KEY)",
|
|
5408
|
+
retryable: false
|
|
5409
|
+
};
|
|
5410
|
+
}
|
|
5411
|
+
const { createKeyPairSignerFromPrivateKeyBytes } = await import('@solana/signers');
|
|
5412
|
+
const {
|
|
5413
|
+
createSolanaRpc,
|
|
5414
|
+
address,
|
|
5415
|
+
pipe,
|
|
5416
|
+
createTransactionMessage,
|
|
5417
|
+
setTransactionMessageFeePayer,
|
|
5418
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
5419
|
+
appendTransactionMessageInstructions,
|
|
5420
|
+
signTransactionMessageWithSigners,
|
|
5421
|
+
getBase64EncodedWireTransaction
|
|
5422
|
+
} = await import('@solana/kit');
|
|
5423
|
+
const {
|
|
5424
|
+
findAssociatedTokenPda,
|
|
5425
|
+
getTransferInstruction,
|
|
5426
|
+
TOKEN_PROGRAM_ADDRESS
|
|
5427
|
+
} = await import('@solana-program/token');
|
|
5428
|
+
const bs58 = await import('bs58');
|
|
5429
|
+
const USDC_MINT = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
5430
|
+
const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
5431
|
+
const rpc = createSolanaRpc(rpcUrl);
|
|
5432
|
+
let signer;
|
|
5433
|
+
try {
|
|
5434
|
+
const secretKey = bs58.default.decode(solanaPrivateKey);
|
|
5435
|
+
const privateKeyBytes = secretKey.slice(0, 32);
|
|
5436
|
+
signer = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes);
|
|
5437
|
+
} catch {
|
|
5438
|
+
return {
|
|
5439
|
+
success: false,
|
|
5440
|
+
error: "Invalid Solana private key format (expected base58)",
|
|
5441
|
+
retryable: false
|
|
5442
|
+
};
|
|
5443
|
+
}
|
|
5444
|
+
const recipientAddress = address(refund.recipientAddress);
|
|
5445
|
+
const [senderAta] = await findAssociatedTokenPda({
|
|
5446
|
+
mint: USDC_MINT,
|
|
5447
|
+
owner: signer.address,
|
|
5448
|
+
tokenProgram: TOKEN_PROGRAM_ADDRESS
|
|
5449
|
+
});
|
|
5450
|
+
const [recipientAta] = await findAssociatedTokenPda({
|
|
5451
|
+
mint: USDC_MINT,
|
|
5452
|
+
owner: recipientAddress,
|
|
5453
|
+
tokenProgram: TOKEN_PROGRAM_ADDRESS
|
|
5454
|
+
});
|
|
5455
|
+
const transferIx = getTransferInstruction({
|
|
5456
|
+
source: senderAta,
|
|
5457
|
+
destination: recipientAta,
|
|
5458
|
+
authority: signer,
|
|
5459
|
+
amount: BigInt(amountRaw)
|
|
5460
|
+
});
|
|
5461
|
+
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
5462
|
+
const tx = pipe(
|
|
5463
|
+
createTransactionMessage({ version: 0 }),
|
|
5464
|
+
(tx2) => setTransactionMessageFeePayer(signer.address, tx2),
|
|
5465
|
+
(tx2) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx2),
|
|
5466
|
+
(tx2) => appendTransactionMessageInstructions([transferIx], tx2)
|
|
5467
|
+
);
|
|
5468
|
+
const signedTx = await signTransactionMessageWithSigners(tx);
|
|
5469
|
+
const base64Tx = getBase64EncodedWireTransaction(signedTx);
|
|
5470
|
+
const txSignature = await rpc.sendTransaction(base64Tx, { encoding: "base64" }).send();
|
|
5471
|
+
this.log("Solana refund sent", {
|
|
5472
|
+
txHash: txSignature,
|
|
5473
|
+
to: refund.recipientAddress,
|
|
5474
|
+
amount: amountRaw
|
|
5475
|
+
});
|
|
5476
|
+
return {
|
|
5477
|
+
success: true,
|
|
5478
|
+
txHash: txSignature,
|
|
5479
|
+
amountRaw,
|
|
5480
|
+
gasCostCents: 0
|
|
5481
|
+
// Solana fees are negligible
|
|
5482
|
+
};
|
|
5483
|
+
} catch (error) {
|
|
5484
|
+
this.log("Solana refund failed", { error: error.message });
|
|
5485
|
+
return {
|
|
5486
|
+
success: false,
|
|
5487
|
+
error: error.message,
|
|
5488
|
+
retryable: true
|
|
5489
|
+
};
|
|
5490
|
+
}
|
|
5338
5491
|
}
|
|
5339
5492
|
/**
|
|
5340
5493
|
* Get endpoint-specific config by matching URL patterns
|
|
@@ -5374,6 +5527,25 @@ function createZauthMiddleware(options) {
|
|
|
5374
5527
|
if (config.debug) {
|
|
5375
5528
|
console.log("[zauthSDK] Refund executor started");
|
|
5376
5529
|
}
|
|
5530
|
+
client.updateRefundConfig({
|
|
5531
|
+
enabled: true,
|
|
5532
|
+
maxRefundUsdCents: Math.round((config.refund.maxRefundUsd || 1) * 100),
|
|
5533
|
+
dailyCapCents: config.refund.dailyCapUsd ? Math.round(config.refund.dailyCapUsd * 100) : void 0,
|
|
5534
|
+
monthlyCapCents: config.refund.monthlyCapUsd ? Math.round(config.refund.monthlyCapUsd * 100) : void 0,
|
|
5535
|
+
triggers: {
|
|
5536
|
+
serverError: config.refund.triggers?.serverError ?? true,
|
|
5537
|
+
timeout: config.refund.triggers?.timeout ?? true,
|
|
5538
|
+
emptyResponse: config.refund.triggers?.emptyResponse ?? true,
|
|
5539
|
+
schemaValidation: config.refund.triggers?.schemaValidation ?? false,
|
|
5540
|
+
minMeaningfulness: config.refund.triggers?.minMeaningfulness ?? 0.3
|
|
5541
|
+
}
|
|
5542
|
+
}).then((result) => {
|
|
5543
|
+
if (config.debug) {
|
|
5544
|
+
console.log("[zauthSDK] Refund config registered with server", { success: result.success });
|
|
5545
|
+
}
|
|
5546
|
+
}).catch((err) => {
|
|
5547
|
+
console.error("[zauthSDK] Failed to register refund config:", err.message);
|
|
5548
|
+
});
|
|
5377
5549
|
}
|
|
5378
5550
|
function shouldMonitorRoute(req) {
|
|
5379
5551
|
if (options.shouldMonitor) {
|