@payai/x402-evm 2.4.1 → 2.4.2
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/cjs/batch-settlement/client/file-storage.d.ts +47 -0
- package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
- package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
- package/dist/cjs/batch-settlement/client/index.js +1565 -0
- package/dist/cjs/batch-settlement/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/facilitator/index.d.ts +71 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2032 -0
- package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
- package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
- package/dist/cjs/batch-settlement/server/index.js +1960 -0
- package/dist/cjs/batch-settlement/server/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +6 -4
- package/dist/cjs/exact/client/index.js +7 -5
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +16 -9
- package/dist/cjs/exact/facilitator/index.js +35 -7
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +40 -1
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +2 -1
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +11 -5
- package/dist/cjs/exact/v1/facilitator/index.js +16 -2
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +113 -7
- package/dist/cjs/index.js +1353 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/{esm/permit2-CyZxwngN.d.mts → cjs/permit2-DhJRUcgY.d.ts} +1 -13
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-CvkPJXBD.d.ts +307 -0
- package/dist/{esm/scheme-DCR7hsa3.d.mts → cjs/scheme-DTQFE9xp.d.ts} +2 -2
- package/dist/{esm/signer-D912R4mq.d.mts → cjs/signer-tYS6Y46X.d.ts} +3 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-Bl6aD0Xg.d.ts +81 -0
- package/dist/cjs/types-CF8P2-NM.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +5 -3
- package/dist/cjs/upto/client/index.js +7 -5
- package/dist/cjs/upto/client/index.js.map +1 -1
- package/dist/cjs/upto/facilitator/index.d.ts +2 -1
- package/dist/cjs/upto/facilitator/index.js +2 -1
- package/dist/cjs/upto/facilitator/index.js.map +1 -1
- package/dist/cjs/upto/server/index.js +40 -1
- package/dist/cjs/upto/server/index.js.map +1 -1
- package/dist/cjs/v1/index.d.ts +2 -1
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/index.d.mts +111 -0
- package/dist/esm/batch-settlement/client/index.mjs +59 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +71 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1235 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/index.d.mts +491 -0
- package/dist/esm/batch-settlement/server/index.mjs +1645 -0
- package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
- package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
- package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
- package/dist/esm/chunk-53USC5VE.mjs +47 -0
- package/dist/esm/chunk-53USC5VE.mjs.map +1 -0
- package/dist/esm/{chunk-GJ57SZGI.mjs → chunk-6WQOGWBE.mjs} +7 -5
- package/dist/esm/{chunk-GJ57SZGI.mjs.map → chunk-6WQOGWBE.mjs.map} +1 -1
- package/dist/esm/{chunk-F3OOHBAW.mjs → chunk-BTYNCDNS.mjs} +42 -2
- package/dist/esm/{chunk-F3OOHBAW.mjs.map → chunk-BTYNCDNS.mjs.map} +1 -1
- package/dist/esm/{chunk-ERK2ZPOY.mjs → chunk-CSQS7ZON.mjs} +27 -7
- package/dist/esm/chunk-CSQS7ZON.mjs.map +1 -0
- package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
- package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
- package/dist/esm/chunk-HYABYUBD.mjs +432 -0
- package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
- package/dist/esm/chunk-IN5YIT5C.mjs +159 -0
- package/dist/esm/chunk-IN5YIT5C.mjs.map +1 -0
- package/dist/esm/{chunk-JII456TS.mjs → chunk-JK7SLLF7.mjs} +1 -1
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/{chunk-C4ZQMS77.mjs → chunk-MACPBXCT.mjs} +2 -216
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-NKYVYGRA.mjs +911 -0
- package/dist/esm/chunk-NKYVYGRA.mjs.map +1 -0
- package/dist/esm/{chunk-FQJR4RCF.mjs → chunk-R7I3RZFF.mjs} +10 -6
- package/dist/esm/{chunk-FQJR4RCF.mjs.map → chunk-R7I3RZFF.mjs.map} +1 -1
- package/dist/esm/{chunk-CRT6YNY5.mjs → chunk-RWLVVO3B.mjs} +21 -61
- package/dist/esm/chunk-RWLVVO3B.mjs.map +1 -0
- package/dist/esm/chunk-TGFAVNUD.mjs +111 -0
- package/dist/esm/chunk-TGFAVNUD.mjs.map +1 -0
- package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
- package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
- package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
- package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
- package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
- package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
- package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
- package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
- package/dist/esm/{chunk-WKBC5YMI.mjs → chunk-YMQCTKDU.mjs} +23 -55
- package/dist/esm/chunk-YMQCTKDU.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +6 -4
- package/dist/esm/exact/client/index.mjs +10 -5
- package/dist/esm/exact/facilitator/index.d.mts +16 -9
- package/dist/esm/exact/facilitator/index.mjs +36 -14
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +1 -1
- package/dist/esm/exact/v1/client/index.d.mts +2 -1
- package/dist/esm/exact/v1/client/index.mjs +5 -2
- package/dist/esm/exact/v1/facilitator/index.d.mts +11 -5
- package/dist/esm/exact/v1/facilitator/index.mjs +5 -2
- package/dist/esm/index.d.mts +113 -7
- package/dist/esm/index.mjs +53 -7
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-DtbSS4Fk.d.mts +307 -0
- package/dist/esm/scheme-gtqAIYPJ.d.mts +47 -0
- package/dist/esm/signer-tYS6Y46X.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-sZ1CDS4P.d.mts +81 -0
- package/dist/esm/types-CF8P2-NM.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +5 -3
- package/dist/esm/upto/client/index.mjs +9 -4
- package/dist/esm/upto/facilitator/index.d.mts +2 -1
- package/dist/esm/upto/facilitator/index.mjs +17 -9
- package/dist/esm/upto/facilitator/index.mjs.map +1 -1
- package/dist/esm/upto/server/index.mjs +1 -1
- package/dist/esm/v1/index.d.mts +2 -1
- package/dist/esm/v1/index.mjs +5 -2
- package/package.json +5 -5
- package/dist/esm/chunk-C4ZQMS77.mjs.map +0 -1
- package/dist/esm/chunk-CRT6YNY5.mjs.map +0 -1
- package/dist/esm/chunk-ERK2ZPOY.mjs.map +0 -1
- package/dist/esm/chunk-JII456TS.mjs.map +0 -1
- package/dist/esm/chunk-WKBC5YMI.mjs.map +0 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/batch-settlement/server/redisStorage.ts
|
|
21
|
+
var redisStorage_exports = {};
|
|
22
|
+
__export(redisStorage_exports, {
|
|
23
|
+
RedisChannelStorage: () => RedisChannelStorage
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(redisStorage_exports);
|
|
26
|
+
var DEFAULT_KEY_PREFIX = "x402:batch-settlement";
|
|
27
|
+
var DEFAULT_LOCK_RETRY_INTERVAL_MS = 10;
|
|
28
|
+
var DEFAULT_SCAN_COUNT = 100;
|
|
29
|
+
var UPDATE_CHANNEL_SCRIPT = `
|
|
30
|
+
local current = redis.call("GET", KEYS[1])
|
|
31
|
+
local expectedExists = ARGV[1]
|
|
32
|
+
local expected = ARGV[2]
|
|
33
|
+
local operation = ARGV[3]
|
|
34
|
+
local nextValue = ARGV[4]
|
|
35
|
+
|
|
36
|
+
if expectedExists == "0" then
|
|
37
|
+
if current ~= false then
|
|
38
|
+
return {0, current}
|
|
39
|
+
end
|
|
40
|
+
elseif current ~= expected then
|
|
41
|
+
return {0, current or false}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if operation == "delete" then
|
|
45
|
+
redis.call("DEL", KEYS[1])
|
|
46
|
+
return {1, false}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if operation == "set" then
|
|
50
|
+
redis.call("SET", KEYS[1], nextValue)
|
|
51
|
+
return {1, nextValue}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return {1, current or false}
|
|
55
|
+
`;
|
|
56
|
+
var RedisChannelStorage = class {
|
|
57
|
+
/**
|
|
58
|
+
* Creates Redis-backed server channel storage.
|
|
59
|
+
*
|
|
60
|
+
* @param options - Redis client and optional key/retry configuration.
|
|
61
|
+
*/
|
|
62
|
+
constructor(options) {
|
|
63
|
+
this.client = options.client;
|
|
64
|
+
this.keyPrefix = options.keyPrefix ?? DEFAULT_KEY_PREFIX;
|
|
65
|
+
this.channelKeyPrefix = `${this.keyPrefix}:server:channel`;
|
|
66
|
+
this.lockRetryIntervalMs = options.lockRetryIntervalMs ?? DEFAULT_LOCK_RETRY_INTERVAL_MS;
|
|
67
|
+
this.scanCount = options.scanCount ?? DEFAULT_SCAN_COUNT;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Loads a persisted channel record, if present.
|
|
71
|
+
*
|
|
72
|
+
* @param channelId - The channel identifier.
|
|
73
|
+
* @returns Parsed channel record or `undefined` when the key is missing.
|
|
74
|
+
*/
|
|
75
|
+
async get(channelId) {
|
|
76
|
+
const raw = await this.client.get(this.channelKey(channelId));
|
|
77
|
+
if (!raw) return void 0;
|
|
78
|
+
return JSON.parse(raw);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Lists all stored channel records by scanning Redis keys.
|
|
82
|
+
*
|
|
83
|
+
* @returns Channel records sorted by channelId.
|
|
84
|
+
*/
|
|
85
|
+
async list() {
|
|
86
|
+
const channels = [];
|
|
87
|
+
for await (const keyOrKeys of this.client.scanIterator({
|
|
88
|
+
MATCH: `${this.channelKeyPrefix}:*`,
|
|
89
|
+
COUNT: this.scanCount
|
|
90
|
+
})) {
|
|
91
|
+
const keys = Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];
|
|
92
|
+
for (const key of keys) {
|
|
93
|
+
if (key.endsWith(":lock")) continue;
|
|
94
|
+
const raw = await this.client.get(key);
|
|
95
|
+
if (!raw) continue;
|
|
96
|
+
channels.push(JSON.parse(raw));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return channels.sort((a, b) => a.channelId.localeCompare(b.channelId));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Atomically inspects and mutates a channel record with Redis compare-and-write retries.
|
|
103
|
+
*
|
|
104
|
+
* @param channelId - The channel identifier.
|
|
105
|
+
* @param update - Mutation callback. Return `undefined` to delete, or `current` to leave unchanged.
|
|
106
|
+
* @returns The final stored channel and whether storage updated, stayed unchanged, or deleted.
|
|
107
|
+
*/
|
|
108
|
+
async updateChannel(channelId, update) {
|
|
109
|
+
const key = this.channelKey(channelId);
|
|
110
|
+
while (true) {
|
|
111
|
+
const currentRaw = await this.client.get(key);
|
|
112
|
+
const current = currentRaw ? JSON.parse(currentRaw) : void 0;
|
|
113
|
+
const next = update(current);
|
|
114
|
+
if (next === current) {
|
|
115
|
+
const result2 = await this.commitUpdate(key, currentRaw, "keep");
|
|
116
|
+
if (result2.applied) return { channel: current, status: "unchanged" };
|
|
117
|
+
await sleep(this.lockRetryIntervalMs);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (!next) {
|
|
121
|
+
const result2 = await this.commitUpdate(key, currentRaw, "delete");
|
|
122
|
+
if (result2.applied) {
|
|
123
|
+
return { channel: void 0, status: current ? "deleted" : "unchanged" };
|
|
124
|
+
}
|
|
125
|
+
await sleep(this.lockRetryIntervalMs);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const nextRaw = JSON.stringify(next);
|
|
129
|
+
const result = await this.commitUpdate(key, currentRaw, "set", nextRaw);
|
|
130
|
+
if (result.applied) return { channel: next, status: "updated" };
|
|
131
|
+
await sleep(this.lockRetryIntervalMs);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Applies a channel mutation only if the key still contains the value that was inspected.
|
|
136
|
+
*
|
|
137
|
+
* @param key - Redis channel key to mutate.
|
|
138
|
+
* @param expectedRaw - Raw JSON value observed before running the update callback.
|
|
139
|
+
* @param operation - Mutation to apply when the observed value is still current.
|
|
140
|
+
* @param nextRaw - Raw JSON value to write for set operations.
|
|
141
|
+
* @returns Whether the mutation was applied.
|
|
142
|
+
*/
|
|
143
|
+
async commitUpdate(key, expectedRaw, operation, nextRaw = "") {
|
|
144
|
+
return parseRedisUpdateResult(
|
|
145
|
+
await this.client.eval(UPDATE_CHANNEL_SCRIPT, {
|
|
146
|
+
keys: [key],
|
|
147
|
+
arguments: [expectedRaw === null ? "0" : "1", expectedRaw ?? "", operation, nextRaw]
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Builds the Redis key for a stored channel record.
|
|
153
|
+
*
|
|
154
|
+
* @param channelId - The channel identifier.
|
|
155
|
+
* @returns Redis key for the channel JSON.
|
|
156
|
+
*/
|
|
157
|
+
channelKey(channelId) {
|
|
158
|
+
return `${this.channelKeyPrefix}:${channelId.toLowerCase()}`;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
function parseRedisUpdateResult(value) {
|
|
162
|
+
if (!Array.isArray(value) || value.length < 1) {
|
|
163
|
+
throw new Error("Unexpected Redis update response");
|
|
164
|
+
}
|
|
165
|
+
const [applied, raw] = value;
|
|
166
|
+
if (applied !== 0 && applied !== 1) {
|
|
167
|
+
throw new Error("Unexpected Redis update status");
|
|
168
|
+
}
|
|
169
|
+
if (raw !== false && raw !== null && raw !== void 0 && typeof raw !== "string") {
|
|
170
|
+
throw new Error("Unexpected Redis update value");
|
|
171
|
+
}
|
|
172
|
+
return { applied: applied === 1 };
|
|
173
|
+
}
|
|
174
|
+
function sleep(ms) {
|
|
175
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
176
|
+
}
|
|
177
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
178
|
+
0 && (module.exports = {
|
|
179
|
+
RedisChannelStorage
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=redis-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/batch-settlement/server/redisStorage.ts"],"sourcesContent":["import type { Channel, ChannelStorage, ChannelUpdateResult } from \"./storage\";\n\nconst DEFAULT_KEY_PREFIX = \"x402:batch-settlement\";\nconst DEFAULT_LOCK_RETRY_INTERVAL_MS = 10;\nconst DEFAULT_SCAN_COUNT = 100;\n\nconst UPDATE_CHANNEL_SCRIPT = `\nlocal current = redis.call(\"GET\", KEYS[1])\nlocal expectedExists = ARGV[1]\nlocal expected = ARGV[2]\nlocal operation = ARGV[3]\nlocal nextValue = ARGV[4]\n\nif expectedExists == \"0\" then\n if current ~= false then\n return {0, current}\n end\nelseif current ~= expected then\n return {0, current or false}\nend\n\nif operation == \"delete\" then\n redis.call(\"DEL\", KEYS[1])\n return {1, false}\nend\n\nif operation == \"set\" then\n redis.call(\"SET\", KEYS[1], nextValue)\n return {1, nextValue}\nend\n\nreturn {1, current or false}\n`;\n\nexport type RedisEvalOptions = {\n keys: string[];\n arguments: string[];\n};\n\nexport type RedisSetOptions = {\n NX?: true;\n PX?: number;\n};\n\nexport type RedisScanOptions = {\n MATCH?: string;\n COUNT?: number;\n};\n\nexport type RedisChannelStorageClient = {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, options?: RedisSetOptions): Promise<string | null>;\n del(key: string): Promise<number>;\n eval(script: string, options: RedisEvalOptions): Promise<unknown>;\n scanIterator(options: RedisScanOptions): AsyncIterable<string | string[]>;\n};\n\nexport type RedisChannelStorageOptions = {\n client: RedisChannelStorageClient;\n keyPrefix?: string;\n lockTtlMs?: number;\n lockRetryIntervalMs?: number;\n lockRenewalIntervalMs?: number;\n scanCount?: number;\n};\n\ntype RedisUpdateOperation = \"delete\" | \"keep\" | \"set\";\n\ntype ParsedRedisUpdateResult = {\n applied: boolean;\n};\n\n/**\n * Redis-backed {@link ChannelStorage} with optimistic atomic updates.\n */\nexport class RedisChannelStorage implements ChannelStorage {\n private readonly client: RedisChannelStorageClient;\n private readonly keyPrefix: string;\n private readonly channelKeyPrefix: string;\n private readonly lockRetryIntervalMs: number;\n private readonly scanCount: number;\n\n /**\n * Creates Redis-backed server channel storage.\n *\n * @param options - Redis client and optional key/retry configuration.\n */\n constructor(options: RedisChannelStorageOptions) {\n this.client = options.client;\n this.keyPrefix = options.keyPrefix ?? DEFAULT_KEY_PREFIX;\n this.channelKeyPrefix = `${this.keyPrefix}:server:channel`;\n this.lockRetryIntervalMs = options.lockRetryIntervalMs ?? DEFAULT_LOCK_RETRY_INTERVAL_MS;\n this.scanCount = options.scanCount ?? DEFAULT_SCAN_COUNT;\n }\n\n /**\n * Loads a persisted channel record, if present.\n *\n * @param channelId - The channel identifier.\n * @returns Parsed channel record or `undefined` when the key is missing.\n */\n async get(channelId: string): Promise<Channel | undefined> {\n const raw = await this.client.get(this.channelKey(channelId));\n if (!raw) return undefined;\n return JSON.parse(raw) as Channel;\n }\n\n /**\n * Lists all stored channel records by scanning Redis keys.\n *\n * @returns Channel records sorted by channelId.\n */\n async list(): Promise<Channel[]> {\n const channels: Channel[] = [];\n for await (const keyOrKeys of this.client.scanIterator({\n MATCH: `${this.channelKeyPrefix}:*`,\n COUNT: this.scanCount,\n })) {\n const keys = Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];\n for (const key of keys) {\n if (key.endsWith(\":lock\")) continue;\n const raw = await this.client.get(key);\n if (!raw) continue;\n channels.push(JSON.parse(raw) as Channel);\n }\n }\n return channels.sort((a, b) => a.channelId.localeCompare(b.channelId));\n }\n\n /**\n * Atomically inspects and mutates a channel record with Redis compare-and-write retries.\n *\n * @param channelId - The channel identifier.\n * @param update - Mutation callback. Return `undefined` to delete, or `current` to leave unchanged.\n * @returns The final stored channel and whether storage updated, stayed unchanged, or deleted.\n */\n async updateChannel(\n channelId: string,\n update: (current: Channel | undefined) => Channel | undefined,\n ): Promise<ChannelUpdateResult> {\n const key = this.channelKey(channelId);\n while (true) {\n const currentRaw = await this.client.get(key);\n const current = currentRaw ? (JSON.parse(currentRaw) as Channel) : undefined;\n const next = update(current);\n\n if (next === current) {\n const result = await this.commitUpdate(key, currentRaw, \"keep\");\n if (result.applied) return { channel: current, status: \"unchanged\" };\n await sleep(this.lockRetryIntervalMs);\n continue;\n }\n\n if (!next) {\n const result = await this.commitUpdate(key, currentRaw, \"delete\");\n if (result.applied) {\n return { channel: undefined, status: current ? \"deleted\" : \"unchanged\" };\n }\n await sleep(this.lockRetryIntervalMs);\n continue;\n }\n\n const nextRaw = JSON.stringify(next);\n const result = await this.commitUpdate(key, currentRaw, \"set\", nextRaw);\n if (result.applied) return { channel: next, status: \"updated\" };\n await sleep(this.lockRetryIntervalMs);\n }\n }\n\n /**\n * Applies a channel mutation only if the key still contains the value that was inspected.\n *\n * @param key - Redis channel key to mutate.\n * @param expectedRaw - Raw JSON value observed before running the update callback.\n * @param operation - Mutation to apply when the observed value is still current.\n * @param nextRaw - Raw JSON value to write for set operations.\n * @returns Whether the mutation was applied.\n */\n private async commitUpdate(\n key: string,\n expectedRaw: string | null,\n operation: RedisUpdateOperation,\n nextRaw = \"\",\n ): Promise<ParsedRedisUpdateResult> {\n return parseRedisUpdateResult(\n await this.client.eval(UPDATE_CHANNEL_SCRIPT, {\n keys: [key],\n arguments: [expectedRaw === null ? \"0\" : \"1\", expectedRaw ?? \"\", operation, nextRaw],\n }),\n );\n }\n\n /**\n * Builds the Redis key for a stored channel record.\n *\n * @param channelId - The channel identifier.\n * @returns Redis key for the channel JSON.\n */\n private channelKey(channelId: string) {\n return `${this.channelKeyPrefix}:${channelId.toLowerCase()}`;\n }\n}\n\n/**\n * Parses the Redis script response.\n *\n * @param value - Raw response from the Redis client.\n * @returns Whether the compare-and-write applied.\n */\nfunction parseRedisUpdateResult(value: unknown): ParsedRedisUpdateResult {\n if (!Array.isArray(value) || value.length < 1) {\n throw new Error(\"Unexpected Redis update response\");\n }\n\n const [applied, raw] = value;\n if (applied !== 0 && applied !== 1) {\n throw new Error(\"Unexpected Redis update status\");\n }\n\n if (raw !== false && raw !== null && raw !== undefined && typeof raw !== \"string\") {\n throw new Error(\"Unexpected Redis update value\");\n }\n\n return { applied: applied === 1 };\n}\n\n/**\n * Resolves after the requested delay.\n *\n * @param ms - Delay in milliseconds.\n * @returns Promise resolved after the delay.\n */\nfunction sleep(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n"],"mappings":"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","names":["result"]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
export { E as ExactEvmScheme } from '../../scheme-
|
|
1
|
+
export { E as ExactEvmScheme } from '../../scheme-DTQFE9xp.js';
|
|
2
2
|
import { x402Client, SelectPaymentRequirements, PaymentPolicy } from '@payai/x402/client';
|
|
3
3
|
import { Network } from '@payai/x402/types';
|
|
4
|
-
import { C as ClientEvmSigner } from '../../signer-
|
|
5
|
-
import { E as ExactEvmSchemeOptions } from '../../
|
|
6
|
-
export {
|
|
4
|
+
import { C as ClientEvmSigner } from '../../signer-tYS6Y46X.js';
|
|
5
|
+
import { E as ExactEvmSchemeOptions } from '../../rpc-DULZzRne.js';
|
|
6
|
+
export { a as ExactEvmSchemeConfig, b as ExactEvmSchemeConfigByChainId } from '../../rpc-DULZzRne.js';
|
|
7
|
+
export { P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-DhJRUcgY.js';
|
|
8
|
+
import 'viem';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Configuration options for registering EVM schemes to an x402Client
|
|
@@ -433,7 +433,7 @@ function resolveExtensionRpcCapabilities(network, signer, options) {
|
|
|
433
433
|
}
|
|
434
434
|
|
|
435
435
|
// src/shared/extensions.ts
|
|
436
|
-
async function trySignEip2612PermitExtension(signer, options, requirements, result, context) {
|
|
436
|
+
async function trySignEip2612PermitExtension(signer, options, requirements, result, context, approvalAmount) {
|
|
437
437
|
const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);
|
|
438
438
|
if (!capabilities.readContract) {
|
|
439
439
|
return void 0;
|
|
@@ -448,6 +448,7 @@ async function trySignEip2612PermitExtension(signer, options, requirements, resu
|
|
|
448
448
|
}
|
|
449
449
|
const chainId = getEvmChainId(requirements.network);
|
|
450
450
|
const tokenAddress = (0, import_viem10.getAddress)(requirements.asset);
|
|
451
|
+
const requiredAllowance = approvalAmount ?? requirements.amount;
|
|
451
452
|
try {
|
|
452
453
|
const allowance = await capabilities.readContract({
|
|
453
454
|
address: tokenAddress,
|
|
@@ -455,7 +456,7 @@ async function trySignEip2612PermitExtension(signer, options, requirements, resu
|
|
|
455
456
|
functionName: "allowance",
|
|
456
457
|
args: [signer.address, PERMIT2_ADDRESS]
|
|
457
458
|
});
|
|
458
|
-
if (allowance >= BigInt(
|
|
459
|
+
if (allowance >= BigInt(requiredAllowance)) {
|
|
459
460
|
return void 0;
|
|
460
461
|
}
|
|
461
462
|
} catch {
|
|
@@ -473,13 +474,13 @@ async function trySignEip2612PermitExtension(signer, options, requirements, resu
|
|
|
473
474
|
tokenVersion,
|
|
474
475
|
chainId,
|
|
475
476
|
deadline,
|
|
476
|
-
|
|
477
|
+
requiredAllowance
|
|
477
478
|
);
|
|
478
479
|
return {
|
|
479
480
|
[EIP2612_GAS_SPONSORING_KEY]: { info }
|
|
480
481
|
};
|
|
481
482
|
}
|
|
482
|
-
async function trySignErc20ApprovalExtension(signer, options, requirements, context) {
|
|
483
|
+
async function trySignErc20ApprovalExtension(signer, options, requirements, context, approvalAmount) {
|
|
483
484
|
const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);
|
|
484
485
|
if (!capabilities.readContract) {
|
|
485
486
|
return void 0;
|
|
@@ -492,6 +493,7 @@ async function trySignErc20ApprovalExtension(signer, options, requirements, cont
|
|
|
492
493
|
}
|
|
493
494
|
const chainId = getEvmChainId(requirements.network);
|
|
494
495
|
const tokenAddress = (0, import_viem10.getAddress)(requirements.asset);
|
|
496
|
+
const requiredAllowance = approvalAmount ?? requirements.amount;
|
|
495
497
|
try {
|
|
496
498
|
const allowance = await capabilities.readContract({
|
|
497
499
|
address: tokenAddress,
|
|
@@ -499,7 +501,7 @@ async function trySignErc20ApprovalExtension(signer, options, requirements, cont
|
|
|
499
501
|
functionName: "allowance",
|
|
500
502
|
args: [signer.address, PERMIT2_ADDRESS]
|
|
501
503
|
});
|
|
502
|
-
if (allowance >= BigInt(
|
|
504
|
+
if (allowance >= BigInt(requiredAllowance)) {
|
|
503
505
|
return void 0;
|
|
504
506
|
}
|
|
505
507
|
} catch {
|