@t402/cosmos 2.4.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.
Files changed (38) hide show
  1. package/README.md +175 -0
  2. package/dist/cjs/exact-direct/client/index.d.ts +50 -0
  3. package/dist/cjs/exact-direct/client/index.js +122 -0
  4. package/dist/cjs/exact-direct/client/index.js.map +1 -0
  5. package/dist/cjs/exact-direct/facilitator/index.d.ts +70 -0
  6. package/dist/cjs/exact-direct/facilitator/index.js +300 -0
  7. package/dist/cjs/exact-direct/facilitator/index.js.map +1 -0
  8. package/dist/cjs/exact-direct/server/index.d.ts +87 -0
  9. package/dist/cjs/exact-direct/server/index.js +241 -0
  10. package/dist/cjs/exact-direct/server/index.js.map +1 -0
  11. package/dist/cjs/index.d.ts +178 -0
  12. package/dist/cjs/index.js +619 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/types-CgseoctH.d.ts +155 -0
  15. package/dist/esm/chunk-2UTEGIZ2.mjs +101 -0
  16. package/dist/esm/chunk-2UTEGIZ2.mjs.map +1 -0
  17. package/dist/esm/chunk-57DBLYIR.mjs +58 -0
  18. package/dist/esm/chunk-57DBLYIR.mjs.map +1 -0
  19. package/dist/esm/chunk-JV6LXL2U.mjs +158 -0
  20. package/dist/esm/chunk-JV6LXL2U.mjs.map +1 -0
  21. package/dist/esm/chunk-QP5VO3IO.mjs +68 -0
  22. package/dist/esm/chunk-QP5VO3IO.mjs.map +1 -0
  23. package/dist/esm/chunk-XUMAS5DJ.mjs +223 -0
  24. package/dist/esm/chunk-XUMAS5DJ.mjs.map +1 -0
  25. package/dist/esm/exact-direct/client/index.d.mts +50 -0
  26. package/dist/esm/exact-direct/client/index.mjs +8 -0
  27. package/dist/esm/exact-direct/client/index.mjs.map +1 -0
  28. package/dist/esm/exact-direct/facilitator/index.d.mts +70 -0
  29. package/dist/esm/exact-direct/facilitator/index.mjs +9 -0
  30. package/dist/esm/exact-direct/facilitator/index.mjs.map +1 -0
  31. package/dist/esm/exact-direct/server/index.d.mts +87 -0
  32. package/dist/esm/exact-direct/server/index.mjs +9 -0
  33. package/dist/esm/exact-direct/server/index.mjs.map +1 -0
  34. package/dist/esm/index.d.mts +178 -0
  35. package/dist/esm/index.mjs +83 -0
  36. package/dist/esm/index.mjs.map +1 -0
  37. package/dist/esm/types-CgseoctH.d.mts +155 -0
  38. package/package.json +96 -0
@@ -0,0 +1,619 @@
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 src_exports = {};
22
+ __export(src_exports, {
23
+ COSMOS_CAIP2_NAMESPACE: () => COSMOS_CAIP2_NAMESPACE,
24
+ COSMOS_NETWORKS: () => COSMOS_NETWORKS,
25
+ DEFAULT_FEE_AMOUNT: () => DEFAULT_FEE_AMOUNT,
26
+ DEFAULT_GAS_LIMIT: () => DEFAULT_GAS_LIMIT,
27
+ DEFAULT_GAS_PRICE: () => DEFAULT_GAS_PRICE,
28
+ ExactDirectCosmosClient: () => ExactDirectCosmosClient,
29
+ ExactDirectCosmosFacilitator: () => ExactDirectCosmosFacilitator,
30
+ ExactDirectCosmosServer: () => ExactDirectCosmosServer,
31
+ MAX_TRANSACTION_AGE: () => MAX_TRANSACTION_AGE,
32
+ MSG_TYPE_SEND: () => MSG_TYPE_SEND,
33
+ NETWORK_REST_ENDPOINTS: () => NETWORK_REST_ENDPOINTS,
34
+ NETWORK_RPC_ENDPOINTS: () => NETWORK_RPC_ENDPOINTS,
35
+ NOBLE_BECH32_PREFIX: () => NOBLE_BECH32_PREFIX,
36
+ NOBLE_MAINNET_CAIP2: () => NOBLE_MAINNET_CAIP2,
37
+ NOBLE_MAINNET_REST: () => NOBLE_MAINNET_REST,
38
+ NOBLE_MAINNET_RPC: () => NOBLE_MAINNET_RPC,
39
+ NOBLE_TESTNET_CAIP2: () => NOBLE_TESTNET_CAIP2,
40
+ NOBLE_TESTNET_REST: () => NOBLE_TESTNET_REST,
41
+ NOBLE_TESTNET_RPC: () => NOBLE_TESTNET_RPC,
42
+ SCHEME_EXACT_DIRECT: () => SCHEME_EXACT_DIRECT,
43
+ TOKEN_REGISTRY: () => TOKEN_REGISTRY,
44
+ USDC_DENOM: () => USDC_DENOM,
45
+ extractNetworkId: () => extractNetworkId,
46
+ formatAmount: () => formatAmount,
47
+ getDefaultToken: () => getDefaultToken,
48
+ getNetworkTokens: () => getNetworkTokens,
49
+ getRestEndpoint: () => getRestEndpoint,
50
+ getRpcEndpoint: () => getRpcEndpoint,
51
+ getSupportedNetworks: () => getSupportedNetworks,
52
+ getTokenByDenom: () => getTokenByDenom,
53
+ getTokenConfig: () => getTokenConfig,
54
+ isNetworkSupported: () => isNetworkSupported,
55
+ isValidAddress: () => isValidAddress,
56
+ normalizeNetwork: () => normalizeNetwork,
57
+ toAtomicUnits: () => toAtomicUnits
58
+ });
59
+ module.exports = __toCommonJS(src_exports);
60
+
61
+ // src/constants.ts
62
+ var NOBLE_MAINNET_CAIP2 = "cosmos:noble-1";
63
+ var NOBLE_TESTNET_CAIP2 = "cosmos:grand-1";
64
+ var COSMOS_NETWORKS = [NOBLE_MAINNET_CAIP2, NOBLE_TESTNET_CAIP2];
65
+ var NOBLE_MAINNET_RPC = "https://noble-rpc.polkachu.com";
66
+ var NOBLE_TESTNET_RPC = "https://rpc.testnet.noble.strange.love";
67
+ var NOBLE_MAINNET_REST = "https://noble-api.polkachu.com";
68
+ var NOBLE_TESTNET_REST = "https://api.testnet.noble.strange.love";
69
+ var NETWORK_RPC_ENDPOINTS = {
70
+ [NOBLE_MAINNET_CAIP2]: NOBLE_MAINNET_RPC,
71
+ [NOBLE_TESTNET_CAIP2]: NOBLE_TESTNET_RPC
72
+ };
73
+ var NETWORK_REST_ENDPOINTS = {
74
+ [NOBLE_MAINNET_CAIP2]: NOBLE_MAINNET_REST,
75
+ [NOBLE_TESTNET_CAIP2]: NOBLE_TESTNET_REST
76
+ };
77
+ var NOBLE_BECH32_PREFIX = "noble";
78
+ var USDC_DENOM = "uusdc";
79
+ var DEFAULT_GAS_LIMIT = 2e5;
80
+ var DEFAULT_GAS_PRICE = "0.025uusdc";
81
+ var DEFAULT_FEE_AMOUNT = "5000";
82
+ var MSG_TYPE_SEND = "/cosmos.bank.v1beta1.MsgSend";
83
+ var SCHEME_EXACT_DIRECT = "exact-direct";
84
+ var MAX_TRANSACTION_AGE = 5 * 60 * 1e3;
85
+ var COSMOS_CAIP2_NAMESPACE = "cosmos";
86
+
87
+ // src/tokens.ts
88
+ var TOKEN_REGISTRY = {
89
+ [NOBLE_MAINNET_CAIP2]: [
90
+ {
91
+ denom: USDC_DENOM,
92
+ symbol: "USDC",
93
+ name: "USD Coin",
94
+ decimals: 6,
95
+ priority: 1
96
+ }
97
+ ],
98
+ [NOBLE_TESTNET_CAIP2]: [
99
+ {
100
+ denom: USDC_DENOM,
101
+ symbol: "USDC",
102
+ name: "USD Coin (Testnet)",
103
+ decimals: 6,
104
+ priority: 1
105
+ }
106
+ ]
107
+ };
108
+ function getTokenConfig(network, symbol) {
109
+ const tokens = TOKEN_REGISTRY[network];
110
+ if (!tokens) return void 0;
111
+ return tokens.find((t) => t.symbol.toUpperCase() === symbol.toUpperCase());
112
+ }
113
+ function getTokenByDenom(network, denom) {
114
+ const tokens = TOKEN_REGISTRY[network];
115
+ if (!tokens) return void 0;
116
+ return tokens.find((t) => t.denom === denom);
117
+ }
118
+ function getDefaultToken(network) {
119
+ const tokens = TOKEN_REGISTRY[network];
120
+ if (!tokens || tokens.length === 0) return void 0;
121
+ return [...tokens].sort((a, b) => a.priority - b.priority)[0];
122
+ }
123
+ function getNetworkTokens(network) {
124
+ return TOKEN_REGISTRY[network] || [];
125
+ }
126
+ function isNetworkSupported(network) {
127
+ return network in TOKEN_REGISTRY;
128
+ }
129
+
130
+ // src/utils.ts
131
+ function normalizeNetwork(network) {
132
+ if (network.startsWith(`${COSMOS_CAIP2_NAMESPACE}:`)) {
133
+ return network;
134
+ }
135
+ return `${COSMOS_CAIP2_NAMESPACE}:${network}`;
136
+ }
137
+ function extractNetworkId(network) {
138
+ if (network.includes(":")) {
139
+ return network.split(":")[1];
140
+ }
141
+ return network;
142
+ }
143
+ function isValidAddress(address) {
144
+ if (!address || address.length < 10) {
145
+ return false;
146
+ }
147
+ return address.startsWith(`${NOBLE_BECH32_PREFIX}1`);
148
+ }
149
+ function getRpcEndpoint(network) {
150
+ const normalizedNetwork = normalizeNetwork(network);
151
+ return NETWORK_RPC_ENDPOINTS[normalizedNetwork] || NETWORK_RPC_ENDPOINTS["cosmos:noble-1"];
152
+ }
153
+ function getRestEndpoint(network) {
154
+ const normalizedNetwork = normalizeNetwork(network);
155
+ return NETWORK_REST_ENDPOINTS[normalizedNetwork] || NETWORK_REST_ENDPOINTS["cosmos:noble-1"];
156
+ }
157
+ function toAtomicUnits(decimalAmount, decimals) {
158
+ const amount = typeof decimalAmount === "string" ? parseFloat(decimalAmount) : decimalAmount;
159
+ if (isNaN(amount)) {
160
+ throw new Error(`Invalid amount: ${decimalAmount}`);
161
+ }
162
+ const multiplier = 10 ** decimals;
163
+ return BigInt(Math.floor(amount * multiplier));
164
+ }
165
+ function formatAmount(amount, decimals) {
166
+ const divisor = BigInt(10 ** decimals);
167
+ const whole = amount / divisor;
168
+ const remainder = amount % divisor;
169
+ const decimal = remainder.toString().padStart(decimals, "0").slice(0, 2);
170
+ return `${whole}.${decimal}`;
171
+ }
172
+ function getSupportedNetworks() {
173
+ return Object.keys(NETWORK_RPC_ENDPOINTS);
174
+ }
175
+
176
+ // src/exact-direct/client/scheme.ts
177
+ var ExactDirectCosmosClient = class {
178
+ /**
179
+ * Creates a new ExactDirectCosmosClient instance.
180
+ *
181
+ * @param signer - The Cosmos signer for client operations
182
+ * @param config - Optional configuration overrides
183
+ */
184
+ constructor(signer, config = {}) {
185
+ this.signer = signer;
186
+ this.config = config;
187
+ this.scheme = SCHEME_EXACT_DIRECT;
188
+ }
189
+ /**
190
+ * Creates a payment payload by executing the transfer.
191
+ *
192
+ * Unlike other schemes where the client creates a signed message for
193
+ * the facilitator to execute, the exact-direct scheme has the client
194
+ * execute the transfer directly. The transaction hash is then used
195
+ * as proof of payment.
196
+ *
197
+ * @param t402Version - The t402 protocol version
198
+ * @param paymentRequirements - The payment requirements
199
+ * @returns Promise resolving to a payment payload with transaction hash
200
+ */
201
+ async createPaymentPayload(t402Version, paymentRequirements) {
202
+ const network = normalizeNetwork(paymentRequirements.network);
203
+ if (!paymentRequirements.payTo) {
204
+ throw new Error("PayTo address is required");
205
+ }
206
+ if (!paymentRequirements.amount) {
207
+ throw new Error("Amount is required");
208
+ }
209
+ if (!isValidAddress(paymentRequirements.payTo)) {
210
+ throw new Error(`Invalid recipient address: ${paymentRequirements.payTo}`);
211
+ }
212
+ if (!isValidAddress(this.signer.address)) {
213
+ throw new Error(`Invalid sender address: ${this.signer.address}`);
214
+ }
215
+ const recipient = paymentRequirements.payTo;
216
+ const amount = paymentRequirements.amount;
217
+ const denom = paymentRequirements.extra?.denom || this.config.denom || USDC_DENOM;
218
+ const txHash = await this.signer.sendTokens(network, recipient, amount, denom);
219
+ const payload = {
220
+ txHash,
221
+ from: this.signer.address,
222
+ to: recipient,
223
+ amount,
224
+ denom
225
+ };
226
+ return {
227
+ t402Version,
228
+ payload
229
+ };
230
+ }
231
+ };
232
+
233
+ // src/exact-direct/server/scheme.ts
234
+ var ExactDirectCosmosServer = class {
235
+ constructor(config = {}) {
236
+ this.scheme = SCHEME_EXACT_DIRECT;
237
+ this.moneyParsers = [];
238
+ this.config = config;
239
+ }
240
+ /**
241
+ * Register a custom money parser in the parser chain.
242
+ * Multiple parsers can be registered - they will be tried in registration order.
243
+ * Each parser receives a decimal amount (e.g., 1.50 for $1.50).
244
+ * If a parser returns null, the next parser in the chain will be tried.
245
+ * The default parser is always the final fallback.
246
+ *
247
+ * @param parser - Custom function to convert amount to AssetAmount (or null to skip)
248
+ * @returns The server instance for chaining
249
+ */
250
+ registerMoneyParser(parser) {
251
+ this.moneyParsers.push(parser);
252
+ return this;
253
+ }
254
+ /**
255
+ * Parses a price into an asset amount.
256
+ * If price is already an AssetAmount, returns it directly.
257
+ * If price is Money (string | number), parses to decimal and tries custom parsers.
258
+ * Falls back to default conversion if all custom parsers return null.
259
+ *
260
+ * @param price - The price to parse
261
+ * @param network - The network to use
262
+ * @returns Promise that resolves to the parsed asset amount
263
+ */
264
+ async parsePrice(price, network) {
265
+ const normalizedNetwork = normalizeNetwork(network);
266
+ if (typeof price === "object" && price !== null && "amount" in price) {
267
+ if (!price.asset) {
268
+ throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);
269
+ }
270
+ return {
271
+ amount: price.amount,
272
+ asset: price.asset,
273
+ extra: price.extra || {}
274
+ };
275
+ }
276
+ const amount = this.parseMoneyToDecimal(price);
277
+ for (const parser of this.moneyParsers) {
278
+ const result = await parser(amount, normalizedNetwork);
279
+ if (result !== null) {
280
+ return result;
281
+ }
282
+ }
283
+ return this.defaultMoneyConversion(amount, normalizedNetwork);
284
+ }
285
+ /**
286
+ * Build payment requirements for this scheme/network combination.
287
+ *
288
+ * @param paymentRequirements - Base payment requirements with amount/asset already set
289
+ * @param supportedKind - The supported kind from facilitator's /supported endpoint
290
+ * @param extensionKeys - Extensions supported by the facilitator
291
+ * @returns Enhanced payment requirements ready to be sent to clients
292
+ */
293
+ async enhancePaymentRequirements(paymentRequirements, supportedKind, extensionKeys) {
294
+ void extensionKeys;
295
+ const extra = { ...paymentRequirements.extra };
296
+ const normalizedNetwork = normalizeNetwork(paymentRequirements.network);
297
+ const token = getDefaultToken(normalizedNetwork);
298
+ if (token) {
299
+ extra.bech32Prefix = NOBLE_BECH32_PREFIX;
300
+ extra.denom = token.denom;
301
+ }
302
+ if (supportedKind.extra?.assetSymbol) {
303
+ extra.assetSymbol = supportedKind.extra.assetSymbol;
304
+ }
305
+ if (supportedKind.extra?.assetDecimals) {
306
+ extra.assetDecimals = supportedKind.extra.assetDecimals;
307
+ }
308
+ if (supportedKind.extra?.assetDenom) {
309
+ extra.assetDenom = supportedKind.extra.assetDenom;
310
+ }
311
+ return {
312
+ ...paymentRequirements,
313
+ extra
314
+ };
315
+ }
316
+ /**
317
+ * Parse Money (string | number) to a decimal number.
318
+ * Handles formats like "$1.50", "1.50", 1.50, etc.
319
+ */
320
+ parseMoneyToDecimal(money) {
321
+ if (typeof money === "number") {
322
+ return money;
323
+ }
324
+ const cleanMoney = money.replace(/^\$/, "").trim();
325
+ const amount = parseFloat(cleanMoney);
326
+ if (isNaN(amount)) {
327
+ throw new Error(`Invalid money format: ${money}`);
328
+ }
329
+ return amount;
330
+ }
331
+ /**
332
+ * Default money conversion implementation.
333
+ * Converts decimal amount to the preferred token on the specified network.
334
+ */
335
+ defaultMoneyConversion(amount, network) {
336
+ const token = this.getDefaultAsset(network);
337
+ const tokenAmount = toAtomicUnits(amount, token.decimals);
338
+ return {
339
+ amount: tokenAmount.toString(),
340
+ asset: token.denom,
341
+ extra: {
342
+ symbol: token.symbol,
343
+ name: token.name,
344
+ decimals: token.decimals
345
+ }
346
+ };
347
+ }
348
+ /**
349
+ * Get the default asset info for a network.
350
+ * Priority: configured preferredToken > network default
351
+ */
352
+ getDefaultAsset(network) {
353
+ if (this.config.preferredToken) {
354
+ const preferred = getTokenConfig(network, this.config.preferredToken);
355
+ if (preferred) return preferred;
356
+ }
357
+ const defaultToken = getDefaultToken(network);
358
+ if (defaultToken) return defaultToken;
359
+ throw new Error(`No tokens configured for network ${network}`);
360
+ }
361
+ /**
362
+ * Get all supported networks
363
+ */
364
+ static getSupportedNetworks() {
365
+ return Object.keys(TOKEN_REGISTRY);
366
+ }
367
+ /**
368
+ * Check if a network is supported
369
+ */
370
+ static isNetworkSupported(network) {
371
+ return network in TOKEN_REGISTRY;
372
+ }
373
+ };
374
+
375
+ // src/exact-direct/facilitator/scheme.ts
376
+ var ExactDirectCosmosFacilitator = class {
377
+ constructor(signer, config) {
378
+ this.signer = signer;
379
+ this.scheme = SCHEME_EXACT_DIRECT;
380
+ this.caipFamily = `${COSMOS_CAIP2_NAMESPACE}:*`;
381
+ this.usedTxs = /* @__PURE__ */ new Map();
382
+ this.config = {
383
+ maxTransactionAge: config?.maxTransactionAge ?? MAX_TRANSACTION_AGE,
384
+ usedTxCacheDuration: config?.usedTxCacheDuration ?? 24 * 60 * 60 * 1e3
385
+ // 24 hours
386
+ };
387
+ this.startCleanupInterval();
388
+ }
389
+ /**
390
+ * Get extra data for a supported kind
391
+ */
392
+ getExtra(network) {
393
+ const token = getDefaultToken(network);
394
+ if (!token) {
395
+ return void 0;
396
+ }
397
+ return {
398
+ assetSymbol: token.symbol,
399
+ assetDecimals: token.decimals,
400
+ assetDenom: token.denom
401
+ };
402
+ }
403
+ /**
404
+ * Get signer addresses for a network
405
+ */
406
+ getSigners(network) {
407
+ return this.signer.getAddresses(network);
408
+ }
409
+ /**
410
+ * Verify a payment payload
411
+ */
412
+ async verify(payload, requirements) {
413
+ const network = normalizeNetwork(requirements.network);
414
+ if (payload.accepted.scheme !== SCHEME_EXACT_DIRECT) {
415
+ return {
416
+ isValid: false,
417
+ invalidReason: "invalid_scheme"
418
+ };
419
+ }
420
+ if (normalizeNetwork(payload.accepted.network) !== network) {
421
+ return {
422
+ isValid: false,
423
+ invalidReason: "network_mismatch"
424
+ };
425
+ }
426
+ const cosmosPayload = payload.payload;
427
+ if (!cosmosPayload.txHash) {
428
+ return {
429
+ isValid: false,
430
+ invalidReason: "missing_tx_hash"
431
+ };
432
+ }
433
+ if (!cosmosPayload.from || !isValidAddress(cosmosPayload.from)) {
434
+ return {
435
+ isValid: false,
436
+ invalidReason: "invalid_from_address"
437
+ };
438
+ }
439
+ if (this.isTxUsed(cosmosPayload.txHash)) {
440
+ return {
441
+ isValid: false,
442
+ invalidReason: "transaction_already_used",
443
+ payer: cosmosPayload.from
444
+ };
445
+ }
446
+ try {
447
+ const tx = await this.signer.queryTransaction(network, cosmosPayload.txHash);
448
+ if (tx.code !== 0) {
449
+ return {
450
+ isValid: false,
451
+ invalidReason: "transaction_failed",
452
+ payer: cosmosPayload.from
453
+ };
454
+ }
455
+ const msgSend = this.findMsgSend(tx.tx.body.messages);
456
+ if (!msgSend) {
457
+ return {
458
+ isValid: false,
459
+ invalidReason: "no_msg_send_found",
460
+ payer: cosmosPayload.from
461
+ };
462
+ }
463
+ if (msgSend.toAddress !== requirements.payTo) {
464
+ return {
465
+ isValid: false,
466
+ invalidReason: "wrong_recipient",
467
+ payer: cosmosPayload.from
468
+ };
469
+ }
470
+ if (msgSend.fromAddress !== cosmosPayload.from) {
471
+ return {
472
+ isValid: false,
473
+ invalidReason: "sender_mismatch",
474
+ payer: cosmosPayload.from
475
+ };
476
+ }
477
+ const expectedDenom = requirements.extra?.denom || requirements.asset;
478
+ const coin = this.getAmountByDenom(msgSend, expectedDenom);
479
+ if (!coin) {
480
+ return {
481
+ isValid: false,
482
+ invalidReason: "wrong_denomination",
483
+ payer: cosmosPayload.from
484
+ };
485
+ }
486
+ const txAmount = BigInt(coin.amount);
487
+ const requiredAmount = BigInt(requirements.amount);
488
+ if (txAmount < requiredAmount) {
489
+ return {
490
+ isValid: false,
491
+ invalidReason: "insufficient_amount",
492
+ payer: cosmosPayload.from
493
+ };
494
+ }
495
+ this.markTxUsed(cosmosPayload.txHash);
496
+ return {
497
+ isValid: true,
498
+ payer: cosmosPayload.from
499
+ };
500
+ } catch {
501
+ return {
502
+ isValid: false,
503
+ invalidReason: "transaction_not_found",
504
+ payer: cosmosPayload.from
505
+ };
506
+ }
507
+ }
508
+ /**
509
+ * Settle a payment - for exact-direct, the transfer is already complete
510
+ */
511
+ async settle(payload, requirements) {
512
+ const verifyResult = await this.verify(payload, requirements);
513
+ if (!verifyResult.isValid) {
514
+ return {
515
+ success: false,
516
+ errorReason: verifyResult.invalidReason || "verification_failed",
517
+ payer: verifyResult.payer,
518
+ transaction: "",
519
+ network: normalizeNetwork(requirements.network)
520
+ };
521
+ }
522
+ const cosmosPayload = payload.payload;
523
+ return {
524
+ success: true,
525
+ transaction: cosmosPayload.txHash,
526
+ network: normalizeNetwork(requirements.network),
527
+ payer: cosmosPayload.from
528
+ };
529
+ }
530
+ /**
531
+ * Find a MsgSend in transaction messages
532
+ */
533
+ findMsgSend(messages) {
534
+ for (const msg of messages) {
535
+ if (msg["@type"] === MSG_TYPE_SEND || !msg["@type"] && msg.fromAddress && msg.toAddress) {
536
+ return msg;
537
+ }
538
+ }
539
+ return null;
540
+ }
541
+ /**
542
+ * Get a specific coin amount from a MsgSend by denomination
543
+ */
544
+ getAmountByDenom(msg, denom) {
545
+ for (const coin of msg.amount) {
546
+ if (coin.denom === denom) {
547
+ return coin;
548
+ }
549
+ }
550
+ return null;
551
+ }
552
+ /**
553
+ * Check if a transaction has been used
554
+ */
555
+ isTxUsed(txHash) {
556
+ return this.usedTxs.has(txHash);
557
+ }
558
+ /**
559
+ * Mark a transaction as used
560
+ */
561
+ markTxUsed(txHash) {
562
+ this.usedTxs.set(txHash, Date.now());
563
+ }
564
+ /**
565
+ * Start the cleanup interval for used transactions
566
+ */
567
+ startCleanupInterval() {
568
+ setInterval(
569
+ () => {
570
+ const cutoff = Date.now() - this.config.usedTxCacheDuration;
571
+ for (const [txHash, usedAt] of this.usedTxs.entries()) {
572
+ if (usedAt < cutoff) {
573
+ this.usedTxs.delete(txHash);
574
+ }
575
+ }
576
+ },
577
+ 60 * 60 * 1e3
578
+ );
579
+ }
580
+ };
581
+ // Annotate the CommonJS export names for ESM import in node:
582
+ 0 && (module.exports = {
583
+ COSMOS_CAIP2_NAMESPACE,
584
+ COSMOS_NETWORKS,
585
+ DEFAULT_FEE_AMOUNT,
586
+ DEFAULT_GAS_LIMIT,
587
+ DEFAULT_GAS_PRICE,
588
+ ExactDirectCosmosClient,
589
+ ExactDirectCosmosFacilitator,
590
+ ExactDirectCosmosServer,
591
+ MAX_TRANSACTION_AGE,
592
+ MSG_TYPE_SEND,
593
+ NETWORK_REST_ENDPOINTS,
594
+ NETWORK_RPC_ENDPOINTS,
595
+ NOBLE_BECH32_PREFIX,
596
+ NOBLE_MAINNET_CAIP2,
597
+ NOBLE_MAINNET_REST,
598
+ NOBLE_MAINNET_RPC,
599
+ NOBLE_TESTNET_CAIP2,
600
+ NOBLE_TESTNET_REST,
601
+ NOBLE_TESTNET_RPC,
602
+ SCHEME_EXACT_DIRECT,
603
+ TOKEN_REGISTRY,
604
+ USDC_DENOM,
605
+ extractNetworkId,
606
+ formatAmount,
607
+ getDefaultToken,
608
+ getNetworkTokens,
609
+ getRestEndpoint,
610
+ getRpcEndpoint,
611
+ getSupportedNetworks,
612
+ getTokenByDenom,
613
+ getTokenConfig,
614
+ isNetworkSupported,
615
+ isValidAddress,
616
+ normalizeNetwork,
617
+ toAtomicUnits
618
+ });
619
+ //# sourceMappingURL=index.js.map