@yodlpay/payment-decoder 1.3.3 → 1.3.4

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.d.ts CHANGED
@@ -41,10 +41,15 @@ interface BridgeInfo extends SwapInfo {
41
41
  destinationTxHash: Hex;
42
42
  tokenOutAmountGross: bigint;
43
43
  }
44
+ interface InferredSwapInfo extends Omit<SwapInfo, "service"> {
45
+ service?: undefined;
46
+ }
44
47
  type PaymentInfo = (PaymentEvent & {
45
48
  type: "direct";
46
49
  }) | (PaymentEvent & SwapInfo & {
47
50
  type: "swap";
51
+ }) | (PaymentEvent & InferredSwapInfo & {
52
+ type: "swap";
48
53
  }) | (PaymentEvent & BridgeInfo & {
49
54
  type: "bridge";
50
55
  });
package/dist/index.js CHANGED
@@ -355,6 +355,57 @@ function findInputTransfer(transfers, sender) {
355
355
  if (!result) return void 0;
356
356
  return { token: result.token, amount: result.amount };
357
357
  }
358
+ function inferSwapFromTransfers(logs, sender, yodlToken) {
359
+ const transfers = extractTokenTransfers(logs);
360
+ const outgoingDifferentToken = transfers.filter(
361
+ (t) => isAddressEqual(t.from, sender) && !isAddressEqual(t.token, yodlToken)
362
+ );
363
+ if (outgoingDifferentToken.length === 0) return void 0;
364
+ const byToken = /* @__PURE__ */ new Map();
365
+ for (const t of outgoingDifferentToken) {
366
+ const key = getAddress(t.token);
367
+ const existing = byToken.get(key);
368
+ if (existing) {
369
+ existing.gross += t.amount;
370
+ } else {
371
+ byToken.set(key, { token: t.token, gross: t.amount, refund: 0n });
372
+ }
373
+ }
374
+ const incomingNonYodl = transfers.filter(
375
+ (t) => isAddressEqual(t.to, sender) && !isAddressEqual(t.token, yodlToken)
376
+ );
377
+ for (const t of incomingNonYodl) {
378
+ const key = getAddress(t.token);
379
+ const existing = byToken.get(key);
380
+ if (existing) {
381
+ existing.refund += t.amount;
382
+ }
383
+ }
384
+ let tokenIn;
385
+ let tokenInAmount = 0n;
386
+ for (const { token, gross, refund } of byToken.values()) {
387
+ const net = gross - refund;
388
+ if (net > tokenInAmount) {
389
+ tokenIn = token;
390
+ tokenInAmount = net;
391
+ }
392
+ }
393
+ if (!tokenIn || tokenInAmount <= 0n) return void 0;
394
+ const incomingYodlToken = transfers.filter(
395
+ (t) => isAddressEqual(t.to, sender) && isAddressEqual(t.token, yodlToken)
396
+ );
397
+ const tokenOutAmount = incomingYodlToken.reduce(
398
+ (sum, t) => sum + t.amount,
399
+ 0n
400
+ );
401
+ if (tokenOutAmount === 0n) return void 0;
402
+ return {
403
+ tokenIn,
404
+ tokenOut: yodlToken,
405
+ tokenInAmount,
406
+ tokenOutAmount
407
+ };
408
+ }
358
409
  function toBlockTimestamp(block) {
359
410
  return new Date(Number(block.timestamp) * 1e3);
360
411
  }
@@ -371,9 +422,14 @@ function buildPaymentEvent(yodlEvent, webhooks, blockTimestamp, senderOverride)
371
422
  import { decodeFunctionData, toFunctionSelector } from "viem";
372
423
 
373
424
  // src/validation.ts
374
- import { chains } from "@yodlpay/tokenlists";
375
425
  import { isAddress, isHex } from "viem";
376
426
  import { z as z3 } from "zod";
427
+
428
+ // src/chains.ts
429
+ import { chains as allChains } from "@yodlpay/tokenlists";
430
+ var chains = allChains.filter((c) => !c.testnet);
431
+
432
+ // src/validation.ts
377
433
  var validChainIds = chains.map((c) => c.id);
378
434
  var txHashSchema = z3.string().regex(/^0x[a-fA-F0-9]{64}$/, "Invalid transaction hash").transform((val) => val);
379
435
  var chainIdSchema = z3.coerce.number().int().refine((id) => validChainIds.includes(id), {
@@ -432,7 +488,6 @@ import {
432
488
  import { entryPoint08Address } from "viem/account-abstraction";
433
489
 
434
490
  // src/clients.ts
435
- import { chains as chains2 } from "@yodlpay/tokenlists";
436
491
  import {
437
492
  createPublicClient,
438
493
  http
@@ -445,7 +500,7 @@ var rpcOverrides = {
445
500
  };
446
501
  function createClients() {
447
502
  const clients = {};
448
- for (const chain of chains2) {
503
+ for (const chain of chains) {
449
504
  clients[chain.id] = createPublicClient({
450
505
  chain,
451
506
  transport: http(rpcOverrides[chain.id])
@@ -479,11 +534,9 @@ async function detectChain(hash, clients) {
479
534
  }
480
535
 
481
536
  // src/relay-client.ts
482
- var MAINNET_RELAY_API = "https://api.relay.link";
483
- var TESTNET_RELAY_API = "https://api.testnets.relay.link";
484
- async function getRelayRequests(params, options) {
485
- const baseUrl = options?.testnet ? TESTNET_RELAY_API : MAINNET_RELAY_API;
486
- const url = new URL(`${baseUrl}/requests/v2`);
537
+ var RELAY_API = "https://api.relay.link";
538
+ async function getRelayRequests(params) {
539
+ const url = new URL(`${RELAY_API}/requests/v2`);
487
540
  for (const [key, value] of Object.entries(params)) {
488
541
  if (value !== void 0) {
489
542
  url.searchParams.set(key, String(value));
@@ -816,6 +869,14 @@ async function decodePayment(hash, chainId2, clients, cachedReceipt) {
816
869
  fillReceipt: receipt
817
870
  });
818
871
  if (bridgeResult2) return bridgeResult2;
872
+ const inferredSwap = inferSwapFromTransfers(
873
+ swapLogs,
874
+ yodlEvent.sender,
875
+ yodlEvent.token
876
+ );
877
+ if (inferredSwap) {
878
+ return { type: "swap", ...paymentEvent, ...inferredSwap };
879
+ }
819
880
  return { type: "direct", ...paymentEvent };
820
881
  }
821
882
  const bridgeResult = await tryDecodeBridge(hash, clients);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yodlpay/payment-decoder",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "Decode Yodl payment hashes into structured payment data",
5
5
  "keywords": [
6
6
  "yodl",