keyring-agent-core 0.2.10 → 0.2.11
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 +9 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var tr=Object.create;var cn=Object.defineProperty;var nr=Object.getOwnPropertyDescriptor;var or=Object.getOwnPropertyNames;var rr=Object.getPrototypeOf,sr=Object.prototype.hasOwnProperty;var ar=(c,e)=>{for(var t in e)cn(c,t,{get:e[t],enumerable:!0})},no=(c,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of or(e))!sr.call(c,r)&&r!==t&&cn(c,r,{get:()=>e[r],enumerable:!(n=nr(e,r))||n.enumerable});return c};var ir=(c,e,t)=>(t=c!=null?tr(rr(c)):{},no(e||!c||!c.__esModule?cn(t,"default",{value:c,enumerable:!0}):t,c)),lr=c=>no(cn({},"__esModule",{value:!0}),c);var ha={};ar(ha,{AI_AGENT_TOOL_NAMES:()=>En,AgentCore:()=>Bn,ApproveTokenTool:()=>Bt,BaseNftMessageTool:()=>ge,BaseSwapService:()=>Ue,BaseTool:()=>v,BaseWalletActionTool:()=>ae,BuyTokenTool:()=>Ot,ChatHistory:()=>$t,DEFAULT_CHAIN:()=>he,DEFAULT_PROVIDER:()=>Jt,DEFAULT_RPC_BY_CHAIN:()=>se,DebridgeAdapter:()=>Tt,EstimatePoolYieldTool:()=>Pt,GeminiProvider:()=>pe,GeminiSearchAiTool:()=>mt,HEX_TO_PANTOGRAPH:()=>wo,KnowledgeBase:()=>Vt,MoralisService:()=>E,NFTContractInfoTool:()=>ut,NFTMetadataTool:()=>dt,NFT_AGENT_TOOL_NAMES:()=>Rn,OpenAddLiquidityFormTool:()=>xt,POOL_AGENT_TOOL_NAMES:()=>Nn,PantographService:()=>Z,PoolByAddressTool:()=>ft,PoolDetailTool:()=>ht,PoolSearchTool:()=>gt,PoolService:()=>Me,PreviewAddLiquidityTool:()=>At,RelayAdapter:()=>vt,Router:()=>Ht,SUPPORTED_CHAINS:()=>$e,SUPPORTED_CHAINS_LABEL:()=>Ne,SWAP_PROVIDER_CONFIG:()=>Sn,SendNativeTool:()=>Lt,SendNftTool:()=>Ft,SendTokenTool:()=>Mt,Subagent:()=>Y,SubgraphCoinPoolPairsTool:()=>Nt,SubgraphPoolByAddressTool:()=>Ut,SubgraphPoolByPositionIdTool:()=>Rt,SubgraphPoolSearchTool:()=>_t,SubgraphPositionDetailTool:()=>Et,SubgraphTrendingPoolsTool:()=>Ct,Summarizer:()=>Wt,SwapServiceFactory:()=>Le,SwapTokenTool:()=>qt,Synthesizer:()=>Gt,TOKEN_AGENT_TOOL_NAMES:()=>Un,TRANSFER_TOPIC:()=>Oo,TRENDING_DEFAULT_BY_HEX_CHAIN:()=>ko,TokenAnalyticsTool:()=>je,TokenHoldersTool:()=>Ye,TokenInfoTool:()=>Ke,TokenScoreTool:()=>ze,ToolRegistry:()=>Fe,TopGainersTool:()=>Xe,TopPoolsTool:()=>pt,TransactionByHashTool:()=>lt,TrendingTokensTool:()=>Qe,UNISWAP_CHAIN_SLUG:()=>en,UpstashKnowledgeBase:()=>Re,WALLET_ACTION_AGENT_TOOL_NAMES:()=>In,WALLET_AGENT_TOOL_NAMES:()=>Cn,WalletApprovalsTool:()=>rt,WalletDefiPositionsTool:()=>at,WalletDefiProtocolPositionsTool:()=>it,WalletDefiSummaryTool:()=>st,WalletHistoryTool:()=>Ze,WalletNFTsTool:()=>ct,WalletNetWorthTool:()=>gn,WalletNftTransfersTool:()=>tt,WalletPnlSummaryTool:()=>nt,WalletPnlTool:()=>ot,WalletTokenBalancesTool:()=>Je,WalletTokenTransfersTool:()=>et,ZERO_ADDRESS:()=>O,buildRangePresets:()=>Zn,buildUniswapPoolUrl:()=>ue,clampTick:()=>ve,configureSupportedChains:()=>mn,createAiAgent:()=>sn,createDefaultSubagents:()=>Dn,createNftAgent:()=>rn,createPoolAgent:()=>an,createTokenAgent:()=>on,createWalletActionAgent:()=>ln,createWalletAgent:()=>nn,ethCallAt:()=>Lo,ethCallByChain:()=>Jn,getAffiliateFee:()=>wt,getChainMeta:()=>ee,getDefaultRpcUrl:()=>ws,getGatewayAddress:()=>An,getNativeTokenInfo:()=>St,getPositionManagerAddress:()=>Pn,getProviderByChain:()=>vn,ingestKnowledgeBase:()=>Zo,priceToTick:()=>De,resolveRpcUrl:()=>kt,roundTickToSpacing:()=>Te,rpcCall:()=>xe,setRpcOverrides:()=>Xn,swapServiceFactory:()=>fe,tickToPrice:()=>le,toPantographChain:()=>zt});module.exports=lr(ha);var ro=ir(require("axios"));var oo="0.2.
|
|
1
|
+
"use strict";var tr=Object.create;var cn=Object.defineProperty;var nr=Object.getOwnPropertyDescriptor;var or=Object.getOwnPropertyNames;var rr=Object.getPrototypeOf,sr=Object.prototype.hasOwnProperty;var ar=(c,e)=>{for(var t in e)cn(c,t,{get:e[t],enumerable:!0})},no=(c,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of or(e))!sr.call(c,r)&&r!==t&&cn(c,r,{get:()=>e[r],enumerable:!(n=nr(e,r))||n.enumerable});return c};var ir=(c,e,t)=>(t=c!=null?tr(rr(c)):{},no(e||!c||!c.__esModule?cn(t,"default",{value:c,enumerable:!0}):t,c)),lr=c=>no(cn({},"__esModule",{value:!0}),c);var ha={};ar(ha,{AI_AGENT_TOOL_NAMES:()=>En,AgentCore:()=>Bn,ApproveTokenTool:()=>Bt,BaseNftMessageTool:()=>ge,BaseSwapService:()=>Ue,BaseTool:()=>v,BaseWalletActionTool:()=>ae,BuyTokenTool:()=>Ot,ChatHistory:()=>$t,DEFAULT_CHAIN:()=>he,DEFAULT_PROVIDER:()=>Jt,DEFAULT_RPC_BY_CHAIN:()=>se,DebridgeAdapter:()=>Tt,EstimatePoolYieldTool:()=>Pt,GeminiProvider:()=>pe,GeminiSearchAiTool:()=>mt,HEX_TO_PANTOGRAPH:()=>wo,KnowledgeBase:()=>Vt,MoralisService:()=>E,NFTContractInfoTool:()=>ut,NFTMetadataTool:()=>dt,NFT_AGENT_TOOL_NAMES:()=>Rn,OpenAddLiquidityFormTool:()=>xt,POOL_AGENT_TOOL_NAMES:()=>Nn,PantographService:()=>Z,PoolByAddressTool:()=>ft,PoolDetailTool:()=>ht,PoolSearchTool:()=>gt,PoolService:()=>Me,PreviewAddLiquidityTool:()=>At,RelayAdapter:()=>vt,Router:()=>Ht,SUPPORTED_CHAINS:()=>$e,SUPPORTED_CHAINS_LABEL:()=>Ne,SWAP_PROVIDER_CONFIG:()=>Sn,SendNativeTool:()=>Lt,SendNftTool:()=>Ft,SendTokenTool:()=>Mt,Subagent:()=>Y,SubgraphCoinPoolPairsTool:()=>Nt,SubgraphPoolByAddressTool:()=>Ut,SubgraphPoolByPositionIdTool:()=>Rt,SubgraphPoolSearchTool:()=>_t,SubgraphPositionDetailTool:()=>Et,SubgraphTrendingPoolsTool:()=>Ct,Summarizer:()=>Wt,SwapServiceFactory:()=>Le,SwapTokenTool:()=>qt,Synthesizer:()=>Gt,TOKEN_AGENT_TOOL_NAMES:()=>Un,TRANSFER_TOPIC:()=>Oo,TRENDING_DEFAULT_BY_HEX_CHAIN:()=>ko,TokenAnalyticsTool:()=>je,TokenHoldersTool:()=>Ye,TokenInfoTool:()=>Ke,TokenScoreTool:()=>ze,ToolRegistry:()=>Fe,TopGainersTool:()=>Xe,TopPoolsTool:()=>pt,TransactionByHashTool:()=>lt,TrendingTokensTool:()=>Qe,UNISWAP_CHAIN_SLUG:()=>en,UpstashKnowledgeBase:()=>Re,WALLET_ACTION_AGENT_TOOL_NAMES:()=>In,WALLET_AGENT_TOOL_NAMES:()=>Cn,WalletApprovalsTool:()=>rt,WalletDefiPositionsTool:()=>at,WalletDefiProtocolPositionsTool:()=>it,WalletDefiSummaryTool:()=>st,WalletHistoryTool:()=>Ze,WalletNFTsTool:()=>ct,WalletNetWorthTool:()=>gn,WalletNftTransfersTool:()=>tt,WalletPnlSummaryTool:()=>nt,WalletPnlTool:()=>ot,WalletTokenBalancesTool:()=>Je,WalletTokenTransfersTool:()=>et,ZERO_ADDRESS:()=>O,buildRangePresets:()=>Zn,buildUniswapPoolUrl:()=>ue,clampTick:()=>ve,configureSupportedChains:()=>mn,createAiAgent:()=>sn,createDefaultSubagents:()=>Dn,createNftAgent:()=>rn,createPoolAgent:()=>an,createTokenAgent:()=>on,createWalletActionAgent:()=>ln,createWalletAgent:()=>nn,ethCallAt:()=>Lo,ethCallByChain:()=>Jn,getAffiliateFee:()=>wt,getChainMeta:()=>ee,getDefaultRpcUrl:()=>ws,getGatewayAddress:()=>An,getNativeTokenInfo:()=>St,getPositionManagerAddress:()=>Pn,getProviderByChain:()=>vn,ingestKnowledgeBase:()=>Zo,priceToTick:()=>De,resolveRpcUrl:()=>kt,roundTickToSpacing:()=>Te,rpcCall:()=>xe,setRpcOverrides:()=>Xn,swapServiceFactory:()=>fe,tickToPrice:()=>le,toPantographChain:()=>zt});module.exports=lr(ha);var ro=ir(require("axios"));var oo="0.2.11";var ur=`keyring-agent-core/${oo} (Keyring Chatbot Agent; +https://keyring.app)`,dr=3e4,mr=typeof process<"u"&&process.versions?.node!=null,qn=class{instance;constructor(e={}){this.instance=ro.default.create({baseURL:e.baseURL,timeout:e.timeout??dr,validateStatus:()=>!0,headers:{Accept:"application/json",...mr?{"User-Agent":e.userAgent??ur}:{},...e.headers}})}async request(e,t,n,r={}){let o=await this.instance.request({...r,method:e,url:t,data:n}),s={};for(let[a,i]of Object.entries(o.headers??{}))i!=null&&(s[a.toLowerCase()]=String(i));return{ok:o.status>=200&&o.status<300,status:o.status,statusText:o.statusText,data:o.data,headers:s}}get(e,t){return this.request("GET",e,void 0,t)}post(e,t,n){return this.request("POST",e,t,n)}put(e,t,n){return this.request("PUT",e,t,n)}patch(e,t,n){return this.request("PATCH",e,t,n)}delete(e,t){return this.request("DELETE",e,void 0,t)}},_=new qn;function N(c){let{data:e,status:t,statusText:n}=c,r=n?`HTTP ${t} ${n}`:`HTTP ${t}`;if(typeof e=="string")return e.trim()||r;if(e&&typeof e=="object"){let o=e,s=i=>i&&typeof i=="object"?i.message:void 0,a=[o.message,o.errorMessage,o.error,o.error_description,o.detail,s(o.error),s(o.data)];for(let i of a)if(typeof i=="string"&&i.trim())return i.trim()}return r}var so={string:"STRING",number:"NUMBER",boolean:"BOOLEAN",object:"OBJECT",array:"ARRAY"},pr="https://nft-demo.keyring.app/api/gemini-stable",hr=new Set([408,429,500,502,503,504]),ao=3e4,un=c=>new Promise(e=>setTimeout(e,c));function dn(c,e,t){if(t!=null&&t>0)return Math.min(t,ao);let n=Math.min(e*2**(c-1),ao);return n/2+Math.random()*(n/2)}function gr(c){if(!c)return null;let e=Number(c);if(Number.isFinite(e))return Math.max(0,e*1e3);let t=Date.parse(c);return Number.isNaN(t)?null:Math.max(0,t-Date.now())}var pe=class{model;maxTokens;temperature;baseUrl;constructor(e){this.model=e.model??"gemini-2.5-flash-lite",this.maxTokens=e.maxTokens??4096,this.temperature=e.temperature??1,this.baseUrl=e.baseUrl??pr}async chat(e,t,n){let{systemInstruction:r,contents:o}=this.toContents(e),{maxRetries:s=5,retryDelayMs:a=1e3}=n??{},i=o.length>0?o:[{role:"user",parts:[{text:"(continue)"}]}];if(n?._debug){console.log("[GeminiProvider] turn sequence:");for(let p of i){let m=p.parts.map(g=>g.functionCall?`fc:${g.functionCall.name}`:g.functionResponse?`fr:${g.functionResponse.name}`:`text:${(g.text??"").slice(0,40)}`).join(", ");console.log(` ${p.role}: [${m}]`)}}let l={contents:i,generationConfig:{maxOutputTokens:this.maxTokens,temperature:this.temperature}};r&&(l.systemInstruction=r),t?.length?(l.tools=[{functionDeclarations:this.toFunctionDeclarations(t)}],n?.forceToolUse&&(l.toolConfig={functionCallingConfig:{mode:"ANY"}})):n?.googleSearch&&(l.tools=[{googleSearch:{}}]);let u=`${this.baseUrl}/v1beta/models/${this.model}:generateContent`,d="Unknown error";for(let p=1;p<=s;p++){let m;try{m=await _.post(u,l,{headers:{"Content-Type":"application/json"}})}catch(b){if(d=b instanceof Error?b.message:String(b),p>=s)break;await un(dn(p,a));continue}if(!m.ok){let b=typeof m.data=="string"?m.data:JSON.stringify(m.data)||m.statusText;if(d=`Gemini proxy error ${m.status}: ${b}`,!hr.has(m.status))throw new Error(d);if(p>=s)break;let T=gr(m.headers["retry-after"]??null);await un(dn(p,a,T));continue}if(m.data==null||typeof m.data!="object"){if(d="Gemini proxy returned invalid JSON",p>=s)break;await un(dn(p,a));continue}let g=m.data,f=g.candidates?.[0];if(!f)return{text:"",toolCalls:[]};let h="",y=[],k=f.content?.parts;if(!Array.isArray(k)||k.length===0){let b=f.finishReason;if(!(b==="SAFETY"||b==="RECITATION")&&p<s){d=`Gemini returned an empty turn (finishReason=${b??"none"})`,await un(dn(p,a));continue}return{text:"",toolCalls:[]}}for(let b of k)b.text&&(h+=b.text),b.functionCall&&y.push({toolName:b.functionCall.name,args:b.functionCall.args??{},callId:b.functionCall.id??`call_${Date.now()}_${Math.random().toString(36).slice(2,8)}`});let w=g.usageMetadata?{promptTokens:g.usageMetadata.promptTokenCount??0,completionTokens:g.usageMetadata.candidatesTokenCount??0,totalTokens:g.usageMetadata.totalTokenCount??0}:void 0;return{text:h,toolCalls:y,usage:w}}throw new Error(d)}toContents(e){let t=[],n=[];for(let a of e){if(a.role==="system"){t.push(a.content);continue}if(a.role==="tool"){n.push({role:"function",parts:[{functionResponse:{name:a.toolName??"unknown",response:{result:a.content},...a.toolCallId?{id:a.toolCallId}:{}}}]});continue}if(a.role==="assistant"&&a.toolCalls?.length){n.push({role:"model",parts:a.toolCalls.map(i=>({functionCall:{name:i.toolName,args:i.args,...i.callId?{id:i.callId}:{}}}))});continue}n.push({role:a.role==="assistant"?"model":"user",parts:[{text:a.content}]})}let r=[];for(let a of n){let i=r[r.length-1],l=a.parts.some(d=>d.functionCall),u=i?.parts.some(d=>d.functionCall);i&&i.role===a.role&&!l&&!u?i.parts.push(...a.parts):r.push({...a,parts:[...a.parts]})}let o=[];for(let a=0;a<r.length;a++){let i=r[a],l=o[o.length-1];i.role==="function"&&!l?.parts.some(d=>d.functionCall)||i.role==="model"&&i.parts.some(d=>d.functionCall)&&!(r[a+1]?.role==="function")||o.push(i)}for(;o.length>0&&o[0].role!=="user";)o.shift();return{systemInstruction:t.length?{role:"user",parts:[{text:t.join(`
|
|
2
2
|
`)}]}:null,contents:o}}toFunctionDeclarations(e){return e.map(t=>{let n={},r=[];for(let o of t.parameters){let s={type:so[o.type]??"STRING",description:o.description};o.type==="array"&&(s.items={type:so[o.items?.type??"string"]??"STRING"}),n[o.name]=s,o.required&&r.push(o.name)}return{name:t.name,description:t.description,parameters:{type:"OBJECT",properties:n,required:r}}})}};var Fe=class{tools=new Map;register(e){if(this.tools.has(e.name))throw new Error(`Tool "${e.name}" is already registered`);this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}get(e){return this.tools.get(e)}has(e){return this.tools.has(e)}getDefinitions(){return Array.from(this.tools.values()).map(e=>({name:e.name,description:e.description,parameters:e.parameters,category:e.category,kind:e.kind}))}getDefinitionsByCategory(e){return this.getDefinitions().filter(t=>t.category===e)}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{toolName:e,callId:`err_${Date.now()}`,success:!1,error:`Tool "${e}" not found in registry`,duration:0};let o=Date.now();try{return{...await r.execute(t,n),duration:Date.now()-o}}catch(s){return{toolName:e,callId:`err_${Date.now()}`,success:!1,error:s instanceof Error?s.message:String(s),duration:Date.now()-o}}}get size(){return this.tools.size}listNames(){return Array.from(this.tools.keys())}};var $e=["0x1","0xa","0x38","0x89","0x2105","0xa4b1","0xa86a","0xe708"],fr=new Set($e),Ee=[...$e],io=new Set(Ee),he="0x1",Ne="Ethereum (0x1), Optimism (0xa), BSC (0x38), Polygon (0x89), Base (0x2105), Arbitrum (0xa4b1), Avalanche (0xa86a), Linea (0xe708)";function yr(c){return c.map(e=>`${Ve[e]??e} (${e})`).join(", ")}function mn(c){let e=new Set;if(c)for(let n of c){let r=Fn(n);r&&e.add(r)}let t=$e.filter(n=>!e.has(n));Ee=t.length>0?[...t]:[...$e],io=new Set(Ee),he=Ee.includes("0x1")?"0x1":Ee[0],Ne=yr(Ee)}var br={"0x1":"0x1",1:"0x1",eth:"0x1",ether:"0x1",ethereum:"0x1",mainnet:"0x1","0xa":"0xa",10:"0xa",op:"0xa",optimism:"0xa","0x38":"0x38",56:"0x38",bsc:"0x38",bnb:"0x38",binance:"0x38","0x89":"0x89",137:"0x89",matic:"0x89",polygon:"0x89","0x2105":"0x2105",8453:"0x2105",base:"0x2105","0xa4b1":"0xa4b1",42161:"0xa4b1",arb:"0xa4b1",arbitrum:"0xa4b1","0xa86a":"0xa86a",43114:"0xa86a",avax:"0xa86a",avalanche:"0xa86a","0xe708":"0xe708",59144:"0xe708",linea:"0xe708"};function ke(c){let e=Fn(c);return e&&io.has(e)?e:null}function Fn(c){if(typeof c!="string")return null;let e=c.trim().toLowerCase();if(!e)return null;let t=br[e];if(t)return t;let n=null;return/^0x[0-9a-f]+$/.test(e)?n=e:/^[0-9]+$/.test(e)&&(n="0x"+Number(e).toString(16)),n&&fr.has(n)?n:null}function pn(c){return ke(c)!==null}var We=class extends Error{constructor(t){super(`Chain "${t}" is not supported. Supported chains: ${Ne}.`);this.requested=t;this.name="UnsupportedChainError"}requested;code="unsupported_chain"},_e=c=>typeof c=="string"&&c.trim()!=="";function lo(c,e){if(_e(c)){let t=ke(c);if(t)return t;throw new We(c.trim())}if(_e(e?.chain)){let t=ke(e.chain);if(t)return t;throw new We(e.chain.trim())}return null}function hn(c,e){return ke(c)??ke(e?.chain)??void 0}var Ve={"0x1":"Ethereum","0xa":"Optimism","0x38":"BSC","0x89":"Polygon","0x2105":"Base","0xa4b1":"Arbitrum","0xa86a":"Avalanche","0xe708":"Linea"};function L(c){let e=Fn(c);return e&&Ve[e]?Ve[e]:typeof c=="string"&&c.trim()?c.trim():"the requested chain"}var wr={bnb:"0x38",matic:"0x89",pol:"0x89",avax:"0xa86a"};function co(c){if(typeof c!="string")return null;let e=c.trim().toLowerCase();return e?wr[e]??null:null}function He(c,e){if(!_e(c))return null;let t=ke(c),n=ke(e?.chain);return!t||!n||t===n?null:{requested:t,connected:n,requestedLabel:Ve[t]??t,connectedLabel:Ve[n]??n}}function kr(){return Ee.map(c=>{let e=Ve[c]??c;return{label:e,prompt:e}})}var z=class extends Error{code="needs_chain_selection";buttons;constructor(e){super("Wallet is connected but no chain is set \u2014 ask the user to pick one."),this.name="NeedsChainSelectionError",this.buttons=e??kr()}},Kt=class extends Error{code="no_wallet_connected";constructor(){super("No wallet address available \u2014 ask the user to connect a wallet or supply one."),this.name="NoWalletConnectedError"}};function K(c,e){if(_e(c))return c.trim();if(_e(e?.walletAddress))return e.walletAddress.trim();throw new Kt}function R(c,e){if(_e(c)){let t=ke(c);if(t)return t;throw new We(c.trim())}if(_e(e?.chain)){let t=ke(e.chain);if(t)return t;throw new We(e.chain.trim())}if(_e(e?.walletAddress))throw new z;return he}var v=class{category;async execute(e,t){let n=`call_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,r=Date.now();try{let o=await this.run(e,t),s=Tr(o);return{toolName:this.name,callId:n,success:!0,data:s.data,duration:Date.now()-r,...s.actionButtons?{actionButtons:s.actionButtons}:{}}}catch(o){return o instanceof z?{toolName:this.name,callId:n,success:!0,data:{_instructions:"The user has a connected wallet but no chain is set. Ask them which chain to use \u2014 the chain-picker buttons rendered below your reply let them choose. Keep the message short in the user's language and do NOT list the chain names yourself (the buttons already show them)."},duration:Date.now()-r,actionButtons:o.buttons}:o instanceof Kt?{toolName:this.name,callId:n,success:!0,data:{_instructions:"The user has not connected a wallet. In the user's language, tell them this action needs a wallet \u2014 they can either connect their wallet or include a wallet address (0x\u2026) directly in their question. Keep it short and friendly."},duration:Date.now()-r}:{toolName:this.name,callId:n,success:!1,error:o instanceof Error?o.message:String(o),duration:Date.now()-r}}}};function Tr(c){if(!c||typeof c!="object")return{data:c};let e=c,t=e.actionButtons;if(!Array.isArray(t)||t.length===0)return{data:c};let{actionButtons:n,...r}=e;return{data:r,actionButtons:t}}var uo=require("js-sha3");function B(c){return typeof c=="string"&&/^0x[0-9a-fA-F]{40}$/.test(c)}function vr(c){return new Uint8Array(uo.keccak256.arrayBuffer(c))}function Yt(c){let e=c.startsWith("0x")?c.slice(2):c,t=e.length%2?"0"+e:e,n=new Uint8Array(t.length/2);for(let r=0;r<n.length;r++)n[r]=parseInt(t.slice(r*2,r*2+2),16);return n}function mo(c){return"0x"+Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}function po(c){return new TextEncoder().encode(c)}function Ie(...c){let e=c.reduce((r,o)=>r+o.length,0),t=new Uint8Array(e),n=0;for(let r of c)t.set(r,n),n+=r.length;return t}function Sr(c,e=32){let t=new Uint8Array(e);return t.set(c,e-c.length),t}function xr(c,e=32){let t=new Uint8Array(e);return t.set(c),t}function ho(c){let e=((c%(1n<<256n)+(1n<<256n))%(1n<<256n)).toString(16).padStart(64,"0");return Yt(e)}function jt(c){return ho(BigInt(c))}function go(c){return c==="uint"?"uint256":c==="int"?"int256":c.match(/^uint$/)?"uint256":c.match(/^int$/)?"int256":c.replace(/^uint(\[|$)/,"uint256$1").replace(/^int(\[|$)/,"int256$1")}function fo(c){let e=go(c.type);if(e==="tuple"||e.startsWith("tuple[")){let t=(c.components??[]).map(fo).join(","),n=e.startsWith("tuple[")?e.slice(5):"";return`(${t})${n}`}return e}function Ar(c){let e=(c.inputs??[]).map(fo).join(",");return`${c.name??""}(${e})`}function $n(c,e){let t=Cr(c.type);if(t){let[r,o]=t;return Pr({...c,type:o},e,r)}if(c.type==="tuple")return _r(c,e);if(c.type==="address"){let r=String(e),o=r.startsWith("0x")?r.slice(2):r;return{dynamic:!1,encoded:Sr(Yt(o.toLowerCase()))}}if(c.type==="bool"){let r=new Uint8Array(32);return r[31]=e?1:0,{dynamic:!1,encoded:r}}let n=go(c.type);if(/^uint\d*$/.test(n))return{dynamic:!1,encoded:jt(BigInt(e))};if(/^int\d*$/.test(n)){let r=BigInt(e);return r<0n&&(r=r+(1n<<256n)),{dynamic:!1,encoded:ho(r)}}if(/^bytes(\d+)$/.test(n)){let r=parseInt(n.slice(5),10),o=typeof e=="string"?Yt(e):e;if(o.length!==r)throw new Error(`bytes${r} expects exactly ${r} bytes, got ${o.length}`);return{dynamic:!1,encoded:xr(o)}}if(n==="bytes"){let r=typeof e=="string"?Yt(e):e,o=Math.ceil(r.length/32)*32,s=new Uint8Array(o);return s.set(r),{dynamic:!0,encoded:Ie(jt(r.length),s)}}if(n==="string"){let r=typeof e=="string"?po(e):e,o=Math.ceil(r.length/32)*32,s=new Uint8Array(o);return s.set(r),{dynamic:!0,encoded:Ie(jt(r.length),s)}}throw new Error(`Unsupported ABI type: ${c.type}`)}function Wn(c){let e=0;for(let{dynamic:o,encoded:s}of c)e+=o?32:s.length;let t=[],n=[],r=0;for(let{dynamic:o,encoded:s}of c)o?(t.push(jt(e+r)),n.push(s),r+=s.length):t.push(s);return Ie(...t,...n)}function Pr(c,e,t){let n=t===null;if(!n&&e.length!==t)throw new Error(`Array length mismatch: expected ${t}, got ${e.length}`);let r=!1,o=[];for(let s of e){let a=$n(c,s);a.dynamic&&(r=!0),o.push(a)}if(n||r){let s=Wn(o);if(n){let a=jt(o.length);return{dynamic:!0,encoded:o.length>0?Ie(a,s):a}}return{dynamic:!0,encoded:s}}return{dynamic:!1,encoded:Ie(...o.map(s=>s.encoded))}}function _r(c,e){let t=c.components??[],n=!1,r=[];for(let o=0;o<t.length;o++){let s=t[o],a=Array.isArray(e)?e[o]:e[s.name??""],i=$n(s,a);i.dynamic&&(n=!0),r.push(i)}return{dynamic:n,encoded:n?Wn(r):Ie(...r.map(o=>o.encoded))}}function Cr(c){let e=c.match(/^(.*)\[(\d+)?\]$/);return e?[e[2]?Number(e[2]):null,e[1]]:void 0}function Ur(c,e){if(c.length!==e.length)throw new Error(`Expected ${c.length} values, got ${e.length}`);if(c.length===0)return"0x";let t=c.map((r,o)=>$n(r,e[o])),n=Wn(t);return mo(n)}function Ge({abi:c,functionName:e,args:t=[]}){let n=c.find(i=>(i.type==="function"||i.type===void 0)&&i.name===e);if(!n)throw new Error(`Function "${e}" not found in ABI`);let r=Ar(n),o=vr(po(r)).slice(0,4),s=n.inputs??[],a=s.length===0||t.length===0?new Uint8Array(0):Yt(Ur(s,t).slice(2));return mo(Ie(o,a))}var Rr="https://wallet-api.pantograph.app",Er="0x0000000000000000000000000000000000000000",wo={"0x1":"ether","0xa":"optimism","0x38":"bsc","0x89":"matic","0x2105":"base","0xa4b1":"arbitrum","0xa86a":"avax","0xe708":"linea"},ko={"0x1":["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"],"0xa":["0x4200000000000000000000000000000000000006","0x68f180fcce6836688e9084f035309e29bf0a2095","0xc47da4cb96ce65a96844a01bfae509f9d5454534"],"0x38":["0x2170ed0880ac9a755fd29b2688956bd959f933f8","0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c"],"0x89":["0x7ceb23fd6bc0add59e62ac25578270cff1b9f619","0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6"],"0x2105":["0x4200000000000000000000000000000000000006","0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf","0xc47da4cb96ce65a96844a01bfae509f9d5454534"],"0xa4b1":["0x82af49447d8a07e3bd95bd0d56f35241523fbab1","0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f"],"0xa86a":["0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab","0x0555e30da8f98308edb960aa94c0db47230d2b9c"],"0xe708":["0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f","0x3aab2285ddcddad8edf438c1bab47e1a9d05a9b4"]};function zt(c){return wo[c.toLowerCase()]||c}function yo(c){let e=[];for(let[t,n]of Object.entries(c))if(n!=null)if(Array.isArray(n))for(let r of n)e.push(`${encodeURIComponent(t)}=${encodeURIComponent(String(r))}`);else e.push(`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`);return e.join("&")}function Vn(c){let e=c,t=e.decimals,n=typeof t=="number"?t:typeof t=="string"?parseInt(t,10):NaN,r=e.price,o=r!=null?parseFloat(String(r)):NaN;return{...e,token_address:e.token_address??e.address??"",decimals:Number.isFinite(n)?n:0,...Number.isFinite(o)?{usd_price:o}:{}}}function J(c){if(c==null)return null;let e=typeof c=="number"?c:parseFloat(String(c));return Number.isFinite(e)?e:null}function bo(c,e){let t=c.decimals,n=typeof t=="number"?t:typeof t=="string"?parseInt(t,10):null,r=J(c.price_change_percentage_24h)??J(c.priceChange24h)??J(c.usd_price_24hr_percent_change)??J(c.price_change_24h)??J(c.priceChange);return{chainId:e,tokenAddress:c.address??c.token_address??"",name:c.name??null,symbol:c.symbol??null,decimals:n!=null&&Number.isFinite(n)?n:null,logo:c.logoURI??c.icon_image??c.logo??null,usdPrice:J(c.price)??J(c.usd_price),marketCap:J(c.market_cap)??J(c.marketCap),totalVolume:{"24h":J(c.total_volume)??J(c.volume24h)},pricePercentChange:{"24h":r}}}var Z=class{baseUrl;constructor(e){this.baseUrl=(e?.baseUrl??Rr).replace(/\/+$/,"")}async enrichTokenPrices(e,t){if(e.length!==0)try{let n=zt(t),r=e.map(u=>u.token_address).join(","),o=`${this.baseUrl}/keyrings/tokens/${n}/v2?addresses=${encodeURIComponent(r)}`,s=await _.get(o);if(!s.ok)return;let a=s.data,i=Array.isArray(a)?a:Array.isArray(a.data)?a.data:[],l=new Map;for(let u of i)u.address&&l.set(u.address.toLowerCase(),{price:u.price!=null?parseFloat(String(u.price)):NaN,icon_image:u.icon_image});for(let u=0;u<e.length;u++){let d=l.get(e[u].token_address.toLowerCase());d&&(d.icon_image&&(e[u].logo=d.icon_image,e[u].thumbnail=d.icon_image),isNaN(d.price)||(e[u].usd_price=d.price,e[u].usd_value=parseFloat(e[u].balance_formatted||"0")*d.price))}}catch{}}async getTokenMetadata(e,t){try{let n=zt(t),r=`${this.baseUrl}/keyrings/tokens/${n}/v2?addresses=${encodeURIComponent(e)}`,o=await _.get(r);if(!o.ok)return null;let s=o.data,a=Array.isArray(s)?s:Array.isArray(s.data)?s.data:[],i=e.toLowerCase()===Er,l=a.find(u=>u.address?.toLowerCase()===e.toLowerCase()||i&&u.address===""||u.token_address?.toLowerCase()===e.toLowerCase()||i&&u.token_address==="");return l?Vn(l):null}catch{return null}}async getTokensMetadata(e,t){let n={};if(e.length===0)return n;try{let r=zt(t),o=`${this.baseUrl}/keyrings/tokens/${r}/v2?addresses=${encodeURIComponent(e.join(","))}`,s=await _.get(o);if(!s.ok)return n;let a=s.data,i=Array.isArray(a)?a:Array.isArray(a.data)?a.data:[],l=new Set(e.map(u=>u.toLowerCase()));for(let u of i){let d=u.address?.toLowerCase()||u.token_address?.toLowerCase()||(u.address===""?"":null);d&&l.has(d)&&(n[d]=Vn(u))}}catch{}return n}async searchTokensByKey(e){let{key:t,chain:n}=e;if(!t)return{success:!1,error:"Search key is required"};let o=parseInt(n||he,16);if(isNaN(o))return{success:!1,error:`Invalid hex chain: ${n}`};try{let s=yo({chainId:o,key:t}),a=`${this.baseUrl}/token-list?${s}`,i=await _.get(a);if(!i.ok)throw new Error(N(i));let l=i.data,u=[];return l?.data?u=Array.isArray(l.data)?l.data:Object.values(l.data).flat():typeof l=="object"&&!Array.isArray(l)&&(u=Object.values(l).flat()),{success:!0,data:u.map(Vn)}}catch(s){return{success:!1,error:s instanceof Error?s.message:"Unknown error"}}}async getTrendingTokens(e){let t=e?.chain||he,n=5,r=e?.limit&&e.limit>0?Math.floor(e.limit):void 0;try{let o=ko[t.toLowerCase()]??[],s=r!=null?r+o.length:n+o.length,[a,i]=await Promise.allSettled([this.fetchTopGainers(t,s),o.length>0?this.getTokensMetadata(o,t):Promise.resolve({})]),l=a.status==="fulfilled"?a.value:[],u=i.status==="fulfilled"?o.map(f=>i.value[f.toLowerCase()]).filter(f=>f!=null).map(f=>bo(f,t)):[],d=new Set,p=[];for(let f of u){let h=f.tokenAddress?.toLowerCase();!h||d.has(h)||(d.add(h),p.push(f))}let m=[];for(let f of l){let h=f.tokenAddress?.toLowerCase();!h||d.has(h)||(d.add(h),m.push(f))}let g=r!=null?[...p,...m].slice(0,r):[...p,...m.slice(0,n)];return await this.enrichTrendingMarketData(g,t),{success:!0,data:g}}catch(o){return{success:!1,error:o instanceof Error?o.message:"Unknown error"}}}async enrichTrendingMarketData(e,t){let n=e.filter(o=>o.tokenAddress&&(o.marketCap==null||o.totalVolume?.["24h"]==null));if(n.length===0)return;let r=await this.getTokensMetadata(n.map(o=>o.tokenAddress),t);for(let o of n){let s=r[o.tokenAddress.toLowerCase()];s&&(o.marketCap==null&&(o.marketCap=J(s.market_cap)??J(s.marketCap)),o.totalVolume?.["24h"]==null&&(o.totalVolume={"24h":J(s.total_volume)??J(s.volume24h)}))}}async fetchTopGainers(e,t,n="24h"){let r=zt(e),o=yo({duration:n,limit:t}),s=`${this.baseUrl}/token-list/top-gainers/${r}${o?`?${o}`:""}`,a=[];for(let i=0;i<5;i++){let l=await _.get(s);if(!l.ok)throw new Error(N(l));let u=l.data;if(a=Array.isArray(u)?u:Array.isArray(u.data)?u.data:[],a.length>0)break;i<4&&await new Promise(d=>setTimeout(d,2e3))}return a.map(i=>bo(i,e))}async getTopGainers(e){let t=e?.chain||he,n=e?.limit&&e.limit>0?Math.floor(e.limit):void 0,r=e?.duration||"24h";try{let o=await this.fetchTopGainers(t,n,r);return await this.enrichTrendingMarketData(o,t),{success:!0,data:o}}catch(o){return{success:!1,error:o instanceof Error?o.message:"Unknown error"}}}};var Nr="https://nft.keyring.app",Ir="https://nft-demo.keyring.app",Dr=.01,U=5,F=1e3,Lr="0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",Mr="0x0000000000000000000000000000000000000000";function V(c){return c||he}function $(c){let e=[];for(let[t,n]of Object.entries(c))if(n!=null)if(Array.isArray(n))for(let r of n)e.push(`${encodeURIComponent(t)}=${encodeURIComponent(String(r))}`);else e.push(`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`);return e.join("&")}function W(c){return new Promise(e=>setTimeout(e,c))}function Br(c){if(Array.isArray(c))return c;if(c&&typeof c=="object"){let e=c;return Array.isArray(e.result)?e.result.map(t=>({protocol_id:t.protocolId,protocol_name:t.protocolName,protocol_url:t.protocolUrl??"",protocol_logo:t.protocolLogo??"",position:{label:t.position.label,address:t.position.address,balance_usd:t.position.balanceUsd??0,total_unclaimed_usd_value:t.position.unclaimedUsd??0,position_details:t.position.details,tokens:t.position.tokens.map(n=>({token_type:n.tokenType,address:n.address,contract_address:n.address,name:n.name??"",symbol:n.symbol??"",decimals:n.decimals??18,logo:n.logo,balance:n.balance??"0",balance_formatted:n.balanceFormatted??"0",usd_price:n.usdPrice,usd_value:n.usdValue}))}})):Object.keys(e).filter(t=>/^\d+$/.test(t)).sort((t,n)=>Number(t)-Number(n)).map(t=>e[t]).filter(t=>!!t&&typeof t=="object")}return[]}function Hn(c){if(Array.isArray(c))return c;if(c&&typeof c=="object"){let e=c;return Array.isArray(e.result)?e.result:Object.keys(e).filter(t=>/^\d+$/.test(t)).sort((t,n)=>Number(t)-Number(n)).map(t=>e[t]).filter(t=>!!t&&typeof t=="object")}return[]}var E=class{baseUrl;v1BaseUrl;pantograph;constructor(e){this.baseUrl=(e?.baseUrl??Nr).replace(/\/+$/,""),this.v1BaseUrl=(e?.v1BaseUrl??Ir).replace(/\/+$/,""),this.pantograph=new Z({baseUrl:e?.pantographUrl})}async getWalletTokenBalances(e){let{address:t,chain:n,tokenAddresses:r,excludeSpam:o=!1,excludeUnverifiedContracts:s=!1}=e;if(!t)return{success:!1,error:"Address is required"};let a=V(n),i="Unknown error";for(let l=1;l<=U;l++)try{let u={chain:a,exclude_spam:o,exclude_unverified_contracts:s,limit:100};r&&(u.token_addresses=r);let d=[],p=null;do{p&&(u.cursor=p);let g=$(u),f=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/tokens?${g}`,h=await _.get(f);if(!h.ok)throw new Error(N(h));let y=h.data,k=y?.data??y;k?.result?.length>0&&d.push(...k.result),p=k?.cursor??null}while(p);let m={result:d};return m?.result?.length>0&&(m.result=m.result.filter(g=>parseFloat(g.balance||"0")>0),m.result=m.result.map(g=>({...g,token_address:g.token_address.toLowerCase()===Lr?Mr:g.token_address})),await this.enrichTokenPrices(m.result,a),m.result=m.result.filter(g=>g.usd_value==null||g.usd_value>=Dr)),{success:!0,data:m}}catch(u){i=u instanceof Error?u.message:"Unknown error",l<U&&await W(F)}return{success:!1,error:i}}async getTokenMetadata(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Token address is required"};let r=V(n),o="Unknown error",s=await this.pantograph.getTokenMetadata(t,r);if(s)return{success:!0,data:s};for(let a=1;a<=U;a++)try{let[i,l]=await Promise.allSettled([_.get(`${this.baseUrl}/api/moralis/proxy/erc20/metadata?${$({chain:r,addresses:[t]})}`),_.get(`${this.baseUrl}/api/moralis/proxy/erc20/${encodeURIComponent(t)}/price?${$({chain:r,include:"percent_change"})}`)]),u=null;if(i.status==="fulfilled"&&i.value.ok){let p=i.value.data;u=(Array.isArray(p)?p:Array.isArray(p?.data)?p.data:[])[0]??null}if(!u){o="Token metadata not found",a<U&&await W(F);continue}let d=null;if(l.status==="fulfilled"&&l.value.ok){let p=l.value.data;d=p?.data??p}return{success:!0,data:{...u,...d?.usd_price?{usd_price:d.usd_price}:{},...d?.usd_price_change_percentage_24h?{usd_price_change_percentage_24h:d.usd_price_change_percentage_24h}:{}}}}catch(i){o=i instanceof Error?i.message:"Unknown error",a<U&&await W(F)}return{success:!1,error:o}}async getWalletNFTs(e){let{address:t,chain:n,limit:r=10,excludeSpam:o=!0,cursor:s,tokenAddresses:a,includePrices:i,format:l="decimal"}=e;if(!t)return{success:!1,error:"Address is required"};let u=V(n),d="Unknown error";for(let p=1;p<=U;p++)try{let m={chain:u,format:l,limit:r,exclude_spam:o,media_items:!0,normalizeMetadata:!0};s&&(m.cursor=s),i&&(m.include_prices=!0),a&&a.length>0&&(m.token_addresses=a);let g=$(m),f=`${this.baseUrl}/api/moralis/proxy/${encodeURIComponent(t)}/nft?${g}`,h=await _.get(f);if(!h.ok)throw new Error(N(h));let y=h.data;return{success:!0,data:y?.data??y}}catch(m){d=m instanceof Error?m.message:"Unknown error",p<U&&await W(F)}return{success:!1,error:d}}async getNftMetadata(e){let{address:t,tokenId:n,chain:r,format:o="decimal",normalizeMetadata:s=!0,mediaItems:a=!0,include:i}=e;if(!t)return{success:!1,error:"NFT contract address is required"};if(n==null||n==="")return{success:!1,error:"Token ID is required"};if(!B(t))return{success:!1,error:"NFT metadata lookup by token ID is only supported on EVM chains"};let l=V(r),u="Unknown error";for(let d=1;d<=U;d++)try{let p={chain:l,format:o,normalizeMetadata:s,media_items:a};i&&(p.include=i);let m=$(p),g=`${this.baseUrl}/api/moralis/proxy/nft/${encodeURIComponent(t)}/${encodeURIComponent(n)}?${m}`,f=await _.get(g);if(!f.ok)throw new Error(N(f));let h=f.data;return{success:!0,data:h?.data??h}}catch(p){u=p instanceof Error?p.message:"Unknown error",d<U&&await W(F)}return{success:!1,error:u}}async getNftContractMetadata(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Contract address is required"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chain:r}),i=`${this.baseUrl}/api/moralis/proxy/nft/${encodeURIComponent(t)}/metadata?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getWalletHistory(e){let{address:t,chain:n,limit:r=25,fromDate:o,toDate:s,fromBlock:a,toBlock:i,cursor:l,order:u="DESC",includeInternalTransactions:d,nftMetadata:p}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet history is only supported for EVM addresses"};let m=V(n),g=Math.max(1,Math.min(100,Math.floor(r))),f="Unknown error";for(let h=1;h<=U;h++)try{let y={chain:m,limit:g,order:u};o&&(y.from_date=o),s&&(y.to_date=s),a!=null&&(y.from_block=a),i!=null&&(y.to_block=i),l&&(y.cursor=l),d!=null&&(y.include_internal_transactions=d),p!=null&&(y.nft_metadata=p);let k=$(y),w=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/history?${k}`,b=await _.get(w);if(!b.ok)throw new Error(N(b));let T=b.data;return{success:!0,data:T?.data??T}}catch(y){f=y instanceof Error?y.message:"Unknown error",h<U&&await W(F)}return{success:!1,error:f}}async getWalletTokenTransfers(e){let{address:t,chain:n,contractAddresses:r,limit:o=25,fromDate:s,toDate:a,fromBlock:i,toBlock:l,cursor:u,order:d="DESC"}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"ERC-20 transfers are only supported for EVM addresses"};let p=V(n),m=Math.max(1,Math.min(100,Math.floor(o))),g="Unknown error";for(let f=1;f<=U;f++)try{let h={chain:p,limit:m,order:d};s&&(h.from_date=s),a&&(h.to_date=a),i!=null&&(h.from_block=i),l!=null&&(h.to_block=l),u&&(h.cursor=u),r?.length&&(h.contract_addresses=r);let y=$(h),k=`${this.baseUrl}/api/moralis/proxy/${encodeURIComponent(t)}/erc20/transfers?${y}`,w=await _.get(k);if(!w.ok)throw new Error(N(w));let b=w.data;return{success:!0,data:b?.data??b}}catch(h){g=h instanceof Error?h.message:"Unknown error",f<U&&await W(F)}return{success:!1,error:g}}async getWalletNftTransfers(e){let{address:t,chain:n,contractAddresses:r,limit:o=25,fromDate:s,toDate:a,fromBlock:i,toBlock:l,cursor:u,order:d="DESC",includePrices:p,format:m="decimal"}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"NFT transfers are only supported for EVM addresses"};let g=V(n),f=Math.max(1,Math.min(100,Math.floor(o))),h="Unknown error";for(let y=1;y<=U;y++)try{let k={chain:g,limit:f,order:d,format:m};s&&(k.from_date=s),a&&(k.to_date=a),i!=null&&(k.from_block=i),l!=null&&(k.to_block=l),u&&(k.cursor=u),r?.length&&(k.contract_addresses=r),p!=null&&(k.include_prices=p);let w=$(k),b=`${this.baseUrl}/api/moralis/proxy/${encodeURIComponent(t)}/nft/transfers?${w}`,T=await _.get(b);if(!T.ok)throw new Error(N(T));let P=T.data;return{success:!0,data:P?.data??P}}catch(k){h=k instanceof Error?k.message:"Unknown error",y<U&&await W(F)}return{success:!1,error:h}}async getTokenHolders(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Contract address is required"};if(!B(t))return{success:!1,error:"Token holders is only supported for EVM contract addresses"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chain:r}),i=`${this.baseUrl}/api/moralis/proxy/erc20/${encodeURIComponent(t)}/holders?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getWalletNetWorth(e){let{address:t,chains:n,excludeSpam:r,excludeUnverifiedContracts:o,maxTokenInactivity:s,minPairSideLiquidityUsd:a}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet net worth is only supported for EVM addresses"};let i="Unknown error";for(let l=1;l<=U;l++)try{let u={};n&&n.length>0&&(u.chains=n.map(y=>V(y))),r!=null&&(u.exclude_spam=r),o!=null&&(u.exclude_unverified_contracts=o),s!=null&&(u.max_token_inactivity=s),a!=null&&(u.min_pair_side_liquidity_usd=a);let d=$(u),p=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/net-worth${d?`?${d}`:""}`,m=await _.get(p);if(!m.ok)throw new Error(N(m));let g=m.data;return{success:!0,data:g?.data??g}}catch(u){i=u instanceof Error?u.message:"Unknown error",l<U&&await W(F)}return{success:!1,error:i}}async getWalletPnlSummary(e){let{address:t,chain:n,days:r}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet PnL summary is only supported for EVM addresses"};let o=V(n),s="Unknown error";for(let a=1;a<=U;a++)try{let i={chain:o};r&&(i.days=r);let l=$(i),u=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/profitability/summary?${l}`,d=await _.get(u);if(!d.ok)throw new Error(N(d));let p=d.data;return{success:!0,data:p?.data??p}}catch(i){s=i instanceof Error?i.message:"Unknown error",a<U&&await W(F)}return{success:!1,error:s}}async getWalletPnl(e){let{address:t,chain:n,days:r,tokenAddresses:o}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet PnL is only supported for EVM addresses"};let s=V(n),a="Unknown error";for(let i=1;i<=U;i++)try{let l={chain:s};r&&(l.days=r),o&&o.length>0&&(l.token_addresses=o.slice(0,25));let u=$(l),d=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/profitability?${u}`,p=await _.get(d);if(!p.ok)throw new Error(N(p));let m=p.data;return{success:!0,data:m?.data??m}}catch(l){a=l instanceof Error?l.message:"Unknown error",i<U&&await W(F)}return{success:!1,error:a}}async getTransactionByHash(e){let{transactionHash:t,chain:n}=e;if(!t)return{success:!1,error:"Transaction hash is required"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chain:r}),i=`${this.baseUrl}/api/moralis/proxy/transaction/${encodeURIComponent(t)}/verbose?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getWalletApprovals(e){let{address:t,chain:n,limit:r,cursor:o}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet approvals are only supported for EVM addresses"};let s=V(n),a="Unknown error";for(let i=1;i<=U;i++)try{let l={chain:s};r!=null&&(l.limit=r),o&&(l.cursor=o);let u=$(l),d=`${this.baseUrl}/api/moralis/proxy/wallets/${encodeURIComponent(t)}/approvals?${u}`,p=await _.get(d);if(!p.ok)throw new Error(N(p));let m=p.data;return{success:!0,data:m?.data??m}}catch(l){a=l instanceof Error?l.message:"Unknown error",i<U&&await W(F)}return{success:!1,error:a}}async getWalletDefiSummary(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet DeFi summary is only supported for EVM addresses"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chains:r}),i=`${this.v1BaseUrl}/api/moralis-v1/proxy/wallets/${encodeURIComponent(t)}/defi/summary?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getWalletDefiPositions(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Address is required"};if(!B(t))return{success:!1,error:"Wallet DeFi positions are only supported for EVM addresses"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chains:r}),i=`${this.v1BaseUrl}/api/moralis-v1/proxy/wallets/${encodeURIComponent(t)}/defi/positions?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data,d=u?.data??u;return{success:!0,data:Br(d)}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getWalletDefiProtocolPositions(e){let{address:t,protocol:n,chain:r}=e;if(!t)return{success:!1,error:"Address is required"};if(!n)return{success:!1,error:"Protocol identifier is required"};if(!B(t))return{success:!1,error:"Wallet DeFi protocol positions are only supported for EVM addresses"};let o=V(r),s="Unknown error";for(let a=1;a<=U;a++)try{let i=$({chains:o}),l=`${this.v1BaseUrl}/api/moralis-v1/proxy/wallets/${encodeURIComponent(t)}/defi/${encodeURIComponent(n)}/positions?${i}`,u=await _.get(l);if(!u.ok)throw new Error(N(u));let m=u.data.result;return{success:!0,data:{protocol_id:m.protocolId,protocol_name:m.protocolName,protocol_url:m.protocolUrl??"",protocol_logo:m.protocolLogo??"",total_usd_value:m.totalUsd??0,total_unclaimed_usd_value:m.totalUnclaimedUsd??null,positions:m.positions.map(f=>({label:f.label,address:f.address,balance_usd:f.balanceUsd??0,total_unclaimed_usd_value:f.unclaimedUsd??0,position_details:f.details,tokens:f.tokens.map(h=>({token_type:h.tokenType,address:h.address,contract_address:h.address,name:h.name??"",symbol:h.symbol??"",decimals:h.decimals??18,logo:h.logo,balance:h.balance??"0",balance_formatted:h.balanceFormatted??"0",usd_price:h.usdPrice,usd_value:h.usdValue}))}))}}}catch(i){s=i instanceof Error?i.message:"Unknown error",a<U&&await W(F)}return{success:!1,error:s}}async searchTokensByKey(e){return this.pantograph.searchTokensByKey(e)}async getTokenAnalytics(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Token contract address is required"};if(!B(t))return{success:!1,error:"Token analytics is only supported for EVM contract addresses"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chain:r}),i=`${this.baseUrl}/api/moralis/proxy/tokens/${encodeURIComponent(t)}/analytics?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getTokenScore(e){let{address:t,chain:n}=e;if(!t)return{success:!1,error:"Token contract address is required"};if(!B(t))return{success:!1,error:"Token score is only supported for EVM contract addresses"};let r=V(n),o="Unknown error";for(let s=1;s<=U;s++)try{let a=$({chain:r}),i=`${this.baseUrl}/api/moralis/proxy/tokens/${encodeURIComponent(t)}/score?${a}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data;return{success:!0,data:u?.data??u}}catch(a){o=a instanceof Error?a.message:"Unknown error",s<U&&await W(F)}return{success:!1,error:o}}async getTrendingTokens(e){let t=e?.chain,n=e?.limit,r="Unknown error";for(let o=1;o<=U;o++)try{let s={};t&&(s.chain=V(t)),n!=null&&(s.limit=n);let a=$(s),i=`${this.baseUrl}/api/moralis/proxy/tokens/trending${a?`?${a}`:""}`,l=await _.get(i);if(!l.ok)throw new Error(N(l));let u=l.data,d=u?.data??u;return{success:!0,data:Hn(d)}}catch(s){r=s instanceof Error?s.message:"Unknown error",o<U&&await W(F)}return{success:!1,error:r}}async getTopGainers(e){let{chain:t,timeFrame:n,minMarketCap:r,securityScore:o}=e??{},s="Unknown error";for(let a=1;a<=U;a++)try{let i={};t&&(i.chain=V(t)),n&&(i.time_frame=n),r!=null&&(i.min_market_cap=r),o!=null&&(i.security_score=o);let l=$(i),u=`${this.baseUrl}/api/moralis/proxy/discovery/tokens/top-gainers${l?`?${l}`:""}`,d=await _.get(u);if(!d.ok)throw new Error(N(d));let p=d.data,m=p?.data??p;return{success:!0,data:Hn(m)}}catch(i){s=i instanceof Error?i.message:"Unknown error",a<U&&await W(F)}return{success:!1,error:s}}async getTopLosers(e){let{chain:t,timeFrame:n,minMarketCap:r,securityScore:o}=e??{},s="Unknown error";for(let a=1;a<=U;a++)try{let i={};t&&(i.chain=V(t)),n&&(i.time_frame=n),r!=null&&(i.min_market_cap=r),o!=null&&(i.security_score=o);let l=$(i),u=`${this.baseUrl}/api/moralis/proxy/discovery/tokens/top-losers${l?`?${l}`:""}`,d=await _.get(u);if(!d.ok)throw new Error(N(d));let p=d.data,m=p?.data??p;return{success:!0,data:Hn(m)}}catch(i){s=i instanceof Error?i.message:"Unknown error",a<U&&await W(F)}return{success:!1,error:s}}async enrichTokenPrices(e,t){return this.pantograph.enrichTokenPrices(e,t)}};var Ke=class extends v{name="get-token-info";description='Get information about a specific cryptocurrency token: price, metadata, 24h change, market data, and user holdings. Use this when the user asks about: token price, token info, "what is X token", "tell me about X", "how much is X worth", or any token-specific question. Supports: Ethereum, Optimism, BSC, Polygon, Base, Arbitrum, Avalanche, Linea';category="blockchain-data";parameters=[{name:"keyword",type:"string",description:'Token symbol, name, or contract address (e.g. "USDC", "Pepe", "ETH", "0x1234\u2026"). If a 0x address is provided, performs a precise contract lookup. Otherwise searches by name/symbol.',required:!0},{name:"chain",type:"string",description:'Hex chain ID: "0x1" Ethereum, "0xa" Optimism, "0x38" BSC, "0x89" Polygon, "0x2105" Base, "0xa4b1" Arbitrum, "0xa86a" Avalanche, "0xe708" Linea. ONLY set this when the user EXPLICITLY names a chain; otherwise OMIT it so the connected wallet chain is used.',required:!1},{name:"prompt",type:"string",description:`A rich, multi-angle research prompt sent to Gemini with Google Search grounding (real-time web access). The prompt must be self-contained \u2014 Gemini does NOT see the user's original message, only this prompt. ALWAYS include: the token symbol/name, the chain, and an instruction to use web search for up-to-date info. When the user asks an open/broad question (e.g. "show me X", "tell me about X", "what is X"), expand the prompt to cover ALL of these angles in one request: (1) what the token/project is and its core utility, (2) current USD price, 24h change, market cap, FDV, 24h volume, (3) recent news, announcements, or notable events in the last 7-30 days, (4) on-chain activity signals (holders, liquidity, unusual flows), (5) team/protocol updates or roadmap items, (6) key risks, red flags, or controversies, (7) sentiment and notable community discussion. When the user asks a narrow question (e.g. "price of X"), still include 2-3 supporting angles for context. Aim for 3-6 sentences. Be specific to the token. Do not use generic filler. Example for "show me JPYT": "Research the JPYT token on Ethereum using up-to-date web sources. Cover: what JPYT is and who issues it; current USD price, 24h change, market cap, FDV, and 24h volume; recent news or announcements in the last 30 days; on-chain signals such as holder count, liquidity, and unusual volume patterns; team or protocol updates; key risks or red flags; and overall sentiment."`,required:!0},{name:"buy_button_label",type:"string",description:`Label for the "Buy" suggestion button shown under the token info, IN THE USER'S CURRENT LANGUAGE. Use the exact placeholder "{token}" (do not translate the braces) for the token symbol; put the localized verb directly in the text. English example: "Buy {token}". Vietnamese example: "Mua {token}". Japanese example: "{token} \u8CFC\u5165". Always include {token}.`,required:!0},{name:"buy_prompt_template",type:"string",description:`A short "buy" command IN THE USER'S CURRENT LANGUAGE, submitted as the next user turn when the Buy button is clicked. Use the exact placeholder "{token}" (do not translate the braces) for the token symbol; put the localized verb directly in the text. English example: "buy {token}". Vietnamese example: "mua {token}". Japanese example: "{token} \u8CFC\u5165". Always include {token}.`,required:!0}];service;llm;constructor(e){super(),this.service=new E(e),this.llm=new pe({})}async run(e,t){let n=e.keyword||"",r=R(e.chain,t),o=e.prompt||"",s=e.buy_button_label||"",a=e.buy_prompt_template||"",i=t?.walletAddress||void 0;return n?await this.searchToken(n,r,o,s,a,i):{error:"Missing required parameter: keyword"}}async execute(e,t){let n=await super.execute(e,t),r=n.data;return n.success&&r&&Array.isArray(r.actionButtons)&&r.actionButtons.length>0&&(n.actionButtons=r.actionButtons),n}async searchToken(e,t,n,r,o,s){let a=[s?`User's connected wallet address: ${s}`:null,t?`Current chain (hex chain ID): ${t}, only consider tokens on this chain`:null,"Use this context to personalize your answer where relevant (e.g. whether the user holds the token, chain-specific data)."].filter(Boolean).join(`
|
|
3
3
|
`),[i,l,u]=await Promise.all([this.service.searchTokensByKey({key:e,chain:t}),s?this.findTokenInWallet(s,t,e):Promise.resolve(null),n?this.askGeminiWithSearch(n,a):Promise.resolve(null)]),d=i.success&&i.data?Array.isArray(i.data)?i.data:[]:[],p=e.toLowerCase(),m=b=>b.symbol?.toLowerCase()===p||b.token_address?.toLowerCase()===p,g=[...d].sort((b,T)=>(m(b)?0:1)-(m(T)?0:1)),f=null,h=g[0];if(h?.token_address){let b=await this.service.getTokenMetadata({address:h.token_address,chain:t});b.success&&b.data&&(f=b.data)}!f&&h&&(f={...h});let y=f?.symbol?.trim(),k=y?[{label:this.fillTemplate(r,y,"Buy {token}"),prompt:this.fillTemplate(o,y,"buy {token}")}]:[];return{_instructions:'Present the token info in a clear summary. Include: token name & symbol, contract address (shortened), current USD price, 24h price change % (prefix "+" for positive, "-" for negative), market cap, fully diluted valuation, 24h trading volume, liquidity, and holder count (if available). If the user holds this token, prominently show their balance and USD value. If research is present, weave its substance naturally into your answer \u2014 fold the relevant points into the description, context, and any notable news or risks. Do NOT add a labelled "AI Analysis" section or any similar heading, and do NOT mention that the analysis came from AI; just write it as part of the token summary. Format numbers in a human-readable way (e.g. $1.23, +5.67%, $12.5M). If a field is null, omit it. A "Buy" button is shown below your reply automatically \u2014 do NOT mention it, list it, or repeat its text.',chain:t,userHoldsToken:!!l,walletBalance:l,token:f,...d.length>1?{searchResults:g.slice(0,10)}:{},research:u,...k.length>0?{actionButtons:k}:{}}}fillTemplate(e,t,n){return(e&&e.includes("{token}")?e:n).replace(/\{token\}/g,t).replace(/\s+/g," ").trim()}async askGeminiWithSearch(e,t){let n=Date.now();try{return(await this.llm.chat([...t?[{role:"system",content:t,timestamp:n}]:[],{role:"user",content:e,timestamp:n}],void 0,{googleSearch:!0,maxRetries:1})).text?.trim()||null}catch{return null}}async findTokenInWallet(e,t,n){if(!n)return null;let r=await this.service.getWalletTokenBalances({address:e,chain:t,excludeSpam:!0,excludeUnverifiedContracts:!0});if(!r.success||!r.data?.result)return null;let o=n.toLowerCase(),s=r.data.result.find(a=>a.token_address.toLowerCase()===o||a.symbol?.toLowerCase()===o||a.name?.toLowerCase().includes(o));return s||null}};var Ye=class extends v{name="get-token-holders";description='Get holder statistics and analytics for an ERC-20 token. Returns: total holder count, holder count changes over time (5min/1h/6h/24h/3d/7d/30d), how holders acquired the token (swap/transfer/airdrop), supply concentration (% held by top 10/25/50/100/250/500 holders), and holder size distribution (whales, sharks, dolphins, fish, octopus, crabs, shrimps). Use tokenSymbol (e.g. "USDC") to look up by name \u2014 the tool auto-resolves the contract address. Use contractAddress when you already have the exact 0x address. Use this tool for questions like: "How many holders does USDC have?" (tokenSymbol=USDC), "Is USDC gaining or losing holders?" (tokenSymbol=USDC \u2192 holderChange), "How many new holders did ETH get in the last 7 days?" (tokenSymbol=WETH), "How concentrated is USDC ownership?" (tokenSymbol=USDC \u2192 holderSupply), "What % of supply do the top 10 holders control?" (tokenSymbol=USDC), "How many whales hold USDT?" (tokenSymbol=USDT \u2192 holderDistribution), "Did most holders buy via swap or transfer?" (tokenSymbol=USDC \u2192 holdersByAcquisition). Supports: Ethereum, Optimism, BSC, Polygon, Base, Arbitrum, Avalanche, Linea. ';category="blockchain-data";parameters=[{name:"tokenSymbol",type:"string",description:`Token symbol (e.g. "USDC", "USDT", "WETH"). The tool resolves the contract address automatically: first checks the connected wallet's balances, then searches by symbol. Takes precedence over contractAddress when both are given.`,required:!1},{name:"contractAddress",type:"string",description:"ERC-20 token contract address (0x\u2026). Use when the exact address is already known. Ignored if tokenSymbol is provided.",required:!1},{name:"chain",type:"string",description:'Hex chain ID: "0x1" Ethereum, "0xa" Optimism, "0x38" BSC, "0x89" Polygon, "0x2105" Base, "0xa4b1" Arbitrum, "0xa86a" Avalanche, "0xe708" Linea . ONLY set this when the user EXPLICITLY names a chain; otherwise OMIT it so the connected wallet chain is used.',required:!1}];service;constructor(e){super(),this.service=new E(e)}async run(e,t){let n=R(e.chain,t),r=t?.walletAddress||void 0,o=typeof e.tokenSymbol=="string"&&e.tokenSymbol?e.tokenSymbol.trim():void 0,s=typeof e.contractAddress=="string"&&e.contractAddress?e.contractAddress.trim():void 0;if(!o&&!s)return{error:'Provide either tokenSymbol (e.g. "USDC") or contractAddress (0x\u2026).'};let a,i;if(o){let d=await this.resolveContractAddress(o,n,r);if(!d)return{error:`Cannot resolve token symbol "${o}" to a contract address on ${n?L(n):"the selected chain"}. Try passing contractAddress directly.`};s=d.address,a=d.symbol,i=d.name}let l=await this.service.getTokenHolders({address:s,chain:n});if(!l.success)return{error:l.error||"Failed to fetch token holder stats"};let u=l.data;return{token:{symbol:a??o??null,name:i??null,contractAddress:s,chain:n||"default"},totalHolders:u.totalHolders,holdersByAcquisition:u.holdersByAcquisition,holderChange:u.holderChange,holderSupply:u.holderSupply,holderDistribution:u.holderDistribution}}async resolveContractAddress(e,t,n){let r=e.toLowerCase();if(n){let s=await this.service.getWalletTokenBalances({address:n,chain:t});if(s.success&&s.data?.result?.length){let a=s.data.result.find(i=>(i.symbol??"").toLowerCase()===r);if(a)return{address:a.token_address,symbol:a.symbol,name:a.name}}}let o=await this.service.searchTokensByKey({key:e,chain:t});if(o.success&&o.data?.length){let a=o.data.find(i=>(i.symbol??"").toLowerCase()===r)??o.data[0];if(a?.token_address)return{address:a.token_address,symbol:a.symbol,name:a.name}}}};var je=class extends v{name="get-token-analytics";description=`Get detailed trading analytics for a single ERC-20 token, broken down across 5min / 1h / 6h / 24h windows. Returns: buy volume, sell volume, unique buyers, unique sellers, buy/sell transaction counts, unique wallets, price % change, current USD price, total liquidity and fully-diluted valuation (FDV). Use tokenSymbol (e.g. "PEPE") to look up by name \u2014 the tool auto-resolves the contract address. Use contractAddress when you already have the exact 0x address. Use this tool for questions like: "How is PEPE trading today?" (tokenSymbol=PEPE), "24h buy vs sell volume for USDC?" (tokenSymbol=USDC \u2192 totalBuyVolume vs totalSellVolume), "Is buying or selling pressure stronger for this token?", "How many unique wallets touched this token in the last hour?" (\u2192 uniqueWallets.1h), "What's the FDV and liquidity of X?" (\u2192 totalFullyDilutedValuation, totalLiquidity), "Price change over 6h?" (\u2192 pricePercentChange.6h). Supports: Ethereum, Optimism, BSC, Polygon, Base, Arbitrum, Avalanche, Linea.`;category="blockchain-data";parameters=[{name:"tokenSymbol",type:"string",description:`Token symbol (e.g. "PEPE", "USDC", "WETH"). The tool resolves the contract address automatically: first checks the connected wallet's balances, then searches by symbol. Takes precedence over contractAddress when both are given.`,required:!1},{name:"contractAddress",type:"string",description:"ERC-20 token contract address (0x\u2026). Use when the exact address is already known. Ignored if tokenSymbol is provided.",required:!1},{name:"chain",type:"string",description:'Hex chain ID: "0x1" Ethereum, "0xa" Optimism, "0x38" BSC, "0x89" Polygon, "0x2105" Base, "0xa4b1" Arbitrum, "0xa86a" Avalanche, "0xe708" Linea. ONLY set this when the user EXPLICITLY names a chain; otherwise OMIT it so the connected wallet chain is used.',required:!1}];service;constructor(e){super(),this.service=new E(e)}async run(e,t){let n=R(e.chain,t),r=t?.walletAddress||void 0,o=typeof e.tokenSymbol=="string"&&e.tokenSymbol?e.tokenSymbol.trim():void 0,s=typeof e.contractAddress=="string"&&e.contractAddress?e.contractAddress.trim():void 0;if(!o&&!s)return{error:'Provide either tokenSymbol (e.g. "PEPE") or contractAddress (0x\u2026).'};let a,i;if(o){let d=await this.resolveContractAddress(o,n,r);if(!d)return{error:`Cannot resolve token symbol "${o}" to a contract address on ${n?L(n):"the selected chain"}. Try passing contractAddress directly.`};s=d.address,a=d.symbol,i=d.name}let l=await this.service.getTokenAnalytics({address:s,chain:n});if(!l.success)return{error:l.error||"Failed to fetch token analytics"};let u=l.data??{};return{token:{symbol:a??o??null,name:i??null,contractAddress:s,chain:n||"default"},usdPrice:u.usdPrice??null,totalLiquidity:u.totalLiquidity??null,totalFullyDilutedValuation:u.totalFullyDilutedValuation??null,totalBuyVolume:u.totalBuyVolume??null,totalSellVolume:u.totalSellVolume??null,totalBuyers:u.totalBuyers??null,totalSellers:u.totalSellers??null,totalBuys:u.totalBuys??null,totalSells:u.totalSells??null,uniqueWallets:u.uniqueWallets??null,pricePercentChange:u.pricePercentChange??null}}async resolveContractAddress(e,t,n){let r=e.toLowerCase();if(n){let s=await this.service.getWalletTokenBalances({address:n,chain:t});if(s.success&&s.data?.result?.length){let a=s.data.result.find(i=>(i.symbol??"").toLowerCase()===r);if(a)return{address:a.token_address,symbol:a.symbol,name:a.name}}}let o=await this.service.searchTokensByKey({key:e,chain:t});if(o.success&&o.data?.length){let a=o.data.find(i=>(i.symbol??"").toLowerCase()===r)??o.data[0];if(a?.token_address)return{address:a.token_address,symbol:a.symbol,name:a.name}}}};var ze=class extends v{name="get-token-score";description=`Get a composite 0\u2013100 health/safety score for a single ERC-20 token, plus the metrics behind it. Returns: overall score, last-updated timestamp, current USD price, paired liquidity, multi-timeframe volume buckets (10m / 30m / 1h / 4h / 12h / 1d / 7d / 30d), same buckets for transaction counts, and supply info (total supply + % held by top 10 holders). Use tokenSymbol (e.g. "PEPE") to look up by name \u2014 the tool auto-resolves the contract address. Use contractAddress when you already have the exact 0x address. Use this tool for questions like: "Is PEPE a safe token?" (tokenSymbol=PEPE \u2192 score), "What's the health/score of USDC?", "How concentrated is X's supply among whales?" (\u2192 metrics.supply.top10Percent), "How much volume did this token do over the last 7 days?" (\u2192 metrics.volumeUsd.7d), "Transaction count for this token in the last hour?" (\u2192 metrics.transactions.1h). Supports: Ethereum, Optimism, BSC, Polygon, Base, Arbitrum, Avalanche, Linea.`;category="blockchain-data";parameters=[{name:"tokenSymbol",type:"string",description:`Token symbol (e.g. "PEPE", "USDC", "WETH"). The tool resolves the contract address automatically: first checks the connected wallet's balances, then searches by symbol. Takes precedence over contractAddress when both are given.`,required:!1},{name:"contractAddress",type:"string",description:"ERC-20 token contract address (0x\u2026). Use when the exact address is already known. Ignored if tokenSymbol is provided.",required:!1},{name:"chain",type:"string",description:'Hex chain ID: "0x1" Ethereum, "0xa" Optimism, "0x38" BSC, "0x89" Polygon, "0x2105" Base, "0xa4b1" Arbitrum, "0xa86a" Avalanche, "0xe708" Linea. ONLY set this when the user EXPLICITLY names a chain; otherwise OMIT it so the connected wallet chain is used.',required:!1}];service;constructor(e){super(),this.service=new E(e)}async run(e,t){let n=R(e.chain,t),r=t?.walletAddress||void 0,o=typeof e.tokenSymbol=="string"&&e.tokenSymbol?e.tokenSymbol.trim():void 0,s=typeof e.contractAddress=="string"&&e.contractAddress?e.contractAddress.trim():void 0;if(!o&&!s)return{error:'Provide either tokenSymbol (e.g. "PEPE") or contractAddress (0x\u2026).'};let a,i;if(o){let p=await this.resolveContractAddress(o,n,r);if(!p)return{error:`Cannot resolve token symbol "${o}" to a contract address on ${n?L(n):"the selected chain"}. Try passing contractAddress directly.`};s=p.address,a=p.symbol,i=p.name}let l=await this.service.getTokenScore({address:s,chain:n});if(!l.success)return{error:l.error||"Failed to fetch token score"};let u=l.data??{},d=u.metrics??{};return{token:{symbol:a??o??null,name:i??null,contractAddress:s,chain:n||"default"},score:u.score??null,updatedAt:u.updatedAt??null,metrics:{usdPrice:d.usdPrice??null,liquidityUsd:d.liquidityUsd??null,volumeUsd:d.volumeUsd??null,transactions:d.transactions??null,supply:d.supply??null}}}async resolveContractAddress(e,t,n){let r=e.toLowerCase();if(n){let s=await this.service.getWalletTokenBalances({address:n,chain:t});if(s.success&&s.data?.result?.length){let a=s.data.result.find(i=>(i.symbol??"").toLowerCase()===r);if(a)return{address:a.token_address,symbol:a.symbol,name:a.name}}}let o=await this.service.searchTokensByKey({key:e,chain:t});if(o.success&&o.data?.length){let a=o.data.find(i=>(i.symbol??"").toLowerCase()===r)??o.data[0];if(a?.token_address)return{address:a.token_address,symbol:a.symbol,name:a.name}}}};var Qe=class extends v{name="get-trending-tokens";description='List tokens trending on-chain right now, ranked by trading activity, volume, liquidity and holder growth. Returns price, market cap, liquidity, holder count, and multi-timeframe buckets (1h / 4h / 12h / 24h) of price change, volume, transaction counts, and unique buyers/sellers. Cross-chain by default \u2014 omit `chain` for a global ranking, or pass it to filter to one network. Use this tool for questions like: "What tokens are trending right now?", "Show me hot tokens", "What\'s popular on Base today?", "Which tokens have the highest 24h volume?", "Biggest movers in the last hour?". Supports: Ethereum, Optimism, BSC, Polygon, Base, Arbitrum, Avalanche, Linea, and more.';category="blockchain-data";parameters=[{name:"chain",type:"string",description:'Optional hex chain ID to scope results to a single network: "0x1" Ethereum, "0xa" Optimism, "0x38" BSC, "0x89" Polygon, "0x2105" Base, "0xa4b1" Arbitrum, "0xa86a" Avalanche, "0xe708" Linea. ONLY set this when the user names a chain. Omit to return cross-chain trending results.',required:!1},{name:"limit",type:"number",description:'Total number of trending tokens to return (chain default tokens + top gainers combined). Only set this when the user asks for a specific count (e.g. "show 20 trending tokens" \u2192 20). Omit otherwise \u2014 when omitted, returns all default tokens plus 5 top gainers.',required:!1},{name:"buy_button_label",type:"string",description:`Label template for the per-token "Buy" suggestion buttons, IN THE USER'S CURRENT LANGUAGE. One button is rendered per trending token, with "{token}" replaced by that token's symbol. Use the exact placeholder "{token}" (do not translate the braces); put the localized verb in the text. English example: "Buy {token}". Vietnamese example: "Mua {token}". Japanese example: "{token} \u8CFC\u5165". Always include {token}.`,required:!0},{name:"buy_prompt_template",type:"string",description:`A short "buy" command template IN THE USER'S CURRENT LANGUAGE, submitted as the next user turn when a token's Buy button is clicked. "{token}" is replaced by that token's symbol. Use the exact placeholder "{token}" (do not translate the braces); put the localized verb in the text. English example: "buy {token}". Vietnamese example: "mua {token}". Japanese example: "{token} \u8CFC\u5165". Always include {token}.`,required:!0}];service;constructor(e){super(),this.service=new Z({baseUrl:e?.pantographUrl})}async run(e,t){let n=hn(e.chain,t),r=e.buy_button_label||"",o=e.buy_prompt_template||"",s=typeof e.limit=="number"&&Number.isFinite(e.limit)&&e.limit>0?Math.floor(e.limit):void 0,a=await this.service.getTrendingTokens({chain:n,limit:s});if(!a.success)return{error:a.error||"Failed to fetch trending tokens"};let i=a.data??[],l=new Set,u=[];for(let d of i){let p=d.symbol?.trim();!p||l.has(p.toLowerCase())||(l.add(p.toLowerCase()),u.push({label:this.fillTemplate(r,p,"Buy {token}"),prompt:this.fillTemplate(o,p,"buy {token}")}))}return{_instructions:`Start with a one-line header like "Here are some of the top trending tokens on <chain name> right now:". Then present the tokens as a numbered list. For EACH token render exactly these lines (omit any line whose value is null):
|
|
4
4
|
<rank>. <name> (<symbol>)
|
|
@@ -585,6 +585,13 @@ CAPABILITIES (tools you own):
|
|
|
585
585
|
- Position lookup by Uniswap V3 NFT id ("position 962961", "pool id 12345", "tell me about position 962961")
|
|
586
586
|
- Concentrated-liquidity price-range candidates for a token pair ("what price range for ETH/USDC?", "best range for USDC/WETH", "g\u1EE3i \xFD kho\u1EA3ng gi\xE1 ETH/USDC")
|
|
587
587
|
|
|
588
|
+
AI FALLBACK (mandatory when no subgraph tool above fits):
|
|
589
|
+
- gemini-search-ai \u2014 a search-grounded Gemini model that answers Uniswap / DeFi pool questions.
|
|
590
|
+
- Use it for broad, conceptual, or protocol-level pool questions that none of the subgraph tools can serve ("tell me about Uniswap pools", "how do Uniswap V3 pools work", "what is concentrated liquidity", "is Uniswap safe").
|
|
591
|
+
- You MUST call a tool every turn. If no subgraph tool fits, call gemini-search-ai \u2014 NEVER answer a pool question from your own knowledge.
|
|
592
|
+
- A gemini-search-ai answer is NOT subgraph data: do NOT prefix it with "According to the latest data from Subgraph Uniswap V3".
|
|
593
|
+
- Build the fallback prompt as a clear, self-contained English instruction with the chain and any token symbols / addresses embedded (the model does not see this conversation). Defaults when vague: chain = Ethereum (or chain from user context), count = top 10, time = last 24h, sort = 24h volume for "top / best / trending".
|
|
594
|
+
|
|
588
595
|
OUT OF SCOPE \u2014 do NOT handle these:
|
|
589
596
|
- "my LP positions" / "my liquidity" / wallet-wide LP list \u2192 tell the user politely this subagent does not handle wallet-scoped LP data.
|
|
590
597
|
- "send / transfer my LP position" \u2192 not handled.
|
|
@@ -639,7 +646,7 @@ FOLLOW-UPS / CONTINUATIONS:
|
|
|
639
646
|
NEVER fabricate pool addresses, token prices, APRs, or position ids. Every value must come from a tool call this turn or the immediately preceding turn.`;function aa(c){return c?`${jo}
|
|
640
647
|
|
|
641
648
|
ADD-LIQUIDITY LINK:
|
|
642
|
-
- If the user mentions adding liquidity / adding a pool / adding a position (including phrases like "add liquidity", "add pool", "add position", "create pool", "create pair", "th\xEAm thanh kho\u1EA3n", "th\xEAm pool", "th\xEAm position"), keep your normal answer content and append this exact link at the end of the response: ${c}`:jo}var zo=["subgraph-search-pools","subgraph-trending-pools","subgraph-pool-by-address","subgraph-pool-by-position-id","subgraph-position-detail","subgraph-coinpool-pairs"];function eo(c,e,t){return new Y({name:"pool-subgraph-agent",domain:"pool",description:["Answers questions about Uniswap V3 liquidity pools using The Graph subgraphs as the primary source","(APR is enriched from DefiLlama Yields; concentrated-liquidity price ranges come from CoinPool).","Scope: (1) pool search by token symbols on one or more EVM chains, with TVL/APR/fee filters and sort by tvl/volume/apr/fee/liquidity;","(2) trending pools ranked by 24h volume on a chain;","(3) pool detail for a specific 0x pool address;","(4) lookup the underlying pool for a Uniswap V3 NFT position id (numeric, e.g. 962961);","(5) full position detail (deposits, withdrawals, collected fees) for a numeric position id;","(6) CoinPool concentrated-liquidity price-range candidates with per-range APR for a token pair.",'NOT in scope: wallet-wide LP holdings ("my positions"), sending/transferring LP NFTs, add-liquidity action flows,',"token metadata (\u2192 token-agent), NFT data (\u2192 nft-agent).","Prefer this subagent over pool-agent when the deployment is configured to use Subgraph data (the two are mutually exclusive at config time)."].join(" "),toolNames:[...zo],systemPrompt:aa(t?.linkAddLiquidity),llm:c,registry:e,options:t})}var ia=`Call exactly ONE tool every turn \u2014 ALWAYS, even for a bare verb with no details ("send token", "buy", "approve"). Never reply in text and never ask the user for missing fields (token, amount, recipient): the tool opens a picker/form that collects them.
|
|
649
|
+
- If the user mentions adding liquidity / adding a pool / adding a position (including phrases like "add liquidity", "add pool", "add position", "create pool", "create pair", "th\xEAm thanh kho\u1EA3n", "th\xEAm pool", "th\xEAm position"), keep your normal answer content and append this exact link at the end of the response: ${c}`:jo}var zo=["subgraph-search-pools","subgraph-trending-pools","subgraph-pool-by-address","subgraph-pool-by-position-id","subgraph-position-detail","subgraph-coinpool-pairs","gemini-search-ai"];function eo(c,e,t){return new Y({name:"pool-subgraph-agent",domain:"pool",description:["Answers questions about Uniswap V3 liquidity pools using The Graph subgraphs as the primary source","(APR is enriched from DefiLlama Yields; concentrated-liquidity price ranges come from CoinPool).","Scope: (1) pool search by token symbols on one or more EVM chains, with TVL/APR/fee filters and sort by tvl/volume/apr/fee/liquidity;","(2) trending pools ranked by 24h volume on a chain;","(3) pool detail for a specific 0x pool address;","(4) lookup the underlying pool for a Uniswap V3 NFT position id (numeric, e.g. 962961);","(5) full position detail (deposits, withdrawals, collected fees) for a numeric position id;","(6) CoinPool concentrated-liquidity price-range candidates with per-range APR for a token pair.",'NOT in scope: wallet-wide LP holdings ("my positions"), sending/transferring LP NFTs, add-liquidity action flows,',"token metadata (\u2192 token-agent), NFT data (\u2192 nft-agent).","Prefer this subagent over pool-agent when the deployment is configured to use Subgraph data (the two are mutually exclusive at config time)."].join(" "),toolNames:[...zo],systemPrompt:aa(t?.linkAddLiquidity),cortexFallbackTool:"gemini-search-ai",llm:c,registry:e,options:t})}var ia=`Call exactly ONE tool every turn \u2014 ALWAYS, even for a bare verb with no details ("send token", "buy", "approve"). Never reply in text and never ask the user for missing fields (token, amount, recipient): the tool opens a picker/form that collects them.
|
|
643
650
|
|
|
644
651
|
Tools:
|
|
645
652
|
- open-send-native-form \u2014 native coin (ETH/BNB/MATIC/\u2026)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyring-agent-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "Core AI chat agent with multi-agent architecture, ReAct pattern, and modular tool system powered by Gemini",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"react-native": "dist/index.js",
|