@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) • 8.7 kB
JavaScript
import{formatUnits as se,formatEther as Re,multicall3Abi as xe,decodeFunctionData as w}from"viem";import{defineChain as ie}from"viem";import{bsc as x,base as N,mode as k,blast as D,linea as O,scroll as M,mantle as U,plasma as B,mainnet as F,polygon as H,arbitrum as P,unichain as W,optimism as Y,avalanche as V,berachain as G,worldchain as X,monad as $,abstract as K}from"viem/chains";var I=ie({id:4663,name:"Robinhood Chain",nativeCurrency:{name:"Ether",symbol:"ETH",decimals:18},rpcUrls:{default:{http:["https://rpc.chain.robinhood.com"]}},blockExplorers:{default:{name:"Blockscout",url:"https://robinhoodchain.blockscout.com"}},contracts:{multicall3:{address:"0xca11bde05977b3631167028862be2a173976ca11"}}});var q=[{"type":"receive","stateMutability":"payable"},{"type":"function","name":"multicall","inputs":[{"name":"calls","type":"tuple[]","internalType":"struct IMultiCall.Call[]","components":[{"name":"target","type":"address","internalType":"address"},{"name":"revertPolicy","type":"uint8","internalType":"enum IMultiCall.RevertPolicy"},{"name":"value","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"contextdepth","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple[]","internalType":"struct IMultiCall.Result[]","components":[{"name":"success","type":"bool","internalType":"bool"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"payable"}];var _=[{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 z={EXECUTE_META_TXN:"0xfd3ad6d4"};var J=[x,N,k,D,O,M,U,B,F,H,P,W,Y,V,G,X,$,K,I];var T={[x.id]:x.nativeCurrency.symbol,[N.id]:N.nativeCurrency.symbol,[k.id]:k.nativeCurrency.symbol,[D.id]:D.nativeCurrency.symbol,[O.id]:O.nativeCurrency.symbol,[M.id]:M.nativeCurrency.symbol,[U.id]:U.nativeCurrency.symbol,[$.id]:$.nativeCurrency.symbol,[B.id]:B.nativeCurrency.symbol,[F.id]:F.nativeCurrency.symbol,[H.id]:H.nativeCurrency.symbol,[W.id]:W.nativeCurrency.symbol,[Y.id]:Y.nativeCurrency.symbol,[P.id]:P.nativeCurrency.symbol,[V.id]:V.nativeCurrency.symbol,[G.id]:G.nativeCurrency.symbol,[X.id]:X.nativeCurrency.symbol,[K.id]:K.nativeCurrency.symbol,[I.id]:I.nativeCurrency.symbol};var C=`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`;var Q=`0x00000000000000cf9e3c5a26621af382fa17f24f`;var Z=`0xcA11bde05977b3631167028862bE2a173976CA11`;var ee=`0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789`;import{fromHex as le,erc20Abi as te,getAddress as j,formatUnits as de,formatEther as ce}from"viem";import{bsc as me,base as ue,mode as pe,blast as ye,linea as be,scroll as fe,mantle as Te,plasma as Ce,mainnet as Ee,polygon as he,arbitrum as Ae,optimism as Le,unichain as ge,avalanche as Ie,berachain as we,worldchain as ve,monad as Se,abstract as _e}from"viem/chains";function ae(i){const c=[me.id,ue.id,pe.id,Se.id,ye.id,be.id,fe.id,Te.id,Ce.id,he.id,Ee.id,Ae.id,Le.id,ge.id,Ie.id,we.id,ve.id,_e.id,I.id];return c.includes(i)}function g(i,c){const{recipient:b,direction:r="to"}=c;let E=0n;const a=b.toLowerCase();function o(e){if(!e.value)return;const s=r==="from"?e.from:e.to;if(s.toLowerCase()===a){E+=le(e.value,"bigint")}}function f(e){for(const s of e){o(s);if(s.calls&&s.calls.length>0){f(s.calls)}}}f(i.calls);return ce(E)}async function re({publicClient:i,transactionReceipt:c}){const b={Transfer:`0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`};const r=c.logs.filter(e=>e.topics[0]===b.Transfer).map(e=>({...e,address:j(e.address)}));const E=[...r.map(e=>({abi:te,address:e.address,functionName:"symbol"})),...r.map(e=>({abi:te,address:e.address,functionName:"decimals"}))];const a=await i.multicall({contracts:E});const o=Math.floor(a.length/2);const f=r.map((e,s)=>{const l=a[s].result;const h=a[o+s].result;if(l==null||h==null||typeof h!=="number"){return null}const v=e.data==="0x"?"0":de(BigInt(e.data),h);const R=e.data==="0x"?0n:BigInt(e.data);const{address:d,topics:S}=e;const{1:A,2:m}=S;const t=j(ne(A));const n=j(ne(m));return{to:n,from:t,symbol:l,amount:v,amountRaw:R,address:d,decimals:h}}).filter(e=>e!=null&&e.amount!=="0");return f}function ne(i){return`0x${i.slice(-40)}`}function oe({logs:i,trace:c,chainId:b,smartContractWallet:r}){const E=i.reduce((s,l)=>{if(l.to===r)return{...s,output:l};if(l.from===r)return{...s,input:l};return s},{});let{input:a,output:o}=E;const f=g(c,{recipient:r});const e=g(c,{recipient:r,direction:"from"});if(!o&&f!=="0"){if(a){return{tokenIn:{address:a.address,amount:a.amount,symbol:a.symbol},tokenOut:{address:C,amount:f,symbol:T[b]}}}else{return null}}if(!a&&e!=="0"){const s=b===56?"WBNB":b===137?"WPOL":"WETH";const l=i.find(h=>h.symbol===s);if(l&&o){return{tokenIn:{address:C,amount:l.amount,symbol:T[b]},tokenOut:{address:o.address,amount:o.amount,symbol:o.symbol}}}else{return null}}if(a&&o){return{tokenIn:{address:a.address,amount:a.amount,symbol:a.symbol},tokenOut:{address:o.address,amount:o.amount,symbol:o.symbol}}}return null}async function Ye({publicClient:i,transactionHash:c,smartContractWallet:b}){const r=i.chain.id;if(!ae(r)){throw new Error(`chainId ${r} is unsupported\u2026`)}const E=i.extend(t=>({async traceCall(n){return t.request({method:"debug_traceTransaction",params:[n.hash,{tracer:"callTracer"}]})}}));const[a,o,f]=await Promise.all([E.traceCall({hash:c}),i.getTransaction({hash:c}),i.getTransactionReceipt({hash:c})]);const{from:e,value:s,to:l}=o;const h=l===ee.toLowerCase();const v=g(a,{recipient:e});if(f.status==="reverted"){const t=J.find(u=>u.id===r);const n=`Unable to parse. Transaction ${c} on ${t?.name} has reverted.`;console.warn(n);return null}const R=s>0n;const d=await re({publicClient:i,transactionReceipt:f});if(h){if(!b){throw new Error("This is an ERC-4337 transaction. You must provide a smart contract wallet address to 0x-parser.")}return oe({logs:d,trace:a,chainId:r,smartContractWallet:b})}const S=d.filter(t=>t.from.toLowerCase()===e.toLowerCase());let A=S.length?S.reduce((t,n)=>({...t,amount:se(t.amountRaw+n.amountRaw,n.decimals),amountRaw:t.amountRaw+n.amountRaw})):d[0];let m=v==="0"?d.find(t=>{return t.to.toLowerCase()===e.toLowerCase()}):{symbol:T[r],amount:v,address:C};if(l?.toLowerCase()===Q.toLowerCase()){const{args:t}=w({abi:q,data:o.input});if(t&&Array.isArray(t)&&t[0]&&Array.isArray(t[0])){const{args:n}=w({abi:_,data:t[0][1]?.data});const u=n[0].recipient.toLowerCase();const p=n[3];const y=g(a,{recipient:u});if(y==="0"){[m]=d.filter(L=>L.to.toLowerCase()===p.toLowerCase())}else{m={symbol:T[r],amount:y,address:C}}}}if(l?.toLowerCase()===Z.toLowerCase()){const{args:t}=w({abi:xe,data:o.input});if(t[0]){const{args:n}=w({abi:_,data:t[0][1]?.callData});const u=n[0].recipient.toLowerCase();const p=n[3];const y=g(a,{recipient:u});if(y==="0"){[m]=d.filter(L=>L.to.toLowerCase()===p.toLowerCase())}else{m={symbol:T[r],amount:y,address:C}}}}if(o.input.startsWith(z.EXECUTE_META_TXN)){const{args:t}=w({abi:_,data:o.input});const{3:n}=t;const u=d.filter(y=>y.from===n);const p=g(a,{recipient:n});if(u.length){A=u[0]}if(p==="0"){m=d[d.length-1];const y=d.filter(L=>L.to.toLowerCase()===n.toLowerCase());if(y.length===1){m={symbol:y[0].symbol,amount:y[0].amount,address:y[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.")}A=d.filter(L=>L.from.toLowerCase()===n.toLowerCase())[0]}else{m={symbol:T[r],amount:p,address:C}}}if(R){const t=Re(s);const n=d.filter(u=>u.to.toLowerCase()===e).reduce((u,p)=>({symbol:p.symbol,amount:se(u.amountRaw+p.amountRaw,p.decimals),amountRaw:u.amountRaw+p.amountRaw,address:p.address}),{symbol:"",amount:"",amountRaw:0n,address:""});return{tokenIn:{symbol:T[r],address:C,amount:t},tokenOut:{symbol:n.symbol,amount:n.amount,address:n.address}}}if(!m){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:A.symbol,amount:A.amount,address:A.address},tokenOut:{symbol:m.symbol,amount:m.amount,address:m.address}}}export{Ye as parseSwap};