@avalabs/svm-module 1.4.6 → 1.5.0

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.cjs CHANGED
@@ -1,11 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  var vmModuleTypes = require('@avalabs/vm-module-types');
4
- require('@solana/rpc');
5
4
  var rpcErrors = require('@metamask/rpc-errors');
5
+ var coreCoingeckoSdk = require('@avalabs/core-coingecko-sdk');
6
+ var zod = require('zod');
7
+ var base = require('@scure/base');
8
+ var coreWalletsSdk = require('@avalabs/core-wallets-sdk');
9
+ var coreUtilsSdk = require('@avalabs/core-utils-sdk');
10
+ var kit = require('@solana/kit');
11
+ var system = require('@solana-program/system');
12
+ var token = require('@solana-program/token');
6
13
 
7
- var m=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var a=(r,e,t)=>(m(r,e,"read from private field"),t?t.call(r):e.get(r)),i=(r,e,t)=>{if(e.has(r))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(r):e.set(r,t);},c=(r,e,t,p)=>(m(r,e,"write to private field"),p?p.call(r,t):e.set(r,t),t);var l={name:"SVM",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/svm-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1","solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"],namespaces:["solana"]},cointype:"501",permissions:{rpc:{dapps:!0,methods:["getGenesisHash"],nonRestrictedMethods:["getGenesisHash"]}},manifestVersion:"0.1"};var f={proxyApiUrl:"https://proxy-api.avax.network"},g={proxyApiUrl:"https://proxy-api-dev.avax.network"},u=r=>{switch(r){case vmModuleTypes.Environment.PRODUCTION:return f;case vmModuleTypes.Environment.DEV:return g}};var o,s,n,d=class{constructor({approvalController:e,environment:t,appInfo:p}){i(this,o,void 0);i(this,s,void 0);i(this,n,void 0);let{proxyApiUrl:y}=u(t);c(this,n,p),c(this,o,y),c(this,s,e),a(this,o),a(this,s),a(this,n);}getProvider(){return Promise.resolve({})}getAddress(){return Promise.resolve({})}getBalances(){return Promise.resolve({})}getManifest(){let e=vmModuleTypes.parseManifest(l);return e.success?e.data:void 0}getNetworkFee(){return Promise.resolve({})}getTransactionHistory(){return Promise.resolve({transactions:[]})}getTokens(){return Promise.resolve([])}async onRpcRequest(e){return {error:rpcErrors.rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}};o=new WeakMap,s=new WeakMap,n=new WeakMap;
14
+ var at=Object.defineProperty;var st=(t,e,r)=>e in t?at(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var ue=(t,e,r)=>(st(t,typeof e!="symbol"?e+"":e,r),r),oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)};var m=(t,e,r)=>(oe(t,e,"read from private field"),r?r.call(t):e.get(t)),I=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r);},w=(t,e,r,n)=>(oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);var fe=(t,e,r)=>(oe(t,e,"access private method"),r);var ae=async({operation:t,isSuccess:e,maxRetries:r=10,backoffPolicy:n=L.exponential()})=>{let a=0,s=0,o;for(;s<r;){s>0&&await it(a);try{let c=await t(s);if(e(c))return c}catch(c){o=c;}a=n(s),s++;}let i=o?`Max retry exceeded. ${o}`:"Max retry exceeded.";throw new Error(i)},L=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return r=>e*1e3}static constantMs(e){return r=>e}};function it(t){return new Promise(e=>setTimeout(e,t))}var se=t=>ae({operation:e=>t(e>0),maxRetries:2,backoffPolicy:L.constant(1),isSuccess:e=>e?.status?.error_code!==429});function ye(t){let e,r=0;for(e=0;e<t.length;e++)r+=t.charCodeAt(e)*(e+1);return r}function ie(t){let e,r=0;for(e=0;e<t.length;e++){let n=ye(t[e]??"");r=r+65027/n;}return (""+r).slice(0,16)}async function b(t,e){let r=await fetch(...t);if(!r.ok)throw new Error(`Request failed with status ${r.status}`);let n=await r.json();return e.parse(n)}var F=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let r=new URLSearchParams(e);return b([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${r}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:r,...n}=e,a=new URLSearchParams(n);return b([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${r}?${a}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}};var Te=coreCoingeckoSdk.getBasicCoingeckoHttp(),D,B,M=class{constructor({storage:e,proxyApiUrl:r}){I(this,D,void 0);I(this,B,void 0);ue(this,"transformSimplePriceResponse",(e,r=[coreCoingeckoSdk.VsCurrencyType.USD])=>{let n={};return Object.keys(e).forEach(a=>{let s=e[a];n[a]={},r.forEach(o=>{n[a]={[o]:{price:s?.[o],change24:s?.[`${o}_24h_change`],vol24:s?.[`${o}_24h_vol`],marketCap:s?.[`${o}_market_cap`]}};});}),n});w(this,D,e),w(this,B,r);}async getSimplePrice({coinIds:e=[],currencies:r=[coreCoingeckoSdk.VsCurrencyType.USD]}){let n,s=`getSimplePrice-${e?`${ie(e)}-${r.toString()}`:`${r.toString()}`}`;if(n=m(this,D)?.get?.(s),n)return n;try{n=await se(o=>this.simplePrice({coinIds:e,currencies:r,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:o}));}catch{n=void 0;}return m(this,D)?.set?.(s,n),n}async getPricesByAddresses(e,r,n=coreCoingeckoSdk.VsCurrencyType.USD){let a,o=`getPricesWithMarketDataByAddresses-${`${ie(e)}-${r}-${n}`}`;if(a=m(this,D)?.get?.(o),a)return a;try{a=await se(i=>this.fetchPricesByAddresses({assetPlatformId:r,tokenAddresses:e,currency:n,useCoingeckoProxy:i}));}catch(i){console.error(i),a=void 0;}return m(this,D)?.set?.(o,a),a}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:r,currency:n=coreCoingeckoSdk.VsCurrencyType.USD,useCoingeckoProxy:a=!1}){if(a){let s=await new F(m(this,B)).simplePriceByContractAddresses({id:e,contract_addresses:r,vs_currencies:[n],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[n])}return coreCoingeckoSdk.simpleTokenPrice(Te,{assetPlatformId:e,tokenAddresses:r,currencies:[n],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:r=[coreCoingeckoSdk.VsCurrencyType.USD],marketCap:n=!1,vol24:a=!1,change24:s=!1,lastUpdated:o=!1,useCoingeckoProxy:i=!1,shouldThrow:c=!0}){if(i){let p=await new F(m(this,B)).simplePrice({ids:e,vs_currencies:r,include_market_cap:n,include_24hr_vol:a,include_24hr_change:s,include_last_updated_at:o});return this.transformSimplePriceResponse(p,r)}return coreCoingeckoSdk.simplePrice(Te,{coinIds:e,currencies:r,marketCap:n,vol24:a,change24:s,lastUpdated:o,shouldThrow:c})}};D=new WeakMap,B=new WeakMap;zod.object({date:zod.string(),usd:zod.record(zod.number())});var E=(t,e)=>({label:t,type:vmModuleTypes.DetailItemType.ADDRESS,value:e});var V=(t,e)=>({label:t,type:vmModuleTypes.DetailItemType.DATA,value:e});var he={name:"SVM",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/svm-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1","solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"],namespaces:["solana"]},cointype:"501",permissions:{rpc:{dapps:!0,methods:["solana_signTransaction","solana_signAndSendTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var gt={proxyApiUrl:"https://proxy-api.avax.network"},Tt={proxyApiUrl:"https://proxy-api-dev.avax.network"},xe=t=>{switch(t){case vmModuleTypes.Environment.PRODUCTION:return gt;case vmModuleTypes.Environment.DEV:return Tt}};var ke=t=>"derivationPathType"in t&&"accountIndex"in t&&typeof t.accountIndex=="number"&&typeof t.derivationPathType=="string";var G=({accountIndex:t})=>{if(t<0)throw rpcErrors.rpcErrors.invalidParams("Account index must be a non-negative integer");return {[vmModuleTypes.NetworkVMType.SVM]:`m/44'/501'/${t}'/0'`}};var ve=async t=>{let{approvalController:e,secretId:r}=t,n=ke(t)?G(t).SVM:void 0,a=await e.requestPublicKey({curve:"ed25519",secretId:r,derivationPath:n});return {[vmModuleTypes.NetworkVMType.SVM]:base.base58.encode(base.hex.decode(a))}};var Ie="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ae="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Re="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",we="/proxy/nownodes/sol",be="https://api.devnet.solana.com";var A=({isTestnet:t,proxyApiUrl:e})=>coreWalletsSdk.getSolanaProvider({isTestnet:t,rpcUrl:t?be:e+we});var ce=1e6,R={high:150*ce,medium:75*ce,low:2*ce},It=t=>(t.length===0?[R.low,R.low]:t.length===1?[t[0],R.low]:t).slice().sort((r,n)=>r-n);async function Ne(t,e){let a=await(await A({isTestnet:!!t.isTestnet,proxyApiUrl:e}).getRecentPrioritizationFees()).send();if(a.length===0||a.every(P=>P.prioritizationFee===0n))return {high:{maxFeePerGas:BigInt(R.high),maxPriorityFeePerGas:BigInt(R.high)},medium:{maxFeePerGas:BigInt(R.medium),maxPriorityFeePerGas:BigInt(R.medium)},low:{maxFeePerGas:BigInt(R.low),maxPriorityFeePerGas:BigInt(R.low)},baseFee:BigInt(R.low),displayDecimals:9,isFixedFee:!1};let o=It(a.map(P=>Number(P.prioritizationFee))),i=o.at(0),c=o.at(-1),p=Math.floor(o.length/2),y=o.length%2===1?o[p]:(o[p-1]+o[p])/2,l=BigInt(Math.ceil(c*1.05)),d=BigInt(Math.ceil(y*1.05)),g=BigInt(Math.ceil(i*1.05));return {high:{maxFeePerGas:l,maxPriorityFeePerGas:l},medium:{maxFeePerGas:d,maxPriorityFeePerGas:d},low:{maxFeePerGas:g,maxPriorityFeePerGas:g},baseFee:g,displayDecimals:9,isFixedFee:!1}}var Rt=zod.z.object({address:zod.z.string(),name:zod.z.string(),symbol:zod.z.string(),contractType:zod.z.literal(vmModuleTypes.TokenType.SPL),caip2Id:zod.z.string().startsWith("solana:"),decimals:zod.z.number(),chainId:zod.z.number().optional(),logoUri:zod.z.string().optional(),color:zod.z.string().optional()}),De=zod.z.array(Rt);async function _e({caip2Id:t,proxyApiUrl:e}){try{return (await b([`${e}/solana-tokens?caip2Id=${t}`],De)).map(n=>({...n,type:n.contractType}))}catch(r){throw console.error("getTokens() failed for",t,r),rpcErrors.rpcErrors.internal(`Failed to fetch tokens for caip2Id "${t}"`)}}var _=t=>t.status==="fulfilled";var Ce=zod.z.object({nativeBalance:zod.z.object({lamports:zod.z.string(),solana:zod.z.string()}),nfts:zod.z.array(zod.z.object({associatedTokenAddress:zod.z.string(),mint:zod.z.string(),name:zod.z.string(),symbol:zod.z.string()})),tokens:zod.z.array(zod.z.object({associatedTokenAddress:zod.z.string(),mint:zod.z.string(),amountRaw:zod.z.string(),amount:zod.z.string(),decimals:zod.z.number(),name:zod.z.string(),symbol:zod.z.string(),logo:zod.z.string().optional().nullable()}))});var $,W,Ee,j=class{constructor({proxyApiUrl:e}){I(this,W);I(this,$,void 0);w(this,$,`${e}/proxy/moralis`);}async getPortfolio({address:e,network:r}){try{let n=fe(this,W,Ee).call(this,`/account/${r}/${e}/portfolio`),a=await b([n],Ce);return {address:e,portfolio:a}}catch(n){console.error("getPortfolio() failed:",n);let a=n instanceof Error?n.message:"unknown error";return {address:e,error:`getPortfolio() failed: ${a}`}}}};$=new WeakMap,W=new WeakSet,Ee=function(e){return `${m(this,$)}${e}`};var Be=t=>{switch(t.caipId){case Ie:return "mainnet";case Ae:return "devnet";case Re:return "testnet";default:throw new Error("Unrecognized CAIP-2 id: "+t.caipId)}};var Oe=async({addresses:t,proxyApiUrl:e,currency:r,network:n,tokenService:a})=>{let s=new j({proxyApiUrl:e}),o=n.pricingProviders?.coingecko.nativeTokenId??"",i=n.pricingProviders?.coingecko.assetPlatformId??"",c=r.toLowerCase(),p=Be(n),y=await Promise.all(t.map(T=>s.getPortfolio({address:T,network:p}))),l=new Set(y.flatMap(T=>"portfolio"in T?T.portfolio.tokens.map(({mint:u})=>u):[])),d=await Promise.allSettled([o?await a.getSimplePrice({coinIds:[o],currencies:[c]}):Promise.resolve(void 0),i?await a.getPricesByAddresses(Array.from(l),i,c):Promise.resolve(void 0)]),[g,P]=d.map(T=>_(T)?T.value:void 0);return y.reduce((T,u)=>{if("error"in u)return {...T,[u.address]:{error:u.error}};let S=new coreUtilsSdk.TokenUnit(u.portfolio.nativeBalance.lamports,9,"SOL"),h=Fe(o,c,g),k=h.priceInCurrency!==void 0?S.mul(h.priceInCurrency):void 0,U={type:vmModuleTypes.TokenType.NATIVE,name:n.networkToken.name,symbol:n.networkToken.symbol,decimals:n.networkToken.decimals,balance:S.toSubUnit(),balanceDisplayValue:S.toString(),balanceInCurrency:k?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:k?.toDisplay({fixedDp:2}),logoUri:n.networkToken.logoUri??"",coingeckoId:o,...h},z=u.portfolio.tokens.reduce((Q,{amountRaw:ee,symbol:le,decimals:me,mint:te,name:rt,logo:nt})=>{let re=new coreUtilsSdk.TokenUnit(ee,me,le),ne=Fe(te,c,P),de=ne.priceInCurrency!==void 0?re.mul(ne.priceInCurrency):void 0,ot={type:vmModuleTypes.TokenType.SPL,address:te,name:rt,symbol:le,decimals:me,balance:re.toSubUnit(),balanceDisplayValue:re.toString(),balanceInCurrency:de?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:de?.toDisplay({fixedDp:2}),logoUri:nt??void 0,reputation:null,...ne};return {...Q,[te]:ot}},{});return {...T,[u.address]:{[n.networkToken.symbol]:U,...z}}},{})},Fe=(t,e,r)=>({priceInCurrency:r?.[t??""]?.[e]?.price??void 0,marketCap:r?.[t??""]?.[e]?.marketCap??void 0,vol24:r?.[t??""]?.[e]?.vol24??void 0,change24:r?.[t??""]?.[e]?.change24??void 0});var pe=t=>({mint:t.mint,owner:t.owner,amount:BigInt(t.uiTokenAmount.amount),decimals:t.uiTokenAmount.decimals}),$e=(t,e,r,n)=>{let a=r.preTokenBalances.reduce((i,{owner:c,mint:p,amount:y})=>({...i,[`${c}-${p}`]:y}),{}),s=r.postTokenBalances.reduce((i,{owner:c,mint:p,amount:y,decimals:l})=>{let d=`${c}-${p}`,g=a[d]??0n,P=y-g;if(P<=0n)return i;let T=Object.keys(a).find(h=>{let[k,U]=h.split("-"),z=r.postTokenBalances.find(({owner:Q,mint:ee})=>Q===k&&ee===p);return U===p&&z&&a[h]>z.amount});if(!T)return i;let u=n.tokens?.filter(h=>"contractType"in h).find(h=>h.address===p)??{contractType:vmModuleTypes.TokenType.SPL,decimals:l,address:p,symbol:"Unknown",name:"Unknown"},S={...u,type:u.contractType,from:{...u,address:T.split("-")[0]},to:{...u,address:c},amount:new coreUtilsSdk.TokenUnit(P,l,"").toDisplay()};return [...i,S]},[]),o=bt(t,e,r,n);return o&&s.push(o),s},bt=(t,e,{paidFee:r,preBalances:n,postBalances:a},s)=>{let o=t[e],i=n[e],c=a[e],p=c!==i?c-i+r:0,y=a.map((P,T)=>P-n[T]);if(!p)return null;let l=p>0,d=new coreUtilsSdk.TokenUnit(Math.abs(p),s.networkToken.decimals,""),g=l?0:Math.max(0,y.findIndex(P=>P===-p));return {amount:d.toDisplay(),from:{address:l?t[g]:o},to:{address:l?o:t[g]},name:s.networkToken.name,symbol:s.networkToken.symbol,type:vmModuleTypes.TokenType.NATIVE}};function He(t){return e=>!!e[t]}var ze=async({isTestnet:t,address:e,proxyApiUrl:r})=>{let n=A({isTestnet:t,proxyApiUrl:r}),s=(await n.getSignaturesForAddress(kit.address(e),{limit:25}).send()).map(i=>i.signature);return (await Promise.allSettled(s.map(async i=>({txHash:i.toString(),tx:await n.getTransaction(i,{encoding:"json",maxSupportedTransactionVersion:0}).send()})))).filter(_).map(i=>i.value).filter(He("tx"))};var Ge=(t,e)=>{let r=e?new URL(e):null;return r&&(r.pathname=`/tx/${t}`),r?.toString()??""};async function je({network:t,address:e,proxyApiUrl:r}){return t.caipId?{transactions:(await ze({isTestnet:!!t.isTestnet,address:e,proxyApiUrl:r})).map(({txHash:s,tx:o})=>{if(!o.meta)return null;let{meta:i,transaction:{message:c}}=o,p=c.accountKeys.map(g=>g.toString()),y=p.indexOf(e),l=y<c.header.numRequiredSignatures,d=$e(p,y,{paidFee:l?Number(i.fee):0,preBalances:i.preBalances.map(Number),postBalances:i.postBalances.map(Number),preTokenBalances:(i.preTokenBalances??[]).map(pe),postTokenBalances:(i.postTokenBalances??[]).map(pe)},t);return {hash:s,txType:l?vmModuleTypes.TransactionType.SEND:vmModuleTypes.TransactionType.RECEIVE,gasUsed:String(o.meta.computeUnitsConsumed??"0"),tokens:d,from:d[0]?.from?.address??p[0],to:d[0]?.to?.address??(l?"":e),isOutgoing:l,isIncoming:!l,isSender:l,timestamp:Number(o.blockTime),isContractCall:!1,gasPrice:String(Number(o.meta.fee)/Number(o.meta.computeUnitsConsumed)),chainId:String(t.chainId),explorerLink:Ge(s,t.explorerUrl)}}).filter(s=>s!==null)}:Promise.reject({error:rpcErrors.rpcErrors.invalidParams("Network must have a CAIP-2 id")})}function K(t){return t.ins.length===0&&t.outs.length===0}function Y(t){return t!=null}var X=(t,e,r,n)=>{if(!(!kit.isInstructionForProgram(t,system.SYSTEM_PROGRAM_ADDRESS)||!kit.isInstructionWithAccounts(t)||!kit.isInstructionWithData(t)))try{if(system.identifySystemInstruction(t)!==system.SystemInstruction.TransferSol)return null;let{accounts:s,data:o}=system.parseTransferSolInstruction({...t,data:Uint8Array.from(t.data)}),c=s.source.address===r===!0?"outs":"ins";return e[c].push({token:{...n,address:""},items:[{displayValue:new coreUtilsSdk.TokenUnit(o.amount,n.decimals,"").toString(),usdPrice:void 0}]}),{title:"Native Transfer",items:[E("From",s.source.address),E("To",s.destination.address)]}}catch{return null}};var qt=async(t,e)=>{try{let r=await t.getAccountInfo(e,{encoding:"jsonParsed"}).send();if(Array.isArray(r.value?.data))return null;let n=r.value?.data.parsed.info;return typeof n?.mint=="string"?n.mint:null}catch{return null}},J=async(t,e,r,n,a)=>{if(!(!a?.length||!kit.isInstructionWithAccounts(e)||!kit.isInstructionWithData(e)))try{if(token.identifyTokenInstruction(e)!==token.TokenInstruction.Transfer)return null;let{accounts:o,data:i}=token.parseTransferInstruction({...e,data:Uint8Array.from(e.data)}),c=await qt(t,o.source.address);if(!c)return null;let p=a.find(d=>d.address.toLowerCase()===c.toLowerCase());if(!p)return null;let l=(o.source.address===n||o.authority.address===n)===!0?"outs":"ins";return r[l].push({token:p,items:[{displayValue:new coreUtilsSdk.TokenUnit(i.amount,p.decimals,"").toString(),usdPrice:void 0}]}),{title:`Transfer ${p.symbol}`,items:[E("From",o.source.address),E("To",o.destination.address)]}}catch{return null}};var jt=zod.z.object({account:zod.z.string(),serializedTx:zod.z.string().base64(),sendOptions:zod.z.object({preflightCommitment:zod.z.enum(["processed","confirmed","finalized"]).optional(),maxRetries:zod.z.bigint().optional(),minContextSlot:zod.z.bigint().optional(),skipPreflight:zod.z.boolean().optional()}).optional()}),Wt=zod.z.tuple([jt]),We=t=>Wt.safeParse(t);var Ye=async({request:t,network:e,approvalController:r,proxyApiUrl:n})=>{let{params:a}=t,{data:s,success:o,error:i}=We(a);if(!o)return console.error("invalid params",i),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:i}})};let[{account:c,serializedTx:p,sendOptions:y}]=s,l=A({isTestnet:!!e.isTestnet,proxyApiUrl:n}),d=await coreWalletsSdk.deserializeTransactionMessage(p,l),g={ins:[],outs:[]},P=await Promise.allSettled(d.instructions.map(async k=>X(k,g,c,e.networkToken)??await J(l,k,g,c,e.tokens)??null)).then(k=>k.filter(_).map(U=>U.value).filter(Y)),T={title:"Approve Transaction",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[V("Raw Data",p)]},...P],balanceChange:K(g)?void 0:g,networkFeeSelector:!1,isSimulationSuccessful:!1},u={type:vmModuleTypes.RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,account:c,data:p},S=await r.requestApproval({request:t,displayData:T,signingData:u});if("error"in S)return {error:S.error};let h;try{h=await Xt(l,S,y);}catch(k){return console.error(k),{error:rpcErrors.rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:k}})}}return {result:h}},Xt=async(t,e,r)=>"txHash"in e?e.txHash:await t.sendTransaction(e.signedData,{...r,encoding:"base64"}).send();var Jt=zod.z.object({account:zod.z.string(),serializedTx:zod.z.string().base64()}),Zt=zod.z.tuple([Jt]),Xe=t=>Zt.safeParse(t);var Ze=async({request:t,network:e,approvalController:r,proxyApiUrl:n})=>{let{params:a}=t,{data:s,success:o,error:i}=Xe(a);if(!o)return console.error("invalid params",i),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:i}})};let[{account:c,serializedTx:p}]=s,y=A({isTestnet:!!e.isTestnet,proxyApiUrl:n}),l=await coreWalletsSdk.deserializeTransactionMessage(p,y),d={ins:[],outs:[]},g=await Promise.allSettled(l.instructions.map(async S=>X(S,d,c,e.networkToken)??await J(y,S,d,c,e.tokens)??null)).then(S=>S.filter(_).map(h=>h.value).filter(Y)),P={title:"Sign Transaction",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[V("Raw Data",p)]},...g],balanceChange:K(d)?void 0:d,networkFeeSelector:!1,isSimulationSuccessful:!1},T={type:vmModuleTypes.RpcMethod.SOLANA_SIGN_TRANSACTION,account:c,data:p},u=await r.requestApproval({request:t,displayData:P,signingData:T});return "error"in u?{error:u.error}:"signedData"in u?{result:u.signedData}:{error:rpcErrors.rpcErrors.invalidRequest("No signed data returned")}};var x,C,H,tt=class{constructor({approvalController:e,environment:r,appInfo:n}){I(this,x,void 0);I(this,C,void 0);I(this,H,void 0);let{proxyApiUrl:a}=xe(r);w(this,H,n),w(this,x,a),w(this,C,e),m(this,x),m(this,C),m(this,H);}async getProvider(e){return A({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}getAddress(){return Promise.resolve({})}buildDerivationPath(e){return G(e)}deriveAddress(e){return ve({...e,approvalController:m(this,C)})}getBalances(e){let r=new M({storage:e.storage,proxyApiUrl:m(this,x)});return Oe({...e,tokenService:r,proxyApiUrl:m(this,x)})}getManifest(){let e=vmModuleTypes.parseManifest(he);return e.success?e.data:void 0}getNetworkFee(e){return Ne(e,m(this,x))}getTransactionHistory(e){return je({network:e.network,address:e.address,proxyApiUrl:m(this,x)})}getTokens(e){return e.caipId?_e({caip2Id:e.caipId,proxyApiUrl:m(this,x)}):Promise.reject({error:rpcErrors.rpcErrors.invalidParams("Network must have a CAIP-2 id")})}async onRpcRequest(e,r){switch(e.method){case vmModuleTypes.RpcMethod.SOLANA_SIGN_TRANSACTION:return Ze({approvalController:m(this,C),proxyApiUrl:m(this,x),network:r,request:e});case vmModuleTypes.RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION:return Ye({approvalController:m(this,C),proxyApiUrl:m(this,x),network:r,request:e})}return {error:rpcErrors.rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}};x=new WeakMap,C=new WeakMap,H=new WeakMap;
8
15
 
9
- exports.SvmModule = d;
16
+ exports.SvmModule = tt;
10
17
  //# sourceMappingURL=out.js.map
11
18
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module.ts","../manifest.json","../src/env.ts"],"names":["parseManifest","rpcErrors","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","_proxyApiUrl","_approvalController","_appInfo","SvmModule","approvalController","appInfo","__privateAdd","proxyApiUrl","__privateSet","__privateGet","result","request"],"mappings":"mVAAA,OACE,iBAAAA,MAOK,2BACP,MAAkD,cAClD,OAAS,aAAAC,MAAiB,uBCV1B,IAAAC,EAAA,CACE,KAAQ,MACR,YAAe,GACf,QAAW,QACX,QAAW,CACT,OAAU,CACR,SAAY,GACZ,SAAY,CACV,IAAO,CACL,SAAY,gBACZ,YAAe,sBACf,SAAY,4BACd,CACF,CACF,CACF,EACA,QAAW,CACT,SAAY,CACV,0CACA,0CACA,yCACF,EACA,WAAc,CAAC,QAAQ,CACzB,EACA,SAAY,MACZ,YAAe,CACb,IAAO,CACL,MAAS,GACT,QAAW,CAAC,gBAAgB,EAC5B,qBAAwB,CAAC,gBAAgB,CAC3C,CACF,EACA,gBAAmB,KACrB,ECjCA,OAAS,eAAAC,MAAmB,2BAMrB,IAAMC,EAAe,CAC1B,YAAa,gCACf,EAEaC,EAAc,CACzB,YAAa,oCACf,EAEaC,EAAUC,GAAkC,CACvD,OAAQA,EAAa,CACnB,KAAKJ,EAAY,WACf,OAAOC,EACT,KAAKD,EAAY,IACf,OAAOE,CACX,CACF,EFrBA,IAAAG,EAAAC,EAAAC,EAeaC,EAAN,KAAkC,CAKvC,YAAY,CAAE,mBAAAC,EAAoB,YAAAL,EAAa,QAAAM,CAAQ,EAAsB,CAJ7EC,EAAA,KAAAN,EAAA,QACAM,EAAA,KAAAL,EAAA,QACAK,EAAA,KAAAJ,EAAA,QAGE,GAAM,CAAE,YAAAK,CAAY,EAAIT,EAAOC,CAAW,EAE1CS,EAAA,KAAKN,EAAWG,GAChBG,EAAA,KAAKR,EAAeO,GACpBC,EAAA,KAAKP,EAAsBG,GAI3BK,EAAA,KAAKT,GACLS,EAAA,KAAKR,GACLQ,EAAA,KAAKP,EACP,CAGA,aAAc,CACZ,OAAO,QAAQ,QAAQ,CAAC,CAA4B,CACtD,CAGA,YAAa,CACX,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAGA,aAAc,CACZ,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAEA,aAAc,CACZ,IAAMQ,EAASlB,EAAcE,CAAY,EACzC,OAAOgB,EAAO,QAAUA,EAAO,KAAO,MACxC,CAGA,eAAgB,CACd,OAAO,QAAQ,QAAQ,CAAC,CAAgB,CAC1C,CAGA,uBAAwB,CACtB,OAAO,QAAQ,QAAQ,CACrB,aAAc,CAAC,CACjB,CAAC,CACH,CAGA,WAAY,CACV,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAGA,MAAM,aAAaC,EAAqB,CACtC,MAAO,CAAE,MAAOlB,EAAU,mBAAmB,UAAUkB,EAAQ,MAAM,gBAAgB,CAAE,CACzF,CACF,EA3DEX,EAAA,YACAC,EAAA,YACAC,EAAA","sourcesContent":["import {\n parseManifest,\n type AppInfo,\n type ApprovalController,\n type ConstructorParams,\n type Module,\n type NetworkFees,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport { type Rpc, type SolanaRpcApiDevnet } from '@solana/rpc';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n\n constructor({ approvalController, environment, appInfo }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n }\n\n // TODO\n getProvider() {\n return Promise.resolve({} as Rpc<SolanaRpcApiDevnet>);\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n // TODO\n getBalances() {\n return Promise.resolve({});\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n // TODO\n getNetworkFee() {\n return Promise.resolve({} as NetworkFees);\n }\n\n // TODO\n getTransactionHistory() {\n return Promise.resolve({\n transactions: [],\n });\n }\n\n // TODO\n getTokens() {\n return Promise.resolve([]);\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest) {\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"getGenesisHash\"],\n \"nonRestrictedMethods\": [\"getGenesisHash\"]\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n"]}
1
+ {"version":3,"sources":["../src/module.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts","../../../packages-internal/utils/src/utils/retry.ts","../../../packages-internal/utils/src/utils/coingecko-retry.ts","../../../packages-internal/utils/src/utils/charsum.ts","../../../packages-internal/utils/src/utils/array-hash.ts","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/utils/fetch-and-verify.ts","../../../packages-internal/utils/src/services/pricing-service/exchange-rates.ts","../../../packages-internal/utils/src/utils/detail-item.ts","../../../packages-internal/utils/src/utils/get-core-headers.ts","../manifest.json","../src/env.ts","../src/handlers/derive-address/derive-address.ts","../../../packages-internal/utils/src/utils/address-derivation.ts","../src/handlers/build-derivation-path/build-derivation-path.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/utils/get-provider.ts","../src/constants.ts","../src/handlers/get-tokens/get-tokens.ts","../src/handlers/get-tokens/spl-token-schema.ts","../src/handlers/get-balances/get-balances.ts","../../../packages-internal/utils/src/utils/is-promise-fulfilled.ts","../src/utils/moralis-service/moralis-schemas.ts","../src/utils/moralis-service/moralis-service.ts","../src/utils/get-network-name.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/extract-transfer.ts","../src/handlers/get-transaction-history/get-wrapped-transactions.ts","../src/utils/has-property-defined.ts","../src/handlers/get-transaction-history/get-explorer-link.ts","../src/handlers/sign-and-send-transaction/sign-and-send-transaction.ts","../src/utils/functional.ts","../src/utils/instruction-parsers/sol-transfer.ts","../src/utils/instruction-parsers/spl-transfer.ts","../src/handlers/sign-and-send-transaction/schema.ts","../src/handlers/sign-transaction/sign-transaction.ts","../src/handlers/sign-transaction/schema.ts"],"names":["parseManifest","RpcMethod","rpcErrors","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","coinIds","cacheId","__privateGet","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","addressItem","label","value","dataItem","AppName","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","NetworkVMType","base58","hex","hasDerivationDetails","buildDerivationPath","accountIndex","deriveAddress","approvalController","secretId","derivationPath","publicKeyHex","getSolanaProvider","SOLANA_MAINNET_CAIP2_ID","SOLANA_DEVNET_CAIP2_ID","SOLANA_TESTNET_CAIP2_ID","RPC_URL_PROXY_API_ENDPOINT","RPC_URL_DEVNET","getProvider","isTestnet","LamportsMultiplier","DEFAULT_PRIORITY_FEE","ensureEnoughData","fees","a","b","getNetworkFee","network","feesRaw","block","sortedFees","minFeeInRecentBlocks","maxFeeInRecentBlocks","midIndex","medianFee","presetHigh","presetMedium","presetLow","TokenType","z","SPL_TOKEN_SCHEMA","SPL_TOKENS_SCHEMA","getTokens","caip2Id","token","error","TokenUnit","isFulfilled","PORTFOLIO_SCHEMA","_baseUrl","_buildUrl","buildUrl_fn","MoralisService","address","url","__privateMethod","portfolio","message","path","getNetworkName","getBalances","addresses","tokenService","moralisService","coingeckoAssetId","coingeckoPlatformId","lowercaseCurrency","solanaNetwork","portfolioResults","mints","mint","tokenPricesPromises","nativePrice","tokenPrices","promise","portfolioAcc","nativeBalanceUnit","nativeMarketData","getMarketData","nativeBalanceInCurrency","solanaBalance","tokenBalances","tokensAcc","amountRaw","symbol","decimals","name","logo","balanceUnit","marketData","balanceInCurrency","coinIdOrAddress","prices","TransactionType","simplifyTokenBalance","balance","extractTokenTranfers","meta","preBalances","acc","owner","amount","transfers","key","preAmount","netChange","sender","k","possibleSender","mintFromPreBalance","possibleSenderPostBalance","postBalanceOwner","postBalanceMint","t","transfer","nativeTransfer","extractNativeTransfer","paidFee","postBalances","nativeBalancePre","nativeBalancePost","nativeTransferAmount","balanceDiffs","isIncoming","unit","otherAddressIndex","diff","solAddress","hasPropertyDefined","thing","getWrappedTransactions","provider","signatures","sig","tx","getExplorerLink","txHash","baseUrl","explorerLink","getTransactionHistory","isSigner","deserializeTransactionMessage","isBalanceChangeEmpty","input","isNotNullish","identifySystemInstruction","parseTransferSolInstruction","SYSTEM_PROGRAM_ADDRESS","SystemInstruction","isInstructionForProgram","isInstructionWithAccounts","isInstructionWithData","tryToParseSolTransfer","instruction","balanceChange","account","networkToken","accounts","balanceChangeKey","parseTransferInstruction","identifyTokenInstruction","TokenInstruction","getTokenMintFromAccountInfo","tokenAccountDetails","info","tryToParseSPLTransfer","tokens","tokenMint","transactionSchema","paramsSchema","parseRequestParams","signAndSendTransaction","request","success","serializedTx","sendOptions","transaction","details","results","displayData","signingData","getTxHash","signTransaction","_approvalController","_appInfo","SvmModule","appInfo"],"mappings":"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","sourcesContent":["import {\n parseManifest,\n RpcMethod,\n type AppInfo,\n type ApprovalController,\n type BuildDerivationPathParams,\n type ConstructorParams,\n type DeriveAddressParams,\n type GetBalancesParams,\n type GetTransactionHistory,\n type Module,\n type Network,\n type NetworkFeeParam,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { TokenService } from '@internal/utils';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\nimport { deriveAddress } from './handlers/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTokens } from './handlers/get-tokens';\nimport { getBalances } from './handlers/get-balances';\nimport { getProvider } from './utils/get-provider';\nimport { getTransactionHistory } from './handlers/get-transaction-history';\nimport { signAndSendTransaction } from './handlers/sign-and-send-transaction';\nimport { signTransaction } from './handlers/sign-transaction';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n\n constructor({ approvalController, environment, appInfo }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n }\n\n async getProvider(network: Network): Promise<SolanaProvider> {\n return getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n buildDerivationPath(params: BuildDerivationPathParams) {\n return buildDerivationPath(params);\n }\n\n deriveAddress(params: DeriveAddressParams) {\n return deriveAddress({\n ...params,\n approvalController: this.#approvalController,\n });\n }\n\n getBalances(params: GetBalancesParams) {\n const tokenService = new TokenService({ storage: params.storage, proxyApiUrl: this.#proxyApiUrl });\n\n return getBalances({\n ...params,\n tokenService,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: NetworkFeeParam) {\n return getNetworkFee(network, this.#proxyApiUrl);\n }\n\n getTransactionHistory(params: GetTransactionHistory) {\n return getTransactionHistory({\n network: params.network,\n address: params.address,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getTokens(network: Network) {\n if (!network.caipId) {\n return Promise.reject({ error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`) });\n }\n\n return getTokens({ caip2Id: network.caipId, proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.SOLANA_SIGN_TRANSACTION: {\n return signTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n });\n }\n case RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION: {\n return signAndSendTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n });\n }\n }\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/core-coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { CoingeckoProxyClient } from './coingecko-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n } catch {\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n } catch (err) {\n console.error(err);\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses({\n id: assetPlatformId,\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n });\n return this.transformSimplePriceResponse(rawData, [currency]);\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n shouldThrow = true,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePrice({\n ids: coinIds,\n vs_currencies: currencies,\n include_market_cap: marketCap,\n include_24hr_vol: vol24,\n include_24hr_change: change24,\n include_last_updated_at: lastUpdated,\n });\n return this.transformSimplePriceResponse(rawData, currencies);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n","const DEFAULT_MAX_RETRIES = 10;\n\ntype RetryParams<T> = {\n operation: (retryIndex: number) => Promise<T>;\n isSuccess: (result: T) => boolean;\n maxRetries?: number;\n backoffPolicy?: RetryBackoffPolicyInterface;\n};\n/*\n * Retries an operation with defined backoff policy.\n *\n * @param operation - The operation to retry.\n * @param isSuccess - The predicate to check if the operation succeeded.\n * @param maxRetries - The maximum number of retries.\n * @param backoffPolicy - Function to generate delay time based on current retry count.\n *\n * @returns The result of the operation.\n * @throws An error if the operation fails after the maximum number of retries.\n *\n * @example\n * const result = await retry(\n * async () => {\n * const response = await fetch('https://example.com')\n * return response.json()\n * },\n * result => result.status === 200\n * )\n */\nexport const retry = async <T>({\n operation,\n isSuccess,\n maxRetries = DEFAULT_MAX_RETRIES,\n backoffPolicy = RetryBackoffPolicy.exponential(),\n}: RetryParams<T>): Promise<T> => {\n let backoffPeriodMillis = 0;\n let retries = 0;\n let lastError: unknown;\n\n while (retries < maxRetries) {\n if (retries > 0) {\n await delay(backoffPeriodMillis);\n }\n\n try {\n const result = await operation(retries);\n\n if (isSuccess(result)) {\n return result;\n }\n } catch (err) {\n // when the operation throws an error, we still retry\n lastError = err;\n }\n\n backoffPeriodMillis = backoffPolicy(retries);\n retries++;\n }\n\n const errorMessage = lastError ? `Max retry exceeded. ${lastError}` : 'Max retry exceeded.';\n\n throw new Error(errorMessage);\n};\n\ntype RetryBackoffPolicyInterface = (retryIndex: number) => number;\n\nexport class RetryBackoffPolicy {\n static exponential(): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n return Math.pow(2, retryIndex) * 1000;\n };\n }\n\n static constant(secondsToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return secondsToDelay * 1000;\n };\n }\n\n static constantMs(msToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return msToDelay;\n };\n }\n}\n\nfunction delay(ms: number) {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { RetryBackoffPolicy, retry } from './retry';\n\ntype Error = {\n status: {\n error_code: number;\n error_message: string;\n };\n};\n\nexport const coingeckoRetry = <T>(\n operation: (useCoingeckoProxy: boolean) => Promise<T | Error>,\n): Promise<T | undefined> => {\n return retry({\n operation: (retryIndex: number) => operation(retryIndex > 0),\n maxRetries: 2,\n backoffPolicy: RetryBackoffPolicy.constant(1),\n isSuccess: (response: T | Error) => {\n const errorStatus = (response as Error)?.status;\n return errorStatus?.error_code !== 429;\n },\n }) as Promise<T | undefined>;\n};\n","export function charsum(s: string): number {\n let i,\n sum = 0;\n for (i = 0; i < s.length; i++) {\n sum += s.charCodeAt(i) * (i + 1);\n }\n return sum;\n}\n","import { charsum } from './charsum';\n\n// from https://stackoverflow.com/a/25105589\nexport function arrayHash(array: string[]): string {\n let i,\n sum = 0;\n for (i = 0; i < array.length; i++) {\n const cs = charsum(array[i] ?? '');\n sum = sum + 65027 / cs;\n }\n return ('' + sum).slice(0, 16);\n}\n","import { RawSimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nexport class CoingeckoProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n simplePrice(params: {\n ids: string[];\n vs_currencies: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n include_last_updated_at?: boolean;\n }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/price?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n\n simplePriceByContractAddresses(params: {\n id: string;\n contract_addresses: string[];\n vs_currencies?: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n }) {\n const { id, ...rawQueryParams } = params;\n\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(rawQueryParams as any);\n\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${id}?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n}\n","import z from 'zod';\nimport type { ZodSchema } from 'zod';\n\nexport async function fetchAndVerify<T extends ZodSchema>(\n fetchOptions: Parameters<typeof fetch>,\n schema: T,\n): Promise<z.infer<T>> {\n const response = await fetch(...fetchOptions);\n\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n\n const responseJson = await response.json();\n return schema.parse(responseJson);\n}\n","import z, { number, object, record, string } from 'zod';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nconst CURRENCY_EXCHANGE_RATES_URL =\n 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.min.json';\n\nconst CURRENCY_EXCHANGE_RATES_FALLBACK_URL = 'https://latest.currency-api.pages.dev/v1/currencies/usd.min.json';\n\nconst ExchangeRateSchema = object({\n date: string(),\n usd: record(number()),\n});\n\ntype ExchangeRate = z.infer<typeof ExchangeRateSchema>;\n\nexport const getExchangeRates = async (): Promise<ExchangeRate> => {\n try {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_URL], ExchangeRateSchema);\n } catch {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_FALLBACK_URL], ExchangeRateSchema);\n }\n};\n","import {\n type AddressItem,\n type CurrencyItem,\n type NodeIDItem,\n type TextItem,\n type DataItem,\n type DateItem,\n type LinkItemValue,\n DetailItemType,\n type LinkItem,\n type FundsRecipientItem,\n} from '@avalabs/vm-module-types';\n\nexport const fundsRecipientItem = (\n address: string,\n amount: bigint,\n maxDecimals: number,\n symbol: string,\n): FundsRecipientItem => ({\n type: DetailItemType.FUNDS_RECIPIENT,\n label: address,\n amount,\n maxDecimals,\n symbol,\n});\n\nexport const currencyItem = (label: string, value: bigint, maxDecimals: number, symbol: string): CurrencyItem => ({\n label,\n type: DetailItemType.CURRENCY,\n value,\n maxDecimals,\n symbol,\n});\n\nexport const textItem = (\n label: string,\n value: string,\n alignment: 'horizontal' | 'vertical' = 'horizontal',\n): TextItem => ({\n label,\n alignment,\n type: DetailItemType.TEXT,\n value,\n});\n\nexport const linkItem = (label: string, value: LinkItemValue): LinkItem => ({\n label,\n value,\n type: DetailItemType.LINK,\n});\n\nexport const addressItem = (label: string, value: string): AddressItem => ({\n label,\n type: DetailItemType.ADDRESS,\n value,\n});\n\nexport const nodeIDItem = (label: string, value: string): NodeIDItem => ({\n label,\n type: DetailItemType.NODE_ID,\n value,\n});\n\nexport const dataItem = (label: string, value: string): DataItem => ({\n label,\n type: DetailItemType.DATA,\n value,\n});\n\nexport const dateItem = (label: string, value: string): DateItem => ({\n label,\n type: DetailItemType.DATE,\n value,\n});\n","import { AppName, type AppInfo } from '@avalabs/vm-module-types';\n\nexport const getCoreHeaders = ({ name, version }: AppInfo): Record<string, string> | undefined => {\n switch (name) {\n case AppName.CORE_MOBILE_IOS:\n case AppName.CORE_MOBILE_ANDROID:\n case AppName.CORE_WEB:\n case AppName.CORE_EXTENSION:\n case AppName.EXPLORER:\n return {\n 'x-application-name': name,\n 'x-application-version': version,\n };\n case AppName.OTHER:\n return undefined;\n }\n};\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"solana_signTransaction\", \"solana_signAndSendTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\nimport { base58, hex } from '@scure/base';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\nimport { buildDerivationPath } from '../build-derivation-path/build-derivation-path';\n\nexport const deriveAddress = async (\n params: DeriveAddressParams & { approvalController: ApprovalController },\n): Promise<DeriveAddressResponse> => {\n const { approvalController, secretId } = params;\n\n // When dealing with single-account private keys, we don't need the derivation path any more.\n const derivationPath = hasDerivationDetails(params) ? buildDerivationPath(params).SVM : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'ed25519',\n secretId,\n derivationPath,\n });\n\n return {\n [NetworkVMType.SVM]: base58.encode(hex.decode(publicKeyHex)),\n };\n};\n","import type { DeriveAddressParams, DetailedDeriveAddressParams } from '@avalabs/vm-module-types';\n\nexport const hasDerivationDetails = (params: DeriveAddressParams): params is DetailedDeriveAddressParams =>\n 'derivationPathType' in params &&\n 'accountIndex' in params &&\n typeof params.accountIndex === 'number' &&\n typeof params.derivationPathType === 'string';\n","import {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\n/**\n * We're deriving the BTC address from the same public key as the Ethereum address,\n * so we can determine the target address when using the Avalanche Bridge.\n */\nexport const buildDerivationPath = ({\n accountIndex,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.SVM> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n return {\n [NetworkVMType.SVM]: `m/44'/501'/${accountIndex}'/0'`,\n };\n};\n","import { type NetworkFeeParam, type NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { SOL_DECIMALS } from '@src/constants';\n\nconst LamportsMultiplier = 1e6;\nexport const DEFAULT_PRIORITY_FEE = {\n high: 150 * LamportsMultiplier,\n medium: 75 * LamportsMultiplier,\n low: 2 * LamportsMultiplier,\n} as const;\n\ntype ValidRecentFees = [number, number, ...number[]];\n\nconst ensureEnoughData = (fees: number[]): ValidRecentFees => {\n const normalizedFees =\n fees.length === 0\n ? [DEFAULT_PRIORITY_FEE.low, DEFAULT_PRIORITY_FEE.low]\n : fees.length === 1\n ? [fees[0]!, DEFAULT_PRIORITY_FEE.low]\n : fees;\n\n return normalizedFees.slice().sort((a, b) => a - b) as ValidRecentFees;\n};\n\n/**\n * The RPC call (getRecentPrioritizationFees) returns the *lowest* priority fees (per compute unit)\n * that resulted in at least one transaction being succesfully included in the block.\n *\n * This means the request usually returns all zeroes - I've only once seen a different value,\n * for a single block out of 150 returned, and it was a 1000 MicroLamports.\n *\n * However, Phantom (the most popular Solana wallet) seems to always add at least a little bit\n * of priority fee.\n *\n * The lowest I've seen in my testing was 0.19 Lamport per compute unit, but this was an outlier.\n * I'm usually paying below 10 Lamports/cu, and sometimes as high as 150 or 300/cu -- all while\n * the RPC call returns zeroes, so it's not super reliable for determining the actual fees being paid :)\n *\n * The implementation here is by no means perfect. The way it I expect it to work is the following:\n * - with low/regular network traffic, users will be suggested to pay the default fees hardcoded below\n * (if we decide to show them at all -- Phantom does not show a widget at all)\n * - only when network congestion is super high, the RPC call will return non-zero values, and only then\n * we will suggest paying higher priority fees.\n */\nexport async function getNetworkFee(network: NetworkFeeParam, proxyApiUrl: string): Promise<NetworkFees> {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n const getFees = await provider.getRecentPrioritizationFees();\n const feesRaw = await getFees.send();\n\n const useDefaultFees = feesRaw.length === 0 || feesRaw.every((block) => block.prioritizationFee === 0n);\n\n if (useDefaultFees) {\n return {\n high: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n },\n medium: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n },\n low: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n },\n baseFee: BigInt(DEFAULT_PRIORITY_FEE.low),\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n }\n\n const sortedFees = ensureEnoughData(feesRaw.map((block) => Number(block.prioritizationFee)));\n // We know the array is not empty and sorted, so we can safely access the first and last elements\n const minFeeInRecentBlocks = sortedFees.at(0)!;\n const maxFeeInRecentBlocks = sortedFees.at(-1)!;\n const midIndex = Math.floor(sortedFees.length / 2);\n const medianFee =\n sortedFees.length % 2 === 1\n ? (sortedFees[midIndex] as number)\n : (sortedFees[midIndex - 1]! + sortedFees[midIndex]!) / 2; // Even length: return average of middle elements\n\n // Prevent the fees from going below the default values\n // If the RPC call returned non-zero values, the network congestion is likely to be very high, so we add 5%.\n // We also prevent returning fees lower than the default, hardcoded values, as the RPC call is not very reliable.\n const presetHigh = BigInt(Math.ceil(maxFeeInRecentBlocks * 1.05));\n const presetMedium = BigInt(Math.ceil(medianFee * 1.05));\n const presetLow = BigInt(Math.ceil(minFeeInRecentBlocks * 1.05));\n\n // TODO: The shape of response here needs a general refactoring, it's not very generic.\n return {\n high: {\n maxFeePerGas: presetHigh,\n maxPriorityFeePerGas: presetHigh,\n },\n medium: {\n maxFeePerGas: presetMedium,\n maxPriorityFeePerGas: presetMedium,\n },\n low: {\n maxFeePerGas: presetLow,\n maxPriorityFeePerGas: presetLow,\n },\n baseFee: presetLow,\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n}\n","import { getSolanaProvider, type SolanaProvider } from '@avalabs/core-wallets-sdk';\n\nimport { RPC_URL_DEVNET, RPC_URL_PROXY_API_ENDPOINT } from '../constants';\n\nexport const getProvider = ({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): SolanaProvider => {\n return getSolanaProvider({\n isTestnet,\n rpcUrl: isTestnet ? RPC_URL_DEVNET : proxyApiUrl + RPC_URL_PROXY_API_ENDPOINT,\n });\n};\n","export const SOL_DECIMALS = 9;\nexport const SOLANA_COIN_ID = 501;\n\nexport const SOLANA_MAINNET_CAIP2_ID = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET_CAIP2_ID = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET_CAIP2_ID = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\nexport const RPC_URL_PROXY_API_ENDPOINT = '/proxy/nownodes/sol';\nexport const RPC_URL_DEVNET = 'https://api.devnet.solana.com';\nexport const RPC_URL_TESTNET = 'https://api.testnet.solana.com';\n","import type { SPLToken } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { SPL_TOKENS_SCHEMA } from './spl-token-schema';\n\nexport async function getTokens({\n caip2Id,\n proxyApiUrl,\n}: {\n caip2Id: string;\n proxyApiUrl: string;\n}): Promise<SPLToken[]> {\n try {\n const tokens = await fetchAndVerify([`${proxyApiUrl}/solana-tokens?caip2Id=${caip2Id}`], SPL_TOKENS_SCHEMA);\n\n return tokens.map((token) => ({ ...token, type: token.contractType }));\n } catch (error) {\n console.error('getTokens() failed for', caip2Id, error);\n throw rpcErrors.internal(`Failed to fetch tokens for caip2Id \"${caip2Id}\"`);\n }\n}\n","import { TokenType } from '@avalabs/vm-module-types';\nimport { z } from 'zod';\n\nexport const SPL_TOKEN_SCHEMA = z.object({\n address: z.string(),\n name: z.string(),\n symbol: z.string(),\n contractType: z.literal(TokenType.SPL),\n caip2Id: z.string().startsWith('solana:'),\n decimals: z.number(),\n chainId: z.number().optional(),\n logoUri: z.string().optional(),\n color: z.string().optional(),\n});\n\nexport const SPL_TOKENS_SCHEMA = z.array(SPL_TOKEN_SCHEMA);\n","import {\n type GetBalancesParams,\n type TokenWithBalanceSVM,\n type TokenWithBalanceSPL,\n TokenType,\n type SimplePriceResponse,\n type Error,\n} from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport type { TokenService } from '@internal/utils';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { SOL_DECIMALS } from '@src/constants';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype GetSolanaBalancesResponse = Record<\n string,\n Record<string, TokenWithBalanceSVM | TokenWithBalanceSPL | Error> | Error\n>;\n\nexport const getBalances = async ({\n addresses,\n proxyApiUrl,\n currency,\n network,\n tokenService,\n}: GetBalancesParams & {\n proxyApiUrl: string;\n tokenService: TokenService;\n}): Promise<GetSolanaBalancesResponse> => {\n const moralisService = new MoralisService({ proxyApiUrl });\n const coingeckoAssetId = network.pricingProviders?.coingecko.nativeTokenId ?? '';\n const coingeckoPlatformId = network.pricingProviders?.coingecko.assetPlatformId ?? '';\n const lowercaseCurrency = currency.toLowerCase();\n const solanaNetwork = getNetworkName(network);\n\n const portfolioResults = await Promise.all(\n addresses.map((address) => moralisService.getPortfolio({ address, network: solanaNetwork })),\n );\n\n const mints = new Set(\n portfolioResults.flatMap((result) => {\n if ('portfolio' in result) {\n return result.portfolio.tokens.map(({ mint }) => mint);\n }\n\n return [];\n }),\n );\n\n const tokenPricesPromises = await Promise.allSettled([\n coingeckoAssetId\n ? await tokenService.getSimplePrice({\n coinIds: [coingeckoAssetId],\n currencies: [lowercaseCurrency as VsCurrencyType],\n })\n : Promise.resolve(undefined),\n coingeckoPlatformId\n ? await tokenService.getPricesByAddresses(\n Array.from(mints),\n coingeckoPlatformId,\n lowercaseCurrency as VsCurrencyType,\n )\n : Promise.resolve(undefined),\n ]);\n const [nativePrice, tokenPrices] = tokenPricesPromises.map((promise) =>\n isFulfilled(promise) ? promise.value : undefined,\n );\n\n return portfolioResults.reduce((portfolioAcc, result) => {\n if ('error' in result) {\n return {\n ...portfolioAcc,\n [result.address]: {\n error: result.error,\n },\n };\n }\n\n const nativeBalanceUnit = new TokenUnit(result.portfolio.nativeBalance.lamports, SOL_DECIMALS, 'SOL');\n const nativeMarketData = getMarketData(coingeckoAssetId, lowercaseCurrency, nativePrice);\n const nativeBalanceInCurrency =\n nativeMarketData.priceInCurrency !== undefined\n ? nativeBalanceUnit.mul(nativeMarketData.priceInCurrency)\n : undefined;\n\n const solanaBalance: TokenWithBalanceSVM = {\n type: TokenType.NATIVE,\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n decimals: network.networkToken.decimals,\n balance: nativeBalanceUnit.toSubUnit(),\n balanceDisplayValue: nativeBalanceUnit.toString(),\n balanceInCurrency: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: network.networkToken.logoUri ?? '',\n coingeckoId: coingeckoAssetId,\n ...nativeMarketData,\n };\n\n const tokenBalances = result.portfolio.tokens.reduce(\n (tokensAcc, { amountRaw, symbol, decimals, mint, name, logo }) => {\n const balanceUnit = new TokenUnit(amountRaw, decimals, symbol);\n const marketData = getMarketData(mint, lowercaseCurrency, tokenPrices);\n const balanceInCurrency =\n marketData.priceInCurrency !== undefined ? balanceUnit.mul(marketData.priceInCurrency) : undefined;\n\n const token: TokenWithBalanceSPL = {\n type: TokenType.SPL,\n address: mint,\n name,\n symbol,\n decimals,\n balance: balanceUnit.toSubUnit(),\n balanceDisplayValue: balanceUnit.toString(),\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: logo ?? undefined,\n reputation: null,\n ...marketData,\n };\n\n return {\n ...tokensAcc,\n [mint]: token,\n };\n },\n {} as Record<string, TokenWithBalanceSPL>,\n );\n\n return {\n ...portfolioAcc,\n [result.address]: {\n [network.networkToken.symbol]: solanaBalance,\n ...tokenBalances,\n },\n };\n }, {} as GetSolanaBalancesResponse);\n};\n\nconst getMarketData = (coinIdOrAddress: string, currency: string, prices?: SimplePriceResponse) => ({\n priceInCurrency: prices?.[coinIdOrAddress ?? '']?.[currency]?.price ?? undefined,\n marketCap: prices?.[coinIdOrAddress ?? '']?.[currency]?.marketCap ?? undefined,\n vol24: prices?.[coinIdOrAddress ?? '']?.[currency]?.vol24 ?? undefined,\n change24: prices?.[coinIdOrAddress ?? '']?.[currency]?.change24 ?? undefined,\n});\n","export const isFulfilled = <T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> =>\n result.status === 'fulfilled';\n","import { z } from 'zod';\n\nexport const PORTFOLIO_SCHEMA = z.object({\n nativeBalance: z.object({\n lamports: z.string(),\n solana: z.string(),\n }),\n nfts: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n name: z.string(),\n symbol: z.string(),\n }),\n ),\n tokens: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n amountRaw: z.string(),\n amount: z.string(),\n decimals: z.number(),\n name: z.string(),\n symbol: z.string(),\n logo: z.string().optional().nullable(),\n }),\n ),\n});\n\nexport type PortfolioResponse = z.infer<typeof PORTFOLIO_SCHEMA>;\n","import { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\n\nimport type { SolanaNetworkName } from '@src/types';\n\nimport { PORTFOLIO_SCHEMA, type PortfolioResponse } from './moralis-schemas';\n\nexport class MoralisService {\n #baseUrl: string;\n\n constructor({ proxyApiUrl }: { proxyApiUrl: string }) {\n this.#baseUrl = `${proxyApiUrl}/proxy/moralis`;\n }\n\n async getPortfolio({\n address,\n network,\n }: {\n network: SolanaNetworkName;\n address: string;\n }): Promise<{ address: string; portfolio: PortfolioResponse } | { address: string; error: string }> {\n try {\n const url = this.#buildUrl(`/account/${network}/${address}/portfolio`);\n const portfolio = await fetchAndVerify([url], PORTFOLIO_SCHEMA);\n\n return {\n address,\n portfolio,\n };\n } catch (error) {\n console.error('getPortfolio() failed:', error);\n\n const message = error instanceof Error ? error.message : 'unknown error';\n\n return {\n address,\n error: `getPortfolio() failed: ${message}`,\n };\n }\n }\n\n #buildUrl(path: string) {\n return `${this.#baseUrl}${path}`;\n }\n}\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { SOLANA_DEVNET_CAIP2_ID, SOLANA_MAINNET_CAIP2_ID, SOLANA_TESTNET_CAIP2_ID } from '../constants';\n\nexport const getNetworkName = (network: Network) => {\n switch (network.caipId) {\n case SOLANA_MAINNET_CAIP2_ID:\n return 'mainnet';\n\n case SOLANA_DEVNET_CAIP2_ID:\n return 'devnet';\n\n case SOLANA_TESTNET_CAIP2_ID:\n return 'testnet';\n\n default:\n throw new Error('Unrecognized CAIP-2 id: ' + network.caipId);\n }\n};\n","import { TransactionType, type Network, type TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { extractTokenTranfers, simplifyTokenBalance } from './extract-transfer';\nimport { getWrappedTransactions } from './get-wrapped-transactions';\nimport { getExplorerLink } from './get-explorer-link';\n\ntype SvmGetTransactionHistory = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport async function getTransactionHistory({\n network,\n address,\n proxyApiUrl,\n}: SvmGetTransactionHistory): Promise<TransactionHistoryResponse> {\n if (!network.caipId) {\n return Promise.reject({\n error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`),\n });\n }\n\n const rawTransactions = await getWrappedTransactions({ isTestnet: Boolean(network.isTestnet), address, proxyApiUrl });\n const transactions = rawTransactions\n .map(({ txHash, tx }) => {\n if (!tx.meta) {\n return null;\n }\n\n const {\n meta,\n transaction: { message },\n } = tx;\n // Typings are wrong here, .toString() fixes it without unnecessary casting\n const addresses = message.accountKeys.map((acc) => acc.toString());\n const accountIndex = addresses.indexOf(address);\n\n // accountKeys property is sorted in Solana transactions. The signing keys\n // are always the first, and the header.numRequiredSignatures tells us how many\n // of the first keys are signers. If the lookup address is a signer, it has to be\n // one of the first N keys.\n const isSigner = accountIndex < message.header.numRequiredSignatures;\n\n const transfers = extractTokenTranfers(\n addresses,\n accountIndex,\n {\n paidFee: isSigner ? Number(meta.fee) : 0,\n preBalances: meta.preBalances.map(Number),\n postBalances: meta.postBalances.map(Number),\n preTokenBalances: (meta.preTokenBalances ?? []).map(simplifyTokenBalance),\n postTokenBalances: (meta.postTokenBalances ?? []).map(simplifyTokenBalance),\n },\n network,\n );\n\n return {\n hash: txHash,\n // We should probably be smarter about the tx type, but this should be enough for MVP\n txType: isSigner ? TransactionType.SEND : TransactionType.RECEIVE,\n gasUsed: String(tx.meta.computeUnitsConsumed ?? '0'),\n tokens: transfers,\n\n // Get to/from addresses from the token transfers if possible.\n // If not possible:\n // - default \"from\" to the signing address\n // - default \"to\" to our address if we're not the signer and leave empty if we don't know.\n from: transfers[0]?.from?.address ?? (addresses[0] as string),\n to: transfers[0]?.to?.address ?? (isSigner ? '' : address),\n isOutgoing: isSigner,\n isIncoming: !isSigner,\n isSender: isSigner,\n timestamp: Number(tx.blockTime),\n isContractCall: false,\n gasPrice: String(Number(tx.meta.fee) / Number(tx.meta.computeUnitsConsumed)),\n chainId: String(network.chainId),\n explorerLink: getExplorerLink(txHash, network.explorerUrl),\n };\n })\n .filter(<T>(tx: T): tx is NonNullable<T> => tx !== null);\n\n return {\n transactions,\n };\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport { TokenType, type Network, type SPLToken, type TxToken } from '@avalabs/vm-module-types';\nimport type { TokenBalance } from '@solana/kit';\n\nexport const simplifyTokenBalance = (balance: TokenBalance): SimpleTokenBalance => ({\n mint: balance.mint as string,\n owner: balance.owner as string,\n amount: BigInt(balance.uiTokenAmount.amount),\n decimals: balance.uiTokenAmount.decimals,\n});\n\nexport const extractTokenTranfers: ExtractTransferFn<'SPL'> = (addresses, accountIndex, meta, network): TxToken[] => {\n // Create a map of initial balances\n const preBalances: Record<string, bigint> = meta.preTokenBalances.reduce(\n (acc, { owner, mint, amount }) => ({\n ...acc,\n [`${owner}-${mint}`]: amount,\n }),\n {},\n );\n\n // Compare with post balances to determine transfers\n const transfers = meta.postTokenBalances.reduce((acc, { owner, mint, amount, decimals }) => {\n const key = `${owner}-${mint}`;\n const preAmount = preBalances[key] ?? 0n;\n const netChange = amount - preAmount;\n\n if (netChange <= 0n) {\n return acc;\n }\n\n // Find sender (the one whose balance decreased)\n const sender = Object.keys(preBalances).find((k) => {\n const [possibleSender, mintFromPreBalance] = k.split('-');\n const possibleSenderPostBalance = meta.postTokenBalances.find(\n ({ owner: postBalanceOwner, mint: postBalanceMint }) =>\n postBalanceOwner === possibleSender && postBalanceMint === mint,\n );\n\n return (\n mintFromPreBalance === mint && possibleSenderPostBalance && preBalances[k]! > possibleSenderPostBalance.amount\n );\n });\n\n if (!sender) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: sender.split('-')[0]!,\n },\n to: {\n ...token,\n address: owner,\n },\n amount: new TokenUnit(netChange, decimals, '').toDisplay(),\n };\n\n return [...acc, transfer];\n }, [] as TxToken[]);\n\n const nativeTransfer = extractNativeTransfer(addresses, accountIndex, meta, network);\n\n if (nativeTransfer) {\n transfers.push(nativeTransfer);\n }\n\n return transfers;\n};\n\nconst extractNativeTransfer: ExtractTransferFn<'native'> = (\n addresses,\n accountIndex,\n { paidFee, preBalances, postBalances },\n network,\n) => {\n const address = addresses[accountIndex]!;\n const nativeBalancePre = preBalances[accountIndex]!;\n const nativeBalancePost = postBalances[accountIndex]!;\n const nativeTransferAmount =\n nativeBalancePost !== nativeBalancePre ? nativeBalancePost - nativeBalancePre + paidFee : 0;\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n\n if (!nativeTransferAmount) {\n return null;\n }\n\n const isIncoming = nativeTransferAmount > 0;\n const unit = new TokenUnit(Math.abs(nativeTransferAmount), network.networkToken.decimals, '');\n // If it's an incoming transaction, we assume it came from the transaction signer.\n // It it's an outgoing transaction, we need to find the address that received this exact amount (minus the fee).\n const otherAddressIndex = isIncoming\n ? 0\n : Math.max(\n 0,\n balanceDiffs.findIndex((diff) => diff === -nativeTransferAmount),\n );\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: isIncoming ? addresses[otherAddressIndex]! : address,\n },\n to: {\n address: isIncoming ? address : addresses[otherAddressIndex]!,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n};\n\ntype SimpleTokenBalance = {\n mint: string;\n owner: string;\n amount: bigint;\n decimals: number;\n};\n\ntype TxMeta = {\n paidFee: number;\n // Native SOL balances\n preBalances: number[];\n postBalances: number[];\n // SPL tokens balances\n preTokenBalances: SimpleTokenBalance[];\n postTokenBalances: SimpleTokenBalance[];\n};\n\ntype ExtractTransferFn<Type extends 'native' | 'SPL'> = (\n addresses: string[],\n accountIndex: number,\n meta: TxMeta,\n network: Network,\n) => Type extends 'native' ? TxToken | null : TxToken[];\n","import { address as solAddress, type GetTransactionApi } from '@solana/kit';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { hasPropertyDefined } from '@src/utils/has-property-defined';\n\ntype ParsedTx = ReturnType<GetTransactionApi['getTransaction']>;\ntype WrappedTransaction = { txHash: string; tx: NonNullable<ParsedTx> };\n\nexport const getWrappedTransactions = async ({\n isTestnet,\n address,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n address: string;\n proxyApiUrl: string;\n}): Promise<WrappedTransaction[]> => {\n const provider = getProvider({ isTestnet, proxyApiUrl });\n\n const signaturesResponse = await provider.getSignaturesForAddress(solAddress(address), { limit: 25 }).send(); // Same as we do for Bitcoin\n const signatures = signaturesResponse.map((sig) => sig.signature);\n const txsRequests = await Promise.allSettled(\n signatures.map(async (sig) => ({\n txHash: sig.toString(),\n tx: await provider.getTransaction(sig, { encoding: 'json', maxSupportedTransactionVersion: 0 }).send(),\n })),\n );\n\n return txsRequests\n .filter(isFulfilled)\n .map((tx) => tx.value)\n .filter(hasPropertyDefined('tx'));\n};\n","export function hasPropertyDefined<T, K extends keyof T>(key: K) {\n return (thing: T): thing is T & Record<K, NonNullable<unknown>> => Boolean(thing[key]);\n}\n","export const getExplorerLink = (txHash: string, baseUrl?: string) => {\n const explorerLink = baseUrl ? new URL(baseUrl) : null;\n\n // Keep the query params in-tact: the Solana explorers like SolScan.io or explorer.solana.com\n // switch between clusters based on the `cluster` query param, not the domain.\n if (explorerLink) {\n explorerLink.pathname = `/tx/${txHash}`;\n }\n\n return explorerLink?.toString() ?? '';\n};\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type BalanceChange,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SigningResult,\n type SPLToken,\n} from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\nimport { type Base64EncodedWireTransaction } from '@solana/kit';\n\nimport { dataItem } from '@internal/utils/src/utils/detail-item';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty, isNotNullish } from '@src/utils/functional';\nimport { tryToParseSolTransfer } from '@src/utils/instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from '@src/utils/instruction-parsers/spl-transfer';\nimport { parseRequestParams, type SendOptions } from './schema';\n\nexport const signAndSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx, sendOptions }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n // TODO: simulate transaction with Blockaid. Parsing like below can be used as a fallback.\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n const displayData: DisplayData = {\n title: 'Approve Transaction',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details: [\n {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', serializedTx)],\n },\n ...details,\n ],\n balanceChange: isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n let txHash;\n\n try {\n txHash = await getTxHash(provider, response, sendOptions);\n } catch (error) {\n console.error(error);\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n return {\n result: txHash,\n };\n};\n\nconst getTxHash = async (\n provider: ReturnType<typeof getProvider>,\n response: SigningResult,\n sendOptions?: SendOptions,\n) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n // broadcast the signed transaction\n const txHash = await provider\n .sendTransaction(response.signedData as Base64EncodedWireTransaction, {\n ...sendOptions,\n encoding: 'base64',\n })\n .send();\n return txHash;\n};\n","import type { BalanceChange } from '@avalabs/vm-module-types';\n\nexport function isBalanceChangeEmpty(input: BalanceChange): boolean {\n return input.ins.length === 0 && input.outs.length === 0;\n}\n\nexport function isNotNullish<I>(input: I): input is NonNullable<I> {\n return input !== null && input !== undefined;\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { BalanceChange, NetworkToken } from '@avalabs/vm-module-types';\nimport {\n identifySystemInstruction,\n parseTransferSolInstruction,\n SYSTEM_PROGRAM_ADDRESS,\n SystemInstruction,\n} from '@solana-program/system';\nimport {\n isInstructionForProgram,\n isInstructionWithAccounts,\n isInstructionWithData,\n type IInstruction,\n} from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nexport const tryToParseSolTransfer = (\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n networkToken: NetworkToken,\n) => {\n if (\n !isInstructionForProgram(instruction, SYSTEM_PROGRAM_ADDRESS) ||\n !isInstructionWithAccounts(instruction) ||\n !isInstructionWithData(instruction)\n ) {\n return;\n }\n\n try {\n const systemInstruction = identifySystemInstruction(instruction);\n\n if (systemInstruction !== SystemInstruction.TransferSol) {\n return null;\n }\n\n const { accounts, data } = parseTransferSolInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferSolInstruction()\n });\n\n const isOutgoing = accounts.source.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token: {\n ...networkToken,\n address: '',\n },\n items: [\n {\n displayValue: new TokenUnit(data.amount, networkToken.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: 'Native Transfer',\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport type { BalanceChange, SPLToken } from '@avalabs/vm-module-types';\nimport { parseTransferInstruction, identifyTokenInstruction, TokenInstruction } from '@solana-program/token';\nimport { isInstructionWithAccounts, isInstructionWithData, type Address, type IInstruction } from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nconst getTokenMintFromAccountInfo = async (provider: SolanaProvider, account: Address): Promise<string | null> => {\n try {\n const tokenAccountDetails = await provider.getAccountInfo(account, { encoding: 'jsonParsed' }).send();\n\n if (Array.isArray(tokenAccountDetails.value?.data)) {\n return null;\n }\n\n const info = tokenAccountDetails.value?.data.parsed.info as Record<string, unknown>;\n return typeof info?.mint === 'string' ? info.mint : null;\n } catch {\n return null;\n }\n};\n\nexport const tryToParseSPLTransfer = async (\n provider: SolanaProvider,\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n tokens?: SPLToken[],\n) => {\n if (!tokens?.length || !isInstructionWithAccounts(instruction) || !isInstructionWithData(instruction)) {\n return;\n }\n\n try {\n const tokenInstruction = identifyTokenInstruction(instruction);\n\n if (tokenInstruction !== TokenInstruction.Transfer) {\n return null;\n }\n\n const { accounts, data } = parseTransferInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferInstruction()\n });\n const tokenMint = await getTokenMintFromAccountInfo(provider, accounts.source.address);\n\n if (!tokenMint) {\n return null;\n }\n\n const token = tokens.find((t) => t.address.toLowerCase() === tokenMint.toLowerCase());\n\n if (!token) {\n return null;\n }\n\n const isOutgoing = accounts.source.address === account || accounts.authority.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token,\n items: [\n {\n displayValue: new TokenUnit(data.amount, token.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: `Transfer ${token.symbol}`,\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n sendOptions: z\n .object({\n preflightCommitment: z.enum(['processed', 'confirmed', 'finalized']).optional(),\n maxRetries: z.bigint().optional(),\n minContextSlot: z.bigint().optional(),\n skipPreflight: z.boolean().optional(),\n })\n .optional(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\nexport type SendOptions = z.infer<typeof transactionSchema>['sendOptions'];\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type BalanceChange,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SPLToken,\n} from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\n\nimport { dataItem } from '@internal/utils/src/utils/detail-item';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty, isNotNullish } from '@src/utils/functional';\nimport { tryToParseSolTransfer } from '@src/utils/instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from '@src/utils/instruction-parsers/spl-transfer';\nimport { parseRequestParams } from './schema';\n\nexport const signTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n // TODO: simulate transaction with Blockaid. Parsing like below can be used as a fallback.\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n const displayData: DisplayData = {\n title: 'Sign Transaction',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details: [\n {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', serializedTx)],\n },\n ...details,\n ],\n balanceChange: isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\n"]}
package/dist/index.d.cts CHANGED
@@ -1,14 +1,24 @@
1
1
  import * as _metamask_rpc_errors from '@metamask/rpc-errors';
2
- import * as _solana_rpc from '@solana/rpc';
3
- import { Rpc } from '@solana/rpc';
4
- import { Module, ConstructorParams, NetworkFees, RpcRequest } from '@avalabs/vm-module-types';
2
+ import * as _avalabs_vm_module_types_dist_rpc_e02a5305 from '@avalabs/vm-module-types/dist/rpc-e02a5305';
3
+ import * as _avalabs_vm_module_types_dist_token from '@avalabs/vm-module-types/dist/token';
4
+ import * as _avalabs_vm_module_types_dist_transaction_history from '@avalabs/vm-module-types/dist/transaction-history';
5
+ import * as _avalabs_vm_module_types_dist_network_fee from '@avalabs/vm-module-types/dist/network-fee';
6
+ import * as _avalabs_vm_module_types_dist_balance from '@avalabs/vm-module-types/dist/balance';
7
+ import * as _avalabs_vm_module_types_dist_error from '@avalabs/vm-module-types/dist/error';
8
+ import * as _avalabs_vm_module_types_dist_common from '@avalabs/vm-module-types/dist/common';
9
+ import { Module, ConstructorParams, Network, BuildDerivationPathParams, DeriveAddressParams, GetBalancesParams, NetworkFeeParam, GetTransactionHistory, RpcRequest } from '@avalabs/vm-module-types';
10
+ import { SolanaProvider } from '@avalabs/core-wallets-sdk';
5
11
 
6
12
  declare class SvmModule implements Module {
7
13
  #private;
8
14
  constructor({ approvalController, environment, appInfo }: ConstructorParams);
9
- getProvider(): Promise<Rpc<_solana_rpc.RequestAirdropApi & _solana_rpc.GetAccountInfoApi & _solana_rpc.GetBalanceApi & _solana_rpc.GetBlockApi & _solana_rpc.GetBlockCommitmentApi & _solana_rpc.GetBlockHeightApi & _solana_rpc.GetBlockProductionApi & _solana_rpc.GetBlocksApi & _solana_rpc.GetBlocksWithLimitApi & _solana_rpc.GetBlockTimeApi & _solana_rpc.GetClusterNodesApi & _solana_rpc.GetEpochInfoApi & _solana_rpc.GetEpochScheduleApi & _solana_rpc.GetFeeForMessageApi & _solana_rpc.GetFirstAvailableBlockApi & _solana_rpc.GetGenesisHashApi & _solana_rpc.GetHealthApi & _solana_rpc.GetHighestSnapshotSlotApi & _solana_rpc.GetIdentityApi & _solana_rpc.GetInflationGovernorApi & _solana_rpc.GetInflationRateApi & _solana_rpc.GetInflationRewardApi & _solana_rpc.GetLargestAccountsApi & _solana_rpc.GetLatestBlockhashApi & _solana_rpc.GetLeaderScheduleApi & _solana_rpc.GetMaxRetransmitSlotApi & _solana_rpc.GetMaxShredInsertSlotApi & _solana_rpc.GetMinimumBalanceForRentExemptionApi & _solana_rpc.GetMultipleAccountsApi & _solana_rpc.GetProgramAccountsApi & _solana_rpc.GetRecentPerformanceSamplesApi & _solana_rpc.GetRecentPrioritizationFeesApi & _solana_rpc.GetSignaturesForAddressApi & _solana_rpc.GetSignatureStatusesApi & _solana_rpc.GetSlotApi & _solana_rpc.GetSlotLeaderApi & _solana_rpc.GetSlotLeadersApi & _solana_rpc.GetStakeMinimumDelegationApi & _solana_rpc.GetSupplyApi & _solana_rpc.GetTokenAccountBalanceApi & _solana_rpc.GetTokenAccountsByDelegateApi & _solana_rpc.GetTokenAccountsByOwnerApi & _solana_rpc.GetTokenLargestAccountsApi & _solana_rpc.GetTokenSupplyApi & _solana_rpc.GetTransactionApi & _solana_rpc.GetTransactionCountApi & _solana_rpc.GetVersionApi & _solana_rpc.GetVoteAccountsApi & _solana_rpc.IsBlockhashValidApi & _solana_rpc.MinimumLedgerSlotApi & _solana_rpc.SendTransactionApi & _solana_rpc.SimulateTransactionApi>>;
15
+ getProvider(network: Network): Promise<SolanaProvider>;
10
16
  getAddress(): Promise<{}>;
11
- getBalances(): Promise<{}>;
17
+ buildDerivationPath(params: BuildDerivationPathParams): Pick<Partial<Record<_avalabs_vm_module_types_dist_common.NetworkVMType, string>>, _avalabs_vm_module_types_dist_common.NetworkVMType.SVM>;
18
+ deriveAddress(params: DeriveAddressParams): Promise<Partial<Record<_avalabs_vm_module_types_dist_common.NetworkVMType, string>>>;
19
+ getBalances(params: GetBalancesParams): Promise<{
20
+ [x: string]: _avalabs_vm_module_types_dist_error.Error | Record<string, _avalabs_vm_module_types_dist_balance.TokenWithBalanceSVM | _avalabs_vm_module_types_dist_balance.TokenWithBalanceSPL | _avalabs_vm_module_types_dist_error.Error>;
21
+ }>;
12
22
  getManifest(): {
13
23
  name: string;
14
24
  description: string;
@@ -49,13 +59,20 @@ declare class SvmModule implements Module {
49
59
  };
50
60
  manifestVersion: string;
51
61
  } | undefined;
52
- getNetworkFee(): Promise<NetworkFees>;
53
- getTransactionHistory(): Promise<{
54
- transactions: never[];
55
- }>;
56
- getTokens(): Promise<never[]>;
57
- onRpcRequest(request: RpcRequest): Promise<{
58
- error: _metamask_rpc_errors.JsonRpcError<_metamask_rpc_errors.OptionalDataWithOptionalCause>;
62
+ getNetworkFee(network: NetworkFeeParam): Promise<_avalabs_vm_module_types_dist_network_fee.NetworkFees>;
63
+ getTransactionHistory(params: GetTransactionHistory): Promise<_avalabs_vm_module_types_dist_transaction_history.TransactionHistoryResponse>;
64
+ getTokens(network: Network): Promise<_avalabs_vm_module_types_dist_token.SPLToken[]>;
65
+ onRpcRequest(request: RpcRequest, network: Network): Promise<{
66
+ error: _avalabs_vm_module_types_dist_rpc_e02a5305.b;
67
+ result?: undefined;
68
+ } | {
69
+ error: _metamask_rpc_errors.JsonRpcError<{
70
+ cause: unknown;
71
+ }>;
72
+ result?: undefined;
73
+ } | {
74
+ result: string;
75
+ error?: undefined;
59
76
  }>;
60
77
  }
61
78
 
package/dist/index.d.ts CHANGED
@@ -1,14 +1,24 @@
1
1
  import * as _metamask_rpc_errors from '@metamask/rpc-errors';
2
- import * as _solana_rpc from '@solana/rpc';
3
- import { Rpc } from '@solana/rpc';
4
- import { Module, ConstructorParams, NetworkFees, RpcRequest } from '@avalabs/vm-module-types';
2
+ import * as _avalabs_vm_module_types_dist_rpc_e02a5305 from '@avalabs/vm-module-types/dist/rpc-e02a5305';
3
+ import * as _avalabs_vm_module_types_dist_token from '@avalabs/vm-module-types/dist/token';
4
+ import * as _avalabs_vm_module_types_dist_transaction_history from '@avalabs/vm-module-types/dist/transaction-history';
5
+ import * as _avalabs_vm_module_types_dist_network_fee from '@avalabs/vm-module-types/dist/network-fee';
6
+ import * as _avalabs_vm_module_types_dist_balance from '@avalabs/vm-module-types/dist/balance';
7
+ import * as _avalabs_vm_module_types_dist_error from '@avalabs/vm-module-types/dist/error';
8
+ import * as _avalabs_vm_module_types_dist_common from '@avalabs/vm-module-types/dist/common';
9
+ import { Module, ConstructorParams, Network, BuildDerivationPathParams, DeriveAddressParams, GetBalancesParams, NetworkFeeParam, GetTransactionHistory, RpcRequest } from '@avalabs/vm-module-types';
10
+ import { SolanaProvider } from '@avalabs/core-wallets-sdk';
5
11
 
6
12
  declare class SvmModule implements Module {
7
13
  #private;
8
14
  constructor({ approvalController, environment, appInfo }: ConstructorParams);
9
- getProvider(): Promise<Rpc<_solana_rpc.RequestAirdropApi & _solana_rpc.GetAccountInfoApi & _solana_rpc.GetBalanceApi & _solana_rpc.GetBlockApi & _solana_rpc.GetBlockCommitmentApi & _solana_rpc.GetBlockHeightApi & _solana_rpc.GetBlockProductionApi & _solana_rpc.GetBlocksApi & _solana_rpc.GetBlocksWithLimitApi & _solana_rpc.GetBlockTimeApi & _solana_rpc.GetClusterNodesApi & _solana_rpc.GetEpochInfoApi & _solana_rpc.GetEpochScheduleApi & _solana_rpc.GetFeeForMessageApi & _solana_rpc.GetFirstAvailableBlockApi & _solana_rpc.GetGenesisHashApi & _solana_rpc.GetHealthApi & _solana_rpc.GetHighestSnapshotSlotApi & _solana_rpc.GetIdentityApi & _solana_rpc.GetInflationGovernorApi & _solana_rpc.GetInflationRateApi & _solana_rpc.GetInflationRewardApi & _solana_rpc.GetLargestAccountsApi & _solana_rpc.GetLatestBlockhashApi & _solana_rpc.GetLeaderScheduleApi & _solana_rpc.GetMaxRetransmitSlotApi & _solana_rpc.GetMaxShredInsertSlotApi & _solana_rpc.GetMinimumBalanceForRentExemptionApi & _solana_rpc.GetMultipleAccountsApi & _solana_rpc.GetProgramAccountsApi & _solana_rpc.GetRecentPerformanceSamplesApi & _solana_rpc.GetRecentPrioritizationFeesApi & _solana_rpc.GetSignaturesForAddressApi & _solana_rpc.GetSignatureStatusesApi & _solana_rpc.GetSlotApi & _solana_rpc.GetSlotLeaderApi & _solana_rpc.GetSlotLeadersApi & _solana_rpc.GetStakeMinimumDelegationApi & _solana_rpc.GetSupplyApi & _solana_rpc.GetTokenAccountBalanceApi & _solana_rpc.GetTokenAccountsByDelegateApi & _solana_rpc.GetTokenAccountsByOwnerApi & _solana_rpc.GetTokenLargestAccountsApi & _solana_rpc.GetTokenSupplyApi & _solana_rpc.GetTransactionApi & _solana_rpc.GetTransactionCountApi & _solana_rpc.GetVersionApi & _solana_rpc.GetVoteAccountsApi & _solana_rpc.IsBlockhashValidApi & _solana_rpc.MinimumLedgerSlotApi & _solana_rpc.SendTransactionApi & _solana_rpc.SimulateTransactionApi>>;
15
+ getProvider(network: Network): Promise<SolanaProvider>;
10
16
  getAddress(): Promise<{}>;
11
- getBalances(): Promise<{}>;
17
+ buildDerivationPath(params: BuildDerivationPathParams): Pick<Partial<Record<_avalabs_vm_module_types_dist_common.NetworkVMType, string>>, _avalabs_vm_module_types_dist_common.NetworkVMType.SVM>;
18
+ deriveAddress(params: DeriveAddressParams): Promise<Partial<Record<_avalabs_vm_module_types_dist_common.NetworkVMType, string>>>;
19
+ getBalances(params: GetBalancesParams): Promise<{
20
+ [x: string]: _avalabs_vm_module_types_dist_error.Error | Record<string, _avalabs_vm_module_types_dist_balance.TokenWithBalanceSVM | _avalabs_vm_module_types_dist_balance.TokenWithBalanceSPL | _avalabs_vm_module_types_dist_error.Error>;
21
+ }>;
12
22
  getManifest(): {
13
23
  name: string;
14
24
  description: string;
@@ -49,13 +59,20 @@ declare class SvmModule implements Module {
49
59
  };
50
60
  manifestVersion: string;
51
61
  } | undefined;
52
- getNetworkFee(): Promise<NetworkFees>;
53
- getTransactionHistory(): Promise<{
54
- transactions: never[];
55
- }>;
56
- getTokens(): Promise<never[]>;
57
- onRpcRequest(request: RpcRequest): Promise<{
58
- error: _metamask_rpc_errors.JsonRpcError<_metamask_rpc_errors.OptionalDataWithOptionalCause>;
62
+ getNetworkFee(network: NetworkFeeParam): Promise<_avalabs_vm_module_types_dist_network_fee.NetworkFees>;
63
+ getTransactionHistory(params: GetTransactionHistory): Promise<_avalabs_vm_module_types_dist_transaction_history.TransactionHistoryResponse>;
64
+ getTokens(network: Network): Promise<_avalabs_vm_module_types_dist_token.SPLToken[]>;
65
+ onRpcRequest(request: RpcRequest, network: Network): Promise<{
66
+ error: _avalabs_vm_module_types_dist_rpc_e02a5305.b;
67
+ result?: undefined;
68
+ } | {
69
+ error: _metamask_rpc_errors.JsonRpcError<{
70
+ cause: unknown;
71
+ }>;
72
+ result?: undefined;
73
+ } | {
74
+ result: string;
75
+ error?: undefined;
59
76
  }>;
60
77
  }
61
78
 
package/dist/index.js CHANGED
@@ -1,9 +1,16 @@
1
- import { parseManifest, Environment } from '@avalabs/vm-module-types';
2
- import '@solana/rpc';
1
+ import { TokenType, parseManifest, RpcMethod, Environment, NetworkVMType, TransactionType, RawSimplePriceResponseSchema, DetailItemType } from '@avalabs/vm-module-types';
3
2
  import { rpcErrors } from '@metamask/rpc-errors';
3
+ import { getBasicCoingeckoHttp, VsCurrencyType, simpleTokenPrice, simplePrice } from '@avalabs/core-coingecko-sdk';
4
+ import { object, string, record, number, z } from 'zod';
5
+ import { base58, hex } from '@scure/base';
6
+ import { getSolanaProvider, deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';
7
+ import { TokenUnit } from '@avalabs/core-utils-sdk';
8
+ import { address, isInstructionForProgram, isInstructionWithAccounts, isInstructionWithData } from '@solana/kit';
9
+ import { SYSTEM_PROGRAM_ADDRESS, identifySystemInstruction, SystemInstruction, parseTransferSolInstruction } from '@solana-program/system';
10
+ import { identifyTokenInstruction, TokenInstruction, parseTransferInstruction } from '@solana-program/token';
4
11
 
5
- var m=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var a=(r,e,t)=>(m(r,e,"read from private field"),t?t.call(r):e.get(r)),i=(r,e,t)=>{if(e.has(r))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(r):e.set(r,t);},c=(r,e,t,p)=>(m(r,e,"write to private field"),p?p.call(r,t):e.set(r,t),t);var l={name:"SVM",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/svm-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1","solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"],namespaces:["solana"]},cointype:"501",permissions:{rpc:{dapps:!0,methods:["getGenesisHash"],nonRestrictedMethods:["getGenesisHash"]}},manifestVersion:"0.1"};var f={proxyApiUrl:"https://proxy-api.avax.network"},g={proxyApiUrl:"https://proxy-api-dev.avax.network"},u=r=>{switch(r){case Environment.PRODUCTION:return f;case Environment.DEV:return g}};var o,s,n,d=class{constructor({approvalController:e,environment:t,appInfo:p}){i(this,o,void 0);i(this,s,void 0);i(this,n,void 0);let{proxyApiUrl:y}=u(t);c(this,n,p),c(this,o,y),c(this,s,e),a(this,o),a(this,s),a(this,n);}getProvider(){return Promise.resolve({})}getAddress(){return Promise.resolve({})}getBalances(){return Promise.resolve({})}getManifest(){let e=parseManifest(l);return e.success?e.data:void 0}getNetworkFee(){return Promise.resolve({})}getTransactionHistory(){return Promise.resolve({transactions:[]})}getTokens(){return Promise.resolve([])}async onRpcRequest(e){return {error:rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}};o=new WeakMap,s=new WeakMap,n=new WeakMap;
12
+ var at=Object.defineProperty;var st=(t,e,r)=>e in t?at(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var ue=(t,e,r)=>(st(t,typeof e!="symbol"?e+"":e,r),r),oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)};var m=(t,e,r)=>(oe(t,e,"read from private field"),r?r.call(t):e.get(t)),I=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r);},w=(t,e,r,n)=>(oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);var fe=(t,e,r)=>(oe(t,e,"access private method"),r);var ae=async({operation:t,isSuccess:e,maxRetries:r=10,backoffPolicy:n=L.exponential()})=>{let a=0,s=0,o;for(;s<r;){s>0&&await it(a);try{let c=await t(s);if(e(c))return c}catch(c){o=c;}a=n(s),s++;}let i=o?`Max retry exceeded. ${o}`:"Max retry exceeded.";throw new Error(i)},L=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return r=>e*1e3}static constantMs(e){return r=>e}};function it(t){return new Promise(e=>setTimeout(e,t))}var se=t=>ae({operation:e=>t(e>0),maxRetries:2,backoffPolicy:L.constant(1),isSuccess:e=>e?.status?.error_code!==429});function ye(t){let e,r=0;for(e=0;e<t.length;e++)r+=t.charCodeAt(e)*(e+1);return r}function ie(t){let e,r=0;for(e=0;e<t.length;e++){let n=ye(t[e]??"");r=r+65027/n;}return (""+r).slice(0,16)}async function b(t,e){let r=await fetch(...t);if(!r.ok)throw new Error(`Request failed with status ${r.status}`);let n=await r.json();return e.parse(n)}var F=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let r=new URLSearchParams(e);return b([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${r}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:r,...n}=e,a=new URLSearchParams(n);return b([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${r}?${a}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}};var Te=getBasicCoingeckoHttp(),D,B,M=class{constructor({storage:e,proxyApiUrl:r}){I(this,D,void 0);I(this,B,void 0);ue(this,"transformSimplePriceResponse",(e,r=[VsCurrencyType.USD])=>{let n={};return Object.keys(e).forEach(a=>{let s=e[a];n[a]={},r.forEach(o=>{n[a]={[o]:{price:s?.[o],change24:s?.[`${o}_24h_change`],vol24:s?.[`${o}_24h_vol`],marketCap:s?.[`${o}_market_cap`]}};});}),n});w(this,D,e),w(this,B,r);}async getSimplePrice({coinIds:e=[],currencies:r=[VsCurrencyType.USD]}){let n,s=`getSimplePrice-${e?`${ie(e)}-${r.toString()}`:`${r.toString()}`}`;if(n=m(this,D)?.get?.(s),n)return n;try{n=await se(o=>this.simplePrice({coinIds:e,currencies:r,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:o}));}catch{n=void 0;}return m(this,D)?.set?.(s,n),n}async getPricesByAddresses(e,r,n=VsCurrencyType.USD){let a,o=`getPricesWithMarketDataByAddresses-${`${ie(e)}-${r}-${n}`}`;if(a=m(this,D)?.get?.(o),a)return a;try{a=await se(i=>this.fetchPricesByAddresses({assetPlatformId:r,tokenAddresses:e,currency:n,useCoingeckoProxy:i}));}catch(i){console.error(i),a=void 0;}return m(this,D)?.set?.(o,a),a}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:r,currency:n=VsCurrencyType.USD,useCoingeckoProxy:a=!1}){if(a){let s=await new F(m(this,B)).simplePriceByContractAddresses({id:e,contract_addresses:r,vs_currencies:[n],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[n])}return simpleTokenPrice(Te,{assetPlatformId:e,tokenAddresses:r,currencies:[n],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:r=[VsCurrencyType.USD],marketCap:n=!1,vol24:a=!1,change24:s=!1,lastUpdated:o=!1,useCoingeckoProxy:i=!1,shouldThrow:c=!0}){if(i){let p=await new F(m(this,B)).simplePrice({ids:e,vs_currencies:r,include_market_cap:n,include_24hr_vol:a,include_24hr_change:s,include_last_updated_at:o});return this.transformSimplePriceResponse(p,r)}return simplePrice(Te,{coinIds:e,currencies:r,marketCap:n,vol24:a,change24:s,lastUpdated:o,shouldThrow:c})}};D=new WeakMap,B=new WeakMap;object({date:string(),usd:record(number())});var E=(t,e)=>({label:t,type:DetailItemType.ADDRESS,value:e});var V=(t,e)=>({label:t,type:DetailItemType.DATA,value:e});var he={name:"SVM",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/svm-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1","solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"],namespaces:["solana"]},cointype:"501",permissions:{rpc:{dapps:!0,methods:["solana_signTransaction","solana_signAndSendTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var gt={proxyApiUrl:"https://proxy-api.avax.network"},Tt={proxyApiUrl:"https://proxy-api-dev.avax.network"},xe=t=>{switch(t){case Environment.PRODUCTION:return gt;case Environment.DEV:return Tt}};var ke=t=>"derivationPathType"in t&&"accountIndex"in t&&typeof t.accountIndex=="number"&&typeof t.derivationPathType=="string";var G=({accountIndex:t})=>{if(t<0)throw rpcErrors.invalidParams("Account index must be a non-negative integer");return {[NetworkVMType.SVM]:`m/44'/501'/${t}'/0'`}};var ve=async t=>{let{approvalController:e,secretId:r}=t,n=ke(t)?G(t).SVM:void 0,a=await e.requestPublicKey({curve:"ed25519",secretId:r,derivationPath:n});return {[NetworkVMType.SVM]:base58.encode(hex.decode(a))}};var Ie="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ae="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Re="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",we="/proxy/nownodes/sol",be="https://api.devnet.solana.com";var A=({isTestnet:t,proxyApiUrl:e})=>getSolanaProvider({isTestnet:t,rpcUrl:t?be:e+we});var ce=1e6,R={high:150*ce,medium:75*ce,low:2*ce},It=t=>(t.length===0?[R.low,R.low]:t.length===1?[t[0],R.low]:t).slice().sort((r,n)=>r-n);async function Ne(t,e){let a=await(await A({isTestnet:!!t.isTestnet,proxyApiUrl:e}).getRecentPrioritizationFees()).send();if(a.length===0||a.every(P=>P.prioritizationFee===0n))return {high:{maxFeePerGas:BigInt(R.high),maxPriorityFeePerGas:BigInt(R.high)},medium:{maxFeePerGas:BigInt(R.medium),maxPriorityFeePerGas:BigInt(R.medium)},low:{maxFeePerGas:BigInt(R.low),maxPriorityFeePerGas:BigInt(R.low)},baseFee:BigInt(R.low),displayDecimals:9,isFixedFee:!1};let o=It(a.map(P=>Number(P.prioritizationFee))),i=o.at(0),c=o.at(-1),p=Math.floor(o.length/2),y=o.length%2===1?o[p]:(o[p-1]+o[p])/2,l=BigInt(Math.ceil(c*1.05)),d=BigInt(Math.ceil(y*1.05)),g=BigInt(Math.ceil(i*1.05));return {high:{maxFeePerGas:l,maxPriorityFeePerGas:l},medium:{maxFeePerGas:d,maxPriorityFeePerGas:d},low:{maxFeePerGas:g,maxPriorityFeePerGas:g},baseFee:g,displayDecimals:9,isFixedFee:!1}}var Rt=z.object({address:z.string(),name:z.string(),symbol:z.string(),contractType:z.literal(TokenType.SPL),caip2Id:z.string().startsWith("solana:"),decimals:z.number(),chainId:z.number().optional(),logoUri:z.string().optional(),color:z.string().optional()}),De=z.array(Rt);async function _e({caip2Id:t,proxyApiUrl:e}){try{return (await b([`${e}/solana-tokens?caip2Id=${t}`],De)).map(n=>({...n,type:n.contractType}))}catch(r){throw console.error("getTokens() failed for",t,r),rpcErrors.internal(`Failed to fetch tokens for caip2Id "${t}"`)}}var _=t=>t.status==="fulfilled";var Ce=z.object({nativeBalance:z.object({lamports:z.string(),solana:z.string()}),nfts:z.array(z.object({associatedTokenAddress:z.string(),mint:z.string(),name:z.string(),symbol:z.string()})),tokens:z.array(z.object({associatedTokenAddress:z.string(),mint:z.string(),amountRaw:z.string(),amount:z.string(),decimals:z.number(),name:z.string(),symbol:z.string(),logo:z.string().optional().nullable()}))});var $,W,Ee,j=class{constructor({proxyApiUrl:e}){I(this,W);I(this,$,void 0);w(this,$,`${e}/proxy/moralis`);}async getPortfolio({address:e,network:r}){try{let n=fe(this,W,Ee).call(this,`/account/${r}/${e}/portfolio`),a=await b([n],Ce);return {address:e,portfolio:a}}catch(n){console.error("getPortfolio() failed:",n);let a=n instanceof Error?n.message:"unknown error";return {address:e,error:`getPortfolio() failed: ${a}`}}}};$=new WeakMap,W=new WeakSet,Ee=function(e){return `${m(this,$)}${e}`};var Be=t=>{switch(t.caipId){case Ie:return "mainnet";case Ae:return "devnet";case Re:return "testnet";default:throw new Error("Unrecognized CAIP-2 id: "+t.caipId)}};var Oe=async({addresses:t,proxyApiUrl:e,currency:r,network:n,tokenService:a})=>{let s=new j({proxyApiUrl:e}),o=n.pricingProviders?.coingecko.nativeTokenId??"",i=n.pricingProviders?.coingecko.assetPlatformId??"",c=r.toLowerCase(),p=Be(n),y=await Promise.all(t.map(T=>s.getPortfolio({address:T,network:p}))),l=new Set(y.flatMap(T=>"portfolio"in T?T.portfolio.tokens.map(({mint:u})=>u):[])),d=await Promise.allSettled([o?await a.getSimplePrice({coinIds:[o],currencies:[c]}):Promise.resolve(void 0),i?await a.getPricesByAddresses(Array.from(l),i,c):Promise.resolve(void 0)]),[g,P]=d.map(T=>_(T)?T.value:void 0);return y.reduce((T,u)=>{if("error"in u)return {...T,[u.address]:{error:u.error}};let S=new TokenUnit(u.portfolio.nativeBalance.lamports,9,"SOL"),h=Fe(o,c,g),k=h.priceInCurrency!==void 0?S.mul(h.priceInCurrency):void 0,U={type:TokenType.NATIVE,name:n.networkToken.name,symbol:n.networkToken.symbol,decimals:n.networkToken.decimals,balance:S.toSubUnit(),balanceDisplayValue:S.toString(),balanceInCurrency:k?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:k?.toDisplay({fixedDp:2}),logoUri:n.networkToken.logoUri??"",coingeckoId:o,...h},z=u.portfolio.tokens.reduce((Q,{amountRaw:ee,symbol:le,decimals:me,mint:te,name:rt,logo:nt})=>{let re=new TokenUnit(ee,me,le),ne=Fe(te,c,P),de=ne.priceInCurrency!==void 0?re.mul(ne.priceInCurrency):void 0,ot={type:TokenType.SPL,address:te,name:rt,symbol:le,decimals:me,balance:re.toSubUnit(),balanceDisplayValue:re.toString(),balanceInCurrency:de?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:de?.toDisplay({fixedDp:2}),logoUri:nt??void 0,reputation:null,...ne};return {...Q,[te]:ot}},{});return {...T,[u.address]:{[n.networkToken.symbol]:U,...z}}},{})},Fe=(t,e,r)=>({priceInCurrency:r?.[t??""]?.[e]?.price??void 0,marketCap:r?.[t??""]?.[e]?.marketCap??void 0,vol24:r?.[t??""]?.[e]?.vol24??void 0,change24:r?.[t??""]?.[e]?.change24??void 0});var pe=t=>({mint:t.mint,owner:t.owner,amount:BigInt(t.uiTokenAmount.amount),decimals:t.uiTokenAmount.decimals}),$e=(t,e,r,n)=>{let a=r.preTokenBalances.reduce((i,{owner:c,mint:p,amount:y})=>({...i,[`${c}-${p}`]:y}),{}),s=r.postTokenBalances.reduce((i,{owner:c,mint:p,amount:y,decimals:l})=>{let d=`${c}-${p}`,g=a[d]??0n,P=y-g;if(P<=0n)return i;let T=Object.keys(a).find(h=>{let[k,U]=h.split("-"),z=r.postTokenBalances.find(({owner:Q,mint:ee})=>Q===k&&ee===p);return U===p&&z&&a[h]>z.amount});if(!T)return i;let u=n.tokens?.filter(h=>"contractType"in h).find(h=>h.address===p)??{contractType:TokenType.SPL,decimals:l,address:p,symbol:"Unknown",name:"Unknown"},S={...u,type:u.contractType,from:{...u,address:T.split("-")[0]},to:{...u,address:c},amount:new TokenUnit(P,l,"").toDisplay()};return [...i,S]},[]),o=bt(t,e,r,n);return o&&s.push(o),s},bt=(t,e,{paidFee:r,preBalances:n,postBalances:a},s)=>{let o=t[e],i=n[e],c=a[e],p=c!==i?c-i+r:0,y=a.map((P,T)=>P-n[T]);if(!p)return null;let l=p>0,d=new TokenUnit(Math.abs(p),s.networkToken.decimals,""),g=l?0:Math.max(0,y.findIndex(P=>P===-p));return {amount:d.toDisplay(),from:{address:l?t[g]:o},to:{address:l?o:t[g]},name:s.networkToken.name,symbol:s.networkToken.symbol,type:TokenType.NATIVE}};function He(t){return e=>!!e[t]}var ze=async({isTestnet:t,address:e,proxyApiUrl:r})=>{let n=A({isTestnet:t,proxyApiUrl:r}),s=(await n.getSignaturesForAddress(address(e),{limit:25}).send()).map(i=>i.signature);return (await Promise.allSettled(s.map(async i=>({txHash:i.toString(),tx:await n.getTransaction(i,{encoding:"json",maxSupportedTransactionVersion:0}).send()})))).filter(_).map(i=>i.value).filter(He("tx"))};var Ge=(t,e)=>{let r=e?new URL(e):null;return r&&(r.pathname=`/tx/${t}`),r?.toString()??""};async function je({network:t,address:e,proxyApiUrl:r}){return t.caipId?{transactions:(await ze({isTestnet:!!t.isTestnet,address:e,proxyApiUrl:r})).map(({txHash:s,tx:o})=>{if(!o.meta)return null;let{meta:i,transaction:{message:c}}=o,p=c.accountKeys.map(g=>g.toString()),y=p.indexOf(e),l=y<c.header.numRequiredSignatures,d=$e(p,y,{paidFee:l?Number(i.fee):0,preBalances:i.preBalances.map(Number),postBalances:i.postBalances.map(Number),preTokenBalances:(i.preTokenBalances??[]).map(pe),postTokenBalances:(i.postTokenBalances??[]).map(pe)},t);return {hash:s,txType:l?TransactionType.SEND:TransactionType.RECEIVE,gasUsed:String(o.meta.computeUnitsConsumed??"0"),tokens:d,from:d[0]?.from?.address??p[0],to:d[0]?.to?.address??(l?"":e),isOutgoing:l,isIncoming:!l,isSender:l,timestamp:Number(o.blockTime),isContractCall:!1,gasPrice:String(Number(o.meta.fee)/Number(o.meta.computeUnitsConsumed)),chainId:String(t.chainId),explorerLink:Ge(s,t.explorerUrl)}}).filter(s=>s!==null)}:Promise.reject({error:rpcErrors.invalidParams("Network must have a CAIP-2 id")})}function K(t){return t.ins.length===0&&t.outs.length===0}function Y(t){return t!=null}var X=(t,e,r,n)=>{if(!(!isInstructionForProgram(t,SYSTEM_PROGRAM_ADDRESS)||!isInstructionWithAccounts(t)||!isInstructionWithData(t)))try{if(identifySystemInstruction(t)!==SystemInstruction.TransferSol)return null;let{accounts:s,data:o}=parseTransferSolInstruction({...t,data:Uint8Array.from(t.data)}),c=s.source.address===r===!0?"outs":"ins";return e[c].push({token:{...n,address:""},items:[{displayValue:new TokenUnit(o.amount,n.decimals,"").toString(),usdPrice:void 0}]}),{title:"Native Transfer",items:[E("From",s.source.address),E("To",s.destination.address)]}}catch{return null}};var qt=async(t,e)=>{try{let r=await t.getAccountInfo(e,{encoding:"jsonParsed"}).send();if(Array.isArray(r.value?.data))return null;let n=r.value?.data.parsed.info;return typeof n?.mint=="string"?n.mint:null}catch{return null}},J=async(t,e,r,n,a)=>{if(!(!a?.length||!isInstructionWithAccounts(e)||!isInstructionWithData(e)))try{if(identifyTokenInstruction(e)!==TokenInstruction.Transfer)return null;let{accounts:o,data:i}=parseTransferInstruction({...e,data:Uint8Array.from(e.data)}),c=await qt(t,o.source.address);if(!c)return null;let p=a.find(d=>d.address.toLowerCase()===c.toLowerCase());if(!p)return null;let l=(o.source.address===n||o.authority.address===n)===!0?"outs":"ins";return r[l].push({token:p,items:[{displayValue:new TokenUnit(i.amount,p.decimals,"").toString(),usdPrice:void 0}]}),{title:`Transfer ${p.symbol}`,items:[E("From",o.source.address),E("To",o.destination.address)]}}catch{return null}};var jt=z.object({account:z.string(),serializedTx:z.string().base64(),sendOptions:z.object({preflightCommitment:z.enum(["processed","confirmed","finalized"]).optional(),maxRetries:z.bigint().optional(),minContextSlot:z.bigint().optional(),skipPreflight:z.boolean().optional()}).optional()}),Wt=z.tuple([jt]),We=t=>Wt.safeParse(t);var Ye=async({request:t,network:e,approvalController:r,proxyApiUrl:n})=>{let{params:a}=t,{data:s,success:o,error:i}=We(a);if(!o)return console.error("invalid params",i),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:i}})};let[{account:c,serializedTx:p,sendOptions:y}]=s,l=A({isTestnet:!!e.isTestnet,proxyApiUrl:n}),d=await deserializeTransactionMessage(p,l),g={ins:[],outs:[]},P=await Promise.allSettled(d.instructions.map(async k=>X(k,g,c,e.networkToken)??await J(l,k,g,c,e.tokens)??null)).then(k=>k.filter(_).map(U=>U.value).filter(Y)),T={title:"Approve Transaction",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[V("Raw Data",p)]},...P],balanceChange:K(g)?void 0:g,networkFeeSelector:!1,isSimulationSuccessful:!1},u={type:RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,account:c,data:p},S=await r.requestApproval({request:t,displayData:T,signingData:u});if("error"in S)return {error:S.error};let h;try{h=await Xt(l,S,y);}catch(k){return console.error(k),{error:rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:k}})}}return {result:h}},Xt=async(t,e,r)=>"txHash"in e?e.txHash:await t.sendTransaction(e.signedData,{...r,encoding:"base64"}).send();var Jt=z.object({account:z.string(),serializedTx:z.string().base64()}),Zt=z.tuple([Jt]),Xe=t=>Zt.safeParse(t);var Ze=async({request:t,network:e,approvalController:r,proxyApiUrl:n})=>{let{params:a}=t,{data:s,success:o,error:i}=Xe(a);if(!o)return console.error("invalid params",i),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:i}})};let[{account:c,serializedTx:p}]=s,y=A({isTestnet:!!e.isTestnet,proxyApiUrl:n}),l=await deserializeTransactionMessage(p,y),d={ins:[],outs:[]},g=await Promise.allSettled(l.instructions.map(async S=>X(S,d,c,e.networkToken)??await J(y,S,d,c,e.tokens)??null)).then(S=>S.filter(_).map(h=>h.value).filter(Y)),P={title:"Sign Transaction",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[V("Raw Data",p)]},...g],balanceChange:K(d)?void 0:d,networkFeeSelector:!1,isSimulationSuccessful:!1},T={type:RpcMethod.SOLANA_SIGN_TRANSACTION,account:c,data:p},u=await r.requestApproval({request:t,displayData:P,signingData:T});return "error"in u?{error:u.error}:"signedData"in u?{result:u.signedData}:{error:rpcErrors.invalidRequest("No signed data returned")}};var x,C,H,tt=class{constructor({approvalController:e,environment:r,appInfo:n}){I(this,x,void 0);I(this,C,void 0);I(this,H,void 0);let{proxyApiUrl:a}=xe(r);w(this,H,n),w(this,x,a),w(this,C,e),m(this,x),m(this,C),m(this,H);}async getProvider(e){return A({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}getAddress(){return Promise.resolve({})}buildDerivationPath(e){return G(e)}deriveAddress(e){return ve({...e,approvalController:m(this,C)})}getBalances(e){let r=new M({storage:e.storage,proxyApiUrl:m(this,x)});return Oe({...e,tokenService:r,proxyApiUrl:m(this,x)})}getManifest(){let e=parseManifest(he);return e.success?e.data:void 0}getNetworkFee(e){return Ne(e,m(this,x))}getTransactionHistory(e){return je({network:e.network,address:e.address,proxyApiUrl:m(this,x)})}getTokens(e){return e.caipId?_e({caip2Id:e.caipId,proxyApiUrl:m(this,x)}):Promise.reject({error:rpcErrors.invalidParams("Network must have a CAIP-2 id")})}async onRpcRequest(e,r){switch(e.method){case RpcMethod.SOLANA_SIGN_TRANSACTION:return Ze({approvalController:m(this,C),proxyApiUrl:m(this,x),network:r,request:e});case RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION:return Ye({approvalController:m(this,C),proxyApiUrl:m(this,x),network:r,request:e})}return {error:rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}};x=new WeakMap,C=new WeakMap,H=new WeakMap;
6
13
 
7
- export { d as SvmModule };
14
+ export { tt as SvmModule };
8
15
  //# sourceMappingURL=out.js.map
9
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module.ts","../manifest.json","../src/env.ts"],"names":["parseManifest","rpcErrors","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","_proxyApiUrl","_approvalController","_appInfo","SvmModule","approvalController","appInfo","__privateAdd","proxyApiUrl","__privateSet","__privateGet","result","request"],"mappings":"mVAAA,OACE,iBAAAA,MAOK,2BACP,MAAkD,cAClD,OAAS,aAAAC,MAAiB,uBCV1B,IAAAC,EAAA,CACE,KAAQ,MACR,YAAe,GACf,QAAW,QACX,QAAW,CACT,OAAU,CACR,SAAY,GACZ,SAAY,CACV,IAAO,CACL,SAAY,gBACZ,YAAe,sBACf,SAAY,4BACd,CACF,CACF,CACF,EACA,QAAW,CACT,SAAY,CACV,0CACA,0CACA,yCACF,EACA,WAAc,CAAC,QAAQ,CACzB,EACA,SAAY,MACZ,YAAe,CACb,IAAO,CACL,MAAS,GACT,QAAW,CAAC,gBAAgB,EAC5B,qBAAwB,CAAC,gBAAgB,CAC3C,CACF,EACA,gBAAmB,KACrB,ECjCA,OAAS,eAAAC,MAAmB,2BAMrB,IAAMC,EAAe,CAC1B,YAAa,gCACf,EAEaC,EAAc,CACzB,YAAa,oCACf,EAEaC,EAAUC,GAAkC,CACvD,OAAQA,EAAa,CACnB,KAAKJ,EAAY,WACf,OAAOC,EACT,KAAKD,EAAY,IACf,OAAOE,CACX,CACF,EFrBA,IAAAG,EAAAC,EAAAC,EAeaC,EAAN,KAAkC,CAKvC,YAAY,CAAE,mBAAAC,EAAoB,YAAAL,EAAa,QAAAM,CAAQ,EAAsB,CAJ7EC,EAAA,KAAAN,EAAA,QACAM,EAAA,KAAAL,EAAA,QACAK,EAAA,KAAAJ,EAAA,QAGE,GAAM,CAAE,YAAAK,CAAY,EAAIT,EAAOC,CAAW,EAE1CS,EAAA,KAAKN,EAAWG,GAChBG,EAAA,KAAKR,EAAeO,GACpBC,EAAA,KAAKP,EAAsBG,GAI3BK,EAAA,KAAKT,GACLS,EAAA,KAAKR,GACLQ,EAAA,KAAKP,EACP,CAGA,aAAc,CACZ,OAAO,QAAQ,QAAQ,CAAC,CAA4B,CACtD,CAGA,YAAa,CACX,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAGA,aAAc,CACZ,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAEA,aAAc,CACZ,IAAMQ,EAASlB,EAAcE,CAAY,EACzC,OAAOgB,EAAO,QAAUA,EAAO,KAAO,MACxC,CAGA,eAAgB,CACd,OAAO,QAAQ,QAAQ,CAAC,CAAgB,CAC1C,CAGA,uBAAwB,CACtB,OAAO,QAAQ,QAAQ,CACrB,aAAc,CAAC,CACjB,CAAC,CACH,CAGA,WAAY,CACV,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAGA,MAAM,aAAaC,EAAqB,CACtC,MAAO,CAAE,MAAOlB,EAAU,mBAAmB,UAAUkB,EAAQ,MAAM,gBAAgB,CAAE,CACzF,CACF,EA3DEX,EAAA,YACAC,EAAA,YACAC,EAAA","sourcesContent":["import {\n parseManifest,\n type AppInfo,\n type ApprovalController,\n type ConstructorParams,\n type Module,\n type NetworkFees,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport { type Rpc, type SolanaRpcApiDevnet } from '@solana/rpc';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n\n constructor({ approvalController, environment, appInfo }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n }\n\n // TODO\n getProvider() {\n return Promise.resolve({} as Rpc<SolanaRpcApiDevnet>);\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n // TODO\n getBalances() {\n return Promise.resolve({});\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n // TODO\n getNetworkFee() {\n return Promise.resolve({} as NetworkFees);\n }\n\n // TODO\n getTransactionHistory() {\n return Promise.resolve({\n transactions: [],\n });\n }\n\n // TODO\n getTokens() {\n return Promise.resolve([]);\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest) {\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"getGenesisHash\"],\n \"nonRestrictedMethods\": [\"getGenesisHash\"]\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n"]}
1
+ {"version":3,"sources":["../src/module.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts","../../../packages-internal/utils/src/utils/retry.ts","../../../packages-internal/utils/src/utils/coingecko-retry.ts","../../../packages-internal/utils/src/utils/charsum.ts","../../../packages-internal/utils/src/utils/array-hash.ts","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/utils/fetch-and-verify.ts","../../../packages-internal/utils/src/services/pricing-service/exchange-rates.ts","../../../packages-internal/utils/src/utils/detail-item.ts","../../../packages-internal/utils/src/utils/get-core-headers.ts","../manifest.json","../src/env.ts","../src/handlers/derive-address/derive-address.ts","../../../packages-internal/utils/src/utils/address-derivation.ts","../src/handlers/build-derivation-path/build-derivation-path.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/utils/get-provider.ts","../src/constants.ts","../src/handlers/get-tokens/get-tokens.ts","../src/handlers/get-tokens/spl-token-schema.ts","../src/handlers/get-balances/get-balances.ts","../../../packages-internal/utils/src/utils/is-promise-fulfilled.ts","../src/utils/moralis-service/moralis-schemas.ts","../src/utils/moralis-service/moralis-service.ts","../src/utils/get-network-name.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/extract-transfer.ts","../src/handlers/get-transaction-history/get-wrapped-transactions.ts","../src/utils/has-property-defined.ts","../src/handlers/get-transaction-history/get-explorer-link.ts","../src/handlers/sign-and-send-transaction/sign-and-send-transaction.ts","../src/utils/functional.ts","../src/utils/instruction-parsers/sol-transfer.ts","../src/utils/instruction-parsers/spl-transfer.ts","../src/handlers/sign-and-send-transaction/schema.ts","../src/handlers/sign-transaction/sign-transaction.ts","../src/handlers/sign-transaction/schema.ts"],"names":["parseManifest","RpcMethod","rpcErrors","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","coinIds","cacheId","__privateGet","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","addressItem","label","value","dataItem","AppName","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","NetworkVMType","base58","hex","hasDerivationDetails","buildDerivationPath","accountIndex","deriveAddress","approvalController","secretId","derivationPath","publicKeyHex","getSolanaProvider","SOLANA_MAINNET_CAIP2_ID","SOLANA_DEVNET_CAIP2_ID","SOLANA_TESTNET_CAIP2_ID","RPC_URL_PROXY_API_ENDPOINT","RPC_URL_DEVNET","getProvider","isTestnet","LamportsMultiplier","DEFAULT_PRIORITY_FEE","ensureEnoughData","fees","a","b","getNetworkFee","network","feesRaw","block","sortedFees","minFeeInRecentBlocks","maxFeeInRecentBlocks","midIndex","medianFee","presetHigh","presetMedium","presetLow","TokenType","z","SPL_TOKEN_SCHEMA","SPL_TOKENS_SCHEMA","getTokens","caip2Id","token","error","TokenUnit","isFulfilled","PORTFOLIO_SCHEMA","_baseUrl","_buildUrl","buildUrl_fn","MoralisService","address","url","__privateMethod","portfolio","message","path","getNetworkName","getBalances","addresses","tokenService","moralisService","coingeckoAssetId","coingeckoPlatformId","lowercaseCurrency","solanaNetwork","portfolioResults","mints","mint","tokenPricesPromises","nativePrice","tokenPrices","promise","portfolioAcc","nativeBalanceUnit","nativeMarketData","getMarketData","nativeBalanceInCurrency","solanaBalance","tokenBalances","tokensAcc","amountRaw","symbol","decimals","name","logo","balanceUnit","marketData","balanceInCurrency","coinIdOrAddress","prices","TransactionType","simplifyTokenBalance","balance","extractTokenTranfers","meta","preBalances","acc","owner","amount","transfers","key","preAmount","netChange","sender","k","possibleSender","mintFromPreBalance","possibleSenderPostBalance","postBalanceOwner","postBalanceMint","t","transfer","nativeTransfer","extractNativeTransfer","paidFee","postBalances","nativeBalancePre","nativeBalancePost","nativeTransferAmount","balanceDiffs","isIncoming","unit","otherAddressIndex","diff","solAddress","hasPropertyDefined","thing","getWrappedTransactions","provider","signatures","sig","tx","getExplorerLink","txHash","baseUrl","explorerLink","getTransactionHistory","isSigner","deserializeTransactionMessage","isBalanceChangeEmpty","input","isNotNullish","identifySystemInstruction","parseTransferSolInstruction","SYSTEM_PROGRAM_ADDRESS","SystemInstruction","isInstructionForProgram","isInstructionWithAccounts","isInstructionWithData","tryToParseSolTransfer","instruction","balanceChange","account","networkToken","accounts","balanceChangeKey","parseTransferInstruction","identifyTokenInstruction","TokenInstruction","getTokenMintFromAccountInfo","tokenAccountDetails","info","tryToParseSPLTransfer","tokens","tokenMint","transactionSchema","paramsSchema","parseRequestParams","signAndSendTransaction","request","success","serializedTx","sendOptions","transaction","details","results","displayData","signingData","getTxHash","signTransaction","_approvalController","_appInfo","SvmModule","appInfo"],"mappings":"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","sourcesContent":["import {\n parseManifest,\n RpcMethod,\n type AppInfo,\n type ApprovalController,\n type BuildDerivationPathParams,\n type ConstructorParams,\n type DeriveAddressParams,\n type GetBalancesParams,\n type GetTransactionHistory,\n type Module,\n type Network,\n type NetworkFeeParam,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { TokenService } from '@internal/utils';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\nimport { deriveAddress } from './handlers/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTokens } from './handlers/get-tokens';\nimport { getBalances } from './handlers/get-balances';\nimport { getProvider } from './utils/get-provider';\nimport { getTransactionHistory } from './handlers/get-transaction-history';\nimport { signAndSendTransaction } from './handlers/sign-and-send-transaction';\nimport { signTransaction } from './handlers/sign-transaction';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n\n constructor({ approvalController, environment, appInfo }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n }\n\n async getProvider(network: Network): Promise<SolanaProvider> {\n return getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n buildDerivationPath(params: BuildDerivationPathParams) {\n return buildDerivationPath(params);\n }\n\n deriveAddress(params: DeriveAddressParams) {\n return deriveAddress({\n ...params,\n approvalController: this.#approvalController,\n });\n }\n\n getBalances(params: GetBalancesParams) {\n const tokenService = new TokenService({ storage: params.storage, proxyApiUrl: this.#proxyApiUrl });\n\n return getBalances({\n ...params,\n tokenService,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: NetworkFeeParam) {\n return getNetworkFee(network, this.#proxyApiUrl);\n }\n\n getTransactionHistory(params: GetTransactionHistory) {\n return getTransactionHistory({\n network: params.network,\n address: params.address,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getTokens(network: Network) {\n if (!network.caipId) {\n return Promise.reject({ error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`) });\n }\n\n return getTokens({ caip2Id: network.caipId, proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.SOLANA_SIGN_TRANSACTION: {\n return signTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n });\n }\n case RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION: {\n return signAndSendTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n });\n }\n }\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/core-coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { CoingeckoProxyClient } from './coingecko-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n } catch {\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n } catch (err) {\n console.error(err);\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses({\n id: assetPlatformId,\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n });\n return this.transformSimplePriceResponse(rawData, [currency]);\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n shouldThrow = true,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePrice({\n ids: coinIds,\n vs_currencies: currencies,\n include_market_cap: marketCap,\n include_24hr_vol: vol24,\n include_24hr_change: change24,\n include_last_updated_at: lastUpdated,\n });\n return this.transformSimplePriceResponse(rawData, currencies);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n","const DEFAULT_MAX_RETRIES = 10;\n\ntype RetryParams<T> = {\n operation: (retryIndex: number) => Promise<T>;\n isSuccess: (result: T) => boolean;\n maxRetries?: number;\n backoffPolicy?: RetryBackoffPolicyInterface;\n};\n/*\n * Retries an operation with defined backoff policy.\n *\n * @param operation - The operation to retry.\n * @param isSuccess - The predicate to check if the operation succeeded.\n * @param maxRetries - The maximum number of retries.\n * @param backoffPolicy - Function to generate delay time based on current retry count.\n *\n * @returns The result of the operation.\n * @throws An error if the operation fails after the maximum number of retries.\n *\n * @example\n * const result = await retry(\n * async () => {\n * const response = await fetch('https://example.com')\n * return response.json()\n * },\n * result => result.status === 200\n * )\n */\nexport const retry = async <T>({\n operation,\n isSuccess,\n maxRetries = DEFAULT_MAX_RETRIES,\n backoffPolicy = RetryBackoffPolicy.exponential(),\n}: RetryParams<T>): Promise<T> => {\n let backoffPeriodMillis = 0;\n let retries = 0;\n let lastError: unknown;\n\n while (retries < maxRetries) {\n if (retries > 0) {\n await delay(backoffPeriodMillis);\n }\n\n try {\n const result = await operation(retries);\n\n if (isSuccess(result)) {\n return result;\n }\n } catch (err) {\n // when the operation throws an error, we still retry\n lastError = err;\n }\n\n backoffPeriodMillis = backoffPolicy(retries);\n retries++;\n }\n\n const errorMessage = lastError ? `Max retry exceeded. ${lastError}` : 'Max retry exceeded.';\n\n throw new Error(errorMessage);\n};\n\ntype RetryBackoffPolicyInterface = (retryIndex: number) => number;\n\nexport class RetryBackoffPolicy {\n static exponential(): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n return Math.pow(2, retryIndex) * 1000;\n };\n }\n\n static constant(secondsToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return secondsToDelay * 1000;\n };\n }\n\n static constantMs(msToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return msToDelay;\n };\n }\n}\n\nfunction delay(ms: number) {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { RetryBackoffPolicy, retry } from './retry';\n\ntype Error = {\n status: {\n error_code: number;\n error_message: string;\n };\n};\n\nexport const coingeckoRetry = <T>(\n operation: (useCoingeckoProxy: boolean) => Promise<T | Error>,\n): Promise<T | undefined> => {\n return retry({\n operation: (retryIndex: number) => operation(retryIndex > 0),\n maxRetries: 2,\n backoffPolicy: RetryBackoffPolicy.constant(1),\n isSuccess: (response: T | Error) => {\n const errorStatus = (response as Error)?.status;\n return errorStatus?.error_code !== 429;\n },\n }) as Promise<T | undefined>;\n};\n","export function charsum(s: string): number {\n let i,\n sum = 0;\n for (i = 0; i < s.length; i++) {\n sum += s.charCodeAt(i) * (i + 1);\n }\n return sum;\n}\n","import { charsum } from './charsum';\n\n// from https://stackoverflow.com/a/25105589\nexport function arrayHash(array: string[]): string {\n let i,\n sum = 0;\n for (i = 0; i < array.length; i++) {\n const cs = charsum(array[i] ?? '');\n sum = sum + 65027 / cs;\n }\n return ('' + sum).slice(0, 16);\n}\n","import { RawSimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nexport class CoingeckoProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n simplePrice(params: {\n ids: string[];\n vs_currencies: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n include_last_updated_at?: boolean;\n }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/price?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n\n simplePriceByContractAddresses(params: {\n id: string;\n contract_addresses: string[];\n vs_currencies?: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n }) {\n const { id, ...rawQueryParams } = params;\n\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(rawQueryParams as any);\n\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${id}?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n}\n","import z from 'zod';\nimport type { ZodSchema } from 'zod';\n\nexport async function fetchAndVerify<T extends ZodSchema>(\n fetchOptions: Parameters<typeof fetch>,\n schema: T,\n): Promise<z.infer<T>> {\n const response = await fetch(...fetchOptions);\n\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n\n const responseJson = await response.json();\n return schema.parse(responseJson);\n}\n","import z, { number, object, record, string } from 'zod';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nconst CURRENCY_EXCHANGE_RATES_URL =\n 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.min.json';\n\nconst CURRENCY_EXCHANGE_RATES_FALLBACK_URL = 'https://latest.currency-api.pages.dev/v1/currencies/usd.min.json';\n\nconst ExchangeRateSchema = object({\n date: string(),\n usd: record(number()),\n});\n\ntype ExchangeRate = z.infer<typeof ExchangeRateSchema>;\n\nexport const getExchangeRates = async (): Promise<ExchangeRate> => {\n try {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_URL], ExchangeRateSchema);\n } catch {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_FALLBACK_URL], ExchangeRateSchema);\n }\n};\n","import {\n type AddressItem,\n type CurrencyItem,\n type NodeIDItem,\n type TextItem,\n type DataItem,\n type DateItem,\n type LinkItemValue,\n DetailItemType,\n type LinkItem,\n type FundsRecipientItem,\n} from '@avalabs/vm-module-types';\n\nexport const fundsRecipientItem = (\n address: string,\n amount: bigint,\n maxDecimals: number,\n symbol: string,\n): FundsRecipientItem => ({\n type: DetailItemType.FUNDS_RECIPIENT,\n label: address,\n amount,\n maxDecimals,\n symbol,\n});\n\nexport const currencyItem = (label: string, value: bigint, maxDecimals: number, symbol: string): CurrencyItem => ({\n label,\n type: DetailItemType.CURRENCY,\n value,\n maxDecimals,\n symbol,\n});\n\nexport const textItem = (\n label: string,\n value: string,\n alignment: 'horizontal' | 'vertical' = 'horizontal',\n): TextItem => ({\n label,\n alignment,\n type: DetailItemType.TEXT,\n value,\n});\n\nexport const linkItem = (label: string, value: LinkItemValue): LinkItem => ({\n label,\n value,\n type: DetailItemType.LINK,\n});\n\nexport const addressItem = (label: string, value: string): AddressItem => ({\n label,\n type: DetailItemType.ADDRESS,\n value,\n});\n\nexport const nodeIDItem = (label: string, value: string): NodeIDItem => ({\n label,\n type: DetailItemType.NODE_ID,\n value,\n});\n\nexport const dataItem = (label: string, value: string): DataItem => ({\n label,\n type: DetailItemType.DATA,\n value,\n});\n\nexport const dateItem = (label: string, value: string): DateItem => ({\n label,\n type: DetailItemType.DATE,\n value,\n});\n","import { AppName, type AppInfo } from '@avalabs/vm-module-types';\n\nexport const getCoreHeaders = ({ name, version }: AppInfo): Record<string, string> | undefined => {\n switch (name) {\n case AppName.CORE_MOBILE_IOS:\n case AppName.CORE_MOBILE_ANDROID:\n case AppName.CORE_WEB:\n case AppName.CORE_EXTENSION:\n case AppName.EXPLORER:\n return {\n 'x-application-name': name,\n 'x-application-version': version,\n };\n case AppName.OTHER:\n return undefined;\n }\n};\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"solana_signTransaction\", \"solana_signAndSendTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\nimport { base58, hex } from '@scure/base';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\nimport { buildDerivationPath } from '../build-derivation-path/build-derivation-path';\n\nexport const deriveAddress = async (\n params: DeriveAddressParams & { approvalController: ApprovalController },\n): Promise<DeriveAddressResponse> => {\n const { approvalController, secretId } = params;\n\n // When dealing with single-account private keys, we don't need the derivation path any more.\n const derivationPath = hasDerivationDetails(params) ? buildDerivationPath(params).SVM : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'ed25519',\n secretId,\n derivationPath,\n });\n\n return {\n [NetworkVMType.SVM]: base58.encode(hex.decode(publicKeyHex)),\n };\n};\n","import type { DeriveAddressParams, DetailedDeriveAddressParams } from '@avalabs/vm-module-types';\n\nexport const hasDerivationDetails = (params: DeriveAddressParams): params is DetailedDeriveAddressParams =>\n 'derivationPathType' in params &&\n 'accountIndex' in params &&\n typeof params.accountIndex === 'number' &&\n typeof params.derivationPathType === 'string';\n","import {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\n/**\n * We're deriving the BTC address from the same public key as the Ethereum address,\n * so we can determine the target address when using the Avalanche Bridge.\n */\nexport const buildDerivationPath = ({\n accountIndex,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.SVM> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n return {\n [NetworkVMType.SVM]: `m/44'/501'/${accountIndex}'/0'`,\n };\n};\n","import { type NetworkFeeParam, type NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { SOL_DECIMALS } from '@src/constants';\n\nconst LamportsMultiplier = 1e6;\nexport const DEFAULT_PRIORITY_FEE = {\n high: 150 * LamportsMultiplier,\n medium: 75 * LamportsMultiplier,\n low: 2 * LamportsMultiplier,\n} as const;\n\ntype ValidRecentFees = [number, number, ...number[]];\n\nconst ensureEnoughData = (fees: number[]): ValidRecentFees => {\n const normalizedFees =\n fees.length === 0\n ? [DEFAULT_PRIORITY_FEE.low, DEFAULT_PRIORITY_FEE.low]\n : fees.length === 1\n ? [fees[0]!, DEFAULT_PRIORITY_FEE.low]\n : fees;\n\n return normalizedFees.slice().sort((a, b) => a - b) as ValidRecentFees;\n};\n\n/**\n * The RPC call (getRecentPrioritizationFees) returns the *lowest* priority fees (per compute unit)\n * that resulted in at least one transaction being succesfully included in the block.\n *\n * This means the request usually returns all zeroes - I've only once seen a different value,\n * for a single block out of 150 returned, and it was a 1000 MicroLamports.\n *\n * However, Phantom (the most popular Solana wallet) seems to always add at least a little bit\n * of priority fee.\n *\n * The lowest I've seen in my testing was 0.19 Lamport per compute unit, but this was an outlier.\n * I'm usually paying below 10 Lamports/cu, and sometimes as high as 150 or 300/cu -- all while\n * the RPC call returns zeroes, so it's not super reliable for determining the actual fees being paid :)\n *\n * The implementation here is by no means perfect. The way it I expect it to work is the following:\n * - with low/regular network traffic, users will be suggested to pay the default fees hardcoded below\n * (if we decide to show them at all -- Phantom does not show a widget at all)\n * - only when network congestion is super high, the RPC call will return non-zero values, and only then\n * we will suggest paying higher priority fees.\n */\nexport async function getNetworkFee(network: NetworkFeeParam, proxyApiUrl: string): Promise<NetworkFees> {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n const getFees = await provider.getRecentPrioritizationFees();\n const feesRaw = await getFees.send();\n\n const useDefaultFees = feesRaw.length === 0 || feesRaw.every((block) => block.prioritizationFee === 0n);\n\n if (useDefaultFees) {\n return {\n high: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n },\n medium: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n },\n low: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n },\n baseFee: BigInt(DEFAULT_PRIORITY_FEE.low),\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n }\n\n const sortedFees = ensureEnoughData(feesRaw.map((block) => Number(block.prioritizationFee)));\n // We know the array is not empty and sorted, so we can safely access the first and last elements\n const minFeeInRecentBlocks = sortedFees.at(0)!;\n const maxFeeInRecentBlocks = sortedFees.at(-1)!;\n const midIndex = Math.floor(sortedFees.length / 2);\n const medianFee =\n sortedFees.length % 2 === 1\n ? (sortedFees[midIndex] as number)\n : (sortedFees[midIndex - 1]! + sortedFees[midIndex]!) / 2; // Even length: return average of middle elements\n\n // Prevent the fees from going below the default values\n // If the RPC call returned non-zero values, the network congestion is likely to be very high, so we add 5%.\n // We also prevent returning fees lower than the default, hardcoded values, as the RPC call is not very reliable.\n const presetHigh = BigInt(Math.ceil(maxFeeInRecentBlocks * 1.05));\n const presetMedium = BigInt(Math.ceil(medianFee * 1.05));\n const presetLow = BigInt(Math.ceil(minFeeInRecentBlocks * 1.05));\n\n // TODO: The shape of response here needs a general refactoring, it's not very generic.\n return {\n high: {\n maxFeePerGas: presetHigh,\n maxPriorityFeePerGas: presetHigh,\n },\n medium: {\n maxFeePerGas: presetMedium,\n maxPriorityFeePerGas: presetMedium,\n },\n low: {\n maxFeePerGas: presetLow,\n maxPriorityFeePerGas: presetLow,\n },\n baseFee: presetLow,\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n}\n","import { getSolanaProvider, type SolanaProvider } from '@avalabs/core-wallets-sdk';\n\nimport { RPC_URL_DEVNET, RPC_URL_PROXY_API_ENDPOINT } from '../constants';\n\nexport const getProvider = ({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): SolanaProvider => {\n return getSolanaProvider({\n isTestnet,\n rpcUrl: isTestnet ? RPC_URL_DEVNET : proxyApiUrl + RPC_URL_PROXY_API_ENDPOINT,\n });\n};\n","export const SOL_DECIMALS = 9;\nexport const SOLANA_COIN_ID = 501;\n\nexport const SOLANA_MAINNET_CAIP2_ID = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET_CAIP2_ID = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET_CAIP2_ID = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\nexport const RPC_URL_PROXY_API_ENDPOINT = '/proxy/nownodes/sol';\nexport const RPC_URL_DEVNET = 'https://api.devnet.solana.com';\nexport const RPC_URL_TESTNET = 'https://api.testnet.solana.com';\n","import type { SPLToken } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { SPL_TOKENS_SCHEMA } from './spl-token-schema';\n\nexport async function getTokens({\n caip2Id,\n proxyApiUrl,\n}: {\n caip2Id: string;\n proxyApiUrl: string;\n}): Promise<SPLToken[]> {\n try {\n const tokens = await fetchAndVerify([`${proxyApiUrl}/solana-tokens?caip2Id=${caip2Id}`], SPL_TOKENS_SCHEMA);\n\n return tokens.map((token) => ({ ...token, type: token.contractType }));\n } catch (error) {\n console.error('getTokens() failed for', caip2Id, error);\n throw rpcErrors.internal(`Failed to fetch tokens for caip2Id \"${caip2Id}\"`);\n }\n}\n","import { TokenType } from '@avalabs/vm-module-types';\nimport { z } from 'zod';\n\nexport const SPL_TOKEN_SCHEMA = z.object({\n address: z.string(),\n name: z.string(),\n symbol: z.string(),\n contractType: z.literal(TokenType.SPL),\n caip2Id: z.string().startsWith('solana:'),\n decimals: z.number(),\n chainId: z.number().optional(),\n logoUri: z.string().optional(),\n color: z.string().optional(),\n});\n\nexport const SPL_TOKENS_SCHEMA = z.array(SPL_TOKEN_SCHEMA);\n","import {\n type GetBalancesParams,\n type TokenWithBalanceSVM,\n type TokenWithBalanceSPL,\n TokenType,\n type SimplePriceResponse,\n type Error,\n} from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport type { TokenService } from '@internal/utils';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { SOL_DECIMALS } from '@src/constants';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype GetSolanaBalancesResponse = Record<\n string,\n Record<string, TokenWithBalanceSVM | TokenWithBalanceSPL | Error> | Error\n>;\n\nexport const getBalances = async ({\n addresses,\n proxyApiUrl,\n currency,\n network,\n tokenService,\n}: GetBalancesParams & {\n proxyApiUrl: string;\n tokenService: TokenService;\n}): Promise<GetSolanaBalancesResponse> => {\n const moralisService = new MoralisService({ proxyApiUrl });\n const coingeckoAssetId = network.pricingProviders?.coingecko.nativeTokenId ?? '';\n const coingeckoPlatformId = network.pricingProviders?.coingecko.assetPlatformId ?? '';\n const lowercaseCurrency = currency.toLowerCase();\n const solanaNetwork = getNetworkName(network);\n\n const portfolioResults = await Promise.all(\n addresses.map((address) => moralisService.getPortfolio({ address, network: solanaNetwork })),\n );\n\n const mints = new Set(\n portfolioResults.flatMap((result) => {\n if ('portfolio' in result) {\n return result.portfolio.tokens.map(({ mint }) => mint);\n }\n\n return [];\n }),\n );\n\n const tokenPricesPromises = await Promise.allSettled([\n coingeckoAssetId\n ? await tokenService.getSimplePrice({\n coinIds: [coingeckoAssetId],\n currencies: [lowercaseCurrency as VsCurrencyType],\n })\n : Promise.resolve(undefined),\n coingeckoPlatformId\n ? await tokenService.getPricesByAddresses(\n Array.from(mints),\n coingeckoPlatformId,\n lowercaseCurrency as VsCurrencyType,\n )\n : Promise.resolve(undefined),\n ]);\n const [nativePrice, tokenPrices] = tokenPricesPromises.map((promise) =>\n isFulfilled(promise) ? promise.value : undefined,\n );\n\n return portfolioResults.reduce((portfolioAcc, result) => {\n if ('error' in result) {\n return {\n ...portfolioAcc,\n [result.address]: {\n error: result.error,\n },\n };\n }\n\n const nativeBalanceUnit = new TokenUnit(result.portfolio.nativeBalance.lamports, SOL_DECIMALS, 'SOL');\n const nativeMarketData = getMarketData(coingeckoAssetId, lowercaseCurrency, nativePrice);\n const nativeBalanceInCurrency =\n nativeMarketData.priceInCurrency !== undefined\n ? nativeBalanceUnit.mul(nativeMarketData.priceInCurrency)\n : undefined;\n\n const solanaBalance: TokenWithBalanceSVM = {\n type: TokenType.NATIVE,\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n decimals: network.networkToken.decimals,\n balance: nativeBalanceUnit.toSubUnit(),\n balanceDisplayValue: nativeBalanceUnit.toString(),\n balanceInCurrency: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: network.networkToken.logoUri ?? '',\n coingeckoId: coingeckoAssetId,\n ...nativeMarketData,\n };\n\n const tokenBalances = result.portfolio.tokens.reduce(\n (tokensAcc, { amountRaw, symbol, decimals, mint, name, logo }) => {\n const balanceUnit = new TokenUnit(amountRaw, decimals, symbol);\n const marketData = getMarketData(mint, lowercaseCurrency, tokenPrices);\n const balanceInCurrency =\n marketData.priceInCurrency !== undefined ? balanceUnit.mul(marketData.priceInCurrency) : undefined;\n\n const token: TokenWithBalanceSPL = {\n type: TokenType.SPL,\n address: mint,\n name,\n symbol,\n decimals,\n balance: balanceUnit.toSubUnit(),\n balanceDisplayValue: balanceUnit.toString(),\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: logo ?? undefined,\n reputation: null,\n ...marketData,\n };\n\n return {\n ...tokensAcc,\n [mint]: token,\n };\n },\n {} as Record<string, TokenWithBalanceSPL>,\n );\n\n return {\n ...portfolioAcc,\n [result.address]: {\n [network.networkToken.symbol]: solanaBalance,\n ...tokenBalances,\n },\n };\n }, {} as GetSolanaBalancesResponse);\n};\n\nconst getMarketData = (coinIdOrAddress: string, currency: string, prices?: SimplePriceResponse) => ({\n priceInCurrency: prices?.[coinIdOrAddress ?? '']?.[currency]?.price ?? undefined,\n marketCap: prices?.[coinIdOrAddress ?? '']?.[currency]?.marketCap ?? undefined,\n vol24: prices?.[coinIdOrAddress ?? '']?.[currency]?.vol24 ?? undefined,\n change24: prices?.[coinIdOrAddress ?? '']?.[currency]?.change24 ?? undefined,\n});\n","export const isFulfilled = <T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> =>\n result.status === 'fulfilled';\n","import { z } from 'zod';\n\nexport const PORTFOLIO_SCHEMA = z.object({\n nativeBalance: z.object({\n lamports: z.string(),\n solana: z.string(),\n }),\n nfts: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n name: z.string(),\n symbol: z.string(),\n }),\n ),\n tokens: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n amountRaw: z.string(),\n amount: z.string(),\n decimals: z.number(),\n name: z.string(),\n symbol: z.string(),\n logo: z.string().optional().nullable(),\n }),\n ),\n});\n\nexport type PortfolioResponse = z.infer<typeof PORTFOLIO_SCHEMA>;\n","import { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\n\nimport type { SolanaNetworkName } from '@src/types';\n\nimport { PORTFOLIO_SCHEMA, type PortfolioResponse } from './moralis-schemas';\n\nexport class MoralisService {\n #baseUrl: string;\n\n constructor({ proxyApiUrl }: { proxyApiUrl: string }) {\n this.#baseUrl = `${proxyApiUrl}/proxy/moralis`;\n }\n\n async getPortfolio({\n address,\n network,\n }: {\n network: SolanaNetworkName;\n address: string;\n }): Promise<{ address: string; portfolio: PortfolioResponse } | { address: string; error: string }> {\n try {\n const url = this.#buildUrl(`/account/${network}/${address}/portfolio`);\n const portfolio = await fetchAndVerify([url], PORTFOLIO_SCHEMA);\n\n return {\n address,\n portfolio,\n };\n } catch (error) {\n console.error('getPortfolio() failed:', error);\n\n const message = error instanceof Error ? error.message : 'unknown error';\n\n return {\n address,\n error: `getPortfolio() failed: ${message}`,\n };\n }\n }\n\n #buildUrl(path: string) {\n return `${this.#baseUrl}${path}`;\n }\n}\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { SOLANA_DEVNET_CAIP2_ID, SOLANA_MAINNET_CAIP2_ID, SOLANA_TESTNET_CAIP2_ID } from '../constants';\n\nexport const getNetworkName = (network: Network) => {\n switch (network.caipId) {\n case SOLANA_MAINNET_CAIP2_ID:\n return 'mainnet';\n\n case SOLANA_DEVNET_CAIP2_ID:\n return 'devnet';\n\n case SOLANA_TESTNET_CAIP2_ID:\n return 'testnet';\n\n default:\n throw new Error('Unrecognized CAIP-2 id: ' + network.caipId);\n }\n};\n","import { TransactionType, type Network, type TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { extractTokenTranfers, simplifyTokenBalance } from './extract-transfer';\nimport { getWrappedTransactions } from './get-wrapped-transactions';\nimport { getExplorerLink } from './get-explorer-link';\n\ntype SvmGetTransactionHistory = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport async function getTransactionHistory({\n network,\n address,\n proxyApiUrl,\n}: SvmGetTransactionHistory): Promise<TransactionHistoryResponse> {\n if (!network.caipId) {\n return Promise.reject({\n error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`),\n });\n }\n\n const rawTransactions = await getWrappedTransactions({ isTestnet: Boolean(network.isTestnet), address, proxyApiUrl });\n const transactions = rawTransactions\n .map(({ txHash, tx }) => {\n if (!tx.meta) {\n return null;\n }\n\n const {\n meta,\n transaction: { message },\n } = tx;\n // Typings are wrong here, .toString() fixes it without unnecessary casting\n const addresses = message.accountKeys.map((acc) => acc.toString());\n const accountIndex = addresses.indexOf(address);\n\n // accountKeys property is sorted in Solana transactions. The signing keys\n // are always the first, and the header.numRequiredSignatures tells us how many\n // of the first keys are signers. If the lookup address is a signer, it has to be\n // one of the first N keys.\n const isSigner = accountIndex < message.header.numRequiredSignatures;\n\n const transfers = extractTokenTranfers(\n addresses,\n accountIndex,\n {\n paidFee: isSigner ? Number(meta.fee) : 0,\n preBalances: meta.preBalances.map(Number),\n postBalances: meta.postBalances.map(Number),\n preTokenBalances: (meta.preTokenBalances ?? []).map(simplifyTokenBalance),\n postTokenBalances: (meta.postTokenBalances ?? []).map(simplifyTokenBalance),\n },\n network,\n );\n\n return {\n hash: txHash,\n // We should probably be smarter about the tx type, but this should be enough for MVP\n txType: isSigner ? TransactionType.SEND : TransactionType.RECEIVE,\n gasUsed: String(tx.meta.computeUnitsConsumed ?? '0'),\n tokens: transfers,\n\n // Get to/from addresses from the token transfers if possible.\n // If not possible:\n // - default \"from\" to the signing address\n // - default \"to\" to our address if we're not the signer and leave empty if we don't know.\n from: transfers[0]?.from?.address ?? (addresses[0] as string),\n to: transfers[0]?.to?.address ?? (isSigner ? '' : address),\n isOutgoing: isSigner,\n isIncoming: !isSigner,\n isSender: isSigner,\n timestamp: Number(tx.blockTime),\n isContractCall: false,\n gasPrice: String(Number(tx.meta.fee) / Number(tx.meta.computeUnitsConsumed)),\n chainId: String(network.chainId),\n explorerLink: getExplorerLink(txHash, network.explorerUrl),\n };\n })\n .filter(<T>(tx: T): tx is NonNullable<T> => tx !== null);\n\n return {\n transactions,\n };\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport { TokenType, type Network, type SPLToken, type TxToken } from '@avalabs/vm-module-types';\nimport type { TokenBalance } from '@solana/kit';\n\nexport const simplifyTokenBalance = (balance: TokenBalance): SimpleTokenBalance => ({\n mint: balance.mint as string,\n owner: balance.owner as string,\n amount: BigInt(balance.uiTokenAmount.amount),\n decimals: balance.uiTokenAmount.decimals,\n});\n\nexport const extractTokenTranfers: ExtractTransferFn<'SPL'> = (addresses, accountIndex, meta, network): TxToken[] => {\n // Create a map of initial balances\n const preBalances: Record<string, bigint> = meta.preTokenBalances.reduce(\n (acc, { owner, mint, amount }) => ({\n ...acc,\n [`${owner}-${mint}`]: amount,\n }),\n {},\n );\n\n // Compare with post balances to determine transfers\n const transfers = meta.postTokenBalances.reduce((acc, { owner, mint, amount, decimals }) => {\n const key = `${owner}-${mint}`;\n const preAmount = preBalances[key] ?? 0n;\n const netChange = amount - preAmount;\n\n if (netChange <= 0n) {\n return acc;\n }\n\n // Find sender (the one whose balance decreased)\n const sender = Object.keys(preBalances).find((k) => {\n const [possibleSender, mintFromPreBalance] = k.split('-');\n const possibleSenderPostBalance = meta.postTokenBalances.find(\n ({ owner: postBalanceOwner, mint: postBalanceMint }) =>\n postBalanceOwner === possibleSender && postBalanceMint === mint,\n );\n\n return (\n mintFromPreBalance === mint && possibleSenderPostBalance && preBalances[k]! > possibleSenderPostBalance.amount\n );\n });\n\n if (!sender) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: sender.split('-')[0]!,\n },\n to: {\n ...token,\n address: owner,\n },\n amount: new TokenUnit(netChange, decimals, '').toDisplay(),\n };\n\n return [...acc, transfer];\n }, [] as TxToken[]);\n\n const nativeTransfer = extractNativeTransfer(addresses, accountIndex, meta, network);\n\n if (nativeTransfer) {\n transfers.push(nativeTransfer);\n }\n\n return transfers;\n};\n\nconst extractNativeTransfer: ExtractTransferFn<'native'> = (\n addresses,\n accountIndex,\n { paidFee, preBalances, postBalances },\n network,\n) => {\n const address = addresses[accountIndex]!;\n const nativeBalancePre = preBalances[accountIndex]!;\n const nativeBalancePost = postBalances[accountIndex]!;\n const nativeTransferAmount =\n nativeBalancePost !== nativeBalancePre ? nativeBalancePost - nativeBalancePre + paidFee : 0;\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n\n if (!nativeTransferAmount) {\n return null;\n }\n\n const isIncoming = nativeTransferAmount > 0;\n const unit = new TokenUnit(Math.abs(nativeTransferAmount), network.networkToken.decimals, '');\n // If it's an incoming transaction, we assume it came from the transaction signer.\n // It it's an outgoing transaction, we need to find the address that received this exact amount (minus the fee).\n const otherAddressIndex = isIncoming\n ? 0\n : Math.max(\n 0,\n balanceDiffs.findIndex((diff) => diff === -nativeTransferAmount),\n );\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: isIncoming ? addresses[otherAddressIndex]! : address,\n },\n to: {\n address: isIncoming ? address : addresses[otherAddressIndex]!,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n};\n\ntype SimpleTokenBalance = {\n mint: string;\n owner: string;\n amount: bigint;\n decimals: number;\n};\n\ntype TxMeta = {\n paidFee: number;\n // Native SOL balances\n preBalances: number[];\n postBalances: number[];\n // SPL tokens balances\n preTokenBalances: SimpleTokenBalance[];\n postTokenBalances: SimpleTokenBalance[];\n};\n\ntype ExtractTransferFn<Type extends 'native' | 'SPL'> = (\n addresses: string[],\n accountIndex: number,\n meta: TxMeta,\n network: Network,\n) => Type extends 'native' ? TxToken | null : TxToken[];\n","import { address as solAddress, type GetTransactionApi } from '@solana/kit';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { hasPropertyDefined } from '@src/utils/has-property-defined';\n\ntype ParsedTx = ReturnType<GetTransactionApi['getTransaction']>;\ntype WrappedTransaction = { txHash: string; tx: NonNullable<ParsedTx> };\n\nexport const getWrappedTransactions = async ({\n isTestnet,\n address,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n address: string;\n proxyApiUrl: string;\n}): Promise<WrappedTransaction[]> => {\n const provider = getProvider({ isTestnet, proxyApiUrl });\n\n const signaturesResponse = await provider.getSignaturesForAddress(solAddress(address), { limit: 25 }).send(); // Same as we do for Bitcoin\n const signatures = signaturesResponse.map((sig) => sig.signature);\n const txsRequests = await Promise.allSettled(\n signatures.map(async (sig) => ({\n txHash: sig.toString(),\n tx: await provider.getTransaction(sig, { encoding: 'json', maxSupportedTransactionVersion: 0 }).send(),\n })),\n );\n\n return txsRequests\n .filter(isFulfilled)\n .map((tx) => tx.value)\n .filter(hasPropertyDefined('tx'));\n};\n","export function hasPropertyDefined<T, K extends keyof T>(key: K) {\n return (thing: T): thing is T & Record<K, NonNullable<unknown>> => Boolean(thing[key]);\n}\n","export const getExplorerLink = (txHash: string, baseUrl?: string) => {\n const explorerLink = baseUrl ? new URL(baseUrl) : null;\n\n // Keep the query params in-tact: the Solana explorers like SolScan.io or explorer.solana.com\n // switch between clusters based on the `cluster` query param, not the domain.\n if (explorerLink) {\n explorerLink.pathname = `/tx/${txHash}`;\n }\n\n return explorerLink?.toString() ?? '';\n};\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type BalanceChange,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SigningResult,\n type SPLToken,\n} from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\nimport { type Base64EncodedWireTransaction } from '@solana/kit';\n\nimport { dataItem } from '@internal/utils/src/utils/detail-item';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty, isNotNullish } from '@src/utils/functional';\nimport { tryToParseSolTransfer } from '@src/utils/instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from '@src/utils/instruction-parsers/spl-transfer';\nimport { parseRequestParams, type SendOptions } from './schema';\n\nexport const signAndSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx, sendOptions }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n // TODO: simulate transaction with Blockaid. Parsing like below can be used as a fallback.\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n const displayData: DisplayData = {\n title: 'Approve Transaction',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details: [\n {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', serializedTx)],\n },\n ...details,\n ],\n balanceChange: isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n let txHash;\n\n try {\n txHash = await getTxHash(provider, response, sendOptions);\n } catch (error) {\n console.error(error);\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n return {\n result: txHash,\n };\n};\n\nconst getTxHash = async (\n provider: ReturnType<typeof getProvider>,\n response: SigningResult,\n sendOptions?: SendOptions,\n) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n // broadcast the signed transaction\n const txHash = await provider\n .sendTransaction(response.signedData as Base64EncodedWireTransaction, {\n ...sendOptions,\n encoding: 'base64',\n })\n .send();\n return txHash;\n};\n","import type { BalanceChange } from '@avalabs/vm-module-types';\n\nexport function isBalanceChangeEmpty(input: BalanceChange): boolean {\n return input.ins.length === 0 && input.outs.length === 0;\n}\n\nexport function isNotNullish<I>(input: I): input is NonNullable<I> {\n return input !== null && input !== undefined;\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { BalanceChange, NetworkToken } from '@avalabs/vm-module-types';\nimport {\n identifySystemInstruction,\n parseTransferSolInstruction,\n SYSTEM_PROGRAM_ADDRESS,\n SystemInstruction,\n} from '@solana-program/system';\nimport {\n isInstructionForProgram,\n isInstructionWithAccounts,\n isInstructionWithData,\n type IInstruction,\n} from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nexport const tryToParseSolTransfer = (\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n networkToken: NetworkToken,\n) => {\n if (\n !isInstructionForProgram(instruction, SYSTEM_PROGRAM_ADDRESS) ||\n !isInstructionWithAccounts(instruction) ||\n !isInstructionWithData(instruction)\n ) {\n return;\n }\n\n try {\n const systemInstruction = identifySystemInstruction(instruction);\n\n if (systemInstruction !== SystemInstruction.TransferSol) {\n return null;\n }\n\n const { accounts, data } = parseTransferSolInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferSolInstruction()\n });\n\n const isOutgoing = accounts.source.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token: {\n ...networkToken,\n address: '',\n },\n items: [\n {\n displayValue: new TokenUnit(data.amount, networkToken.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: 'Native Transfer',\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport type { BalanceChange, SPLToken } from '@avalabs/vm-module-types';\nimport { parseTransferInstruction, identifyTokenInstruction, TokenInstruction } from '@solana-program/token';\nimport { isInstructionWithAccounts, isInstructionWithData, type Address, type IInstruction } from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nconst getTokenMintFromAccountInfo = async (provider: SolanaProvider, account: Address): Promise<string | null> => {\n try {\n const tokenAccountDetails = await provider.getAccountInfo(account, { encoding: 'jsonParsed' }).send();\n\n if (Array.isArray(tokenAccountDetails.value?.data)) {\n return null;\n }\n\n const info = tokenAccountDetails.value?.data.parsed.info as Record<string, unknown>;\n return typeof info?.mint === 'string' ? info.mint : null;\n } catch {\n return null;\n }\n};\n\nexport const tryToParseSPLTransfer = async (\n provider: SolanaProvider,\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n tokens?: SPLToken[],\n) => {\n if (!tokens?.length || !isInstructionWithAccounts(instruction) || !isInstructionWithData(instruction)) {\n return;\n }\n\n try {\n const tokenInstruction = identifyTokenInstruction(instruction);\n\n if (tokenInstruction !== TokenInstruction.Transfer) {\n return null;\n }\n\n const { accounts, data } = parseTransferInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferInstruction()\n });\n const tokenMint = await getTokenMintFromAccountInfo(provider, accounts.source.address);\n\n if (!tokenMint) {\n return null;\n }\n\n const token = tokens.find((t) => t.address.toLowerCase() === tokenMint.toLowerCase());\n\n if (!token) {\n return null;\n }\n\n const isOutgoing = accounts.source.address === account || accounts.authority.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token,\n items: [\n {\n displayValue: new TokenUnit(data.amount, token.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: `Transfer ${token.symbol}`,\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n sendOptions: z\n .object({\n preflightCommitment: z.enum(['processed', 'confirmed', 'finalized']).optional(),\n maxRetries: z.bigint().optional(),\n minContextSlot: z.bigint().optional(),\n skipPreflight: z.boolean().optional(),\n })\n .optional(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\nexport type SendOptions = z.infer<typeof transactionSchema>['sendOptions'];\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type BalanceChange,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SPLToken,\n} from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\n\nimport { dataItem } from '@internal/utils/src/utils/detail-item';\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty, isNotNullish } from '@src/utils/functional';\nimport { tryToParseSolTransfer } from '@src/utils/instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from '@src/utils/instruction-parsers/spl-transfer';\nimport { parseRequestParams } from './schema';\n\nexport const signTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n // TODO: simulate transaction with Blockaid. Parsing like below can be used as a fallback.\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n const displayData: DisplayData = {\n title: 'Sign Transaction',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details: [\n {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', serializedTx)],\n },\n ...details,\n ],\n balanceChange: isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\n"]}
package/manifest.json CHANGED
@@ -26,8 +26,8 @@
26
26
  "permissions": {
27
27
  "rpc": {
28
28
  "dapps": true,
29
- "methods": ["getGenesisHash"],
30
- "nonRestrictedMethods": ["getGenesisHash"]
29
+ "methods": ["solana_signTransaction", "solana_signAndSendTransaction"],
30
+ "nonRestrictedMethods": []
31
31
  }
32
32
  },
33
33
  "manifestVersion": "0.1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avalabs/svm-module",
3
- "version": "1.4.6",
3
+ "version": "1.5.0",
4
4
  "main": "dist/index.cjs",
5
5
  "module": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -11,9 +11,16 @@
11
11
  ],
12
12
  "license": "Limited Ecosystem License",
13
13
  "dependencies": {
14
+ "@avalabs/core-coingecko-sdk": "3.1.0-alpha.44",
15
+ "@avalabs/core-utils-sdk": "3.1.0-alpha.44",
16
+ "@avalabs/core-wallets-sdk": "3.1.0-alpha.44",
14
17
  "@metamask/rpc-errors": "6.3.0",
15
- "@solana/rpc": "2.0.0",
16
- "@avalabs/vm-module-types": "1.4.6"
18
+ "@scure/base": "1.2.4",
19
+ "@solana/kit": "2.1.0",
20
+ "@solana-program/system": "0.7.0",
21
+ "@solana-program/token": "0.5.1",
22
+ "zod": "3.23.8",
23
+ "@avalabs/vm-module-types": "1.5.0"
17
24
  },
18
25
  "devDependencies": {
19
26
  "@types/jest": "29.5.7",
@@ -21,8 +28,8 @@
21
28
  "jest-environment-jsdom": "29.7.0",
22
29
  "ts-jest": "29.1.1",
23
30
  "tsup": "7.2.0",
24
- "@internal/tsup-config": "0.0.1",
25
- "@internal/utils": "0.4.0",
31
+ "@internal/tsup-config": "0.0.2",
32
+ "@internal/utils": "0.5.0",
26
33
  "eslint-config-custom": "0.0.1"
27
34
  },
28
35
  "volta": {