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