@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.
- package/dist/index.js +73 -35
- 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
|
-
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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
|
-
|
|
412
|
-
|
|
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) =>
|
|
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
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|
|
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 =
|
|
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
|
|
852
|
-
zeroAddress
|
|
889
|
+
isAddressEqual as isAddressEqual5,
|
|
890
|
+
zeroAddress as zeroAddress3
|
|
853
891
|
} from "viem";
|
|
854
892
|
async function buildTokenInfo(params, clients) {
|
|
855
|
-
const sameToken =
|
|
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 ??
|
|
1006
|
+
const processorAddress = firstWebhook?.webhookAddress ?? zeroAddress3;
|
|
969
1007
|
const processorMemo = firstWebhook?.memo ?? "";
|
|
970
1008
|
const tokenInfo = await extractTokenInfo(
|
|
971
1009
|
paymentInfo,
|