@perkos/scheme-deferred 1.0.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 ADDED
@@ -0,0 +1,376 @@
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/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFERRED_ESCROW_ABI: () => DEFERRED_ESCROW_ABI,
24
+ DEFERRED_ESCROW_CLAIM_VOUCHER_ABI: () => DEFERRED_ESCROW_CLAIM_VOUCHER_ABI,
25
+ DEFERRED_ESCROW_GET_BALANCE_ABI: () => DEFERRED_ESCROW_GET_BALANCE_ABI,
26
+ DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI: () => DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
27
+ DeferredSchemeVerifier: () => DeferredSchemeVerifier,
28
+ ERC20_BALANCE_ABI: () => ERC20_BALANCE_ABI,
29
+ VOUCHER_TYPES: () => VOUCHER_TYPES,
30
+ VOUCHER_TYPE_DEF: () => VOUCHER_TYPE_DEF,
31
+ createEIP712Domain: () => createEIP712Domain,
32
+ createVoucherMessage: () => createVoucherMessage,
33
+ createVoucherTuple: () => createVoucherTuple,
34
+ generateVoucherId: () => generateVoucherId,
35
+ parseSignature: () => parseSignature
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+ var import_viem = require("viem");
39
+ var import_util_chains = require("@perkos/util-chains");
40
+ var VOUCHER_TYPE_DEF = [
41
+ { name: "id", type: "bytes32" },
42
+ { name: "buyer", type: "address" },
43
+ { name: "seller", type: "address" },
44
+ { name: "valueAggregate", type: "uint256" },
45
+ { name: "asset", type: "address" },
46
+ { name: "timestamp", type: "uint64" },
47
+ { name: "nonce", type: "uint256" },
48
+ { name: "escrow", type: "address" },
49
+ { name: "chainId", type: "uint256" }
50
+ ];
51
+ var VOUCHER_TYPES = {
52
+ Voucher: VOUCHER_TYPE_DEF
53
+ };
54
+ var ERC20_BALANCE_ABI = [
55
+ {
56
+ name: "balanceOf",
57
+ type: "function",
58
+ stateMutability: "view",
59
+ inputs: [{ name: "account", type: "address" }],
60
+ outputs: [{ name: "", type: "uint256" }]
61
+ }
62
+ ];
63
+ var DEFERRED_ESCROW_GET_BALANCE_ABI = [
64
+ {
65
+ name: "getAvailableBalance",
66
+ type: "function",
67
+ stateMutability: "view",
68
+ inputs: [
69
+ { name: "buyer", type: "address" },
70
+ { name: "seller", type: "address" },
71
+ { name: "asset", type: "address" }
72
+ ],
73
+ outputs: [{ name: "", type: "uint256" }]
74
+ }
75
+ ];
76
+ var DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI = [
77
+ {
78
+ name: "voucherClaimed",
79
+ type: "function",
80
+ stateMutability: "view",
81
+ inputs: [
82
+ { name: "voucherId", type: "bytes32" },
83
+ { name: "nonce", type: "uint256" }
84
+ ],
85
+ outputs: [{ name: "", type: "bool" }]
86
+ }
87
+ ];
88
+ var DEFERRED_ESCROW_CLAIM_VOUCHER_ABI = [
89
+ {
90
+ name: "claimVoucher",
91
+ type: "function",
92
+ stateMutability: "nonpayable",
93
+ inputs: [
94
+ {
95
+ name: "voucher",
96
+ type: "tuple",
97
+ components: [
98
+ { name: "id", type: "bytes32" },
99
+ { name: "buyer", type: "address" },
100
+ { name: "seller", type: "address" },
101
+ { name: "valueAggregate", type: "uint256" },
102
+ { name: "asset", type: "address" },
103
+ { name: "timestamp", type: "uint64" },
104
+ { name: "nonce", type: "uint256" },
105
+ { name: "escrow", type: "address" },
106
+ { name: "chainId", type: "uint256" }
107
+ ]
108
+ },
109
+ { name: "signature", type: "bytes" }
110
+ ],
111
+ outputs: []
112
+ }
113
+ ];
114
+ var DEFERRED_ESCROW_ABI = [
115
+ ...DEFERRED_ESCROW_GET_BALANCE_ABI,
116
+ ...DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
117
+ ...DEFERRED_ESCROW_CLAIM_VOUCHER_ABI
118
+ ];
119
+ var DeferredSchemeVerifier = class {
120
+ constructor(config) {
121
+ this.network = config.network;
122
+ this.chainId = (0, import_util_chains.getChainIdFromNetwork)(config.network) || 1;
123
+ this.escrowAddress = config.escrowAddress;
124
+ this.domainName = config.domainName || "X402DeferredEscrow";
125
+ this.domainVersion = config.domainVersion || "1";
126
+ const chain = (0, import_util_chains.getChainById)(this.chainId);
127
+ const rpcUrl = config.rpcUrl || (0, import_util_chains.getRpcUrl)(this.chainId);
128
+ if (!chain || !rpcUrl) {
129
+ throw new Error(`Unsupported network: ${config.network}`);
130
+ }
131
+ this.publicClient = (0, import_viem.createPublicClient)({
132
+ chain,
133
+ transport: (0, import_viem.http)(rpcUrl)
134
+ });
135
+ }
136
+ /**
137
+ * Verify a deferred scheme payment voucher
138
+ */
139
+ async verify(payload, requirements) {
140
+ try {
141
+ const { voucher, signature } = payload;
142
+ if (!this.validateVoucher(voucher, requirements)) {
143
+ return {
144
+ isValid: false,
145
+ invalidReason: "Voucher fields invalid",
146
+ payer: null
147
+ };
148
+ }
149
+ const signer = await this.recoverSigner(voucher, signature);
150
+ if (!signer) {
151
+ return {
152
+ isValid: false,
153
+ invalidReason: "Invalid signature",
154
+ payer: null
155
+ };
156
+ }
157
+ if (signer.toLowerCase() !== voucher.buyer.toLowerCase()) {
158
+ return {
159
+ isValid: false,
160
+ invalidReason: `Signer does not match buyer. Recovered: ${signer}, Expected: ${voucher.buyer}`,
161
+ payer: null
162
+ };
163
+ }
164
+ const claimed = await this.isVoucherClaimed(
165
+ voucher.id,
166
+ BigInt(voucher.nonce)
167
+ );
168
+ if (claimed) {
169
+ return {
170
+ isValid: false,
171
+ invalidReason: "Voucher already claimed",
172
+ payer: null
173
+ };
174
+ }
175
+ const balance = await this.getEscrowBalance(
176
+ voucher.buyer,
177
+ voucher.seller,
178
+ voucher.asset
179
+ );
180
+ const valueAggregate = BigInt(voucher.valueAggregate);
181
+ if (balance < valueAggregate) {
182
+ return {
183
+ isValid: false,
184
+ invalidReason: "Insufficient escrow balance",
185
+ payer: null
186
+ };
187
+ }
188
+ return {
189
+ isValid: true,
190
+ invalidReason: null,
191
+ payer: voucher.buyer
192
+ };
193
+ } catch (error) {
194
+ return {
195
+ isValid: false,
196
+ invalidReason: error instanceof Error ? error.message : "Verification failed",
197
+ payer: null
198
+ };
199
+ }
200
+ }
201
+ /**
202
+ * Validate voucher fields against requirements
203
+ */
204
+ validateVoucher(voucher, requirements) {
205
+ if (voucher.escrow.toLowerCase() !== this.escrowAddress.toLowerCase()) {
206
+ return false;
207
+ }
208
+ if (BigInt(voucher.chainId) !== BigInt(this.chainId)) {
209
+ return false;
210
+ }
211
+ if (voucher.seller.toLowerCase() !== requirements.payTo.toLowerCase()) {
212
+ return false;
213
+ }
214
+ const valueAggregate = BigInt(voucher.valueAggregate);
215
+ const maxAmount = BigInt(requirements.maxAmountRequired);
216
+ if (valueAggregate > maxAmount) {
217
+ return false;
218
+ }
219
+ if (voucher.asset.toLowerCase() !== requirements.asset.toLowerCase()) {
220
+ return false;
221
+ }
222
+ return true;
223
+ }
224
+ /**
225
+ * Recover signer from EIP-712 typed data signature
226
+ */
227
+ async recoverSigner(voucher, signature) {
228
+ try {
229
+ const domain = this.getEIP712Domain();
230
+ const message = {
231
+ id: voucher.id,
232
+ buyer: voucher.buyer,
233
+ seller: voucher.seller,
234
+ valueAggregate: BigInt(voucher.valueAggregate),
235
+ asset: voucher.asset,
236
+ timestamp: BigInt(voucher.timestamp),
237
+ nonce: BigInt(voucher.nonce),
238
+ escrow: voucher.escrow,
239
+ chainId: BigInt(voucher.chainId)
240
+ };
241
+ const recoveredAddress = await (0, import_viem.recoverTypedDataAddress)({
242
+ domain,
243
+ types: VOUCHER_TYPES,
244
+ primaryType: "Voucher",
245
+ message,
246
+ signature
247
+ });
248
+ return recoveredAddress;
249
+ } catch {
250
+ return null;
251
+ }
252
+ }
253
+ /**
254
+ * Get EIP-712 domain for escrow contract
255
+ */
256
+ getEIP712Domain() {
257
+ return {
258
+ name: this.domainName,
259
+ version: this.domainVersion,
260
+ chainId: this.chainId,
261
+ verifyingContract: this.escrowAddress
262
+ };
263
+ }
264
+ /**
265
+ * Check if voucher has been claimed
266
+ */
267
+ async isVoucherClaimed(voucherId, nonce) {
268
+ try {
269
+ const claimed = await this.publicClient.readContract({
270
+ address: this.escrowAddress,
271
+ abi: DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
272
+ functionName: "voucherClaimed",
273
+ args: [voucherId, nonce]
274
+ });
275
+ return claimed;
276
+ } catch {
277
+ return false;
278
+ }
279
+ }
280
+ /**
281
+ * Get available escrow balance
282
+ */
283
+ async getEscrowBalance(buyer, seller, asset) {
284
+ try {
285
+ const balance = await this.publicClient.readContract({
286
+ address: this.escrowAddress,
287
+ abi: DEFERRED_ESCROW_GET_BALANCE_ABI,
288
+ functionName: "getAvailableBalance",
289
+ args: [buyer, seller, asset]
290
+ });
291
+ return balance;
292
+ } catch {
293
+ return 0n;
294
+ }
295
+ }
296
+ /**
297
+ * Get network name
298
+ */
299
+ getNetwork() {
300
+ return this.network;
301
+ }
302
+ /**
303
+ * Get chain ID
304
+ */
305
+ getChainId() {
306
+ return this.chainId;
307
+ }
308
+ /**
309
+ * Get escrow address
310
+ */
311
+ getEscrowAddress() {
312
+ return this.escrowAddress;
313
+ }
314
+ };
315
+ function parseSignature(signature) {
316
+ const sig = signature.slice(2);
317
+ const r = `0x${sig.slice(0, 64)}`;
318
+ const s = `0x${sig.slice(64, 128)}`;
319
+ const v = parseInt(sig.slice(128, 130), 16);
320
+ return { v, r, s };
321
+ }
322
+ function createEIP712Domain(chainId, escrowAddress, domainName, domainVersion) {
323
+ return {
324
+ name: domainName || "X402DeferredEscrow",
325
+ version: domainVersion || "1",
326
+ chainId,
327
+ verifyingContract: escrowAddress
328
+ };
329
+ }
330
+ function generateVoucherId() {
331
+ const bytes = new Uint8Array(32);
332
+ crypto.getRandomValues(bytes);
333
+ return `0x${Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("")}`;
334
+ }
335
+ function createVoucherMessage(id, buyer, seller, valueAggregate, asset, timestamp, nonce, escrow, chainId) {
336
+ return {
337
+ id,
338
+ buyer,
339
+ seller,
340
+ valueAggregate: BigInt(valueAggregate),
341
+ asset,
342
+ timestamp: BigInt(timestamp),
343
+ nonce: BigInt(nonce),
344
+ escrow,
345
+ chainId: BigInt(chainId)
346
+ };
347
+ }
348
+ function createVoucherTuple(voucher) {
349
+ return {
350
+ id: voucher.id,
351
+ buyer: voucher.buyer,
352
+ seller: voucher.seller,
353
+ valueAggregate: BigInt(voucher.valueAggregate),
354
+ asset: voucher.asset,
355
+ timestamp: BigInt(voucher.timestamp),
356
+ nonce: BigInt(voucher.nonce),
357
+ escrow: voucher.escrow,
358
+ chainId: BigInt(voucher.chainId)
359
+ };
360
+ }
361
+ // Annotate the CommonJS export names for ESM import in node:
362
+ 0 && (module.exports = {
363
+ DEFERRED_ESCROW_ABI,
364
+ DEFERRED_ESCROW_CLAIM_VOUCHER_ABI,
365
+ DEFERRED_ESCROW_GET_BALANCE_ABI,
366
+ DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
367
+ DeferredSchemeVerifier,
368
+ ERC20_BALANCE_ABI,
369
+ VOUCHER_TYPES,
370
+ VOUCHER_TYPE_DEF,
371
+ createEIP712Domain,
372
+ createVoucherMessage,
373
+ createVoucherTuple,
374
+ generateVoucherId,
375
+ parseSignature
376
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,347 @@
1
+ // src/index.ts
2
+ import {
3
+ createPublicClient,
4
+ http,
5
+ recoverTypedDataAddress
6
+ } from "viem";
7
+ import {
8
+ getChainById,
9
+ getChainIdFromNetwork,
10
+ getRpcUrl
11
+ } from "@perkos/util-chains";
12
+ var VOUCHER_TYPE_DEF = [
13
+ { name: "id", type: "bytes32" },
14
+ { name: "buyer", type: "address" },
15
+ { name: "seller", type: "address" },
16
+ { name: "valueAggregate", type: "uint256" },
17
+ { name: "asset", type: "address" },
18
+ { name: "timestamp", type: "uint64" },
19
+ { name: "nonce", type: "uint256" },
20
+ { name: "escrow", type: "address" },
21
+ { name: "chainId", type: "uint256" }
22
+ ];
23
+ var VOUCHER_TYPES = {
24
+ Voucher: VOUCHER_TYPE_DEF
25
+ };
26
+ var ERC20_BALANCE_ABI = [
27
+ {
28
+ name: "balanceOf",
29
+ type: "function",
30
+ stateMutability: "view",
31
+ inputs: [{ name: "account", type: "address" }],
32
+ outputs: [{ name: "", type: "uint256" }]
33
+ }
34
+ ];
35
+ var DEFERRED_ESCROW_GET_BALANCE_ABI = [
36
+ {
37
+ name: "getAvailableBalance",
38
+ type: "function",
39
+ stateMutability: "view",
40
+ inputs: [
41
+ { name: "buyer", type: "address" },
42
+ { name: "seller", type: "address" },
43
+ { name: "asset", type: "address" }
44
+ ],
45
+ outputs: [{ name: "", type: "uint256" }]
46
+ }
47
+ ];
48
+ var DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI = [
49
+ {
50
+ name: "voucherClaimed",
51
+ type: "function",
52
+ stateMutability: "view",
53
+ inputs: [
54
+ { name: "voucherId", type: "bytes32" },
55
+ { name: "nonce", type: "uint256" }
56
+ ],
57
+ outputs: [{ name: "", type: "bool" }]
58
+ }
59
+ ];
60
+ var DEFERRED_ESCROW_CLAIM_VOUCHER_ABI = [
61
+ {
62
+ name: "claimVoucher",
63
+ type: "function",
64
+ stateMutability: "nonpayable",
65
+ inputs: [
66
+ {
67
+ name: "voucher",
68
+ type: "tuple",
69
+ components: [
70
+ { name: "id", type: "bytes32" },
71
+ { name: "buyer", type: "address" },
72
+ { name: "seller", type: "address" },
73
+ { name: "valueAggregate", type: "uint256" },
74
+ { name: "asset", type: "address" },
75
+ { name: "timestamp", type: "uint64" },
76
+ { name: "nonce", type: "uint256" },
77
+ { name: "escrow", type: "address" },
78
+ { name: "chainId", type: "uint256" }
79
+ ]
80
+ },
81
+ { name: "signature", type: "bytes" }
82
+ ],
83
+ outputs: []
84
+ }
85
+ ];
86
+ var DEFERRED_ESCROW_ABI = [
87
+ ...DEFERRED_ESCROW_GET_BALANCE_ABI,
88
+ ...DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
89
+ ...DEFERRED_ESCROW_CLAIM_VOUCHER_ABI
90
+ ];
91
+ var DeferredSchemeVerifier = class {
92
+ constructor(config) {
93
+ this.network = config.network;
94
+ this.chainId = getChainIdFromNetwork(config.network) || 1;
95
+ this.escrowAddress = config.escrowAddress;
96
+ this.domainName = config.domainName || "X402DeferredEscrow";
97
+ this.domainVersion = config.domainVersion || "1";
98
+ const chain = getChainById(this.chainId);
99
+ const rpcUrl = config.rpcUrl || getRpcUrl(this.chainId);
100
+ if (!chain || !rpcUrl) {
101
+ throw new Error(`Unsupported network: ${config.network}`);
102
+ }
103
+ this.publicClient = createPublicClient({
104
+ chain,
105
+ transport: http(rpcUrl)
106
+ });
107
+ }
108
+ /**
109
+ * Verify a deferred scheme payment voucher
110
+ */
111
+ async verify(payload, requirements) {
112
+ try {
113
+ const { voucher, signature } = payload;
114
+ if (!this.validateVoucher(voucher, requirements)) {
115
+ return {
116
+ isValid: false,
117
+ invalidReason: "Voucher fields invalid",
118
+ payer: null
119
+ };
120
+ }
121
+ const signer = await this.recoverSigner(voucher, signature);
122
+ if (!signer) {
123
+ return {
124
+ isValid: false,
125
+ invalidReason: "Invalid signature",
126
+ payer: null
127
+ };
128
+ }
129
+ if (signer.toLowerCase() !== voucher.buyer.toLowerCase()) {
130
+ return {
131
+ isValid: false,
132
+ invalidReason: `Signer does not match buyer. Recovered: ${signer}, Expected: ${voucher.buyer}`,
133
+ payer: null
134
+ };
135
+ }
136
+ const claimed = await this.isVoucherClaimed(
137
+ voucher.id,
138
+ BigInt(voucher.nonce)
139
+ );
140
+ if (claimed) {
141
+ return {
142
+ isValid: false,
143
+ invalidReason: "Voucher already claimed",
144
+ payer: null
145
+ };
146
+ }
147
+ const balance = await this.getEscrowBalance(
148
+ voucher.buyer,
149
+ voucher.seller,
150
+ voucher.asset
151
+ );
152
+ const valueAggregate = BigInt(voucher.valueAggregate);
153
+ if (balance < valueAggregate) {
154
+ return {
155
+ isValid: false,
156
+ invalidReason: "Insufficient escrow balance",
157
+ payer: null
158
+ };
159
+ }
160
+ return {
161
+ isValid: true,
162
+ invalidReason: null,
163
+ payer: voucher.buyer
164
+ };
165
+ } catch (error) {
166
+ return {
167
+ isValid: false,
168
+ invalidReason: error instanceof Error ? error.message : "Verification failed",
169
+ payer: null
170
+ };
171
+ }
172
+ }
173
+ /**
174
+ * Validate voucher fields against requirements
175
+ */
176
+ validateVoucher(voucher, requirements) {
177
+ if (voucher.escrow.toLowerCase() !== this.escrowAddress.toLowerCase()) {
178
+ return false;
179
+ }
180
+ if (BigInt(voucher.chainId) !== BigInt(this.chainId)) {
181
+ return false;
182
+ }
183
+ if (voucher.seller.toLowerCase() !== requirements.payTo.toLowerCase()) {
184
+ return false;
185
+ }
186
+ const valueAggregate = BigInt(voucher.valueAggregate);
187
+ const maxAmount = BigInt(requirements.maxAmountRequired);
188
+ if (valueAggregate > maxAmount) {
189
+ return false;
190
+ }
191
+ if (voucher.asset.toLowerCase() !== requirements.asset.toLowerCase()) {
192
+ return false;
193
+ }
194
+ return true;
195
+ }
196
+ /**
197
+ * Recover signer from EIP-712 typed data signature
198
+ */
199
+ async recoverSigner(voucher, signature) {
200
+ try {
201
+ const domain = this.getEIP712Domain();
202
+ const message = {
203
+ id: voucher.id,
204
+ buyer: voucher.buyer,
205
+ seller: voucher.seller,
206
+ valueAggregate: BigInt(voucher.valueAggregate),
207
+ asset: voucher.asset,
208
+ timestamp: BigInt(voucher.timestamp),
209
+ nonce: BigInt(voucher.nonce),
210
+ escrow: voucher.escrow,
211
+ chainId: BigInt(voucher.chainId)
212
+ };
213
+ const recoveredAddress = await recoverTypedDataAddress({
214
+ domain,
215
+ types: VOUCHER_TYPES,
216
+ primaryType: "Voucher",
217
+ message,
218
+ signature
219
+ });
220
+ return recoveredAddress;
221
+ } catch {
222
+ return null;
223
+ }
224
+ }
225
+ /**
226
+ * Get EIP-712 domain for escrow contract
227
+ */
228
+ getEIP712Domain() {
229
+ return {
230
+ name: this.domainName,
231
+ version: this.domainVersion,
232
+ chainId: this.chainId,
233
+ verifyingContract: this.escrowAddress
234
+ };
235
+ }
236
+ /**
237
+ * Check if voucher has been claimed
238
+ */
239
+ async isVoucherClaimed(voucherId, nonce) {
240
+ try {
241
+ const claimed = await this.publicClient.readContract({
242
+ address: this.escrowAddress,
243
+ abi: DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
244
+ functionName: "voucherClaimed",
245
+ args: [voucherId, nonce]
246
+ });
247
+ return claimed;
248
+ } catch {
249
+ return false;
250
+ }
251
+ }
252
+ /**
253
+ * Get available escrow balance
254
+ */
255
+ async getEscrowBalance(buyer, seller, asset) {
256
+ try {
257
+ const balance = await this.publicClient.readContract({
258
+ address: this.escrowAddress,
259
+ abi: DEFERRED_ESCROW_GET_BALANCE_ABI,
260
+ functionName: "getAvailableBalance",
261
+ args: [buyer, seller, asset]
262
+ });
263
+ return balance;
264
+ } catch {
265
+ return 0n;
266
+ }
267
+ }
268
+ /**
269
+ * Get network name
270
+ */
271
+ getNetwork() {
272
+ return this.network;
273
+ }
274
+ /**
275
+ * Get chain ID
276
+ */
277
+ getChainId() {
278
+ return this.chainId;
279
+ }
280
+ /**
281
+ * Get escrow address
282
+ */
283
+ getEscrowAddress() {
284
+ return this.escrowAddress;
285
+ }
286
+ };
287
+ function parseSignature(signature) {
288
+ const sig = signature.slice(2);
289
+ const r = `0x${sig.slice(0, 64)}`;
290
+ const s = `0x${sig.slice(64, 128)}`;
291
+ const v = parseInt(sig.slice(128, 130), 16);
292
+ return { v, r, s };
293
+ }
294
+ function createEIP712Domain(chainId, escrowAddress, domainName, domainVersion) {
295
+ return {
296
+ name: domainName || "X402DeferredEscrow",
297
+ version: domainVersion || "1",
298
+ chainId,
299
+ verifyingContract: escrowAddress
300
+ };
301
+ }
302
+ function generateVoucherId() {
303
+ const bytes = new Uint8Array(32);
304
+ crypto.getRandomValues(bytes);
305
+ return `0x${Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("")}`;
306
+ }
307
+ function createVoucherMessage(id, buyer, seller, valueAggregate, asset, timestamp, nonce, escrow, chainId) {
308
+ return {
309
+ id,
310
+ buyer,
311
+ seller,
312
+ valueAggregate: BigInt(valueAggregate),
313
+ asset,
314
+ timestamp: BigInt(timestamp),
315
+ nonce: BigInt(nonce),
316
+ escrow,
317
+ chainId: BigInt(chainId)
318
+ };
319
+ }
320
+ function createVoucherTuple(voucher) {
321
+ return {
322
+ id: voucher.id,
323
+ buyer: voucher.buyer,
324
+ seller: voucher.seller,
325
+ valueAggregate: BigInt(voucher.valueAggregate),
326
+ asset: voucher.asset,
327
+ timestamp: BigInt(voucher.timestamp),
328
+ nonce: BigInt(voucher.nonce),
329
+ escrow: voucher.escrow,
330
+ chainId: BigInt(voucher.chainId)
331
+ };
332
+ }
333
+ export {
334
+ DEFERRED_ESCROW_ABI,
335
+ DEFERRED_ESCROW_CLAIM_VOUCHER_ABI,
336
+ DEFERRED_ESCROW_GET_BALANCE_ABI,
337
+ DEFERRED_ESCROW_VOUCHER_CLAIMED_ABI,
338
+ DeferredSchemeVerifier,
339
+ ERC20_BALANCE_ABI,
340
+ VOUCHER_TYPES,
341
+ VOUCHER_TYPE_DEF,
342
+ createEIP712Domain,
343
+ createVoucherMessage,
344
+ createVoucherTuple,
345
+ generateVoucherId,
346
+ parseSignature
347
+ };