@yodlpay/payment-decoder 1.3.6 → 1.3.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.
Files changed (2) hide show
  1. package/dist/index.js +73 -35
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ import { tokenlist } from "@yodlpay/tokenlists";
30
30
  import {
31
31
  erc20Abi as erc20Abi2,
32
32
  getAddress,
33
- isAddressEqual,
33
+ isAddressEqual as isAddressEqual2,
34
34
  parseEventLogs
35
35
  } from "viem";
36
36
 
@@ -48,9 +48,17 @@ import {
48
48
  erc20Abi,
49
49
  getContract,
50
50
  hexToString,
51
- stringify
51
+ isAddressEqual,
52
+ stringify,
53
+ zeroAddress
52
54
  } from "viem";
53
55
  import { z } from "zod";
56
+
57
+ // src/chains.ts
58
+ import { chains as allChains } from "@yodlpay/tokenlists";
59
+ var chains = allChains.filter((c) => !c.testnet);
60
+
61
+ // src/utils.ts
54
62
  function decodeMemo(memo) {
55
63
  if (!memo || memo === "0x") return "";
56
64
  try {
@@ -62,6 +70,19 @@ function decodeMemo(memo) {
62
70
  var erc20String = z.string().max(64).transform((s) => s.replace(/\p{Cc}/gu, ""));
63
71
  var erc20Decimals = z.number().int().nonnegative().max(36);
64
72
  async function resolveToken(address, chainId2, client) {
73
+ if (isAddressEqual(address, zeroAddress)) {
74
+ const chain = chains.find((c) => c.id === chainId2);
75
+ if (!chain) {
76
+ throw new Error(`Native token requested for unknown chainId ${chainId2}`);
77
+ }
78
+ return {
79
+ chainId: chainId2,
80
+ address,
81
+ name: chain.nativeCurrency.name,
82
+ symbol: chain.nativeCurrency.symbol,
83
+ decimals: chain.nativeCurrency.decimals
84
+ };
85
+ }
65
86
  try {
66
87
  return getTokenByAddress(address, chainId2);
67
88
  } catch {
@@ -85,7 +106,7 @@ async function resolveToken(address, chainId2, client) {
85
106
  function decodeYodlFromLogs(logs, routerAddress) {
86
107
  const parsed = parseEventLogs({
87
108
  abi: yodlAbi,
88
- logs: logs.filter((l) => isAddressEqual(l.address, routerAddress)),
109
+ logs: logs.filter((l) => isAddressEqual2(l.address, routerAddress)),
89
110
  eventName: "Yodl",
90
111
  strict: true
91
112
  });
@@ -133,7 +154,7 @@ function extractTokenTransfers(logs) {
133
154
  });
134
155
  }
135
156
  function isKnownToken(address) {
136
- return tokenlist.some((t) => isAddressEqual(t.address, address));
157
+ return tokenlist.some((t) => isAddressEqual2(t.address, address));
137
158
  }
138
159
  function transferSignature(t) {
139
160
  return `${getAddress(t.from)}:${getAddress(t.to)}:${t.amount}`;
@@ -180,7 +201,7 @@ function detectMirrorTokens(allTransfers) {
180
201
  return mirrors;
181
202
  }
182
203
  function findInputTransfer(transfers, sender) {
183
- const fromSender = transfers.filter((t) => isAddressEqual(t.from, sender));
204
+ const fromSender = transfers.filter((t) => isAddressEqual2(t.from, sender));
184
205
  if (fromSender.length === 0) return void 0;
185
206
  const maxAmount = fromSender.reduce(
186
207
  (max, t) => t.amount > max ? t.amount : max,
@@ -201,7 +222,7 @@ function findInputTransfer(transfers, sender) {
201
222
  function inferSwapFromTransfers(logs, sender, yodlToken) {
202
223
  const transfers = extractTokenTransfers(logs);
203
224
  const outgoingDifferentToken = transfers.filter(
204
- (t) => isAddressEqual(t.from, sender) && !isAddressEqual(t.token, yodlToken)
225
+ (t) => isAddressEqual2(t.from, sender) && !isAddressEqual2(t.token, yodlToken)
205
226
  );
206
227
  if (outgoingDifferentToken.length === 0) return void 0;
207
228
  const byToken = /* @__PURE__ */ new Map();
@@ -215,7 +236,7 @@ function inferSwapFromTransfers(logs, sender, yodlToken) {
215
236
  }
216
237
  }
217
238
  const incomingNonYodl = transfers.filter(
218
- (t) => isAddressEqual(t.to, sender) && !isAddressEqual(t.token, yodlToken)
239
+ (t) => isAddressEqual2(t.to, sender) && !isAddressEqual2(t.token, yodlToken)
219
240
  );
220
241
  for (const t of incomingNonYodl) {
221
242
  const key = getAddress(t.token);
@@ -235,7 +256,7 @@ function inferSwapFromTransfers(logs, sender, yodlToken) {
235
256
  }
236
257
  if (!tokenIn || tokenInAmount <= 0n) return void 0;
237
258
  const incomingYodlToken = transfers.filter(
238
- (t) => isAddressEqual(t.to, sender) && isAddressEqual(t.token, yodlToken)
259
+ (t) => isAddressEqual2(t.to, sender) && isAddressEqual2(t.token, yodlToken)
239
260
  );
240
261
  const tokenOutAmount = incomingYodlToken.reduce(
241
262
  (sum, t) => sum + t.amount,
@@ -267,12 +288,6 @@ import { decodeFunctionData, toFunctionSelector } from "viem";
267
288
  // src/validation.ts
268
289
  import { isAddress, isHash, isHex } from "viem";
269
290
  import { z as z2 } from "zod";
270
-
271
- // src/chains.ts
272
- import { chains as allChains } from "@yodlpay/tokenlists";
273
- var chains = allChains.filter((c) => !c.testnet);
274
-
275
- // src/validation.ts
276
291
  var validChainIds = chains.map((c) => c.id);
277
292
  var txHashSchema = z2.string().refine((val) => isHash(val), "Invalid transaction hash");
278
293
  var chainIdSchema = z2.coerce.number().int().refine((id) => validChainIds.includes(id), {
@@ -408,8 +423,10 @@ async function fetchAcrossDepositByTx(hash) {
408
423
  // src/bridges/relay-bridge.ts
409
424
  import { getRouter } from "@yodlpay/tokenlists";
410
425
  import {
411
- isAddressEqual as isAddressEqual2,
412
- parseEventLogs as parseEventLogs2
426
+ isAddress as isAddress2,
427
+ isAddressEqual as isAddressEqual3,
428
+ parseEventLogs as parseEventLogs2,
429
+ zeroAddress as zeroAddress2
413
430
  } from "viem";
414
431
  import { entryPoint08Abi, entryPoint08Address } from "viem/account-abstraction";
415
432
 
@@ -502,7 +519,7 @@ function extractSenderFromSource(sourceReceipt) {
502
519
  const userOps = parseEventLogs2({
503
520
  abi: entryPoint08Abi,
504
521
  logs: sourceReceipt.logs.filter(
505
- (l) => isAddressEqual2(l.address, entryPoint08Address)
522
+ (l) => isAddressEqual3(l.address, entryPoint08Address)
506
523
  ),
507
524
  eventName: "UserOperationEvent"
508
525
  });
@@ -552,12 +569,15 @@ function parseRelayResponse(request) {
552
569
  if (!inTx?.hash || !inTx?.chainId || !outTx?.hash || !outTx?.chainId) {
553
570
  throw new NoBridgeFoundError();
554
571
  }
572
+ const rawInputToken = data?.metadata?.currencyIn?.currency?.address;
573
+ const inputToken = rawInputToken && isAddress2(rawInputToken) ? rawInputToken : void 0;
555
574
  return {
556
575
  sourceChainId: inTx.chainId,
557
576
  sourceTxHash: inTx.hash,
558
577
  destinationChainId: outTx.chainId,
559
578
  destinationTxHash: outTx.hash,
560
- inputAmountGross: BigInt(data?.metadata?.currencyIn?.amount ?? 0)
579
+ inputAmountGross: BigInt(data?.metadata?.currencyIn?.amount ?? 0),
580
+ inputToken
561
581
  };
562
582
  }
563
583
  async function decodeRelayBridgePayment(hash, clients, options = {}) {
@@ -567,7 +587,8 @@ async function decodeRelayBridgePayment(hash, clients, options = {}) {
567
587
  sourceTxHash,
568
588
  destinationChainId,
569
589
  destinationTxHash,
570
- inputAmountGross
590
+ inputAmountGross,
591
+ inputToken
571
592
  } = parseRelayResponse(request);
572
593
  const destProvider = clients[destinationChainId];
573
594
  const sourceProvider = clients[sourceChainId];
@@ -593,16 +614,33 @@ async function decodeRelayBridgePayment(hash, clients, options = {}) {
593
614
  destProvider.getBlock({ blockNumber: destReceipt.blockNumber }),
594
615
  destProvider.getTransaction({ hash: destinationTxHash })
595
616
  ]);
596
- const tokens = await resolveBridgeTokens(
597
- sourceReceipt,
598
- destReceipt,
599
- yodlEvent,
600
- sender,
601
- inputAmountGross,
602
- sourceChainId,
603
- destinationChainId,
604
- clients
605
- );
617
+ let tokens;
618
+ try {
619
+ tokens = await resolveBridgeTokens(
620
+ sourceReceipt,
621
+ destReceipt,
622
+ yodlEvent,
623
+ sender,
624
+ inputAmountGross,
625
+ sourceChainId,
626
+ destinationChainId,
627
+ clients
628
+ );
629
+ } catch (error) {
630
+ if (error instanceof ExpectedDecodeError && inputToken && isAddressEqual3(inputToken, zeroAddress2) && inputAmountGross > 0n) {
631
+ const swapEvent = decodeSwapFromLogs(destReceipt.logs);
632
+ const tokenOutAmountGross = swapEvent ? swapEvent.tokenOutAmount : yodlEvent.amount;
633
+ tokens = {
634
+ tokenIn: inputToken,
635
+ tokenInAmount: inputAmountGross,
636
+ tokenOut: yodlEvent.token,
637
+ tokenOutAmount: yodlEvent.amount,
638
+ tokenOutAmountGross
639
+ };
640
+ } else {
641
+ throw error;
642
+ }
643
+ }
606
644
  const bridge = {
607
645
  sourceChainId,
608
646
  sourceTxHash,
@@ -777,7 +815,7 @@ async function decodeBridgePayment(hash, clients, options = {}) {
777
815
 
778
816
  // src/core/payment-decoder.ts
779
817
  import { getRouter as getRouter3 } from "@yodlpay/tokenlists";
780
- import { isAddressEqual as isAddressEqual3 } from "viem";
818
+ import { isAddressEqual as isAddressEqual4 } from "viem";
781
819
  async function tryDecodeBridge(hash, clients, options = {}) {
782
820
  try {
783
821
  return await decodeBridgePayment(hash, clients, options);
@@ -809,7 +847,7 @@ async function decodePayment(hash, chainId2, clients, cachedReceipt) {
809
847
  return { type: "swap", ...paymentEvent2, ...swapEvent };
810
848
  }
811
849
  const effectiveSender = extractSenderFromSource(receipt);
812
- const isSameChainPayment = isAddressEqual3(
850
+ const isSameChainPayment = isAddressEqual4(
813
851
  effectiveSender,
814
852
  yodlEvent.sender
815
853
  );
@@ -848,11 +886,11 @@ async function decodePayment(hash, chainId2, clients, cachedReceipt) {
848
886
  // src/core/yodl-payment.ts
849
887
  import {
850
888
  formatUnits,
851
- isAddressEqual as isAddressEqual4,
852
- zeroAddress
889
+ isAddressEqual as isAddressEqual5,
890
+ zeroAddress as zeroAddress3
853
891
  } from "viem";
854
892
  async function buildTokenInfo(params, clients) {
855
- const sameToken = isAddressEqual4(params.tokenIn, params.tokenOut) && params.inChainId === params.outChainId;
893
+ const sameToken = isAddressEqual5(params.tokenIn, params.tokenOut) && params.inChainId === params.outChainId;
856
894
  const [inToken, outToken] = sameToken ? await resolveToken(
857
895
  params.tokenIn,
858
896
  params.inChainId,
@@ -965,7 +1003,7 @@ async function decodeYodlPayment(txHash2, chainId2, clients, cachedReceipt) {
965
1003
  cachedReceipt
966
1004
  );
967
1005
  const firstWebhook = paymentInfo.webhooks[0];
968
- const processorAddress = firstWebhook?.webhookAddress ?? zeroAddress;
1006
+ const processorAddress = firstWebhook?.webhookAddress ?? zeroAddress3;
969
1007
  const processorMemo = firstWebhook?.memo ?? "";
970
1008
  const tokenInfo = await extractTokenInfo(
971
1009
  paymentInfo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yodlpay/payment-decoder",
3
- "version": "1.3.6",
3
+ "version": "1.3.7",
4
4
  "description": "Decode Yodl payment hashes into structured payment data",
5
5
  "keywords": [
6
6
  "yodl",