UNPKG

@0x/0x-parser

Version:

🧾 Designed for 0x integrators: This library parses 0x transactions on EVM blockchains into a format that is both user-friendly and easy to understand.

2 lines (1 loc) • 6.79 kB
import{parseUnits as Ce,formatUnits as ee,formatEther as he,multicall3Abi as Ae,decodeFunctionData as W}from"viem";import{bsc as I,base as v,mode as x,blast as N,linea as R,scroll as k,mantle as D,mainnet as O,polygon as U,arbitrum as B,unichain as H,optimism as P,avalanche as F,berachain as M,worldchain as Y}from"viem/chains";var V=[{inputs:[{components:[{internalType:"address",name:"recipient",type:"address"},{internalType:"contract IERC20",name:"buyToken",type:"address"},{internalType:"uint256",name:"minAmountOut",type:"uint256"}],internalType:"struct SettlerBase.AllowedSlippage",name:"slippage",type:"tuple"},{internalType:"bytes[]",name:"actions",type:"bytes[]"},{internalType:"bytes32",name:"",type:"bytes32"},{internalType:"address",name:"msgSender",type:"address"},{internalType:"bytes",name:"sig",type:"bytes"}],name:"executeMetaTxn",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"nonpayable",type:"function"}];var $={EXECUTE_META_TXN:"0xfd3ad6d4"};var K=[I,v,x,N,R,k,D,O,U,B,H,P,F,M,Y];var E={[I.id]:I.nativeCurrency.symbol,[v.id]:v.nativeCurrency.symbol,[x.id]:x.nativeCurrency.symbol,[N.id]:N.nativeCurrency.symbol,[R.id]:R.nativeCurrency.symbol,[k.id]:k.nativeCurrency.symbol,[D.id]:D.nativeCurrency.symbol,[O.id]:O.nativeCurrency.symbol,[U.id]:U.nativeCurrency.symbol,[H.id]:H.nativeCurrency.symbol,[P.id]:P.nativeCurrency.symbol,[B.id]:B.nativeCurrency.symbol,[F.id]:F.nativeCurrency.symbol,[M.id]:M.nativeCurrency.symbol,[Y.id]:Y.nativeCurrency.symbol};var C=`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`;var j=`0xcA11bde05977b3631167028862bE2a173976CA11`;var G=`0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789`;import{fromHex as te,erc20Abi as q,getAddress as X,formatUnits as ne,formatEther as re}from"viem";import{bsc as oe,base as se,mode as ae,blast as ie,linea as de,scroll as ce,mantle as me,mainnet as le,polygon as ue,arbitrum as pe,optimism as ye,unichain as fe,avalanche as be,berachain as Te,worldchain as Ee}from"viem/chains";function J(i){const d=[oe.id,se.id,ae.id,ie.id,de.id,ce.id,me.id,ue.id,le.id,pe.id,ye.id,fe.id,be.id,Te.id,Ee.id];return d.includes(i)}function g(i,d){const{recipient:l,direction:n="to"}=d;let T=0n;const t=l.toLowerCase();function s(e){if(!e.value)return;const a=n==="from"?e.from:e.to;if(a.toLowerCase()===t){T+=te(e.value,"bigint")}}function p(e){for(const a of e){s(a);if(a.calls&&a.calls.length>0){p(a.calls)}}}p(i.calls);return re(T)}async function Q({publicClient:i,transactionReceipt:d}){const l={Transfer:`0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`};const n=d.logs.filter(e=>e.topics[0]===l.Transfer).map(e=>({...e,address:X(e.address)}));const T=[...n.map(e=>({abi:q,address:e.address,functionName:"symbol"})),...n.map(e=>({abi:q,address:e.address,functionName:"decimals"}))];const t=await i.multicall({contracts:T});const s=Math.floor(t.length/2);const p=n.map((e,a)=>{const m=t[a].result;const A=t[s+a].result;const S=e.data==="0x"?"0":ne(BigInt(e.data),A);const w=e.data==="0x"?0n:BigInt(e.data);const{address:c,topics:_}=e;const{1:h,2:u}=_;const r=X(z(h));const o=X(z(u));return{to:o,from:r,symbol:m,amount:S,amountRaw:w,address:c,decimals:A}}).filter(e=>e.amount!=="0");return p}function z(i){return`0x${i.slice(-40)}`}function Z({logs:i,trace:d,chainId:l,smartContractWallet:n}){const T=i.reduce((a,m)=>{if(m.to===n)return{...a,output:m};if(m.from===n)return{...a,input:m};return a},{});let{input:t,output:s}=T;const p=g(d,{recipient:n});const e=g(d,{recipient:n,direction:"from"});if(!s&&p!=="0"){if(t){return{tokenIn:{address:t.address,amount:t.amount,symbol:t.symbol},tokenOut:{address:C,amount:p,symbol:E[l]}}}else{return null}}if(!t&&e!=="0"){const a=l===56?"WBNB":l===137?"WPOL":"WETH";const m=i.find(A=>A.symbol===a);if(m&&s){return{tokenIn:{address:C,amount:m.amount,symbol:E[l]},tokenOut:{address:s.address,amount:s.amount,symbol:s.symbol}}}else{return null}}if(t&&s){return{tokenIn:{address:t.address,amount:t.amount,symbol:t.symbol},tokenOut:{address:s.address,amount:s.amount,symbol:s.symbol}}}return null}async function Re({publicClient:i,transactionHash:d,smartContractWallet:l}){const n=i.chain.id;if(!J(n)){throw new Error(`chainId ${n} is unsupported\u2026`)}const T=i.extend(r=>({async traceCall(o){return r.request({method:"debug_traceTransaction",params:[o.hash,{tracer:"callTracer"}]})}}));const[t,s,p]=await Promise.all([T.traceCall({hash:d}),i.getTransaction({hash:d}),i.getTransactionReceipt({hash:d})]);const{from:e,value:a,to:m}=s;const A=m===G.toLowerCase();const S=g(t,{recipient:e});if(p.status==="reverted"){const r=K.find(y=>y.id===n);const o=`Unable to parse. Transaction ${d} on ${r?.name} has reverted.`;console.warn(o);return null}const w=a>0n;const c=await Q({publicClient:i,transactionReceipt:p});if(A){if(!l){throw new Error("This is an ERC-4337 transaction. You must provide a smart contract wallet address to 0x-parser.")}return Z({logs:c,trace:t,chainId:n,smartContractWallet:l})}const _=c.filter(r=>r.from.toLowerCase()===e.toLowerCase());let h=_.length?_.reduce((r,o)=>({...r,amount:ee(r.amountRaw+o.amountRaw,o.decimals),amountRaw:r.amountRaw+o.amountRaw})):c[0];let u=S==="0"?c.find(r=>{return r.to.toLowerCase()===e.toLowerCase()}):{symbol:E[n],amount:S,address:C};if(m?.toLowerCase()===j.toLowerCase()){const{args:r}=W({abi:Ae,data:s.input});const{args:o}=W({abi:V,data:r[0][1].callData});const y=o[0].recipient.toLowerCase();const f=o[3];const b=g(t,{recipient:y});if(b==="0"){[u]=c.filter(L=>L.to.toLowerCase()===f.toLowerCase())}else{u={symbol:E[n],amount:b,address:C}}}if(s.input.startsWith($.EXECUTE_META_TXN)){const{args:r}=W({abi:V,data:s.input});const{3:o}=r;const y=c.filter(b=>b.from===o);const f=g(t,{recipient:o});if(y.length){h=y[0]}if(f==="0"){u=c[c.length-1];const b=c.filter(L=>L.to.toLowerCase()===o.toLowerCase());if(b.length===1){u={symbol:b[0].symbol,amount:b[0].amount,address:b[0].address}}else{console.error("File a bug report here, including the expected results (URL to a block explorer) and the unexpected results: https://github.com/0xProject/0x-parser/issues/new/choose.")}h=c.filter(L=>L.from.toLowerCase()===o.toLowerCase())[0]}else{u={symbol:E[n],amount:f,address:C}}}if(w){const r=he(a);const o=c.filter(y=>y.to.toLowerCase()===e).reduce((y,f)=>({symbol:f.symbol,amount:ee(BigInt(y.amount)+Ce(f.amount,f.decimals),f.decimals),address:f.address}),{symbol:"",amount:"",address:""});return{tokenIn:{symbol:E[n],address:C,amount:r},tokenOut:o}}if(!u){console.error("File a bug report here, including the expected results (URL to a block explorer) and the unexpected results: https://github.com/0xProject/0x-parser/issues/new/choose.");return null}return{tokenIn:{symbol:h.symbol,amount:h.amount,address:h.address},tokenOut:{symbol:u.symbol,amount:u.amount,address:u.address}}}export{Re as parseSwap};