@avalabs/bitcoin-module 1.10.2 → 1.11.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
@@ -8,9 +8,9 @@ var zod = require('zod');
8
8
  var coreUtilsSdk = require('@avalabs/core-utils-sdk');
9
9
  var bitcoinjsLib = require('bitcoinjs-lib');
10
10
 
11
- var Ge=Object.defineProperty;var Le=(r,e,t)=>e in r?Ge(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var se=(r,e,t)=>(Le(r,typeof e!="symbol"?e+"":e,t),t),ae=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var m=(r,e,t)=>(ae(r,e,"read from private field"),t?t.call(r):e.get(r)),C=(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);},E=(r,e,t,o)=>(ae(r,e,"write to private field"),o?o.call(r,t):e.set(r,t),t);var Fe={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},Me={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},ce=r=>{switch(r){case vmModuleTypes.Environment.PRODUCTION:return Fe;case vmModuleTypes.Environment.DEV:return Me}};var pe={name:"Bitcoin",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/bitcoin-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["bip122:000000000019d6689c085ae165831e93","bip122:000000000933ea01ad0ee984209779ba"],namespaces:["bip122"]},cointype:"0",permissions:{rpc:{dapps:!0,methods:["bitcoin_sendTransaction","bitcoin_signTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var re=async({operation:r,isSuccess:e,maxRetries:t=10,backoffPolicy:o=_.exponential()})=>{let n=0,s=0,a;for(;s<t;){s>0&&await $e(n);try{let c=await r(s);if(e(c))return c}catch(c){a=c;}n=o(s),s++;}let i=a?`Max retry exceeded. ${a}`:"Max retry exceeded.";throw new Error(i)},_=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return t=>e*1e3}static constantMs(e){return t=>e}static linearThenExponential(e,t){return o=>{if(o<e)return (o+1)*t;let n=o-e+1,s=e*t,a=2*t*(Math.pow(2,n)-1);return s+a}}};function $e(r){return new Promise(e=>setTimeout(e,r))}var oe=r=>re({operation:e=>r(e>0),maxRetries:2,backoffPolicy:_.constant(1),isSuccess:e=>e?.status?.error_code!==429});function me(r){let e,t=0;for(e=0;e<r.length;e++)t+=r.charCodeAt(e)*(e+1);return t}function ne(r){let e,t=0;for(e=0;e<r.length;e++){let o=me(r[e]??"");t=t+65027/o;}return (""+t).slice(0,16)}async function H(r,e){let t=await fetch(...r);if(!t.ok)throw new Error(`Request failed with status ${t.status}`);let o=await t.json();return e.parse(o)}var G=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let t=new URLSearchParams(e);return H([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${t}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:t,...o}=e,n=new URLSearchParams(o);return H([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${t}?${n}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}};var de=coreCoingeckoSdk.getBasicCoingeckoHttp(),I,N,F=class{constructor({storage:e,proxyApiUrl:t}){C(this,I,void 0);C(this,N,void 0);se(this,"transformSimplePriceResponse",(e,t=[coreCoingeckoSdk.VsCurrencyType.USD])=>{let o={};return Object.keys(e).forEach(n=>{let s=e[n];o[n]={},t.forEach(a=>{o[n]={[a]:{price:s?.[a],change24:s?.[`${a}_24h_change`],vol24:s?.[`${a}_24h_vol`],marketCap:s?.[`${a}_market_cap`]}};});}),o});E(this,I,e),E(this,N,t);}async getSimplePrice({coinIds:e=[],currencies:t=[coreCoingeckoSdk.VsCurrencyType.USD]}){let o,s=`getSimplePrice-${e?`${ne(e)}-${t.toString()}`:`${t.toString()}`}`;if(o=m(this,I)?.get?.(s),o)return o;try{o=await oe(a=>this.simplePrice({coinIds:e,currencies:t,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:a}));}catch{o=void 0;}return m(this,I)?.set?.(s,o),o}async getPricesByAddresses(e,t,o=coreCoingeckoSdk.VsCurrencyType.USD){let n,a=`getPricesWithMarketDataByAddresses-${`${ne(e)}-${t}-${o}`}`;if(n=m(this,I)?.get?.(a),n)return n;try{n=await oe(i=>this.fetchPricesByAddresses({assetPlatformId:t,tokenAddresses:e,currency:o,useCoingeckoProxy:i}));}catch(i){console.error(i),n=void 0;}return m(this,I)?.set?.(a,n),n}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:t,currency:o=coreCoingeckoSdk.VsCurrencyType.USD,useCoingeckoProxy:n=!1}){if(n){let s=await new G(m(this,N)).simplePriceByContractAddresses({id:e,contract_addresses:t,vs_currencies:[o],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[o])}return coreCoingeckoSdk.simpleTokenPrice(de,{assetPlatformId:e,tokenAddresses:t,currencies:[o],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:t=[coreCoingeckoSdk.VsCurrencyType.USD],marketCap:o=!1,vol24:n=!1,change24:s=!1,lastUpdated:a=!1,useCoingeckoProxy:i=!1,shouldThrow:c=!0}){if(i){let p=await new G(m(this,N)).simplePrice({ids:e,vs_currencies:t,include_market_cap:o,include_24hr_vol:n,include_24hr_change:s,include_last_updated_at:a});return this.transformSimplePriceResponse(p,t)}return coreCoingeckoSdk.simplePrice(de,{coinIds:e,currencies:t,marketCap:o,vol24:n,change24:s,lastUpdated:a,shouldThrow:c})}};I=new WeakMap,N=new WeakMap;zod.object({date:zod.string(),usd:zod.record(zod.number())});var ue=(r,e,t,o)=>({type:vmModuleTypes.DetailItemType.FUNDS_RECIPIENT,label:r,amount:e,maxDecimals:t,symbol:o}),U=(r,e,t,o)=>({label:r,type:vmModuleTypes.DetailItemType.CURRENCY,value:e,maxDecimals:t,symbol:o});var K=(r,e)=>({label:r,value:e,type:vmModuleTypes.DetailItemType.LINK}),O=(r,e)=>({label:r,type:vmModuleTypes.DetailItemType.ADDRESS,value:e});var ye=process.env.GLACIER_API_KEY;var M=()=>ye;var f=async({isTestnet:r,proxyApiUrl:e})=>{let t=M();return new coreWalletsSdk.BitcoinProvider(!r,void 0,`${e}/proxy/nownodes/${r?"btcbook-testnet":"btcbook"}`,`${e}/proxy/nownodes/${r?"btc-testnet":"btc"}`,t?{token:t}:{})};async function fe({isTestnet:r,proxyApiUrl:e}){let t=await f({isTestnet:r,proxyApiUrl:e}),{high:o,low:n,medium:s}=await t.getFeeRates();return {low:{maxFeePerGas:BigInt(n)},medium:{maxFeePerGas:BigInt(s)},high:{maxFeePerGas:BigInt(o)},isFixedFee:!1}}var Te=(r,{address:e,network:t})=>{let{explorerUrl:o,networkToken:n}=t,s=r.addresses[0]??"";return {chainId:t.chainId.toString(),explorerLink:`${o}/tx/${r.hash}`,from:r.isSender?e:s,gasUsed:r.fee.toString(),hash:r.hash,isContractCall:!1,isIncoming:!r.isSender,isOutgoing:r.isSender,isSender:r.isSender,timestamp:r.receivedTime*1e3,to:r.isSender?s:e,tokens:[{amount:(Math.abs(r.amount)/10**n.decimals).toString(),decimal:n.decimals.toString(),name:n.name,symbol:n.symbol,type:vmModuleTypes.TokenType.NATIVE}],txType:r.isSender?vmModuleTypes.TransactionType.SEND:vmModuleTypes.TransactionType.RECEIVE}};var he=async({address:r,network:e,proxyApiUrl:t})=>(await(await f({isTestnet:!!e.isTestnet,proxyApiUrl:t})).getTxHistory(r)).map(s=>Te(s,{address:r,network:e}));var Pe=(r,e,t)=>{let o=t?.[r]?.[e??""]??{};return {priceInCurrency:o.price??void 0,marketCap:o.marketCap??void 0,vol24:o.vol24??void 0,change24:o.change24??void 0}};var j=async({addresses:r,currency:e,network:t,withScripts:o=!1,proxyApiUrl:n,storage:s})=>{let a=await f({isTestnet:!!t.isTestnet,proxyApiUrl:n}),i=new F({proxyApiUrl:n,storage:s}),c=t.pricingProviders?.coingecko.nativeTokenId,d=typeof e=="string"&&typeof c=="string"?await i.getSimplePrice({coinIds:[c],currencies:[e]}):void 0,{priceInCurrency:l,change24:h,marketCap:g,vol24:v}=Pe(c??"",e,d);return (await Promise.allSettled(r.map(async y=>{let{balance:T,utxos:S,balanceUnconfirmed:D,utxosUnconfirmed:R}=await a.getUtxoBalance(y,o),b=new coreUtilsSdk.TokenUnit(T,t.networkToken.decimals,t.networkToken.symbol),k=l!==void 0?b.mul(l):void 0,B=b.toDisplay(),A=new coreUtilsSdk.TokenUnit(D,t.networkToken.decimals,t.networkToken.symbol),V=l!==void 0?A.mul(l):void 0,He=t.networkToken.symbol;return {[y]:{[He]:{...t.networkToken,utxos:S,utxosUnconfirmed:R,coingeckoId:c??"",type:vmModuleTypes.TokenType.NATIVE,balance:b.toSubUnit(),balanceDisplayValue:B,balanceInCurrency:k?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:k?.toDisplay({fixedDp:2}),priceInCurrency:l,marketCap:g,vol24:v,change24:h,unconfirmedBalance:A.toSubUnit(),unconfirmedBalanceDisplayValue:A.toDisplay(),unconfirmedBalanceInCurrency:V?.toDisplay({fixedDp:2,asNumber:!0}),unconfirmedBalanceCurrencyDisplayValue:V?.toDisplay({fixedDp:2})}}}}))).reduce((y,T)=>T.status==="rejected"?y:{...y,...T.value},{})};var be=async({accountIndex:r,xpub:e,network:t,walletType:o})=>{let n=!!t?.isTestnet;switch(o){case vmModuleTypes.WalletType.Mnemonic:case vmModuleTypes.WalletType.Ledger:case vmModuleTypes.WalletType.Keystone:return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBech32AddressFromXPub(e,r,n?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)};case vmModuleTypes.WalletType.LedgerLive:case vmModuleTypes.WalletType.Seedless:{let s=Buffer.from(e,"hex");return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBtcAddressFromPubKey(s,n?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)}}default:throw rpcErrors.rpcErrors.invalidParams(`Unsupported wallet type: ${o}`)}};var ot=zod.z.object({from:zod.z.string(),to:zod.z.string(),amount:zod.z.number(),feeRate:zod.z.number()}),Re=r=>ot.safeParse(r);var ke=r=>{if(!r)return !1;let e="utxos"in r,t="locked"in r,o="unlockedUnstaked"in r;return e&&!o&&!t};var W=(r,e)=>Math.ceil(r/e);var Y=new Map,Be=(r,e,t,o)=>(Y.set(r,{signingData:e,displayData:t}),{updateTx:({feeRate:n})=>{let s=Y.get(r);if(!s)throw rpcErrors.rpcErrors.resourceNotFound();let{signingData:a}=s;if(typeof n>"u"||n===a.data.feeRate)return s;let{account:i,data:{to:c,amount:p,balance:d}}=a,{inputs:l,outputs:h,fee:g}=coreWalletsSdk.createTransferTx(c,i,p,n,d.utxos,o.getNetwork());if(!l||!h)throw rpcErrors.rpcErrors.internal("Unable to create transaction");let v={...a,data:{...a.data,fee:g,feeRate:n,gasLimit:W(g,n),inputs:l,outputs:h}},x={...s,signingData:v};return Y.set(r,x),x},cleanup:()=>Y.delete(r)});var Q=async({explorerUrl:r,provider:e,txHash:t,onTransactionPending:o,onTransactionConfirmed:n,onTransactionReverted:s,request:a})=>{try{o({txHash:t,request:a}),await e.waitForTx(t);let i=`${r}/tx/${t}`;n({txHash:t,explorerLink:i,request:a});}catch(i){console.error(i),s({txHash:t,request:a});}};var J=async(r,e)=>"txHash"in e?e.txHash:r.issueRawTx(e.signedData);var Ae=async({request:r,network:e,approvalController:t,proxyApiUrl:o})=>{let{dappInfo:n,params:s}=r,{success:a,data:i,error:c}=Re(s);if(!a)return console.error("invalid params",c),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:c}})};let d=(await j({addresses:[i.from],network:e,proxyApiUrl:o,withScripts:!0}))?.[i.from]?.[e.networkToken.symbol];if(!ke(d))return {error:rpcErrors.rpcErrors.internal("Balance for the source account is not available")};let l=await f({isTestnet:!!e.isTestnet,proxyApiUrl:o}),{to:h,from:g,amount:v,feeRate:x}=i,{inputs:y,outputs:T,fee:S}=coreWalletsSdk.createTransferTx(h,g,v,x,d.utxos,l.getNetwork());if(!y||!T)return {error:rpcErrors.rpcErrors.internal("Unable to create transaction")};let D={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[K("Website",n),O("From",g),O("To",h),U("Amount",BigInt(v),e.networkToken.decimals,e.networkToken.symbol)]}],networkFeeSelector:!0},R={type:vmModuleTypes.RpcMethod.BITCOIN_SEND_TRANSACTION,account:g,data:{to:h,amount:v,fee:S,feeRate:x,gasLimit:W(S,x),inputs:y,outputs:T,balance:d}},{updateTx:b,cleanup:k}=Be(r.requestId,R,D,l),B=await t.requestApproval({request:r,displayData:D,signingData:R,updateTx:b});if(k(),"error"in B)return {error:B.error};let A;try{A=await J(l,B);}catch(V){return {error:rpcErrors.rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:V}})}}return Q({explorerUrl:e.explorerUrl??"",provider:l,txHash:A,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:A}};var it=zod.z.object({txHash:zod.z.string(),txHex:zod.z.string().optional(),index:zod.z.number(),value:zod.z.number(),script:zod.z.string().min(1),blockHeight:zod.z.number(),confirmations:zod.z.number(),confirmedTime:zod.z.string().optional()}),ct=zod.z.object({address:zod.z.string(),value:zod.z.number()}),pt=zod.z.object({inputs:zod.z.array(it).min(1),outputs:zod.z.array(ct).min(1)}),we=r=>pt.safeParse(r);var Se=async({request:r,network:e,approvalController:t,proxyApiUrl:o})=>{let{dappInfo:n,params:s}=r,{success:a,data:i,error:c}=we(s);if(!a)return console.error("invalid params",c),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:c}})};let p=await f({isTestnet:!!e.isTestnet,proxyApiUrl:o}),{details:d,error:l}=await dt(i,p);if(l)return {error:rpcErrors.rpcErrors.internal({message:"Transaction invalid or cannot be parsed",data:{cause:l}})};let{fee:h,fromAddress:g,outputs:v,transferTotal:x}=d,{decimals:y,symbol:T}=e.networkToken,S={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[K("Website",n),O("From",g),U("Total Transferred Amount",BigInt(x),y,T)]},{title:"Recipients",items:v.map(({address:k,value:B})=>ue(k,BigInt(B),y,T))},{title:"Network Fee",items:[U("Total Fee",BigInt(h),y,T)]}],networkFeeSelector:!1},D={type:vmModuleTypes.RpcMethod.BITCOIN_SIGN_TRANSACTION,account:g,data:{inputs:i.inputs,outputs:i.outputs}},R=await t.requestApproval({request:r,displayData:S,signingData:D});if("error"in R)return {error:R.error};let b;try{b=await J(p,R);}catch(k){return {error:rpcErrors.rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:k}})}}return Q({explorerUrl:e.explorerUrl??"",provider:p,txHash:b,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:b}},lt=r=>{let e=Array.from(new Set(r.map(({script:t})=>t)));if(e.length!==1)throw rpcErrors.rpcErrors.invalidParams({message:`All input UTXOs must belong to a single address, found ${e.length}`});return e[0]},dt=async(r,e)=>{try{let t=lt(r.inputs),o=await e.getAddressFromScript(t),n=r.outputs.filter(({address:p})=>p!==o),s=r.inputs.reduce((p,{value:d})=>p+d,0),a=r.outputs.reduce((p,{value:d})=>p+d,0),i=n.reduce((p,{value:d})=>p+d,0),c=s-a;return ut(n),{error:null,details:{fromAddress:o,outputs:n,fee:c,transferTotal:i}}}catch(t){return console.error(t),{details:null,error:t instanceof Error?t:new Error(t?.toString()??"Unknown error")}}};function ut(r){if(r.length<1)throw new Error("No actual output is provided, this transaction would only burn funds")}var De=r=>"derivationPathType"in r&&"accountIndex"in r&&typeof r.accountIndex=="number"&&typeof r.derivationPathType=="string";var te=({accountIndex:r,derivationPathType:e})=>{if(r<0)throw rpcErrors.rpcErrors.invalidParams("Account index must be a non-negative integer");switch(e){case"bip44":return {[vmModuleTypes.NetworkVMType.BITCOIN]:`m/44'/60'/0'/0/${r}`};case"ledger_live":return {[vmModuleTypes.NetworkVMType.BITCOIN]:`m/44'/60'/${r}'/0/0`};default:throw rpcErrors.rpcErrors.invalidParams(`Unsupported derivation path type: ${e}`)}};var Ne=async r=>{let{approvalController:e,network:t,secretId:o}=r,n=De(r)?te(r).BITCOIN:void 0,s=await e.requestPublicKey({curve:"secp256k1",secretId:o,derivationPath:n}),a=Buffer.from(s,"hex");return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBtcAddressFromPubKey(a,t.isTestnet?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)}};var P,w,Oe=class{constructor({environment:e,approvalController:t}){C(this,P,void 0);C(this,w,void 0);let{proxyApiUrl:o}=ce(e);E(this,w,t),E(this,P,o);}getProvider(e){return f({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,P)})}getAddress({accountIndex:e,xpub:t,walletType:o,network:n}){return be({accountIndex:e,xpub:t,network:n,walletType:o})}buildDerivationPath(e){return te(e)}deriveAddress(e){return Ne({...e,approvalController:m(this,w)})}getBalances({addresses:e,currency:t,network:o,storage:n}){return j({addresses:e,currency:t,network:o,proxyApiUrl:m(this,P),storage:n})}getManifest(){let e=vmModuleTypes.parseManifest(pe);return e.success?e.data:void 0}getNetworkFee(e){return fe({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,P)})}async getTransactionHistory({address:e,network:t}){return {transactions:await he({address:e,network:t,proxyApiUrl:m(this,P)})}}getTokens(e){return Promise.resolve([])}async onRpcRequest(e,t){switch(e.method){case vmModuleTypes.RpcMethod.BITCOIN_SEND_TRANSACTION:return Ae({request:e,network:t,approvalController:m(this,w),proxyApiUrl:m(this,P)});case vmModuleTypes.RpcMethod.BITCOIN_SIGN_TRANSACTION:return Se({request:e,network:t,approvalController:m(this,w),proxyApiUrl:m(this,P)});default:return {error:rpcErrors.rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}}};P=new WeakMap,w=new WeakMap;
11
+ var Ge=Object.defineProperty;var Le=(r,e,t)=>e in r?Ge(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var ae=(r,e,t)=>(Le(r,typeof e!="symbol"?e+"":e,t),t),ie=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var m=(r,e,t)=>(ie(r,e,"read from private field"),t?t.call(r):e.get(r)),_=(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);},E=(r,e,t,n)=>(ie(r,e,"write to private field"),n?n.call(r,t):e.set(r,t),t);var Fe={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},qe={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},pe=r=>{switch(r){case vmModuleTypes.Environment.PRODUCTION:return Fe;case vmModuleTypes.Environment.DEV:return qe}};var me={name:"Bitcoin",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/bitcoin-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["bip122:000000000019d6689c085ae165831e93","bip122:000000000933ea01ad0ee984209779ba"],namespaces:["bip122"]},cointype:"0",permissions:{rpc:{dapps:!0,methods:["bitcoin_sendTransaction","bitcoin_signTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var ne=async({operation:r,isSuccess:e,maxRetries:t=10,backoffPolicy:n=N.exponential()})=>{let o=0,s=0,a;for(;s<t;){s>0&&await Me(o);try{let p=await r(s);if(e(p))return p}catch(p){a=p;}o=n(s),s++;}let i=a?`Max retry exceeded. ${a}`:"Max retry exceeded.";throw new Error(i)},N=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return t=>e*1e3}static constantMs(e){return t=>e}static linearThenExponential(e,t){return n=>{if(n<e)return (n+1)*t;let o=n-e+1,s=e*t,a=2*t*(Math.pow(2,o)-1);return s+a}}};function Me(r){return new Promise(e=>setTimeout(e,r))}var oe=r=>ne({operation:e=>r(e>0),maxRetries:2,backoffPolicy:N.constant(1),isSuccess:e=>e?.status?.error_code!==429});function le(r){let e,t=0;for(e=0;e<r.length;e++)t+=r.charCodeAt(e)*(e+1);return t}function se(r){let e,t=0;for(e=0;e<r.length;e++){let n=le(r[e]??"");t=t+65027/n;}return (""+t).slice(0,16)}async function B(r,e){let t=await fetch(...r);if(!t.ok)throw new Error(`Request failed with status ${t.status}`);let n=await t.json();return e.parse(n)}var L=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let t=new URLSearchParams(e);return B([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${t}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:t,...n}=e,o=new URLSearchParams(n);return B([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${t}?${o}`,{method:"POST",headers:{"Content-Type":"application/json"}}],vmModuleTypes.RawSimplePriceResponseSchema)}};var Ve=zod.z.array(zod.z.object({internalId:zod.z.string(),id:zod.z.string(),symbol:zod.z.string(),name:zod.z.string(),image:zod.z.string().optional().nullable(),current_price:zod.z.number().optional().nullable(),price_change_percentage_24h:zod.z.number().optional().nullable(),market_cap:zod.z.number().optional().nullable(),total_volume:zod.z.number().optional().nullable(),platforms:zod.z.record(zod.z.string(),zod.z.string())})),V=class{constructor(e){this.proxyApiUrl=e;}watchlistToken(e){let t=new URLSearchParams(e);return B([`${this.proxyApiUrl}/watchlist/tokens?${t}`,{method:"GET",headers:{"Content-Type":"application/json"}}],Ve)}};var de=coreCoingeckoSdk.getBasicCoingeckoHttp(),k,S,F=class{constructor({storage:e,proxyApiUrl:t}){_(this,k,void 0);_(this,S,void 0);ae(this,"transformSimplePriceResponse",(e,t=[coreCoingeckoSdk.VsCurrencyType.USD])=>{let n={};return Object.keys(e).forEach(o=>{let s=e[o];n[o]={},t.forEach(a=>{n[o]={[a]:{price:s?.[a],change24:s?.[`${a}_24h_change`],vol24:s?.[`${a}_24h_vol`],marketCap:s?.[`${a}_market_cap`]}};});}),n});E(this,k,e),E(this,S,t);}async getWatchlistDataForToken({tokenDetails:e,currency:t=coreCoingeckoSdk.VsCurrencyType.USD}){let o=(await new V(m(this,S)).watchlistToken({tokens:e.symbol,currency:t})).filter(s=>e.isNative?s.internalId===`NATIVE-${e.symbol.toLowerCase()}`:s.platforms[e.caip2Id]===e.address)[0];return o?{priceInCurrency:o.current_price??0,change24:o.price_change_percentage_24h??0,marketCap:o.market_cap??0,vol24:o.total_volume??0}:{priceInCurrency:0,change24:0,marketCap:0,vol24:0}}async getSimplePrice({coinIds:e=[],currencies:t=[coreCoingeckoSdk.VsCurrencyType.USD]}){let n,s=`getSimplePrice-${e?`${se(e)}-${t.toString()}`:`${t.toString()}`}`;if(n=m(this,k)?.get?.(s),n)return n;try{n=await oe(a=>this.simplePrice({coinIds:e,currencies:t,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:a}));}catch{n=void 0;}return m(this,k)?.set?.(s,n),n}async getPricesByAddresses(e,t,n=coreCoingeckoSdk.VsCurrencyType.USD){let o,a=`getPricesWithMarketDataByAddresses-${`${se(e)}-${t}-${n}`}`;if(o=m(this,k)?.get?.(a),o)return o;try{o=await oe(i=>this.fetchPricesByAddresses({assetPlatformId:t,tokenAddresses:e,currency:n,useCoingeckoProxy:i}));}catch(i){console.error(i),o=void 0;}return m(this,k)?.set?.(a,o),o}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:t,currency:n=coreCoingeckoSdk.VsCurrencyType.USD,useCoingeckoProxy:o=!1}){if(o){let s=await new L(m(this,S)).simplePriceByContractAddresses({id:e,contract_addresses:t,vs_currencies:[n],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[n])}return coreCoingeckoSdk.simpleTokenPrice(de,{assetPlatformId:e,tokenAddresses:t,currencies:[n],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:t=[coreCoingeckoSdk.VsCurrencyType.USD],marketCap:n=!1,vol24:o=!1,change24:s=!1,lastUpdated:a=!1,useCoingeckoProxy:i=!1,shouldThrow:p=!0}){if(i){let l=await new L(m(this,S)).simplePrice({ids:e,vs_currencies:t,include_market_cap:n,include_24hr_vol:o,include_24hr_change:s,include_last_updated_at:a});return this.transformSimplePriceResponse(l,t)}return coreCoingeckoSdk.simplePrice(de,{coinIds:e,currencies:t,marketCap:n,vol24:o,change24:s,lastUpdated:a,shouldThrow:p})}};k=new WeakMap,S=new WeakMap;zod.object({date:zod.string(),usd:zod.record(zod.number())});var ye=(r,e,t,n)=>({type:vmModuleTypes.DetailItemType.FUNDS_RECIPIENT,label:r,amount:e,maxDecimals:t,symbol:n}),O=(r,e,t,n)=>({label:r,type:vmModuleTypes.DetailItemType.CURRENCY,value:e,maxDecimals:t,symbol:n});var j=(r,e)=>({label:r,value:e,type:vmModuleTypes.DetailItemType.LINK}),H=(r,e)=>({label:r,type:vmModuleTypes.DetailItemType.ADDRESS,value:e});var fe=process.env.GLACIER_API_KEY;var q=()=>fe;var g=async({isTestnet:r,proxyApiUrl:e})=>{let t=q();return new coreWalletsSdk.BitcoinProvider(!r,void 0,`${e}/proxy/nownodes/${r?"btcbook-testnet":"btcbook"}`,`${e}/proxy/nownodes/${r?"btc-testnet":"btc"}`,t?{token:t}:{})};async function ge({isTestnet:r,proxyApiUrl:e}){let t=await g({isTestnet:r,proxyApiUrl:e}),{high:n,low:o,medium:s}=await t.getFeeRates();return {low:{maxFeePerGas:BigInt(o)},medium:{maxFeePerGas:BigInt(s)},high:{maxFeePerGas:BigInt(n)},isFixedFee:!1}}var Te=(r,{address:e,network:t})=>{let{explorerUrl:n,networkToken:o}=t,s=r.addresses[0]??"";return {chainId:t.chainId.toString(),explorerLink:`${n}/tx/${r.hash}`,from:r.isSender?e:s,gasUsed:r.fee.toString(),hash:r.hash,isContractCall:!1,isIncoming:!r.isSender,isOutgoing:r.isSender,isSender:r.isSender,timestamp:r.receivedTime*1e3,to:r.isSender?s:e,tokens:[{amount:(Math.abs(r.amount)/10**o.decimals).toString(),decimal:o.decimals.toString(),name:o.name,symbol:o.symbol,type:vmModuleTypes.TokenType.NATIVE}],txType:r.isSender?vmModuleTypes.TransactionType.SEND:vmModuleTypes.TransactionType.RECEIVE}};var Pe=async({address:r,network:e,proxyApiUrl:t})=>(await(await g({isTestnet:!!e.isTestnet,proxyApiUrl:t})).getTxHistory(r)).map(s=>Te(s,{address:r,network:e}));var K=async({addresses:r,currency:e,network:t,withScripts:n=!1,proxyApiUrl:o,storage:s})=>{let a=await g({isTestnet:!!t.isTestnet,proxyApiUrl:o}),i=new F({proxyApiUrl:o,storage:s}),p=t.pricingProviders?.coingecko.nativeTokenId,c=typeof e=="string"&&typeof p=="string"?await i.getWatchlistDataForToken({tokenDetails:{symbol:t.networkToken.symbol,isNative:!0,caip2Id:t.caipId??""},currency:e}):void 0;return (await Promise.allSettled(r.map(async d=>{let{balance:y,utxos:b,balanceUnconfirmed:T,utxosUnconfirmed:I}=await a.getUtxoBalance(d,n),P=new coreUtilsSdk.TokenUnit(y,t.networkToken.decimals,t.networkToken.symbol),w=c?.priceInCurrency!==void 0?P.mul(c.priceInCurrency):void 0,C=P.toDisplay(),v=new coreUtilsSdk.TokenUnit(T,t.networkToken.decimals,t.networkToken.symbol),R=c?.priceInCurrency!==void 0?v.mul(c.priceInCurrency):void 0,A=t.networkToken.symbol;return {[d]:{[A]:{...t.networkToken,utxos:b,utxosUnconfirmed:I,coingeckoId:p??"",type:vmModuleTypes.TokenType.NATIVE,balance:P.toSubUnit(),balanceDisplayValue:C,balanceInCurrency:w?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:w?.toDisplay({fixedDp:2}),priceInCurrency:c?.priceInCurrency,marketCap:c?.marketCap,vol24:c?.vol24,change24:c?.change24,unconfirmedBalance:v.toSubUnit(),unconfirmedBalanceDisplayValue:v.toDisplay(),unconfirmedBalanceInCurrency:R?.toDisplay({fixedDp:2,asNumber:!0}),unconfirmedBalanceCurrencyDisplayValue:R?.toDisplay({fixedDp:2})}}}}))).reduce((d,y)=>y.status==="rejected"?d:{...d,...y.value},{})};var be=async({accountIndex:r,xpub:e,network:t,walletType:n})=>{let o=!!t?.isTestnet;switch(n){case vmModuleTypes.WalletType.Mnemonic:case vmModuleTypes.WalletType.Ledger:case vmModuleTypes.WalletType.Keystone:return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBech32AddressFromXPub(e,r,o?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)};case vmModuleTypes.WalletType.LedgerLive:case vmModuleTypes.WalletType.Seedless:{let s=Buffer.from(e,"hex");return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBtcAddressFromPubKey(s,o?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)}}default:throw rpcErrors.rpcErrors.invalidParams(`Unsupported wallet type: ${n}`)}};var ot=zod.z.object({from:zod.z.string(),to:zod.z.string(),amount:zod.z.number(),feeRate:zod.z.number()}),Ie=r=>ot.safeParse(r);var Re=r=>{if(!r)return !1;let e="utxos"in r,t="locked"in r,n="unlockedUnstaked"in r;return e&&!n&&!t};var z=(r,e)=>Math.ceil(r/e);var Y=new Map,we=(r,e,t,n)=>(Y.set(r,{signingData:e,displayData:t}),{updateTx:({feeRate:o})=>{let s=Y.get(r);if(!s)throw rpcErrors.rpcErrors.resourceNotFound();let{signingData:a}=s;if(typeof o>"u"||o===a.data.feeRate)return s;let{account:i,data:{to:p,amount:l,balance:c}}=a,{inputs:h,outputs:d,fee:y}=coreWalletsSdk.createTransferTx(p,i,l,o,c.utxos,n.getNetwork());if(!h||!d)throw rpcErrors.rpcErrors.internal("Unable to create transaction");let b={...a,data:{...a.data,fee:y,feeRate:o,gasLimit:z(y,o),inputs:h,outputs:d}},T={...s,signingData:b};return Y.set(r,T),T},cleanup:()=>Y.delete(r)});var Q=async({explorerUrl:r,provider:e,txHash:t,onTransactionPending:n,onTransactionConfirmed:o,onTransactionReverted:s,request:a})=>{try{n({txHash:t,request:a}),await e.waitForTx(t);let i=`${r}/tx/${t}`;o({txHash:t,explorerLink:i,request:a});}catch(i){console.error(i),s({txHash:t,request:a});}};var J=async(r,e)=>"txHash"in e?e.txHash:r.issueRawTx(e.signedData);var Ae=async({request:r,network:e,approvalController:t,proxyApiUrl:n})=>{let{dappInfo:o,params:s}=r,{success:a,data:i,error:p}=Ie(s);if(!a)return console.error("invalid params",p),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:p}})};let c=(await K({addresses:[i.from],network:e,proxyApiUrl:n,withScripts:!0}))?.[i.from]?.[e.networkToken.symbol];if(!Re(c))return {error:rpcErrors.rpcErrors.internal("Balance for the source account is not available")};let h=await g({isTestnet:!!e.isTestnet,proxyApiUrl:n}),{to:d,from:y,amount:b,feeRate:T}=i,{inputs:I,outputs:P,fee:w}=coreWalletsSdk.createTransferTx(d,y,b,T,c.utxos,h.getNetwork());if(!I||!P)return {error:rpcErrors.rpcErrors.internal("Unable to create transaction")};let C={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[j("Website",o),H("From",y),H("To",d),O("Amount",BigInt(b),e.networkToken.decimals,e.networkToken.symbol)]}],networkFeeSelector:!0},v={type:vmModuleTypes.RpcMethod.BITCOIN_SEND_TRANSACTION,account:y,data:{to:d,amount:b,fee:w,feeRate:T,gasLimit:z(w,T),inputs:I,outputs:P,balance:c}},{updateTx:R,cleanup:A}=we(r.requestId,v,C,h),G=await t.requestApproval({request:r,displayData:C,signingData:v,updateTx:R});if(A(),"error"in G)return {error:G.error};let re;try{re=await J(h,G);}catch(He){return {error:rpcErrors.rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:He}})}}return Q({explorerUrl:e.explorerUrl??"",provider:h,txHash:re,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:re}};var ct=zod.z.object({txHash:zod.z.string(),txHex:zod.z.string().optional(),index:zod.z.number(),value:zod.z.number(),script:zod.z.string().min(1),blockHeight:zod.z.number(),confirmations:zod.z.number(),confirmedTime:zod.z.string().optional()}),pt=zod.z.object({address:zod.z.string(),value:zod.z.number()}),mt=zod.z.object({inputs:zod.z.array(ct).min(1),outputs:zod.z.array(pt).min(1)}),Be=r=>mt.safeParse(r);var Se=async({request:r,network:e,approvalController:t,proxyApiUrl:n})=>{let{dappInfo:o,params:s}=r,{success:a,data:i,error:p}=Be(s);if(!a)return console.error("invalid params",p),{error:rpcErrors.rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:p}})};let l=await g({isTestnet:!!e.isTestnet,proxyApiUrl:n}),{details:c,error:h}=await dt(i,l);if(h)return {error:rpcErrors.rpcErrors.internal({message:"Transaction invalid or cannot be parsed",data:{cause:h}})};let{fee:d,fromAddress:y,outputs:b,transferTotal:T}=c,{decimals:I,symbol:P}=e.networkToken,w={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[j("Website",o),H("From",y),O("Total Transferred Amount",BigInt(T),I,P)]},{title:"Recipients",items:b.map(({address:A,value:G})=>ye(A,BigInt(G),I,P))},{title:"Network Fee",items:[O("Total Fee",BigInt(d),I,P)]}],networkFeeSelector:!1},C={type:vmModuleTypes.RpcMethod.BITCOIN_SIGN_TRANSACTION,account:y,data:{inputs:i.inputs,outputs:i.outputs}},v=await t.requestApproval({request:r,displayData:w,signingData:C});if("error"in v)return {error:v.error};let R;try{R=await J(l,v);}catch(A){return {error:rpcErrors.rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:A}})}}return Q({explorerUrl:e.explorerUrl??"",provider:l,txHash:R,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:R}},ut=r=>{let e=Array.from(new Set(r.map(({script:t})=>t)));if(e.length!==1)throw rpcErrors.rpcErrors.invalidParams({message:`All input UTXOs must belong to a single address, found ${e.length}`});return e[0]},dt=async(r,e)=>{try{let t=ut(r.inputs),n=await e.getAddressFromScript(t),o=r.outputs.filter(({address:l})=>l!==n),s=r.inputs.reduce((l,{value:c})=>l+c,0),a=r.outputs.reduce((l,{value:c})=>l+c,0),i=o.reduce((l,{value:c})=>l+c,0),p=s-a;return yt(o),{error:null,details:{fromAddress:n,outputs:o,fee:p,transferTotal:i}}}catch(t){return console.error(t),{details:null,error:t instanceof Error?t:new Error(t?.toString()??"Unknown error")}}};function yt(r){if(r.length<1)throw new Error("No actual output is provided, this transaction would only burn funds")}var De=r=>"derivationPathType"in r&&"accountIndex"in r&&typeof r.accountIndex=="number"&&typeof r.derivationPathType=="string";var te=({accountIndex:r,derivationPathType:e})=>{if(r<0)throw rpcErrors.rpcErrors.invalidParams("Account index must be a non-negative integer");switch(e){case"bip44":return {[vmModuleTypes.NetworkVMType.BITCOIN]:`m/44'/60'/0'/0/${r}`};case"ledger_live":return {[vmModuleTypes.NetworkVMType.BITCOIN]:`m/44'/60'/${r}'/0/0`};default:throw rpcErrors.rpcErrors.invalidParams(`Unsupported derivation path type: ${e}`)}};var Ne=async r=>{let{approvalController:e,network:t,secretId:n}=r,o=De(r)?te(r).BITCOIN:void 0,s=await e.requestPublicKey({curve:"secp256k1",secretId:n,derivationPath:o}),a=Buffer.from(s,"hex");return {[vmModuleTypes.NetworkVMType.BITCOIN]:coreWalletsSdk.getBtcAddressFromPubKey(a,t.isTestnet?bitcoinjsLib.networks.testnet:bitcoinjsLib.networks.bitcoin)}};var x,D,Oe=class{constructor({environment:e,approvalController:t}){_(this,x,void 0);_(this,D,void 0);let{proxyApiUrl:n}=pe(e);E(this,D,t),E(this,x,n);}getProvider(e){return g({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}getAddress({accountIndex:e,xpub:t,walletType:n,network:o}){return be({accountIndex:e,xpub:t,network:o,walletType:n})}buildDerivationPath(e){return te(e)}deriveAddress(e){return Ne({...e,approvalController:m(this,D)})}getBalances({addresses:e,currency:t,network:n,storage:o}){return K({addresses:e,currency:t,network:n,proxyApiUrl:m(this,x),storage:o})}getManifest(){let e=vmModuleTypes.parseManifest(me);return e.success?e.data:void 0}getNetworkFee(e){return ge({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}async getTransactionHistory({address:e,network:t}){return {transactions:await Pe({address:e,network:t,proxyApiUrl:m(this,x)})}}getTokens(e){return Promise.resolve([])}async onRpcRequest(e,t){switch(e.method){case vmModuleTypes.RpcMethod.BITCOIN_SEND_TRANSACTION:return Ae({request:e,network:t,approvalController:m(this,D),proxyApiUrl:m(this,x)});case vmModuleTypes.RpcMethod.BITCOIN_SIGN_TRANSACTION:return Se({request:e,network:t,approvalController:m(this,D),proxyApiUrl:m(this,x)});default:return {error:rpcErrors.rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}}};x=new WeakMap,D=new WeakMap;
12
12
 
13
13
  exports.BitcoinModule = Oe;
14
- exports.calculateGasLimit = W;
14
+ exports.calculateGasLimit = z;
15
15
  //# sourceMappingURL=out.js.map
16
16
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module.ts","../src/env.ts","../manifest.json","../src/utils/get-provider.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","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/handlers/get-transaction-history/convert-btc-transaction.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-balances/get-balances.ts","../src/utils/extract-token-market-data.ts","../src/handlers/get-address/get-address.ts","../src/handlers/bitcoin-send-transaction/bitcoin-send-transaction.ts","../src/handlers/bitcoin-send-transaction/schema.ts","../src/utils/is-btc-balance.ts","../src/utils/calculate-gas-limit.ts","../src/utils/bitcoin-tx-updater.ts","../src/utils/wait-for-tx-receipt.ts","../src/utils/get-tx-hash.ts","../src/handlers/bitcoin-sign-transaction/bitcoin-sign-transaction.ts","../src/handlers/bitcoin-sign-transaction/schema.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"],"names":["RpcMethod","parseManifest","rpcErrors","Environment","prodEnv","devEnv","getEnv","environment","manifest_default","BitcoinProvider","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","base","incSum","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","fundsRecipientItem","address","amount","maxDecimals","symbol","currencyItem","label","value","linkItem","addressItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","getProvider","isTestnet","glacierApiKey","getNetworkFee","provider","high","low","medium","TokenType","TransactionType","convertBtcTransaction","tx","network","explorerUrl","networkToken","txAddress","getTransactionHistory","TokenUnit","extractTokenMarketData","coinId","coinData","getBalances","addresses","withScripts","tokenService","coingeckoTokenId","marketData","priceInCurrency","balanceInSatoshis","utxos","unconfirmedBalanceInSatoshis","utxosUnconfirmed","balance","balanceInCurrency","balanceDisplayValue","unconfirmedBalance","unconfirmedBalanceInCurrency","acc","accountBalance","getBech32AddressFromXPub","getBtcAddressFromPubKey","networks","NetworkVMType","WalletType","getAddress","accountIndex","xpub","walletType","pubKeyBuffer","z","paramsSchema","parseRequestParams","isBtcBalance","hasUtxos","hasLocked","hasUnlockedUnstaked","createTransferTx","calculateGasLimit","fee","feeRate","requests","getTxUpdater","requestId","signingData","displayData","request","account","to","inputs","outputs","newData","updatedRequest","waitForTransactionReceipt","txHash","onTransactionPending","onTransactionConfirmed","onTransactionReverted","explorerLink","getTxHash","bitcoinSendTransaction","approvalController","dappInfo","rawParams","success","parseError","btcBalance","from","updateTx","cleanup","error","inputUtxo","outputUtxo","bitcoinSignTransaction","details","detailsError","parseTxDetails","fromAddress","transferTotal","decimals","getScript","scripts","script","inputsTotal","outputsTotal","assertNonEmpty","hasDerivationDetails","buildDerivationPath","derivationPathType","deriveAddress","secretId","derivationPath","publicKeyHex","publicKey","_approvalController","BitcoinModule"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetAddressParams,\n GetAddressResponse,\n ApprovalController,\n ConstructorParams,\n DeriveAddressParams,\n BuildDerivationPathParams,\n} from '@avalabs/vm-module-types';\nimport { RpcMethod, parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getEnv } from './env';\n\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getBalances } from './handlers/get-balances/get-balances';\nimport { getAddress } from './handlers/get-address/get-address';\nimport { bitcoinSendTransaction } from './handlers/bitcoin-send-transaction/bitcoin-send-transaction';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getProvider } from './utils/get-provider';\nimport { bitcoinSignTransaction } from './handlers/bitcoin-sign-transaction/bitcoin-sign-transaction';\nimport { deriveAddress } from './handlers/derive-address/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path/build-derivation-path';\n\nexport class BitcoinModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n\n constructor({ environment, approvalController }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#approvalController = approvalController;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n getProvider(network: Network): Promise<BitcoinProvider> {\n return getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getAddress({ accountIndex, xpub, walletType, network }: GetAddressParams): Promise<GetAddressResponse> {\n return getAddress({ accountIndex, xpub, network, walletType });\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({ addresses, currency, network, storage }: GetBalancesParams) {\n return getBalances({\n addresses,\n currency,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n storage,\n });\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: Network): Promise<NetworkFees> {\n return getNetworkFee({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n async getTransactionHistory({ address, network }: GetTransactionHistory) {\n return {\n transactions: await getTransactionHistory({\n address,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n }),\n };\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.BITCOIN_SEND_TRANSACTION:\n return bitcoinSendTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n case RpcMethod.BITCOIN_SIGN_TRANSACTION:\n return bitcoinSignTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\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","{\n \"name\": \"Bitcoin\",\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/bitcoin-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\"bip122:000000000019d6689c085ae165831e93\", \"bip122:000000000933ea01ad0ee984209779ba\"],\n \"namespaces\": [\"bip122\"]\n },\n \"cointype\": \"0\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"bitcoin_sendTransaction\", \"bitcoin_signTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getGlacierApiKey } from '@internal/utils';\n\ntype ProviderParams = {\n isTestnet: boolean;\n proxyApiUrl: string;\n};\n\nexport const getProvider = async ({ isTestnet, proxyApiUrl }: ProviderParams): Promise<BitcoinProvider> => {\n const glacierApiKey = getGlacierApiKey();\n\n return new BitcoinProvider(\n !isTestnet,\n undefined,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btcbook-testnet' : 'btcbook'}`,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btc-testnet' : 'btc'}`,\n glacierApiKey ? { token: glacierApiKey } : {},\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 /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\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 type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\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 addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\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\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\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","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\n/**\n * Returns {@link NetworkFees} based on `estimatesmartfee` RPC call\n */\nexport async function getNetworkFee({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): Promise<NetworkFees> {\n const provider = await getProvider({\n isTestnet,\n proxyApiUrl,\n });\n\n const { high, low, medium } = await provider.getFeeRates();\n\n return {\n low: {\n maxFeePerGas: BigInt(low),\n },\n medium: {\n maxFeePerGas: BigInt(medium),\n },\n high: {\n maxFeePerGas: BigInt(high),\n },\n isFixedFee: false,\n };\n}\n","import { TokenType, TransactionType, type Network, type Transaction } from '@avalabs/vm-module-types';\nimport type { BitcoinHistoryTx } from '@avalabs/core-wallets-sdk';\n\ntype ConverterOptions = {\n address: string;\n network: Network;\n};\n\nexport const convertBtcTransaction = (tx: BitcoinHistoryTx, { address, network }: ConverterOptions): Transaction => {\n const { explorerUrl, networkToken } = network;\n const txAddress = tx.addresses[0] ?? '';\n\n return {\n chainId: network.chainId.toString(),\n explorerLink: `${explorerUrl}/tx/${tx.hash}`,\n from: tx.isSender ? address : txAddress,\n gasUsed: tx.fee.toString(),\n hash: tx.hash,\n isContractCall: false,\n isIncoming: !tx.isSender,\n isOutgoing: tx.isSender,\n isSender: tx.isSender,\n timestamp: tx.receivedTime * 1000,\n to: tx.isSender ? txAddress : address,\n tokens: [\n {\n amount: (Math.abs(tx.amount) / 10 ** networkToken.decimals).toString(),\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n },\n ],\n txType: tx.isSender ? TransactionType.SEND : TransactionType.RECEIVE,\n };\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\nimport { convertBtcTransaction } from './convert-btc-transaction';\n\ntype GetBtcTransactionHistoryOptions = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport const getTransactionHistory = async ({ address, network, proxyApiUrl }: GetBtcTransactionHistoryOptions) => {\n const provider = await getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n const rawHistory = await provider.getTxHistory(address);\n\n return rawHistory.map((tx) =>\n convertBtcTransaction(tx, {\n address,\n network,\n }),\n );\n};\n","import { type GetBalancesParams, TokenType, type TokenWithBalanceBTC } from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport { TokenService } from '@internal/utils';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { extractTokenMarketData } from '../../utils/extract-token-market-data';\n\ntype GetBtcBalancesResponse = Record<string, Record<string, TokenWithBalanceBTC>>;\n\ntype GetBTCBalancesParams = Omit<GetBalancesParams, 'currency'> & {\n proxyApiUrl: string;\n withScripts?: boolean;\n currency?: string;\n};\n\nexport const getBalances = async ({\n addresses,\n currency,\n network,\n withScripts = false,\n proxyApiUrl,\n storage,\n}: GetBTCBalancesParams): Promise<GetBtcBalancesResponse> => {\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const tokenService = new TokenService({ proxyApiUrl, storage });\n const coingeckoTokenId = network.pricingProviders?.coingecko.nativeTokenId;\n const withPrices = typeof currency === 'string' && typeof coingeckoTokenId === 'string';\n const marketData = withPrices\n ? await tokenService.getSimplePrice({\n coinIds: [coingeckoTokenId],\n currencies: [currency] as VsCurrencyType[],\n })\n : undefined;\n const { priceInCurrency, change24, marketCap, vol24 } = extractTokenMarketData(\n coingeckoTokenId ?? '',\n currency,\n marketData,\n );\n\n const balances = await Promise.allSettled(\n addresses.map(async (address) => {\n const {\n balance: balanceInSatoshis,\n utxos,\n balanceUnconfirmed: unconfirmedBalanceInSatoshis,\n utxosUnconfirmed,\n } = await provider.getUtxoBalance(address, withScripts);\n\n const balance = new TokenUnit(balanceInSatoshis, network.networkToken.decimals, network.networkToken.symbol);\n const balanceInCurrency = priceInCurrency !== undefined ? balance.mul(priceInCurrency) : undefined;\n const balanceDisplayValue = balance.toDisplay();\n\n const unconfirmedBalance = new TokenUnit(\n unconfirmedBalanceInSatoshis,\n network.networkToken.decimals,\n network.networkToken.symbol,\n );\n const unconfirmedBalanceInCurrency =\n priceInCurrency !== undefined ? unconfirmedBalance.mul(priceInCurrency) : undefined;\n\n const symbol = network.networkToken.symbol;\n\n return {\n [address]: {\n [symbol]: {\n ...network.networkToken,\n utxos,\n utxosUnconfirmed,\n coingeckoId: coingeckoTokenId ?? '',\n type: TokenType.NATIVE,\n balance: balance.toSubUnit(),\n balanceDisplayValue,\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n priceInCurrency,\n marketCap,\n vol24,\n change24,\n unconfirmedBalance: unconfirmedBalance.toSubUnit(),\n unconfirmedBalanceDisplayValue: unconfirmedBalance.toDisplay(),\n unconfirmedBalanceInCurrency: unconfirmedBalanceInCurrency?.toDisplay({\n fixedDp: 2,\n asNumber: true,\n }),\n unconfirmedBalanceCurrencyDisplayValue: unconfirmedBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n },\n },\n };\n }),\n );\n\n return balances.reduce((acc, accountBalance) => {\n if (accountBalance.status === 'rejected') {\n return acc;\n }\n\n return {\n ...acc,\n ...accountBalance.value,\n };\n }, {});\n};\n","import type { SimplePriceResponse, TokenMarketData } from '@avalabs/vm-module-types';\n\nexport const extractTokenMarketData = (\n coinId: string,\n currency?: string,\n data?: SimplePriceResponse,\n): TokenMarketData => {\n const coinData = data?.[coinId]?.[currency ?? ''] ?? {};\n\n return {\n priceInCurrency: coinData.price ?? undefined,\n marketCap: coinData.marketCap ?? undefined,\n vol24: coinData.vol24 ?? undefined,\n change24: coinData.change24 ?? undefined,\n };\n};\n","import type { GetAddressParams, GetAddressResponse } from '@avalabs/vm-module-types';\nimport { getBech32AddressFromXPub, getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\nimport { NetworkVMType, WalletType } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\ntype GetAddress = Omit<GetAddressParams, 'xpubXP'>;\n\nexport const getAddress = async ({\n accountIndex,\n xpub,\n network,\n walletType,\n}: GetAddress): Promise<GetAddressResponse> => {\n const isTestnet = Boolean(network?.isTestnet);\n switch (walletType) {\n case WalletType.Mnemonic:\n case WalletType.Ledger:\n case WalletType.Keystone: {\n return {\n [NetworkVMType.BITCOIN]: getBech32AddressFromXPub(\n xpub,\n accountIndex,\n isTestnet ? networks.testnet : networks.bitcoin,\n ),\n };\n }\n case WalletType.LedgerLive:\n case WalletType.Seedless: {\n const pubKeyBuffer = Buffer.from(xpub, 'hex');\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(pubKeyBuffer, isTestnet ? networks.testnet : networks.bitcoin),\n };\n }\n default:\n throw rpcErrors.invalidParams(`Unsupported wallet type: ${walletType}`);\n }\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { parseRequestParams } from './schema';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getProvider } from '../../utils/get-provider';\nimport { getBalances } from '../get-balances/get-balances';\nimport { isBtcBalance } from '../../utils/is-btc-balance';\nimport { createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport { calculateGasLimit } from '../../utils/calculate-gas-limit';\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { linkItem } from '@internal/utils/src/utils/detail-item';\nimport { getTxUpdater } from '../../utils/bitcoin-tx-updater';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\n\ntype BitcoinSendTransactionParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSendTransactionParams) => {\n const { dappInfo, params: rawParams } = request;\n\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const balances = await getBalances({ addresses: [params.from], network, proxyApiUrl, withScripts: true });\n const btcBalance = balances?.[params.from]?.[network.networkToken.symbol];\n\n if (!isBtcBalance(btcBalance)) {\n return {\n error: rpcErrors.internal('Balance for the source account is not available'),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { to, from, amount, feeRate } = params;\n\n const { inputs, outputs, fee } = createTransferTx(\n to,\n from,\n amount,\n feeRate,\n btcBalance.utxos as BitcoinInputUTXO[], // we asked for scripts in getBalances() call\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n return {\n error: rpcErrors.internal('Unable to create transaction'),\n };\n }\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', from),\n addressItem('To', to),\n currencyItem('Amount', BigInt(amount), network.networkToken.decimals, network.networkToken.symbol),\n ],\n },\n ],\n networkFeeSelector: true,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SEND_TRANSACTION,\n account: from,\n data: {\n to,\n amount,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n balance: btcBalance,\n },\n };\n\n const { updateTx, cleanup } = getTxUpdater(request.requestId, signingData, displayData, provider);\n const response = await approvalController.requestApproval({ request, displayData, signingData, updateTx });\n\n cleanup();\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n","import { z } from 'zod';\n\nconst paramsSchema = z.object({\n from: z.string(),\n to: z.string(),\n amount: z.number(),\n feeRate: z.number(),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSendTransactionParams = z.infer<typeof paramsSchema>;\n","import type { TokenWithBalance, TokenWithBalanceBTC } from '@avalabs/vm-module-types';\n\nexport const isBtcBalance = (balance?: TokenWithBalance): balance is TokenWithBalanceBTC => {\n if (!balance) {\n return false;\n }\n\n const hasUtxos = 'utxos' in balance; // BTC, P-Chain or X-Chain\n const hasLocked = 'locked' in balance; // X-Chain only\n const hasUnlockedUnstaked = 'unlockedUnstaked' in balance; // P-Chain only\n\n return hasUtxos && !hasUnlockedUnstaked && !hasLocked;\n};\n","// The transaction's byte size is for BTC as gasLimit is for EVM.\n// Bitcoin's formula for fee is `transactionByteLength * feeRate`.\n// Since we know the `fee` and the `feeRate`, we can get the transaction's\n// byte length by division.\n//\n// Note: We use `Math.ceil` here to ensure the gasLimit is sufficient and\n// to avoid any decimal values. Rounding up helps prevent underestimating the\n// required gas, as gasLimit must be an integer. While this may slightly increase\n// the fee, it minimizes the risk of transaction failure due to insufficient gasLimit.\n\nexport const calculateGasLimit = (fee: number, feeRate: number): number => {\n return Math.ceil(fee / feeRate);\n};\n","import { BitcoinProvider, createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport type { BtcTxUpdateFn, DisplayData, RpcMethod, SigningData } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { calculateGasLimit } from './calculate-gas-limit';\n\ntype SigningData_BtcSendTx = Extract<SigningData, { type: RpcMethod.BITCOIN_SEND_TRANSACTION }>;\n\nconst requests = new Map<string, { signingData: SigningData_BtcSendTx; displayData: DisplayData }>();\n\nexport const getTxUpdater = (\n requestId: string,\n signingData: SigningData_BtcSendTx,\n displayData: DisplayData,\n provider: BitcoinProvider,\n): { updateTx: BtcTxUpdateFn; cleanup: () => void } => {\n requests.set(requestId, { signingData, displayData });\n\n return {\n updateTx: ({ feeRate }) => {\n const request = requests.get(requestId);\n\n if (!request) {\n throw rpcErrors.resourceNotFound();\n }\n\n const { signingData } = request;\n\n if (typeof feeRate === 'undefined' || feeRate === signingData.data.feeRate) {\n return request;\n }\n\n const {\n account,\n data: { to, amount, balance },\n } = signingData;\n const { inputs, outputs, fee } = createTransferTx(\n to,\n account,\n amount,\n feeRate,\n balance.utxos as BitcoinInputUTXO[],\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n throw rpcErrors.internal('Unable to create transaction');\n }\n\n const newData = {\n ...signingData,\n data: {\n ...signingData.data,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n },\n };\n\n const updatedRequest = { ...request, signingData: newData };\n requests.set(requestId, updatedRequest);\n\n return updatedRequest;\n },\n cleanup: () => requests.delete(requestId),\n };\n};\n","import type { Hex, RpcRequest } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const waitForTransactionReceipt = async ({\n explorerUrl,\n provider,\n txHash,\n onTransactionPending,\n onTransactionConfirmed,\n onTransactionReverted,\n request,\n}: {\n explorerUrl: string;\n provider: BitcoinProvider;\n txHash: Hex;\n onTransactionPending: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n onTransactionConfirmed: ({\n txHash,\n explorerLink,\n request,\n }: {\n txHash: Hex;\n explorerLink: string;\n request: RpcRequest;\n }) => void;\n onTransactionReverted: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n request: RpcRequest;\n}) => {\n try {\n onTransactionPending({ txHash, request });\n await provider.waitForTx(txHash);\n const explorerLink = `${explorerUrl}/tx/${txHash}`;\n onTransactionConfirmed({ txHash, explorerLink, request });\n } catch (err) {\n console.error(err);\n onTransactionReverted({ txHash, request });\n }\n};\n","import type { SigningResult } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const getTxHash = async (provider: BitcoinProvider, response: SigningResult) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n return provider.issueRawTx(response.signedData);\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { BitcoinProvider, BitcoinInputUTXO, BitcoinOutputUTXO } from '@avalabs/core-wallets-sdk';\n\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { fundsRecipientItem, linkItem } from '@internal/utils/src/utils/detail-item';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\nimport { parseRequestParams, type BitcoinSignTransactionParams } from './schema';\n\ntype BitcoinSignTransactionRequestParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSignTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSignTransactionRequestParams) => {\n const { dappInfo, params: rawParams } = request;\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, error: detailsError } = await parseTxDetails(params, provider);\n if (detailsError) {\n return {\n error: rpcErrors.internal({ message: 'Transaction invalid or cannot be parsed', data: { cause: detailsError } }),\n };\n }\n\n const { fee, fromAddress, outputs, transferTotal } = details;\n const { decimals, symbol } = network.networkToken;\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', fromAddress),\n currencyItem('Total Transferred Amount', BigInt(transferTotal), decimals, symbol),\n ],\n },\n {\n title: 'Recipients',\n items: outputs.map(({ address, value }) => fundsRecipientItem(address, BigInt(value), decimals, symbol)),\n },\n { title: 'Network Fee', items: [currencyItem('Total Fee', BigInt(fee), decimals, symbol)] },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SIGN_TRANSACTION,\n account: fromAddress,\n data: {\n inputs: params.inputs,\n outputs: params.outputs,\n },\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n\nconst getScript = (inputs: BitcoinInputUTXO[]): string => {\n const scripts = Array.from(new Set(inputs.map(({ script }) => script)));\n\n if (scripts.length !== 1) {\n throw rpcErrors.invalidParams({\n message: `All input UTXOs must belong to a single address, found ${scripts.length}`,\n });\n }\n\n return scripts[0]!;\n};\n\nconst parseTxDetails = async (\n params: BitcoinSignTransactionParams,\n provider: BitcoinProvider,\n): Promise<\n | {\n details: {\n fromAddress: string;\n outputs: [BitcoinOutputUTXO, ...BitcoinOutputUTXO[]];\n fee: number;\n transferTotal: number;\n };\n error: null;\n }\n | { details: null; error: Error }\n> => {\n try {\n const script = getScript(params.inputs);\n const fromAddress = await provider.getAddressFromScript(script);\n const outputs = params.outputs.filter(({ address }) => address !== fromAddress);\n const inputsTotal = params.inputs.reduce((sum, { value }) => sum + value, 0);\n const outputsTotal = params.outputs.reduce((sum, { value }) => sum + value, 0); // with the change address\n const transferTotal = outputs.reduce((sum, { value }) => sum + value, 0); // without the change address\n const fee = inputsTotal - outputsTotal;\n\n assertNonEmpty(outputs);\n\n return {\n error: null,\n details: {\n fromAddress,\n outputs,\n fee,\n transferTotal,\n },\n };\n } catch (error) {\n console.error(error);\n return {\n details: null,\n error: error instanceof Error ? error : new Error(error?.toString() ?? 'Unknown error'),\n };\n }\n};\n\nfunction assertNonEmpty<T>(array: T[]): asserts array is [T, ...T[]] {\n if (array.length < 1) {\n throw new Error('No actual output is provided, this transaction would only burn funds');\n }\n}\n","import { z } from 'zod';\n\nconst inputUtxo = z.object({\n txHash: z.string(),\n txHex: z.string().optional(),\n index: z.number(),\n value: z.number(),\n script: z.string().min(1), // Just make sure it's never an empty string\n blockHeight: z.number(),\n confirmations: z.number(),\n confirmedTime: z.string().optional(),\n});\n\nconst outputUtxo = z.object({\n address: z.string(),\n value: z.number(),\n});\n\nconst paramsSchema = z.object({\n inputs: z.array(inputUtxo).min(1),\n outputs: z.array(outputUtxo).min(1),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSignTransactionParams = z.infer<typeof paramsSchema>;\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\n\nimport { getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\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, network, 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).BITCOIN : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'secp256k1',\n secretId,\n derivationPath,\n });\n const publicKey = Buffer.from(publicKeyHex, 'hex');\n\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(\n publicKey,\n network.isTestnet ? networks.testnet : networks.bitcoin,\n ),\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 { rpcErrors } from '@metamask/rpc-errors';\nimport {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\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 derivationPathType,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.BITCOIN> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n switch (derivationPathType) {\n case 'bip44':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/0'/0/${accountIndex}`,\n };\n\n case 'ledger_live':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/${accountIndex}'/0/0`,\n };\n\n default:\n throw rpcErrors.invalidParams(`Unsupported derivation path type: ${derivationPathType}`);\n }\n};\n"]}
1
+ {"version":3,"sources":["../src/module.ts","../src/env.ts","../manifest.json","../src/utils/get-provider.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/token-service/watchlist-proxy-client.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","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/handlers/get-transaction-history/convert-btc-transaction.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-balances/get-balances.ts","../src/handlers/get-address/get-address.ts","../src/handlers/bitcoin-send-transaction/bitcoin-send-transaction.ts","../src/handlers/bitcoin-send-transaction/schema.ts","../src/utils/is-btc-balance.ts","../src/utils/calculate-gas-limit.ts","../src/utils/bitcoin-tx-updater.ts","../src/utils/wait-for-tx-receipt.ts","../src/utils/get-tx-hash.ts","../src/handlers/bitcoin-sign-transaction/bitcoin-sign-transaction.ts","../src/handlers/bitcoin-sign-transaction/schema.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"],"names":["RpcMethod","parseManifest","rpcErrors","Environment","prodEnv","devEnv","getEnv","environment","manifest_default","BitcoinProvider","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","n","base","incSum","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","z","WatchlistTokenResponseSchema","WatchlistProxyClient","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","tokenDetails","tokenInfo","__privateGet","token","coinIds","cacheId","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","fundsRecipientItem","address","amount","maxDecimals","symbol","currencyItem","label","value","linkItem","addressItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","getProvider","isTestnet","glacierApiKey","getNetworkFee","provider","high","low","medium","TokenType","TransactionType","convertBtcTransaction","tx","network","explorerUrl","networkToken","txAddress","getTransactionHistory","TokenUnit","getBalances","addresses","withScripts","tokenService","coingeckoTokenId","marketData","balanceInSatoshis","utxos","unconfirmedBalanceInSatoshis","utxosUnconfirmed","balance","balanceInCurrency","balanceDisplayValue","unconfirmedBalance","unconfirmedBalanceInCurrency","acc","accountBalance","getBech32AddressFromXPub","getBtcAddressFromPubKey","networks","NetworkVMType","WalletType","getAddress","accountIndex","xpub","walletType","pubKeyBuffer","paramsSchema","parseRequestParams","isBtcBalance","hasUtxos","hasLocked","hasUnlockedUnstaked","createTransferTx","calculateGasLimit","fee","feeRate","requests","getTxUpdater","requestId","signingData","displayData","request","account","to","inputs","outputs","newData","updatedRequest","waitForTransactionReceipt","txHash","onTransactionPending","onTransactionConfirmed","onTransactionReverted","explorerLink","getTxHash","bitcoinSendTransaction","approvalController","dappInfo","rawParams","success","parseError","btcBalance","from","updateTx","cleanup","error","inputUtxo","outputUtxo","bitcoinSignTransaction","details","detailsError","parseTxDetails","fromAddress","transferTotal","decimals","getScript","scripts","script","inputsTotal","outputsTotal","assertNonEmpty","hasDerivationDetails","buildDerivationPath","derivationPathType","deriveAddress","secretId","derivationPath","publicKeyHex","publicKey","_approvalController","BitcoinModule"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetAddressParams,\n GetAddressResponse,\n ApprovalController,\n ConstructorParams,\n DeriveAddressParams,\n BuildDerivationPathParams,\n} from '@avalabs/vm-module-types';\nimport { RpcMethod, parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getEnv } from './env';\n\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getBalances } from './handlers/get-balances/get-balances';\nimport { getAddress } from './handlers/get-address/get-address';\nimport { bitcoinSendTransaction } from './handlers/bitcoin-send-transaction/bitcoin-send-transaction';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getProvider } from './utils/get-provider';\nimport { bitcoinSignTransaction } from './handlers/bitcoin-sign-transaction/bitcoin-sign-transaction';\nimport { deriveAddress } from './handlers/derive-address/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path/build-derivation-path';\n\nexport class BitcoinModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n\n constructor({ environment, approvalController }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#approvalController = approvalController;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n getProvider(network: Network): Promise<BitcoinProvider> {\n return getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getAddress({ accountIndex, xpub, walletType, network }: GetAddressParams): Promise<GetAddressResponse> {\n return getAddress({ accountIndex, xpub, network, walletType });\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({ addresses, currency, network, storage }: GetBalancesParams) {\n return getBalances({\n addresses,\n currency,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n storage,\n });\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: Network): Promise<NetworkFees> {\n return getNetworkFee({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n async getTransactionHistory({ address, network }: GetTransactionHistory) {\n return {\n transactions: await getTransactionHistory({\n address,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n }),\n };\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.BITCOIN_SEND_TRANSACTION:\n return bitcoinSendTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n case RpcMethod.BITCOIN_SIGN_TRANSACTION:\n return bitcoinSignTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\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","{\n \"name\": \"Bitcoin\",\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/bitcoin-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\"bip122:000000000019d6689c085ae165831e93\", \"bip122:000000000933ea01ad0ee984209779ba\"],\n \"namespaces\": [\"bip122\"]\n },\n \"cointype\": \"0\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"bitcoin_sendTransaction\", \"bitcoin_signTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getGlacierApiKey } from '@internal/utils';\n\ntype ProviderParams = {\n isTestnet: boolean;\n proxyApiUrl: string;\n};\n\nexport const getProvider = async ({ isTestnet, proxyApiUrl }: ProviderParams): Promise<BitcoinProvider> => {\n const glacierApiKey = getGlacierApiKey();\n\n return new BitcoinProvider(\n !isTestnet,\n undefined,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btcbook-testnet' : 'btcbook'}`,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btc-testnet' : 'btc'}`,\n glacierApiKey ? { token: glacierApiKey } : {},\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';\nimport { WatchlistProxyClient } from './watchlist-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 async getWatchlistDataForToken({\n tokenDetails,\n currency = VsCurrencyType.USD,\n }: {\n tokenDetails: {\n symbol: string;\n isNative: boolean;\n caip2Id: string;\n address?: string;\n };\n currency: VsCurrencyType;\n }): Promise<{\n priceInCurrency: number;\n change24: number;\n marketCap: number;\n vol24: number;\n }> {\n const data = (\n await new WatchlistProxyClient(this.#proxyApiUrl).watchlistToken({\n tokens: tokenDetails.symbol,\n currency: currency,\n })\n ).filter((token) => {\n return tokenDetails.isNative\n ? token.internalId === `NATIVE-${tokenDetails.symbol.toLowerCase()}`\n : token.platforms[tokenDetails.caip2Id] === tokenDetails.address;\n });\n\n const tokenInfo = data[0];\n\n if (!tokenInfo) {\n return {\n priceInCurrency: 0,\n change24: 0,\n marketCap: 0,\n vol24: 0,\n };\n }\n\n return {\n priceInCurrency: tokenInfo.current_price ?? 0,\n change24: tokenInfo.price_change_percentage_24h ?? 0,\n marketCap: tokenInfo.market_cap ?? 0,\n vol24: tokenInfo.total_volume ?? 0,\n };\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 /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\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 { fetchAndVerify } from '../../utils/fetch-and-verify';\nimport { z } from 'zod';\n\nconst WatchlistTokenResponseSchema = z.array(\n z.object({\n // the object has more properties than the ones listed here, but we only need these at the moment\n internalId: z.string(),\n id: z.string(),\n symbol: z.string(),\n name: z.string(),\n image: z.string().optional().nullable(),\n current_price: z.number().optional().nullable(),\n price_change_percentage_24h: z.number().optional().nullable(),\n market_cap: z.number().optional().nullable(),\n total_volume: z.number().optional().nullable(),\n platforms: z.record(z.string(), z.string()),\n }),\n);\n\nexport class WatchlistProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n watchlistToken(params: { tokens: string; currency: string }) {\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}/watchlist/tokens?${queryParams}`,\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n WatchlistTokenResponseSchema,\n );\n }\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 type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\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 addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\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\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\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","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\n/**\n * Returns {@link NetworkFees} based on `estimatesmartfee` RPC call\n */\nexport async function getNetworkFee({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): Promise<NetworkFees> {\n const provider = await getProvider({\n isTestnet,\n proxyApiUrl,\n });\n\n const { high, low, medium } = await provider.getFeeRates();\n\n return {\n low: {\n maxFeePerGas: BigInt(low),\n },\n medium: {\n maxFeePerGas: BigInt(medium),\n },\n high: {\n maxFeePerGas: BigInt(high),\n },\n isFixedFee: false,\n };\n}\n","import { TokenType, TransactionType, type Network, type Transaction } from '@avalabs/vm-module-types';\nimport type { BitcoinHistoryTx } from '@avalabs/core-wallets-sdk';\n\ntype ConverterOptions = {\n address: string;\n network: Network;\n};\n\nexport const convertBtcTransaction = (tx: BitcoinHistoryTx, { address, network }: ConverterOptions): Transaction => {\n const { explorerUrl, networkToken } = network;\n const txAddress = tx.addresses[0] ?? '';\n\n return {\n chainId: network.chainId.toString(),\n explorerLink: `${explorerUrl}/tx/${tx.hash}`,\n from: tx.isSender ? address : txAddress,\n gasUsed: tx.fee.toString(),\n hash: tx.hash,\n isContractCall: false,\n isIncoming: !tx.isSender,\n isOutgoing: tx.isSender,\n isSender: tx.isSender,\n timestamp: tx.receivedTime * 1000,\n to: tx.isSender ? txAddress : address,\n tokens: [\n {\n amount: (Math.abs(tx.amount) / 10 ** networkToken.decimals).toString(),\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n },\n ],\n txType: tx.isSender ? TransactionType.SEND : TransactionType.RECEIVE,\n };\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\nimport { convertBtcTransaction } from './convert-btc-transaction';\n\ntype GetBtcTransactionHistoryOptions = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport const getTransactionHistory = async ({ address, network, proxyApiUrl }: GetBtcTransactionHistoryOptions) => {\n const provider = await getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n const rawHistory = await provider.getTxHistory(address);\n\n return rawHistory.map((tx) =>\n convertBtcTransaction(tx, {\n address,\n network,\n }),\n );\n};\n","import { type GetBalancesParams, TokenType, type TokenWithBalanceBTC } from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport { TokenService } from '@internal/utils';\n\nimport { getProvider } from '../../utils/get-provider';\n\ntype GetBtcBalancesResponse = Record<string, Record<string, TokenWithBalanceBTC>>;\n\ntype GetBTCBalancesParams = Omit<GetBalancesParams, 'currency'> & {\n proxyApiUrl: string;\n withScripts?: boolean;\n currency?: string;\n};\n\nexport const getBalances = async ({\n addresses,\n currency,\n network,\n withScripts = false,\n proxyApiUrl,\n storage,\n}: GetBTCBalancesParams): Promise<GetBtcBalancesResponse> => {\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const tokenService = new TokenService({ proxyApiUrl, storage });\n const coingeckoTokenId = network.pricingProviders?.coingecko.nativeTokenId;\n const withPrices = typeof currency === 'string' && typeof coingeckoTokenId === 'string';\n const marketData = withPrices\n ? await tokenService.getWatchlistDataForToken({\n tokenDetails: {\n symbol: network.networkToken.symbol,\n isNative: true,\n caip2Id: network.caipId ?? '',\n },\n currency: currency as VsCurrencyType,\n })\n : undefined;\n\n const balances = await Promise.allSettled(\n addresses.map(async (address) => {\n const {\n balance: balanceInSatoshis,\n utxos,\n balanceUnconfirmed: unconfirmedBalanceInSatoshis,\n utxosUnconfirmed,\n } = await provider.getUtxoBalance(address, withScripts);\n\n const balance = new TokenUnit(balanceInSatoshis, network.networkToken.decimals, network.networkToken.symbol);\n const balanceInCurrency =\n marketData?.priceInCurrency !== undefined ? balance.mul(marketData.priceInCurrency) : undefined;\n const balanceDisplayValue = balance.toDisplay();\n\n const unconfirmedBalance = new TokenUnit(\n unconfirmedBalanceInSatoshis,\n network.networkToken.decimals,\n network.networkToken.symbol,\n );\n const unconfirmedBalanceInCurrency =\n marketData?.priceInCurrency !== undefined ? unconfirmedBalance.mul(marketData.priceInCurrency) : undefined;\n\n const symbol = network.networkToken.symbol;\n\n return {\n [address]: {\n [symbol]: {\n ...network.networkToken,\n utxos,\n utxosUnconfirmed,\n coingeckoId: coingeckoTokenId ?? '',\n type: TokenType.NATIVE,\n balance: balance.toSubUnit(),\n balanceDisplayValue,\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n priceInCurrency: marketData?.priceInCurrency,\n marketCap: marketData?.marketCap,\n vol24: marketData?.vol24,\n change24: marketData?.change24,\n unconfirmedBalance: unconfirmedBalance.toSubUnit(),\n unconfirmedBalanceDisplayValue: unconfirmedBalance.toDisplay(),\n unconfirmedBalanceInCurrency: unconfirmedBalanceInCurrency?.toDisplay({\n fixedDp: 2,\n asNumber: true,\n }),\n unconfirmedBalanceCurrencyDisplayValue: unconfirmedBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n },\n },\n };\n }),\n );\n\n return balances.reduce((acc, accountBalance) => {\n if (accountBalance.status === 'rejected') {\n return acc;\n }\n\n return {\n ...acc,\n ...accountBalance.value,\n };\n }, {});\n};\n","import type { GetAddressParams, GetAddressResponse } from '@avalabs/vm-module-types';\nimport { getBech32AddressFromXPub, getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\nimport { NetworkVMType, WalletType } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\ntype GetAddress = Omit<GetAddressParams, 'xpubXP'>;\n\nexport const getAddress = async ({\n accountIndex,\n xpub,\n network,\n walletType,\n}: GetAddress): Promise<GetAddressResponse> => {\n const isTestnet = Boolean(network?.isTestnet);\n switch (walletType) {\n case WalletType.Mnemonic:\n case WalletType.Ledger:\n case WalletType.Keystone: {\n return {\n [NetworkVMType.BITCOIN]: getBech32AddressFromXPub(\n xpub,\n accountIndex,\n isTestnet ? networks.testnet : networks.bitcoin,\n ),\n };\n }\n case WalletType.LedgerLive:\n case WalletType.Seedless: {\n const pubKeyBuffer = Buffer.from(xpub, 'hex');\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(pubKeyBuffer, isTestnet ? networks.testnet : networks.bitcoin),\n };\n }\n default:\n throw rpcErrors.invalidParams(`Unsupported wallet type: ${walletType}`);\n }\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { parseRequestParams } from './schema';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getProvider } from '../../utils/get-provider';\nimport { getBalances } from '../get-balances/get-balances';\nimport { isBtcBalance } from '../../utils/is-btc-balance';\nimport { createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport { calculateGasLimit } from '../../utils/calculate-gas-limit';\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { linkItem } from '@internal/utils/src/utils/detail-item';\nimport { getTxUpdater } from '../../utils/bitcoin-tx-updater';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\n\ntype BitcoinSendTransactionParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSendTransactionParams) => {\n const { dappInfo, params: rawParams } = request;\n\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const balances = await getBalances({ addresses: [params.from], network, proxyApiUrl, withScripts: true });\n const btcBalance = balances?.[params.from]?.[network.networkToken.symbol];\n\n if (!isBtcBalance(btcBalance)) {\n return {\n error: rpcErrors.internal('Balance for the source account is not available'),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { to, from, amount, feeRate } = params;\n\n const { inputs, outputs, fee } = createTransferTx(\n to,\n from,\n amount,\n feeRate,\n btcBalance.utxos as BitcoinInputUTXO[], // we asked for scripts in getBalances() call\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n return {\n error: rpcErrors.internal('Unable to create transaction'),\n };\n }\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', from),\n addressItem('To', to),\n currencyItem('Amount', BigInt(amount), network.networkToken.decimals, network.networkToken.symbol),\n ],\n },\n ],\n networkFeeSelector: true,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SEND_TRANSACTION,\n account: from,\n data: {\n to,\n amount,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n balance: btcBalance,\n },\n };\n\n const { updateTx, cleanup } = getTxUpdater(request.requestId, signingData, displayData, provider);\n const response = await approvalController.requestApproval({ request, displayData, signingData, updateTx });\n\n cleanup();\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n","import { z } from 'zod';\n\nconst paramsSchema = z.object({\n from: z.string(),\n to: z.string(),\n amount: z.number(),\n feeRate: z.number(),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSendTransactionParams = z.infer<typeof paramsSchema>;\n","import type { TokenWithBalance, TokenWithBalanceBTC } from '@avalabs/vm-module-types';\n\nexport const isBtcBalance = (balance?: TokenWithBalance): balance is TokenWithBalanceBTC => {\n if (!balance) {\n return false;\n }\n\n const hasUtxos = 'utxos' in balance; // BTC, P-Chain or X-Chain\n const hasLocked = 'locked' in balance; // X-Chain only\n const hasUnlockedUnstaked = 'unlockedUnstaked' in balance; // P-Chain only\n\n return hasUtxos && !hasUnlockedUnstaked && !hasLocked;\n};\n","// The transaction's byte size is for BTC as gasLimit is for EVM.\n// Bitcoin's formula for fee is `transactionByteLength * feeRate`.\n// Since we know the `fee` and the `feeRate`, we can get the transaction's\n// byte length by division.\n//\n// Note: We use `Math.ceil` here to ensure the gasLimit is sufficient and\n// to avoid any decimal values. Rounding up helps prevent underestimating the\n// required gas, as gasLimit must be an integer. While this may slightly increase\n// the fee, it minimizes the risk of transaction failure due to insufficient gasLimit.\n\nexport const calculateGasLimit = (fee: number, feeRate: number): number => {\n return Math.ceil(fee / feeRate);\n};\n","import { BitcoinProvider, createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport type { BtcTxUpdateFn, DisplayData, RpcMethod, SigningData } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { calculateGasLimit } from './calculate-gas-limit';\n\ntype SigningData_BtcSendTx = Extract<SigningData, { type: RpcMethod.BITCOIN_SEND_TRANSACTION }>;\n\nconst requests = new Map<string, { signingData: SigningData_BtcSendTx; displayData: DisplayData }>();\n\nexport const getTxUpdater = (\n requestId: string,\n signingData: SigningData_BtcSendTx,\n displayData: DisplayData,\n provider: BitcoinProvider,\n): { updateTx: BtcTxUpdateFn; cleanup: () => void } => {\n requests.set(requestId, { signingData, displayData });\n\n return {\n updateTx: ({ feeRate }) => {\n const request = requests.get(requestId);\n\n if (!request) {\n throw rpcErrors.resourceNotFound();\n }\n\n const { signingData } = request;\n\n if (typeof feeRate === 'undefined' || feeRate === signingData.data.feeRate) {\n return request;\n }\n\n const {\n account,\n data: { to, amount, balance },\n } = signingData;\n const { inputs, outputs, fee } = createTransferTx(\n to,\n account,\n amount,\n feeRate,\n balance.utxos as BitcoinInputUTXO[],\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n throw rpcErrors.internal('Unable to create transaction');\n }\n\n const newData = {\n ...signingData,\n data: {\n ...signingData.data,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n },\n };\n\n const updatedRequest = { ...request, signingData: newData };\n requests.set(requestId, updatedRequest);\n\n return updatedRequest;\n },\n cleanup: () => requests.delete(requestId),\n };\n};\n","import type { Hex, RpcRequest } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const waitForTransactionReceipt = async ({\n explorerUrl,\n provider,\n txHash,\n onTransactionPending,\n onTransactionConfirmed,\n onTransactionReverted,\n request,\n}: {\n explorerUrl: string;\n provider: BitcoinProvider;\n txHash: Hex;\n onTransactionPending: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n onTransactionConfirmed: ({\n txHash,\n explorerLink,\n request,\n }: {\n txHash: Hex;\n explorerLink: string;\n request: RpcRequest;\n }) => void;\n onTransactionReverted: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n request: RpcRequest;\n}) => {\n try {\n onTransactionPending({ txHash, request });\n await provider.waitForTx(txHash);\n const explorerLink = `${explorerUrl}/tx/${txHash}`;\n onTransactionConfirmed({ txHash, explorerLink, request });\n } catch (err) {\n console.error(err);\n onTransactionReverted({ txHash, request });\n }\n};\n","import type { SigningResult } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const getTxHash = async (provider: BitcoinProvider, response: SigningResult) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n return provider.issueRawTx(response.signedData);\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { BitcoinProvider, BitcoinInputUTXO, BitcoinOutputUTXO } from '@avalabs/core-wallets-sdk';\n\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { fundsRecipientItem, linkItem } from '@internal/utils/src/utils/detail-item';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\nimport { parseRequestParams, type BitcoinSignTransactionParams } from './schema';\n\ntype BitcoinSignTransactionRequestParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSignTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSignTransactionRequestParams) => {\n const { dappInfo, params: rawParams } = request;\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, error: detailsError } = await parseTxDetails(params, provider);\n if (detailsError) {\n return {\n error: rpcErrors.internal({ message: 'Transaction invalid or cannot be parsed', data: { cause: detailsError } }),\n };\n }\n\n const { fee, fromAddress, outputs, transferTotal } = details;\n const { decimals, symbol } = network.networkToken;\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', fromAddress),\n currencyItem('Total Transferred Amount', BigInt(transferTotal), decimals, symbol),\n ],\n },\n {\n title: 'Recipients',\n items: outputs.map(({ address, value }) => fundsRecipientItem(address, BigInt(value), decimals, symbol)),\n },\n { title: 'Network Fee', items: [currencyItem('Total Fee', BigInt(fee), decimals, symbol)] },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SIGN_TRANSACTION,\n account: fromAddress,\n data: {\n inputs: params.inputs,\n outputs: params.outputs,\n },\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n\nconst getScript = (inputs: BitcoinInputUTXO[]): string => {\n const scripts = Array.from(new Set(inputs.map(({ script }) => script)));\n\n if (scripts.length !== 1) {\n throw rpcErrors.invalidParams({\n message: `All input UTXOs must belong to a single address, found ${scripts.length}`,\n });\n }\n\n return scripts[0]!;\n};\n\nconst parseTxDetails = async (\n params: BitcoinSignTransactionParams,\n provider: BitcoinProvider,\n): Promise<\n | {\n details: {\n fromAddress: string;\n outputs: [BitcoinOutputUTXO, ...BitcoinOutputUTXO[]];\n fee: number;\n transferTotal: number;\n };\n error: null;\n }\n | { details: null; error: Error }\n> => {\n try {\n const script = getScript(params.inputs);\n const fromAddress = await provider.getAddressFromScript(script);\n const outputs = params.outputs.filter(({ address }) => address !== fromAddress);\n const inputsTotal = params.inputs.reduce((sum, { value }) => sum + value, 0);\n const outputsTotal = params.outputs.reduce((sum, { value }) => sum + value, 0); // with the change address\n const transferTotal = outputs.reduce((sum, { value }) => sum + value, 0); // without the change address\n const fee = inputsTotal - outputsTotal;\n\n assertNonEmpty(outputs);\n\n return {\n error: null,\n details: {\n fromAddress,\n outputs,\n fee,\n transferTotal,\n },\n };\n } catch (error) {\n console.error(error);\n return {\n details: null,\n error: error instanceof Error ? error : new Error(error?.toString() ?? 'Unknown error'),\n };\n }\n};\n\nfunction assertNonEmpty<T>(array: T[]): asserts array is [T, ...T[]] {\n if (array.length < 1) {\n throw new Error('No actual output is provided, this transaction would only burn funds');\n }\n}\n","import { z } from 'zod';\n\nconst inputUtxo = z.object({\n txHash: z.string(),\n txHex: z.string().optional(),\n index: z.number(),\n value: z.number(),\n script: z.string().min(1), // Just make sure it's never an empty string\n blockHeight: z.number(),\n confirmations: z.number(),\n confirmedTime: z.string().optional(),\n});\n\nconst outputUtxo = z.object({\n address: z.string(),\n value: z.number(),\n});\n\nconst paramsSchema = z.object({\n inputs: z.array(inputUtxo).min(1),\n outputs: z.array(outputUtxo).min(1),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSignTransactionParams = z.infer<typeof paramsSchema>;\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\n\nimport { getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\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, network, 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).BITCOIN : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'secp256k1',\n secretId,\n derivationPath,\n });\n const publicKey = Buffer.from(publicKeyHex, 'hex');\n\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(\n publicKey,\n network.isTestnet ? networks.testnet : networks.bitcoin,\n ),\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 { rpcErrors } from '@metamask/rpc-errors';\nimport {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\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 derivationPathType,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.BITCOIN> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n switch (derivationPathType) {\n case 'bip44':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/0'/0/${accountIndex}`,\n };\n\n case 'ledger_live':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/${accountIndex}'/0/0`,\n };\n\n default:\n throw rpcErrors.invalidParams(`Unsupported derivation path type: ${derivationPathType}`);\n }\n};\n"]}
package/dist/index.js CHANGED
@@ -2,12 +2,12 @@ import { parseManifest, RpcMethod, Environment, TokenType, WalletType, NetworkVM
2
2
  import { rpcErrors } from '@metamask/rpc-errors';
3
3
  import { BitcoinProvider, getBtcAddressFromPubKey, getBech32AddressFromXPub, createTransferTx } from '@avalabs/core-wallets-sdk';
4
4
  import { getBasicCoingeckoHttp, VsCurrencyType, simpleTokenPrice, simplePrice } from '@avalabs/core-coingecko-sdk';
5
- import { object, string, record, number, z } from 'zod';
5
+ import { z as z$1, object, string, record, number } from 'zod';
6
6
  import { TokenUnit } from '@avalabs/core-utils-sdk';
7
7
  import { networks } from 'bitcoinjs-lib';
8
8
 
9
- var Ge=Object.defineProperty;var Le=(r,e,t)=>e in r?Ge(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var se=(r,e,t)=>(Le(r,typeof e!="symbol"?e+"":e,t),t),ae=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var m=(r,e,t)=>(ae(r,e,"read from private field"),t?t.call(r):e.get(r)),C=(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);},E=(r,e,t,o)=>(ae(r,e,"write to private field"),o?o.call(r,t):e.set(r,t),t);var Fe={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},Me={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},ce=r=>{switch(r){case Environment.PRODUCTION:return Fe;case Environment.DEV:return Me}};var pe={name:"Bitcoin",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/bitcoin-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["bip122:000000000019d6689c085ae165831e93","bip122:000000000933ea01ad0ee984209779ba"],namespaces:["bip122"]},cointype:"0",permissions:{rpc:{dapps:!0,methods:["bitcoin_sendTransaction","bitcoin_signTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var re=async({operation:r,isSuccess:e,maxRetries:t=10,backoffPolicy:o=_.exponential()})=>{let n=0,s=0,a;for(;s<t;){s>0&&await $e(n);try{let c=await r(s);if(e(c))return c}catch(c){a=c;}n=o(s),s++;}let i=a?`Max retry exceeded. ${a}`:"Max retry exceeded.";throw new Error(i)},_=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return t=>e*1e3}static constantMs(e){return t=>e}static linearThenExponential(e,t){return o=>{if(o<e)return (o+1)*t;let n=o-e+1,s=e*t,a=2*t*(Math.pow(2,n)-1);return s+a}}};function $e(r){return new Promise(e=>setTimeout(e,r))}var oe=r=>re({operation:e=>r(e>0),maxRetries:2,backoffPolicy:_.constant(1),isSuccess:e=>e?.status?.error_code!==429});function me(r){let e,t=0;for(e=0;e<r.length;e++)t+=r.charCodeAt(e)*(e+1);return t}function ne(r){let e,t=0;for(e=0;e<r.length;e++){let o=me(r[e]??"");t=t+65027/o;}return (""+t).slice(0,16)}async function H(r,e){let t=await fetch(...r);if(!t.ok)throw new Error(`Request failed with status ${t.status}`);let o=await t.json();return e.parse(o)}var G=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let t=new URLSearchParams(e);return H([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${t}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:t,...o}=e,n=new URLSearchParams(o);return H([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${t}?${n}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}};var de=getBasicCoingeckoHttp(),I,N,F=class{constructor({storage:e,proxyApiUrl:t}){C(this,I,void 0);C(this,N,void 0);se(this,"transformSimplePriceResponse",(e,t=[VsCurrencyType.USD])=>{let o={};return Object.keys(e).forEach(n=>{let s=e[n];o[n]={},t.forEach(a=>{o[n]={[a]:{price:s?.[a],change24:s?.[`${a}_24h_change`],vol24:s?.[`${a}_24h_vol`],marketCap:s?.[`${a}_market_cap`]}};});}),o});E(this,I,e),E(this,N,t);}async getSimplePrice({coinIds:e=[],currencies:t=[VsCurrencyType.USD]}){let o,s=`getSimplePrice-${e?`${ne(e)}-${t.toString()}`:`${t.toString()}`}`;if(o=m(this,I)?.get?.(s),o)return o;try{o=await oe(a=>this.simplePrice({coinIds:e,currencies:t,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:a}));}catch{o=void 0;}return m(this,I)?.set?.(s,o),o}async getPricesByAddresses(e,t,o=VsCurrencyType.USD){let n,a=`getPricesWithMarketDataByAddresses-${`${ne(e)}-${t}-${o}`}`;if(n=m(this,I)?.get?.(a),n)return n;try{n=await oe(i=>this.fetchPricesByAddresses({assetPlatformId:t,tokenAddresses:e,currency:o,useCoingeckoProxy:i}));}catch(i){console.error(i),n=void 0;}return m(this,I)?.set?.(a,n),n}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:t,currency:o=VsCurrencyType.USD,useCoingeckoProxy:n=!1}){if(n){let s=await new G(m(this,N)).simplePriceByContractAddresses({id:e,contract_addresses:t,vs_currencies:[o],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[o])}return simpleTokenPrice(de,{assetPlatformId:e,tokenAddresses:t,currencies:[o],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:t=[VsCurrencyType.USD],marketCap:o=!1,vol24:n=!1,change24:s=!1,lastUpdated:a=!1,useCoingeckoProxy:i=!1,shouldThrow:c=!0}){if(i){let p=await new G(m(this,N)).simplePrice({ids:e,vs_currencies:t,include_market_cap:o,include_24hr_vol:n,include_24hr_change:s,include_last_updated_at:a});return this.transformSimplePriceResponse(p,t)}return simplePrice(de,{coinIds:e,currencies:t,marketCap:o,vol24:n,change24:s,lastUpdated:a,shouldThrow:c})}};I=new WeakMap,N=new WeakMap;object({date:string(),usd:record(number())});var ue=(r,e,t,o)=>({type:DetailItemType.FUNDS_RECIPIENT,label:r,amount:e,maxDecimals:t,symbol:o}),U=(r,e,t,o)=>({label:r,type:DetailItemType.CURRENCY,value:e,maxDecimals:t,symbol:o});var K=(r,e)=>({label:r,value:e,type:DetailItemType.LINK}),O=(r,e)=>({label:r,type:DetailItemType.ADDRESS,value:e});var ye=process.env.GLACIER_API_KEY;var M=()=>ye;var f=async({isTestnet:r,proxyApiUrl:e})=>{let t=M();return new BitcoinProvider(!r,void 0,`${e}/proxy/nownodes/${r?"btcbook-testnet":"btcbook"}`,`${e}/proxy/nownodes/${r?"btc-testnet":"btc"}`,t?{token:t}:{})};async function fe({isTestnet:r,proxyApiUrl:e}){let t=await f({isTestnet:r,proxyApiUrl:e}),{high:o,low:n,medium:s}=await t.getFeeRates();return {low:{maxFeePerGas:BigInt(n)},medium:{maxFeePerGas:BigInt(s)},high:{maxFeePerGas:BigInt(o)},isFixedFee:!1}}var Te=(r,{address:e,network:t})=>{let{explorerUrl:o,networkToken:n}=t,s=r.addresses[0]??"";return {chainId:t.chainId.toString(),explorerLink:`${o}/tx/${r.hash}`,from:r.isSender?e:s,gasUsed:r.fee.toString(),hash:r.hash,isContractCall:!1,isIncoming:!r.isSender,isOutgoing:r.isSender,isSender:r.isSender,timestamp:r.receivedTime*1e3,to:r.isSender?s:e,tokens:[{amount:(Math.abs(r.amount)/10**n.decimals).toString(),decimal:n.decimals.toString(),name:n.name,symbol:n.symbol,type:TokenType.NATIVE}],txType:r.isSender?TransactionType.SEND:TransactionType.RECEIVE}};var he=async({address:r,network:e,proxyApiUrl:t})=>(await(await f({isTestnet:!!e.isTestnet,proxyApiUrl:t})).getTxHistory(r)).map(s=>Te(s,{address:r,network:e}));var Pe=(r,e,t)=>{let o=t?.[r]?.[e??""]??{};return {priceInCurrency:o.price??void 0,marketCap:o.marketCap??void 0,vol24:o.vol24??void 0,change24:o.change24??void 0}};var j=async({addresses:r,currency:e,network:t,withScripts:o=!1,proxyApiUrl:n,storage:s})=>{let a=await f({isTestnet:!!t.isTestnet,proxyApiUrl:n}),i=new F({proxyApiUrl:n,storage:s}),c=t.pricingProviders?.coingecko.nativeTokenId,d=typeof e=="string"&&typeof c=="string"?await i.getSimplePrice({coinIds:[c],currencies:[e]}):void 0,{priceInCurrency:l,change24:h,marketCap:g,vol24:v}=Pe(c??"",e,d);return (await Promise.allSettled(r.map(async y=>{let{balance:T,utxos:S,balanceUnconfirmed:D,utxosUnconfirmed:R}=await a.getUtxoBalance(y,o),b=new TokenUnit(T,t.networkToken.decimals,t.networkToken.symbol),k=l!==void 0?b.mul(l):void 0,B=b.toDisplay(),A=new TokenUnit(D,t.networkToken.decimals,t.networkToken.symbol),V=l!==void 0?A.mul(l):void 0,He=t.networkToken.symbol;return {[y]:{[He]:{...t.networkToken,utxos:S,utxosUnconfirmed:R,coingeckoId:c??"",type:TokenType.NATIVE,balance:b.toSubUnit(),balanceDisplayValue:B,balanceInCurrency:k?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:k?.toDisplay({fixedDp:2}),priceInCurrency:l,marketCap:g,vol24:v,change24:h,unconfirmedBalance:A.toSubUnit(),unconfirmedBalanceDisplayValue:A.toDisplay(),unconfirmedBalanceInCurrency:V?.toDisplay({fixedDp:2,asNumber:!0}),unconfirmedBalanceCurrencyDisplayValue:V?.toDisplay({fixedDp:2})}}}}))).reduce((y,T)=>T.status==="rejected"?y:{...y,...T.value},{})};var be=async({accountIndex:r,xpub:e,network:t,walletType:o})=>{let n=!!t?.isTestnet;switch(o){case WalletType.Mnemonic:case WalletType.Ledger:case WalletType.Keystone:return {[NetworkVMType.BITCOIN]:getBech32AddressFromXPub(e,r,n?networks.testnet:networks.bitcoin)};case WalletType.LedgerLive:case WalletType.Seedless:{let s=Buffer.from(e,"hex");return {[NetworkVMType.BITCOIN]:getBtcAddressFromPubKey(s,n?networks.testnet:networks.bitcoin)}}default:throw rpcErrors.invalidParams(`Unsupported wallet type: ${o}`)}};var ot=z.object({from:z.string(),to:z.string(),amount:z.number(),feeRate:z.number()}),Re=r=>ot.safeParse(r);var ke=r=>{if(!r)return !1;let e="utxos"in r,t="locked"in r,o="unlockedUnstaked"in r;return e&&!o&&!t};var W=(r,e)=>Math.ceil(r/e);var Y=new Map,Be=(r,e,t,o)=>(Y.set(r,{signingData:e,displayData:t}),{updateTx:({feeRate:n})=>{let s=Y.get(r);if(!s)throw rpcErrors.resourceNotFound();let{signingData:a}=s;if(typeof n>"u"||n===a.data.feeRate)return s;let{account:i,data:{to:c,amount:p,balance:d}}=a,{inputs:l,outputs:h,fee:g}=createTransferTx(c,i,p,n,d.utxos,o.getNetwork());if(!l||!h)throw rpcErrors.internal("Unable to create transaction");let v={...a,data:{...a.data,fee:g,feeRate:n,gasLimit:W(g,n),inputs:l,outputs:h}},x={...s,signingData:v};return Y.set(r,x),x},cleanup:()=>Y.delete(r)});var Q=async({explorerUrl:r,provider:e,txHash:t,onTransactionPending:o,onTransactionConfirmed:n,onTransactionReverted:s,request:a})=>{try{o({txHash:t,request:a}),await e.waitForTx(t);let i=`${r}/tx/${t}`;n({txHash:t,explorerLink:i,request:a});}catch(i){console.error(i),s({txHash:t,request:a});}};var J=async(r,e)=>"txHash"in e?e.txHash:r.issueRawTx(e.signedData);var Ae=async({request:r,network:e,approvalController:t,proxyApiUrl:o})=>{let{dappInfo:n,params:s}=r,{success:a,data:i,error:c}=Re(s);if(!a)return console.error("invalid params",c),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:c}})};let d=(await j({addresses:[i.from],network:e,proxyApiUrl:o,withScripts:!0}))?.[i.from]?.[e.networkToken.symbol];if(!ke(d))return {error:rpcErrors.internal("Balance for the source account is not available")};let l=await f({isTestnet:!!e.isTestnet,proxyApiUrl:o}),{to:h,from:g,amount:v,feeRate:x}=i,{inputs:y,outputs:T,fee:S}=createTransferTx(h,g,v,x,d.utxos,l.getNetwork());if(!y||!T)return {error:rpcErrors.internal("Unable to create transaction")};let D={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[K("Website",n),O("From",g),O("To",h),U("Amount",BigInt(v),e.networkToken.decimals,e.networkToken.symbol)]}],networkFeeSelector:!0},R={type:RpcMethod.BITCOIN_SEND_TRANSACTION,account:g,data:{to:h,amount:v,fee:S,feeRate:x,gasLimit:W(S,x),inputs:y,outputs:T,balance:d}},{updateTx:b,cleanup:k}=Be(r.requestId,R,D,l),B=await t.requestApproval({request:r,displayData:D,signingData:R,updateTx:b});if(k(),"error"in B)return {error:B.error};let A;try{A=await J(l,B);}catch(V){return {error:rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:V}})}}return Q({explorerUrl:e.explorerUrl??"",provider:l,txHash:A,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:A}};var it=z.object({txHash:z.string(),txHex:z.string().optional(),index:z.number(),value:z.number(),script:z.string().min(1),blockHeight:z.number(),confirmations:z.number(),confirmedTime:z.string().optional()}),ct=z.object({address:z.string(),value:z.number()}),pt=z.object({inputs:z.array(it).min(1),outputs:z.array(ct).min(1)}),we=r=>pt.safeParse(r);var Se=async({request:r,network:e,approvalController:t,proxyApiUrl:o})=>{let{dappInfo:n,params:s}=r,{success:a,data:i,error:c}=we(s);if(!a)return console.error("invalid params",c),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:c}})};let p=await f({isTestnet:!!e.isTestnet,proxyApiUrl:o}),{details:d,error:l}=await dt(i,p);if(l)return {error:rpcErrors.internal({message:"Transaction invalid or cannot be parsed",data:{cause:l}})};let{fee:h,fromAddress:g,outputs:v,transferTotal:x}=d,{decimals:y,symbol:T}=e.networkToken,S={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[K("Website",n),O("From",g),U("Total Transferred Amount",BigInt(x),y,T)]},{title:"Recipients",items:v.map(({address:k,value:B})=>ue(k,BigInt(B),y,T))},{title:"Network Fee",items:[U("Total Fee",BigInt(h),y,T)]}],networkFeeSelector:!1},D={type:RpcMethod.BITCOIN_SIGN_TRANSACTION,account:g,data:{inputs:i.inputs,outputs:i.outputs}},R=await t.requestApproval({request:r,displayData:S,signingData:D});if("error"in R)return {error:R.error};let b;try{b=await J(p,R);}catch(k){return {error:rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:k}})}}return Q({explorerUrl:e.explorerUrl??"",provider:p,txHash:b,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:b}},lt=r=>{let e=Array.from(new Set(r.map(({script:t})=>t)));if(e.length!==1)throw rpcErrors.invalidParams({message:`All input UTXOs must belong to a single address, found ${e.length}`});return e[0]},dt=async(r,e)=>{try{let t=lt(r.inputs),o=await e.getAddressFromScript(t),n=r.outputs.filter(({address:p})=>p!==o),s=r.inputs.reduce((p,{value:d})=>p+d,0),a=r.outputs.reduce((p,{value:d})=>p+d,0),i=n.reduce((p,{value:d})=>p+d,0),c=s-a;return ut(n),{error:null,details:{fromAddress:o,outputs:n,fee:c,transferTotal:i}}}catch(t){return console.error(t),{details:null,error:t instanceof Error?t:new Error(t?.toString()??"Unknown error")}}};function ut(r){if(r.length<1)throw new Error("No actual output is provided, this transaction would only burn funds")}var De=r=>"derivationPathType"in r&&"accountIndex"in r&&typeof r.accountIndex=="number"&&typeof r.derivationPathType=="string";var te=({accountIndex:r,derivationPathType:e})=>{if(r<0)throw rpcErrors.invalidParams("Account index must be a non-negative integer");switch(e){case"bip44":return {[NetworkVMType.BITCOIN]:`m/44'/60'/0'/0/${r}`};case"ledger_live":return {[NetworkVMType.BITCOIN]:`m/44'/60'/${r}'/0/0`};default:throw rpcErrors.invalidParams(`Unsupported derivation path type: ${e}`)}};var Ne=async r=>{let{approvalController:e,network:t,secretId:o}=r,n=De(r)?te(r).BITCOIN:void 0,s=await e.requestPublicKey({curve:"secp256k1",secretId:o,derivationPath:n}),a=Buffer.from(s,"hex");return {[NetworkVMType.BITCOIN]:getBtcAddressFromPubKey(a,t.isTestnet?networks.testnet:networks.bitcoin)}};var P,w,Oe=class{constructor({environment:e,approvalController:t}){C(this,P,void 0);C(this,w,void 0);let{proxyApiUrl:o}=ce(e);E(this,w,t),E(this,P,o);}getProvider(e){return f({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,P)})}getAddress({accountIndex:e,xpub:t,walletType:o,network:n}){return be({accountIndex:e,xpub:t,network:n,walletType:o})}buildDerivationPath(e){return te(e)}deriveAddress(e){return Ne({...e,approvalController:m(this,w)})}getBalances({addresses:e,currency:t,network:o,storage:n}){return j({addresses:e,currency:t,network:o,proxyApiUrl:m(this,P),storage:n})}getManifest(){let e=parseManifest(pe);return e.success?e.data:void 0}getNetworkFee(e){return fe({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,P)})}async getTransactionHistory({address:e,network:t}){return {transactions:await he({address:e,network:t,proxyApiUrl:m(this,P)})}}getTokens(e){return Promise.resolve([])}async onRpcRequest(e,t){switch(e.method){case RpcMethod.BITCOIN_SEND_TRANSACTION:return Ae({request:e,network:t,approvalController:m(this,w),proxyApiUrl:m(this,P)});case RpcMethod.BITCOIN_SIGN_TRANSACTION:return Se({request:e,network:t,approvalController:m(this,w),proxyApiUrl:m(this,P)});default:return {error:rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}}};P=new WeakMap,w=new WeakMap;
9
+ var Ge=Object.defineProperty;var Le=(r,e,t)=>e in r?Ge(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var ae=(r,e,t)=>(Le(r,typeof e!="symbol"?e+"":e,t),t),ie=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var m=(r,e,t)=>(ie(r,e,"read from private field"),t?t.call(r):e.get(r)),_=(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);},E=(r,e,t,n)=>(ie(r,e,"write to private field"),n?n.call(r,t):e.set(r,t),t);var Fe={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},qe={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},pe=r=>{switch(r){case Environment.PRODUCTION:return Fe;case Environment.DEV:return qe}};var me={name:"Bitcoin",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/index.js",packageName:"@avalabs/bitcoin-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["bip122:000000000019d6689c085ae165831e93","bip122:000000000933ea01ad0ee984209779ba"],namespaces:["bip122"]},cointype:"0",permissions:{rpc:{dapps:!0,methods:["bitcoin_sendTransaction","bitcoin_signTransaction"],nonRestrictedMethods:[]}},manifestVersion:"0.1"};var ne=async({operation:r,isSuccess:e,maxRetries:t=10,backoffPolicy:n=N.exponential()})=>{let o=0,s=0,a;for(;s<t;){s>0&&await Me(o);try{let p=await r(s);if(e(p))return p}catch(p){a=p;}o=n(s),s++;}let i=a?`Max retry exceeded. ${a}`:"Max retry exceeded.";throw new Error(i)},N=class{static exponential(){return e=>Math.pow(2,e)*1e3}static constant(e){return t=>e*1e3}static constantMs(e){return t=>e}static linearThenExponential(e,t){return n=>{if(n<e)return (n+1)*t;let o=n-e+1,s=e*t,a=2*t*(Math.pow(2,o)-1);return s+a}}};function Me(r){return new Promise(e=>setTimeout(e,r))}var oe=r=>ne({operation:e=>r(e>0),maxRetries:2,backoffPolicy:N.constant(1),isSuccess:e=>e?.status?.error_code!==429});function le(r){let e,t=0;for(e=0;e<r.length;e++)t+=r.charCodeAt(e)*(e+1);return t}function se(r){let e,t=0;for(e=0;e<r.length;e++){let n=le(r[e]??"");t=t+65027/n;}return (""+t).slice(0,16)}async function B(r,e){let t=await fetch(...r);if(!t.ok)throw new Error(`Request failed with status ${t.status}`);let n=await t.json();return e.parse(n)}var L=class{constructor(e){this.proxyApiUrl=e;}simplePrice(e){let t=new URLSearchParams(e);return B([`${this.proxyApiUrl}/proxy/coingecko/simple/price?${t}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}simplePriceByContractAddresses(e){let{id:t,...n}=e,o=new URLSearchParams(n);return B([`${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${t}?${o}`,{method:"POST",headers:{"Content-Type":"application/json"}}],RawSimplePriceResponseSchema)}};var Ve=z$1.array(z$1.object({internalId:z$1.string(),id:z$1.string(),symbol:z$1.string(),name:z$1.string(),image:z$1.string().optional().nullable(),current_price:z$1.number().optional().nullable(),price_change_percentage_24h:z$1.number().optional().nullable(),market_cap:z$1.number().optional().nullable(),total_volume:z$1.number().optional().nullable(),platforms:z$1.record(z$1.string(),z$1.string())})),V=class{constructor(e){this.proxyApiUrl=e;}watchlistToken(e){let t=new URLSearchParams(e);return B([`${this.proxyApiUrl}/watchlist/tokens?${t}`,{method:"GET",headers:{"Content-Type":"application/json"}}],Ve)}};var de=getBasicCoingeckoHttp(),k,S,F=class{constructor({storage:e,proxyApiUrl:t}){_(this,k,void 0);_(this,S,void 0);ae(this,"transformSimplePriceResponse",(e,t=[VsCurrencyType.USD])=>{let n={};return Object.keys(e).forEach(o=>{let s=e[o];n[o]={},t.forEach(a=>{n[o]={[a]:{price:s?.[a],change24:s?.[`${a}_24h_change`],vol24:s?.[`${a}_24h_vol`],marketCap:s?.[`${a}_market_cap`]}};});}),n});E(this,k,e),E(this,S,t);}async getWatchlistDataForToken({tokenDetails:e,currency:t=VsCurrencyType.USD}){let o=(await new V(m(this,S)).watchlistToken({tokens:e.symbol,currency:t})).filter(s=>e.isNative?s.internalId===`NATIVE-${e.symbol.toLowerCase()}`:s.platforms[e.caip2Id]===e.address)[0];return o?{priceInCurrency:o.current_price??0,change24:o.price_change_percentage_24h??0,marketCap:o.market_cap??0,vol24:o.total_volume??0}:{priceInCurrency:0,change24:0,marketCap:0,vol24:0}}async getSimplePrice({coinIds:e=[],currencies:t=[VsCurrencyType.USD]}){let n,s=`getSimplePrice-${e?`${se(e)}-${t.toString()}`:`${t.toString()}`}`;if(n=m(this,k)?.get?.(s),n)return n;try{n=await oe(a=>this.simplePrice({coinIds:e,currencies:t,marketCap:!0,vol24:!0,change24:!0,useCoingeckoProxy:a}));}catch{n=void 0;}return m(this,k)?.set?.(s,n),n}async getPricesByAddresses(e,t,n=VsCurrencyType.USD){let o,a=`getPricesWithMarketDataByAddresses-${`${se(e)}-${t}-${n}`}`;if(o=m(this,k)?.get?.(a),o)return o;try{o=await oe(i=>this.fetchPricesByAddresses({assetPlatformId:t,tokenAddresses:e,currency:n,useCoingeckoProxy:i}));}catch(i){console.error(i),o=void 0;}return m(this,k)?.set?.(a,o),o}async fetchPricesByAddresses({assetPlatformId:e,tokenAddresses:t,currency:n=VsCurrencyType.USD,useCoingeckoProxy:o=!1}){if(o){let s=await new L(m(this,S)).simplePriceByContractAddresses({id:e,contract_addresses:t,vs_currencies:[n],include_market_cap:!0,include_24hr_vol:!0,include_24hr_change:!0});return this.transformSimplePriceResponse(s,[n])}return simpleTokenPrice(de,{assetPlatformId:e,tokenAddresses:t,currencies:[n],marketCap:!0,vol24:!0,change24:!0})}async simplePrice({coinIds:e=[],currencies:t=[VsCurrencyType.USD],marketCap:n=!1,vol24:o=!1,change24:s=!1,lastUpdated:a=!1,useCoingeckoProxy:i=!1,shouldThrow:p=!0}){if(i){let l=await new L(m(this,S)).simplePrice({ids:e,vs_currencies:t,include_market_cap:n,include_24hr_vol:o,include_24hr_change:s,include_last_updated_at:a});return this.transformSimplePriceResponse(l,t)}return simplePrice(de,{coinIds:e,currencies:t,marketCap:n,vol24:o,change24:s,lastUpdated:a,shouldThrow:p})}};k=new WeakMap,S=new WeakMap;object({date:string(),usd:record(number())});var ye=(r,e,t,n)=>({type:DetailItemType.FUNDS_RECIPIENT,label:r,amount:e,maxDecimals:t,symbol:n}),O=(r,e,t,n)=>({label:r,type:DetailItemType.CURRENCY,value:e,maxDecimals:t,symbol:n});var j=(r,e)=>({label:r,value:e,type:DetailItemType.LINK}),H=(r,e)=>({label:r,type:DetailItemType.ADDRESS,value:e});var fe=process.env.GLACIER_API_KEY;var q=()=>fe;var g=async({isTestnet:r,proxyApiUrl:e})=>{let t=q();return new BitcoinProvider(!r,void 0,`${e}/proxy/nownodes/${r?"btcbook-testnet":"btcbook"}`,`${e}/proxy/nownodes/${r?"btc-testnet":"btc"}`,t?{token:t}:{})};async function ge({isTestnet:r,proxyApiUrl:e}){let t=await g({isTestnet:r,proxyApiUrl:e}),{high:n,low:o,medium:s}=await t.getFeeRates();return {low:{maxFeePerGas:BigInt(o)},medium:{maxFeePerGas:BigInt(s)},high:{maxFeePerGas:BigInt(n)},isFixedFee:!1}}var Te=(r,{address:e,network:t})=>{let{explorerUrl:n,networkToken:o}=t,s=r.addresses[0]??"";return {chainId:t.chainId.toString(),explorerLink:`${n}/tx/${r.hash}`,from:r.isSender?e:s,gasUsed:r.fee.toString(),hash:r.hash,isContractCall:!1,isIncoming:!r.isSender,isOutgoing:r.isSender,isSender:r.isSender,timestamp:r.receivedTime*1e3,to:r.isSender?s:e,tokens:[{amount:(Math.abs(r.amount)/10**o.decimals).toString(),decimal:o.decimals.toString(),name:o.name,symbol:o.symbol,type:TokenType.NATIVE}],txType:r.isSender?TransactionType.SEND:TransactionType.RECEIVE}};var Pe=async({address:r,network:e,proxyApiUrl:t})=>(await(await g({isTestnet:!!e.isTestnet,proxyApiUrl:t})).getTxHistory(r)).map(s=>Te(s,{address:r,network:e}));var K=async({addresses:r,currency:e,network:t,withScripts:n=!1,proxyApiUrl:o,storage:s})=>{let a=await g({isTestnet:!!t.isTestnet,proxyApiUrl:o}),i=new F({proxyApiUrl:o,storage:s}),p=t.pricingProviders?.coingecko.nativeTokenId,c=typeof e=="string"&&typeof p=="string"?await i.getWatchlistDataForToken({tokenDetails:{symbol:t.networkToken.symbol,isNative:!0,caip2Id:t.caipId??""},currency:e}):void 0;return (await Promise.allSettled(r.map(async d=>{let{balance:y,utxos:b,balanceUnconfirmed:T,utxosUnconfirmed:I}=await a.getUtxoBalance(d,n),P=new TokenUnit(y,t.networkToken.decimals,t.networkToken.symbol),w=c?.priceInCurrency!==void 0?P.mul(c.priceInCurrency):void 0,C=P.toDisplay(),v=new TokenUnit(T,t.networkToken.decimals,t.networkToken.symbol),R=c?.priceInCurrency!==void 0?v.mul(c.priceInCurrency):void 0,A=t.networkToken.symbol;return {[d]:{[A]:{...t.networkToken,utxos:b,utxosUnconfirmed:I,coingeckoId:p??"",type:TokenType.NATIVE,balance:P.toSubUnit(),balanceDisplayValue:C,balanceInCurrency:w?.toDisplay({fixedDp:2,asNumber:!0}),balanceCurrencyDisplayValue:w?.toDisplay({fixedDp:2}),priceInCurrency:c?.priceInCurrency,marketCap:c?.marketCap,vol24:c?.vol24,change24:c?.change24,unconfirmedBalance:v.toSubUnit(),unconfirmedBalanceDisplayValue:v.toDisplay(),unconfirmedBalanceInCurrency:R?.toDisplay({fixedDp:2,asNumber:!0}),unconfirmedBalanceCurrencyDisplayValue:R?.toDisplay({fixedDp:2})}}}}))).reduce((d,y)=>y.status==="rejected"?d:{...d,...y.value},{})};var be=async({accountIndex:r,xpub:e,network:t,walletType:n})=>{let o=!!t?.isTestnet;switch(n){case WalletType.Mnemonic:case WalletType.Ledger:case WalletType.Keystone:return {[NetworkVMType.BITCOIN]:getBech32AddressFromXPub(e,r,o?networks.testnet:networks.bitcoin)};case WalletType.LedgerLive:case WalletType.Seedless:{let s=Buffer.from(e,"hex");return {[NetworkVMType.BITCOIN]:getBtcAddressFromPubKey(s,o?networks.testnet:networks.bitcoin)}}default:throw rpcErrors.invalidParams(`Unsupported wallet type: ${n}`)}};var ot=z$1.object({from:z$1.string(),to:z$1.string(),amount:z$1.number(),feeRate:z$1.number()}),Ie=r=>ot.safeParse(r);var Re=r=>{if(!r)return !1;let e="utxos"in r,t="locked"in r,n="unlockedUnstaked"in r;return e&&!n&&!t};var z=(r,e)=>Math.ceil(r/e);var Y=new Map,we=(r,e,t,n)=>(Y.set(r,{signingData:e,displayData:t}),{updateTx:({feeRate:o})=>{let s=Y.get(r);if(!s)throw rpcErrors.resourceNotFound();let{signingData:a}=s;if(typeof o>"u"||o===a.data.feeRate)return s;let{account:i,data:{to:p,amount:l,balance:c}}=a,{inputs:h,outputs:d,fee:y}=createTransferTx(p,i,l,o,c.utxos,n.getNetwork());if(!h||!d)throw rpcErrors.internal("Unable to create transaction");let b={...a,data:{...a.data,fee:y,feeRate:o,gasLimit:z(y,o),inputs:h,outputs:d}},T={...s,signingData:b};return Y.set(r,T),T},cleanup:()=>Y.delete(r)});var Q=async({explorerUrl:r,provider:e,txHash:t,onTransactionPending:n,onTransactionConfirmed:o,onTransactionReverted:s,request:a})=>{try{n({txHash:t,request:a}),await e.waitForTx(t);let i=`${r}/tx/${t}`;o({txHash:t,explorerLink:i,request:a});}catch(i){console.error(i),s({txHash:t,request:a});}};var J=async(r,e)=>"txHash"in e?e.txHash:r.issueRawTx(e.signedData);var Ae=async({request:r,network:e,approvalController:t,proxyApiUrl:n})=>{let{dappInfo:o,params:s}=r,{success:a,data:i,error:p}=Ie(s);if(!a)return console.error("invalid params",p),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:p}})};let c=(await K({addresses:[i.from],network:e,proxyApiUrl:n,withScripts:!0}))?.[i.from]?.[e.networkToken.symbol];if(!Re(c))return {error:rpcErrors.internal("Balance for the source account is not available")};let h=await g({isTestnet:!!e.isTestnet,proxyApiUrl:n}),{to:d,from:y,amount:b,feeRate:T}=i,{inputs:I,outputs:P,fee:w}=createTransferTx(d,y,b,T,c.utxos,h.getNetwork());if(!I||!P)return {error:rpcErrors.internal("Unable to create transaction")};let C={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[j("Website",o),H("From",y),H("To",d),O("Amount",BigInt(b),e.networkToken.decimals,e.networkToken.symbol)]}],networkFeeSelector:!0},v={type:RpcMethod.BITCOIN_SEND_TRANSACTION,account:y,data:{to:d,amount:b,fee:w,feeRate:T,gasLimit:z(w,T),inputs:I,outputs:P,balance:c}},{updateTx:R,cleanup:A}=we(r.requestId,v,C,h),G=await t.requestApproval({request:r,displayData:C,signingData:v,updateTx:R});if(A(),"error"in G)return {error:G.error};let re;try{re=await J(h,G);}catch(He){return {error:rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:He}})}}return Q({explorerUrl:e.explorerUrl??"",provider:h,txHash:re,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:re}};var ct=z$1.object({txHash:z$1.string(),txHex:z$1.string().optional(),index:z$1.number(),value:z$1.number(),script:z$1.string().min(1),blockHeight:z$1.number(),confirmations:z$1.number(),confirmedTime:z$1.string().optional()}),pt=z$1.object({address:z$1.string(),value:z$1.number()}),mt=z$1.object({inputs:z$1.array(ct).min(1),outputs:z$1.array(pt).min(1)}),Be=r=>mt.safeParse(r);var Se=async({request:r,network:e,approvalController:t,proxyApiUrl:n})=>{let{dappInfo:o,params:s}=r,{success:a,data:i,error:p}=Be(s);if(!a)return console.error("invalid params",p),{error:rpcErrors.invalidParams({message:"Transaction params are invalid",data:{cause:p}})};let l=await g({isTestnet:!!e.isTestnet,proxyApiUrl:n}),{details:c,error:h}=await dt(i,l);if(h)return {error:rpcErrors.internal({message:"Transaction invalid or cannot be parsed",data:{cause:h}})};let{fee:d,fromAddress:y,outputs:b,transferTotal:T}=c,{decimals:I,symbol:P}=e.networkToken,w={title:"Do you approve this transaction?",network:{chainId:e.chainId,name:e.chainName,logoUri:e.logoUri},details:[{title:"Transaction Details",items:[j("Website",o),H("From",y),O("Total Transferred Amount",BigInt(T),I,P)]},{title:"Recipients",items:b.map(({address:A,value:G})=>ye(A,BigInt(G),I,P))},{title:"Network Fee",items:[O("Total Fee",BigInt(d),I,P)]}],networkFeeSelector:!1},C={type:RpcMethod.BITCOIN_SIGN_TRANSACTION,account:y,data:{inputs:i.inputs,outputs:i.outputs}},v=await t.requestApproval({request:r,displayData:w,signingData:C});if("error"in v)return {error:v.error};let R;try{R=await J(l,v);}catch(A){return {error:rpcErrors.internal({message:"Unable to get transaction hash",data:{cause:A}})}}return Q({explorerUrl:e.explorerUrl??"",provider:l,txHash:R,onTransactionPending:t.onTransactionPending,onTransactionConfirmed:t.onTransactionConfirmed,onTransactionReverted:t.onTransactionReverted,request:r}),{result:R}},ut=r=>{let e=Array.from(new Set(r.map(({script:t})=>t)));if(e.length!==1)throw rpcErrors.invalidParams({message:`All input UTXOs must belong to a single address, found ${e.length}`});return e[0]},dt=async(r,e)=>{try{let t=ut(r.inputs),n=await e.getAddressFromScript(t),o=r.outputs.filter(({address:l})=>l!==n),s=r.inputs.reduce((l,{value:c})=>l+c,0),a=r.outputs.reduce((l,{value:c})=>l+c,0),i=o.reduce((l,{value:c})=>l+c,0),p=s-a;return yt(o),{error:null,details:{fromAddress:n,outputs:o,fee:p,transferTotal:i}}}catch(t){return console.error(t),{details:null,error:t instanceof Error?t:new Error(t?.toString()??"Unknown error")}}};function yt(r){if(r.length<1)throw new Error("No actual output is provided, this transaction would only burn funds")}var De=r=>"derivationPathType"in r&&"accountIndex"in r&&typeof r.accountIndex=="number"&&typeof r.derivationPathType=="string";var te=({accountIndex:r,derivationPathType:e})=>{if(r<0)throw rpcErrors.invalidParams("Account index must be a non-negative integer");switch(e){case"bip44":return {[NetworkVMType.BITCOIN]:`m/44'/60'/0'/0/${r}`};case"ledger_live":return {[NetworkVMType.BITCOIN]:`m/44'/60'/${r}'/0/0`};default:throw rpcErrors.invalidParams(`Unsupported derivation path type: ${e}`)}};var Ne=async r=>{let{approvalController:e,network:t,secretId:n}=r,o=De(r)?te(r).BITCOIN:void 0,s=await e.requestPublicKey({curve:"secp256k1",secretId:n,derivationPath:o}),a=Buffer.from(s,"hex");return {[NetworkVMType.BITCOIN]:getBtcAddressFromPubKey(a,t.isTestnet?networks.testnet:networks.bitcoin)}};var x,D,Oe=class{constructor({environment:e,approvalController:t}){_(this,x,void 0);_(this,D,void 0);let{proxyApiUrl:n}=pe(e);E(this,D,t),E(this,x,n);}getProvider(e){return g({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}getAddress({accountIndex:e,xpub:t,walletType:n,network:o}){return be({accountIndex:e,xpub:t,network:o,walletType:n})}buildDerivationPath(e){return te(e)}deriveAddress(e){return Ne({...e,approvalController:m(this,D)})}getBalances({addresses:e,currency:t,network:n,storage:o}){return K({addresses:e,currency:t,network:n,proxyApiUrl:m(this,x),storage:o})}getManifest(){let e=parseManifest(me);return e.success?e.data:void 0}getNetworkFee(e){return ge({isTestnet:!!e.isTestnet,proxyApiUrl:m(this,x)})}async getTransactionHistory({address:e,network:t}){return {transactions:await Pe({address:e,network:t,proxyApiUrl:m(this,x)})}}getTokens(e){return Promise.resolve([])}async onRpcRequest(e,t){switch(e.method){case RpcMethod.BITCOIN_SEND_TRANSACTION:return Ae({request:e,network:t,approvalController:m(this,D),proxyApiUrl:m(this,x)});case RpcMethod.BITCOIN_SIGN_TRANSACTION:return Se({request:e,network:t,approvalController:m(this,D),proxyApiUrl:m(this,x)});default:return {error:rpcErrors.methodNotSupported(`Method ${e.method} not supported`)}}}};x=new WeakMap,D=new WeakMap;
10
10
 
11
- export { Oe as BitcoinModule, W as calculateGasLimit };
11
+ export { Oe as BitcoinModule, z as calculateGasLimit };
12
12
  //# sourceMappingURL=out.js.map
13
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module.ts","../src/env.ts","../manifest.json","../src/utils/get-provider.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","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/handlers/get-transaction-history/convert-btc-transaction.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-balances/get-balances.ts","../src/utils/extract-token-market-data.ts","../src/handlers/get-address/get-address.ts","../src/handlers/bitcoin-send-transaction/bitcoin-send-transaction.ts","../src/handlers/bitcoin-send-transaction/schema.ts","../src/utils/is-btc-balance.ts","../src/utils/calculate-gas-limit.ts","../src/utils/bitcoin-tx-updater.ts","../src/utils/wait-for-tx-receipt.ts","../src/utils/get-tx-hash.ts","../src/handlers/bitcoin-sign-transaction/bitcoin-sign-transaction.ts","../src/handlers/bitcoin-sign-transaction/schema.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"],"names":["RpcMethod","parseManifest","rpcErrors","Environment","prodEnv","devEnv","getEnv","environment","manifest_default","BitcoinProvider","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","base","incSum","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","fundsRecipientItem","address","amount","maxDecimals","symbol","currencyItem","label","value","linkItem","addressItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","getProvider","isTestnet","glacierApiKey","getNetworkFee","provider","high","low","medium","TokenType","TransactionType","convertBtcTransaction","tx","network","explorerUrl","networkToken","txAddress","getTransactionHistory","TokenUnit","extractTokenMarketData","coinId","coinData","getBalances","addresses","withScripts","tokenService","coingeckoTokenId","marketData","priceInCurrency","balanceInSatoshis","utxos","unconfirmedBalanceInSatoshis","utxosUnconfirmed","balance","balanceInCurrency","balanceDisplayValue","unconfirmedBalance","unconfirmedBalanceInCurrency","acc","accountBalance","getBech32AddressFromXPub","getBtcAddressFromPubKey","networks","NetworkVMType","WalletType","getAddress","accountIndex","xpub","walletType","pubKeyBuffer","z","paramsSchema","parseRequestParams","isBtcBalance","hasUtxos","hasLocked","hasUnlockedUnstaked","createTransferTx","calculateGasLimit","fee","feeRate","requests","getTxUpdater","requestId","signingData","displayData","request","account","to","inputs","outputs","newData","updatedRequest","waitForTransactionReceipt","txHash","onTransactionPending","onTransactionConfirmed","onTransactionReverted","explorerLink","getTxHash","bitcoinSendTransaction","approvalController","dappInfo","rawParams","success","parseError","btcBalance","from","updateTx","cleanup","error","inputUtxo","outputUtxo","bitcoinSignTransaction","details","detailsError","parseTxDetails","fromAddress","transferTotal","decimals","getScript","scripts","script","inputsTotal","outputsTotal","assertNonEmpty","hasDerivationDetails","buildDerivationPath","derivationPathType","deriveAddress","secretId","derivationPath","publicKeyHex","publicKey","_approvalController","BitcoinModule"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetAddressParams,\n GetAddressResponse,\n ApprovalController,\n ConstructorParams,\n DeriveAddressParams,\n BuildDerivationPathParams,\n} from '@avalabs/vm-module-types';\nimport { RpcMethod, parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getEnv } from './env';\n\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getBalances } from './handlers/get-balances/get-balances';\nimport { getAddress } from './handlers/get-address/get-address';\nimport { bitcoinSendTransaction } from './handlers/bitcoin-send-transaction/bitcoin-send-transaction';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getProvider } from './utils/get-provider';\nimport { bitcoinSignTransaction } from './handlers/bitcoin-sign-transaction/bitcoin-sign-transaction';\nimport { deriveAddress } from './handlers/derive-address/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path/build-derivation-path';\n\nexport class BitcoinModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n\n constructor({ environment, approvalController }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#approvalController = approvalController;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n getProvider(network: Network): Promise<BitcoinProvider> {\n return getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getAddress({ accountIndex, xpub, walletType, network }: GetAddressParams): Promise<GetAddressResponse> {\n return getAddress({ accountIndex, xpub, network, walletType });\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({ addresses, currency, network, storage }: GetBalancesParams) {\n return getBalances({\n addresses,\n currency,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n storage,\n });\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: Network): Promise<NetworkFees> {\n return getNetworkFee({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n async getTransactionHistory({ address, network }: GetTransactionHistory) {\n return {\n transactions: await getTransactionHistory({\n address,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n }),\n };\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.BITCOIN_SEND_TRANSACTION:\n return bitcoinSendTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n case RpcMethod.BITCOIN_SIGN_TRANSACTION:\n return bitcoinSignTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\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","{\n \"name\": \"Bitcoin\",\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/bitcoin-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\"bip122:000000000019d6689c085ae165831e93\", \"bip122:000000000933ea01ad0ee984209779ba\"],\n \"namespaces\": [\"bip122\"]\n },\n \"cointype\": \"0\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"bitcoin_sendTransaction\", \"bitcoin_signTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getGlacierApiKey } from '@internal/utils';\n\ntype ProviderParams = {\n isTestnet: boolean;\n proxyApiUrl: string;\n};\n\nexport const getProvider = async ({ isTestnet, proxyApiUrl }: ProviderParams): Promise<BitcoinProvider> => {\n const glacierApiKey = getGlacierApiKey();\n\n return new BitcoinProvider(\n !isTestnet,\n undefined,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btcbook-testnet' : 'btcbook'}`,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btc-testnet' : 'btc'}`,\n glacierApiKey ? { token: glacierApiKey } : {},\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 /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\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 type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\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 addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\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\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\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","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\n/**\n * Returns {@link NetworkFees} based on `estimatesmartfee` RPC call\n */\nexport async function getNetworkFee({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): Promise<NetworkFees> {\n const provider = await getProvider({\n isTestnet,\n proxyApiUrl,\n });\n\n const { high, low, medium } = await provider.getFeeRates();\n\n return {\n low: {\n maxFeePerGas: BigInt(low),\n },\n medium: {\n maxFeePerGas: BigInt(medium),\n },\n high: {\n maxFeePerGas: BigInt(high),\n },\n isFixedFee: false,\n };\n}\n","import { TokenType, TransactionType, type Network, type Transaction } from '@avalabs/vm-module-types';\nimport type { BitcoinHistoryTx } from '@avalabs/core-wallets-sdk';\n\ntype ConverterOptions = {\n address: string;\n network: Network;\n};\n\nexport const convertBtcTransaction = (tx: BitcoinHistoryTx, { address, network }: ConverterOptions): Transaction => {\n const { explorerUrl, networkToken } = network;\n const txAddress = tx.addresses[0] ?? '';\n\n return {\n chainId: network.chainId.toString(),\n explorerLink: `${explorerUrl}/tx/${tx.hash}`,\n from: tx.isSender ? address : txAddress,\n gasUsed: tx.fee.toString(),\n hash: tx.hash,\n isContractCall: false,\n isIncoming: !tx.isSender,\n isOutgoing: tx.isSender,\n isSender: tx.isSender,\n timestamp: tx.receivedTime * 1000,\n to: tx.isSender ? txAddress : address,\n tokens: [\n {\n amount: (Math.abs(tx.amount) / 10 ** networkToken.decimals).toString(),\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n },\n ],\n txType: tx.isSender ? TransactionType.SEND : TransactionType.RECEIVE,\n };\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\nimport { convertBtcTransaction } from './convert-btc-transaction';\n\ntype GetBtcTransactionHistoryOptions = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport const getTransactionHistory = async ({ address, network, proxyApiUrl }: GetBtcTransactionHistoryOptions) => {\n const provider = await getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n const rawHistory = await provider.getTxHistory(address);\n\n return rawHistory.map((tx) =>\n convertBtcTransaction(tx, {\n address,\n network,\n }),\n );\n};\n","import { type GetBalancesParams, TokenType, type TokenWithBalanceBTC } from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport { TokenService } from '@internal/utils';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { extractTokenMarketData } from '../../utils/extract-token-market-data';\n\ntype GetBtcBalancesResponse = Record<string, Record<string, TokenWithBalanceBTC>>;\n\ntype GetBTCBalancesParams = Omit<GetBalancesParams, 'currency'> & {\n proxyApiUrl: string;\n withScripts?: boolean;\n currency?: string;\n};\n\nexport const getBalances = async ({\n addresses,\n currency,\n network,\n withScripts = false,\n proxyApiUrl,\n storage,\n}: GetBTCBalancesParams): Promise<GetBtcBalancesResponse> => {\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const tokenService = new TokenService({ proxyApiUrl, storage });\n const coingeckoTokenId = network.pricingProviders?.coingecko.nativeTokenId;\n const withPrices = typeof currency === 'string' && typeof coingeckoTokenId === 'string';\n const marketData = withPrices\n ? await tokenService.getSimplePrice({\n coinIds: [coingeckoTokenId],\n currencies: [currency] as VsCurrencyType[],\n })\n : undefined;\n const { priceInCurrency, change24, marketCap, vol24 } = extractTokenMarketData(\n coingeckoTokenId ?? '',\n currency,\n marketData,\n );\n\n const balances = await Promise.allSettled(\n addresses.map(async (address) => {\n const {\n balance: balanceInSatoshis,\n utxos,\n balanceUnconfirmed: unconfirmedBalanceInSatoshis,\n utxosUnconfirmed,\n } = await provider.getUtxoBalance(address, withScripts);\n\n const balance = new TokenUnit(balanceInSatoshis, network.networkToken.decimals, network.networkToken.symbol);\n const balanceInCurrency = priceInCurrency !== undefined ? balance.mul(priceInCurrency) : undefined;\n const balanceDisplayValue = balance.toDisplay();\n\n const unconfirmedBalance = new TokenUnit(\n unconfirmedBalanceInSatoshis,\n network.networkToken.decimals,\n network.networkToken.symbol,\n );\n const unconfirmedBalanceInCurrency =\n priceInCurrency !== undefined ? unconfirmedBalance.mul(priceInCurrency) : undefined;\n\n const symbol = network.networkToken.symbol;\n\n return {\n [address]: {\n [symbol]: {\n ...network.networkToken,\n utxos,\n utxosUnconfirmed,\n coingeckoId: coingeckoTokenId ?? '',\n type: TokenType.NATIVE,\n balance: balance.toSubUnit(),\n balanceDisplayValue,\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n priceInCurrency,\n marketCap,\n vol24,\n change24,\n unconfirmedBalance: unconfirmedBalance.toSubUnit(),\n unconfirmedBalanceDisplayValue: unconfirmedBalance.toDisplay(),\n unconfirmedBalanceInCurrency: unconfirmedBalanceInCurrency?.toDisplay({\n fixedDp: 2,\n asNumber: true,\n }),\n unconfirmedBalanceCurrencyDisplayValue: unconfirmedBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n },\n },\n };\n }),\n );\n\n return balances.reduce((acc, accountBalance) => {\n if (accountBalance.status === 'rejected') {\n return acc;\n }\n\n return {\n ...acc,\n ...accountBalance.value,\n };\n }, {});\n};\n","import type { SimplePriceResponse, TokenMarketData } from '@avalabs/vm-module-types';\n\nexport const extractTokenMarketData = (\n coinId: string,\n currency?: string,\n data?: SimplePriceResponse,\n): TokenMarketData => {\n const coinData = data?.[coinId]?.[currency ?? ''] ?? {};\n\n return {\n priceInCurrency: coinData.price ?? undefined,\n marketCap: coinData.marketCap ?? undefined,\n vol24: coinData.vol24 ?? undefined,\n change24: coinData.change24 ?? undefined,\n };\n};\n","import type { GetAddressParams, GetAddressResponse } from '@avalabs/vm-module-types';\nimport { getBech32AddressFromXPub, getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\nimport { NetworkVMType, WalletType } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\ntype GetAddress = Omit<GetAddressParams, 'xpubXP'>;\n\nexport const getAddress = async ({\n accountIndex,\n xpub,\n network,\n walletType,\n}: GetAddress): Promise<GetAddressResponse> => {\n const isTestnet = Boolean(network?.isTestnet);\n switch (walletType) {\n case WalletType.Mnemonic:\n case WalletType.Ledger:\n case WalletType.Keystone: {\n return {\n [NetworkVMType.BITCOIN]: getBech32AddressFromXPub(\n xpub,\n accountIndex,\n isTestnet ? networks.testnet : networks.bitcoin,\n ),\n };\n }\n case WalletType.LedgerLive:\n case WalletType.Seedless: {\n const pubKeyBuffer = Buffer.from(xpub, 'hex');\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(pubKeyBuffer, isTestnet ? networks.testnet : networks.bitcoin),\n };\n }\n default:\n throw rpcErrors.invalidParams(`Unsupported wallet type: ${walletType}`);\n }\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { parseRequestParams } from './schema';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getProvider } from '../../utils/get-provider';\nimport { getBalances } from '../get-balances/get-balances';\nimport { isBtcBalance } from '../../utils/is-btc-balance';\nimport { createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport { calculateGasLimit } from '../../utils/calculate-gas-limit';\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { linkItem } from '@internal/utils/src/utils/detail-item';\nimport { getTxUpdater } from '../../utils/bitcoin-tx-updater';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\n\ntype BitcoinSendTransactionParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSendTransactionParams) => {\n const { dappInfo, params: rawParams } = request;\n\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const balances = await getBalances({ addresses: [params.from], network, proxyApiUrl, withScripts: true });\n const btcBalance = balances?.[params.from]?.[network.networkToken.symbol];\n\n if (!isBtcBalance(btcBalance)) {\n return {\n error: rpcErrors.internal('Balance for the source account is not available'),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { to, from, amount, feeRate } = params;\n\n const { inputs, outputs, fee } = createTransferTx(\n to,\n from,\n amount,\n feeRate,\n btcBalance.utxos as BitcoinInputUTXO[], // we asked for scripts in getBalances() call\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n return {\n error: rpcErrors.internal('Unable to create transaction'),\n };\n }\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', from),\n addressItem('To', to),\n currencyItem('Amount', BigInt(amount), network.networkToken.decimals, network.networkToken.symbol),\n ],\n },\n ],\n networkFeeSelector: true,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SEND_TRANSACTION,\n account: from,\n data: {\n to,\n amount,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n balance: btcBalance,\n },\n };\n\n const { updateTx, cleanup } = getTxUpdater(request.requestId, signingData, displayData, provider);\n const response = await approvalController.requestApproval({ request, displayData, signingData, updateTx });\n\n cleanup();\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n","import { z } from 'zod';\n\nconst paramsSchema = z.object({\n from: z.string(),\n to: z.string(),\n amount: z.number(),\n feeRate: z.number(),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSendTransactionParams = z.infer<typeof paramsSchema>;\n","import type { TokenWithBalance, TokenWithBalanceBTC } from '@avalabs/vm-module-types';\n\nexport const isBtcBalance = (balance?: TokenWithBalance): balance is TokenWithBalanceBTC => {\n if (!balance) {\n return false;\n }\n\n const hasUtxos = 'utxos' in balance; // BTC, P-Chain or X-Chain\n const hasLocked = 'locked' in balance; // X-Chain only\n const hasUnlockedUnstaked = 'unlockedUnstaked' in balance; // P-Chain only\n\n return hasUtxos && !hasUnlockedUnstaked && !hasLocked;\n};\n","// The transaction's byte size is for BTC as gasLimit is for EVM.\n// Bitcoin's formula for fee is `transactionByteLength * feeRate`.\n// Since we know the `fee` and the `feeRate`, we can get the transaction's\n// byte length by division.\n//\n// Note: We use `Math.ceil` here to ensure the gasLimit is sufficient and\n// to avoid any decimal values. Rounding up helps prevent underestimating the\n// required gas, as gasLimit must be an integer. While this may slightly increase\n// the fee, it minimizes the risk of transaction failure due to insufficient gasLimit.\n\nexport const calculateGasLimit = (fee: number, feeRate: number): number => {\n return Math.ceil(fee / feeRate);\n};\n","import { BitcoinProvider, createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport type { BtcTxUpdateFn, DisplayData, RpcMethod, SigningData } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { calculateGasLimit } from './calculate-gas-limit';\n\ntype SigningData_BtcSendTx = Extract<SigningData, { type: RpcMethod.BITCOIN_SEND_TRANSACTION }>;\n\nconst requests = new Map<string, { signingData: SigningData_BtcSendTx; displayData: DisplayData }>();\n\nexport const getTxUpdater = (\n requestId: string,\n signingData: SigningData_BtcSendTx,\n displayData: DisplayData,\n provider: BitcoinProvider,\n): { updateTx: BtcTxUpdateFn; cleanup: () => void } => {\n requests.set(requestId, { signingData, displayData });\n\n return {\n updateTx: ({ feeRate }) => {\n const request = requests.get(requestId);\n\n if (!request) {\n throw rpcErrors.resourceNotFound();\n }\n\n const { signingData } = request;\n\n if (typeof feeRate === 'undefined' || feeRate === signingData.data.feeRate) {\n return request;\n }\n\n const {\n account,\n data: { to, amount, balance },\n } = signingData;\n const { inputs, outputs, fee } = createTransferTx(\n to,\n account,\n amount,\n feeRate,\n balance.utxos as BitcoinInputUTXO[],\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n throw rpcErrors.internal('Unable to create transaction');\n }\n\n const newData = {\n ...signingData,\n data: {\n ...signingData.data,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n },\n };\n\n const updatedRequest = { ...request, signingData: newData };\n requests.set(requestId, updatedRequest);\n\n return updatedRequest;\n },\n cleanup: () => requests.delete(requestId),\n };\n};\n","import type { Hex, RpcRequest } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const waitForTransactionReceipt = async ({\n explorerUrl,\n provider,\n txHash,\n onTransactionPending,\n onTransactionConfirmed,\n onTransactionReverted,\n request,\n}: {\n explorerUrl: string;\n provider: BitcoinProvider;\n txHash: Hex;\n onTransactionPending: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n onTransactionConfirmed: ({\n txHash,\n explorerLink,\n request,\n }: {\n txHash: Hex;\n explorerLink: string;\n request: RpcRequest;\n }) => void;\n onTransactionReverted: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n request: RpcRequest;\n}) => {\n try {\n onTransactionPending({ txHash, request });\n await provider.waitForTx(txHash);\n const explorerLink = `${explorerUrl}/tx/${txHash}`;\n onTransactionConfirmed({ txHash, explorerLink, request });\n } catch (err) {\n console.error(err);\n onTransactionReverted({ txHash, request });\n }\n};\n","import type { SigningResult } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const getTxHash = async (provider: BitcoinProvider, response: SigningResult) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n return provider.issueRawTx(response.signedData);\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { BitcoinProvider, BitcoinInputUTXO, BitcoinOutputUTXO } from '@avalabs/core-wallets-sdk';\n\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { fundsRecipientItem, linkItem } from '@internal/utils/src/utils/detail-item';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\nimport { parseRequestParams, type BitcoinSignTransactionParams } from './schema';\n\ntype BitcoinSignTransactionRequestParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSignTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSignTransactionRequestParams) => {\n const { dappInfo, params: rawParams } = request;\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, error: detailsError } = await parseTxDetails(params, provider);\n if (detailsError) {\n return {\n error: rpcErrors.internal({ message: 'Transaction invalid or cannot be parsed', data: { cause: detailsError } }),\n };\n }\n\n const { fee, fromAddress, outputs, transferTotal } = details;\n const { decimals, symbol } = network.networkToken;\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', fromAddress),\n currencyItem('Total Transferred Amount', BigInt(transferTotal), decimals, symbol),\n ],\n },\n {\n title: 'Recipients',\n items: outputs.map(({ address, value }) => fundsRecipientItem(address, BigInt(value), decimals, symbol)),\n },\n { title: 'Network Fee', items: [currencyItem('Total Fee', BigInt(fee), decimals, symbol)] },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SIGN_TRANSACTION,\n account: fromAddress,\n data: {\n inputs: params.inputs,\n outputs: params.outputs,\n },\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n\nconst getScript = (inputs: BitcoinInputUTXO[]): string => {\n const scripts = Array.from(new Set(inputs.map(({ script }) => script)));\n\n if (scripts.length !== 1) {\n throw rpcErrors.invalidParams({\n message: `All input UTXOs must belong to a single address, found ${scripts.length}`,\n });\n }\n\n return scripts[0]!;\n};\n\nconst parseTxDetails = async (\n params: BitcoinSignTransactionParams,\n provider: BitcoinProvider,\n): Promise<\n | {\n details: {\n fromAddress: string;\n outputs: [BitcoinOutputUTXO, ...BitcoinOutputUTXO[]];\n fee: number;\n transferTotal: number;\n };\n error: null;\n }\n | { details: null; error: Error }\n> => {\n try {\n const script = getScript(params.inputs);\n const fromAddress = await provider.getAddressFromScript(script);\n const outputs = params.outputs.filter(({ address }) => address !== fromAddress);\n const inputsTotal = params.inputs.reduce((sum, { value }) => sum + value, 0);\n const outputsTotal = params.outputs.reduce((sum, { value }) => sum + value, 0); // with the change address\n const transferTotal = outputs.reduce((sum, { value }) => sum + value, 0); // without the change address\n const fee = inputsTotal - outputsTotal;\n\n assertNonEmpty(outputs);\n\n return {\n error: null,\n details: {\n fromAddress,\n outputs,\n fee,\n transferTotal,\n },\n };\n } catch (error) {\n console.error(error);\n return {\n details: null,\n error: error instanceof Error ? error : new Error(error?.toString() ?? 'Unknown error'),\n };\n }\n};\n\nfunction assertNonEmpty<T>(array: T[]): asserts array is [T, ...T[]] {\n if (array.length < 1) {\n throw new Error('No actual output is provided, this transaction would only burn funds');\n }\n}\n","import { z } from 'zod';\n\nconst inputUtxo = z.object({\n txHash: z.string(),\n txHex: z.string().optional(),\n index: z.number(),\n value: z.number(),\n script: z.string().min(1), // Just make sure it's never an empty string\n blockHeight: z.number(),\n confirmations: z.number(),\n confirmedTime: z.string().optional(),\n});\n\nconst outputUtxo = z.object({\n address: z.string(),\n value: z.number(),\n});\n\nconst paramsSchema = z.object({\n inputs: z.array(inputUtxo).min(1),\n outputs: z.array(outputUtxo).min(1),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSignTransactionParams = z.infer<typeof paramsSchema>;\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\n\nimport { getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\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, network, 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).BITCOIN : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'secp256k1',\n secretId,\n derivationPath,\n });\n const publicKey = Buffer.from(publicKeyHex, 'hex');\n\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(\n publicKey,\n network.isTestnet ? networks.testnet : networks.bitcoin,\n ),\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 { rpcErrors } from '@metamask/rpc-errors';\nimport {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\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 derivationPathType,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.BITCOIN> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n switch (derivationPathType) {\n case 'bip44':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/0'/0/${accountIndex}`,\n };\n\n case 'ledger_live':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/${accountIndex}'/0/0`,\n };\n\n default:\n throw rpcErrors.invalidParams(`Unsupported derivation path type: ${derivationPathType}`);\n }\n};\n"]}
1
+ {"version":3,"sources":["../src/module.ts","../src/env.ts","../manifest.json","../src/utils/get-provider.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/token-service/watchlist-proxy-client.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","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/handlers/get-transaction-history/convert-btc-transaction.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-balances/get-balances.ts","../src/handlers/get-address/get-address.ts","../src/handlers/bitcoin-send-transaction/bitcoin-send-transaction.ts","../src/handlers/bitcoin-send-transaction/schema.ts","../src/utils/is-btc-balance.ts","../src/utils/calculate-gas-limit.ts","../src/utils/bitcoin-tx-updater.ts","../src/utils/wait-for-tx-receipt.ts","../src/utils/get-tx-hash.ts","../src/handlers/bitcoin-sign-transaction/bitcoin-sign-transaction.ts","../src/handlers/bitcoin-sign-transaction/schema.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"],"names":["RpcMethod","parseManifest","rpcErrors","Environment","prodEnv","devEnv","getEnv","environment","manifest_default","BitcoinProvider","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","n","base","incSum","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","z","WatchlistTokenResponseSchema","WatchlistProxyClient","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","tokenDetails","tokenInfo","__privateGet","token","coinIds","cacheId","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","fundsRecipientItem","address","amount","maxDecimals","symbol","currencyItem","label","value","linkItem","addressItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","getProvider","isTestnet","glacierApiKey","getNetworkFee","provider","high","low","medium","TokenType","TransactionType","convertBtcTransaction","tx","network","explorerUrl","networkToken","txAddress","getTransactionHistory","TokenUnit","getBalances","addresses","withScripts","tokenService","coingeckoTokenId","marketData","balanceInSatoshis","utxos","unconfirmedBalanceInSatoshis","utxosUnconfirmed","balance","balanceInCurrency","balanceDisplayValue","unconfirmedBalance","unconfirmedBalanceInCurrency","acc","accountBalance","getBech32AddressFromXPub","getBtcAddressFromPubKey","networks","NetworkVMType","WalletType","getAddress","accountIndex","xpub","walletType","pubKeyBuffer","paramsSchema","parseRequestParams","isBtcBalance","hasUtxos","hasLocked","hasUnlockedUnstaked","createTransferTx","calculateGasLimit","fee","feeRate","requests","getTxUpdater","requestId","signingData","displayData","request","account","to","inputs","outputs","newData","updatedRequest","waitForTransactionReceipt","txHash","onTransactionPending","onTransactionConfirmed","onTransactionReverted","explorerLink","getTxHash","bitcoinSendTransaction","approvalController","dappInfo","rawParams","success","parseError","btcBalance","from","updateTx","cleanup","error","inputUtxo","outputUtxo","bitcoinSignTransaction","details","detailsError","parseTxDetails","fromAddress","transferTotal","decimals","getScript","scripts","script","inputsTotal","outputsTotal","assertNonEmpty","hasDerivationDetails","buildDerivationPath","derivationPathType","deriveAddress","secretId","derivationPath","publicKeyHex","publicKey","_approvalController","BitcoinModule"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetAddressParams,\n GetAddressResponse,\n ApprovalController,\n ConstructorParams,\n DeriveAddressParams,\n BuildDerivationPathParams,\n} from '@avalabs/vm-module-types';\nimport { RpcMethod, parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getEnv } from './env';\n\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getBalances } from './handlers/get-balances/get-balances';\nimport { getAddress } from './handlers/get-address/get-address';\nimport { bitcoinSendTransaction } from './handlers/bitcoin-send-transaction/bitcoin-send-transaction';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getProvider } from './utils/get-provider';\nimport { bitcoinSignTransaction } from './handlers/bitcoin-sign-transaction/bitcoin-sign-transaction';\nimport { deriveAddress } from './handlers/derive-address/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path/build-derivation-path';\n\nexport class BitcoinModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n\n constructor({ environment, approvalController }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#approvalController = approvalController;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n getProvider(network: Network): Promise<BitcoinProvider> {\n return getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getAddress({ accountIndex, xpub, walletType, network }: GetAddressParams): Promise<GetAddressResponse> {\n return getAddress({ accountIndex, xpub, network, walletType });\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({ addresses, currency, network, storage }: GetBalancesParams) {\n return getBalances({\n addresses,\n currency,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n storage,\n });\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: Network): Promise<NetworkFees> {\n return getNetworkFee({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n async getTransactionHistory({ address, network }: GetTransactionHistory) {\n return {\n transactions: await getTransactionHistory({\n address,\n network,\n proxyApiUrl: this.#proxyApiUrl,\n }),\n };\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.BITCOIN_SEND_TRANSACTION:\n return bitcoinSendTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n case RpcMethod.BITCOIN_SIGN_TRANSACTION:\n return bitcoinSignTransaction({\n request,\n network,\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n });\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\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","{\n \"name\": \"Bitcoin\",\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/bitcoin-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\"bip122:000000000019d6689c085ae165831e93\", \"bip122:000000000933ea01ad0ee984209779ba\"],\n \"namespaces\": [\"bip122\"]\n },\n \"cointype\": \"0\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"bitcoin_sendTransaction\", \"bitcoin_signTransaction\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { BitcoinProvider } from '@avalabs/core-wallets-sdk';\nimport { getGlacierApiKey } from '@internal/utils';\n\ntype ProviderParams = {\n isTestnet: boolean;\n proxyApiUrl: string;\n};\n\nexport const getProvider = async ({ isTestnet, proxyApiUrl }: ProviderParams): Promise<BitcoinProvider> => {\n const glacierApiKey = getGlacierApiKey();\n\n return new BitcoinProvider(\n !isTestnet,\n undefined,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btcbook-testnet' : 'btcbook'}`,\n `${proxyApiUrl}/proxy/nownodes/${isTestnet ? 'btc-testnet' : 'btc'}`,\n glacierApiKey ? { token: glacierApiKey } : {},\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';\nimport { WatchlistProxyClient } from './watchlist-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 async getWatchlistDataForToken({\n tokenDetails,\n currency = VsCurrencyType.USD,\n }: {\n tokenDetails: {\n symbol: string;\n isNative: boolean;\n caip2Id: string;\n address?: string;\n };\n currency: VsCurrencyType;\n }): Promise<{\n priceInCurrency: number;\n change24: number;\n marketCap: number;\n vol24: number;\n }> {\n const data = (\n await new WatchlistProxyClient(this.#proxyApiUrl).watchlistToken({\n tokens: tokenDetails.symbol,\n currency: currency,\n })\n ).filter((token) => {\n return tokenDetails.isNative\n ? token.internalId === `NATIVE-${tokenDetails.symbol.toLowerCase()}`\n : token.platforms[tokenDetails.caip2Id] === tokenDetails.address;\n });\n\n const tokenInfo = data[0];\n\n if (!tokenInfo) {\n return {\n priceInCurrency: 0,\n change24: 0,\n marketCap: 0,\n vol24: 0,\n };\n }\n\n return {\n priceInCurrency: tokenInfo.current_price ?? 0,\n change24: tokenInfo.price_change_percentage_24h ?? 0,\n marketCap: tokenInfo.market_cap ?? 0,\n vol24: tokenInfo.total_volume ?? 0,\n };\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 /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\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 { fetchAndVerify } from '../../utils/fetch-and-verify';\nimport { z } from 'zod';\n\nconst WatchlistTokenResponseSchema = z.array(\n z.object({\n // the object has more properties than the ones listed here, but we only need these at the moment\n internalId: z.string(),\n id: z.string(),\n symbol: z.string(),\n name: z.string(),\n image: z.string().optional().nullable(),\n current_price: z.number().optional().nullable(),\n price_change_percentage_24h: z.number().optional().nullable(),\n market_cap: z.number().optional().nullable(),\n total_volume: z.number().optional().nullable(),\n platforms: z.record(z.string(), z.string()),\n }),\n);\n\nexport class WatchlistProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n watchlistToken(params: { tokens: string; currency: string }) {\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}/watchlist/tokens?${queryParams}`,\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n WatchlistTokenResponseSchema,\n );\n }\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 type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\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 addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\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\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\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","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\n/**\n * Returns {@link NetworkFees} based on `estimatesmartfee` RPC call\n */\nexport async function getNetworkFee({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): Promise<NetworkFees> {\n const provider = await getProvider({\n isTestnet,\n proxyApiUrl,\n });\n\n const { high, low, medium } = await provider.getFeeRates();\n\n return {\n low: {\n maxFeePerGas: BigInt(low),\n },\n medium: {\n maxFeePerGas: BigInt(medium),\n },\n high: {\n maxFeePerGas: BigInt(high),\n },\n isFixedFee: false,\n };\n}\n","import { TokenType, TransactionType, type Network, type Transaction } from '@avalabs/vm-module-types';\nimport type { BitcoinHistoryTx } from '@avalabs/core-wallets-sdk';\n\ntype ConverterOptions = {\n address: string;\n network: Network;\n};\n\nexport const convertBtcTransaction = (tx: BitcoinHistoryTx, { address, network }: ConverterOptions): Transaction => {\n const { explorerUrl, networkToken } = network;\n const txAddress = tx.addresses[0] ?? '';\n\n return {\n chainId: network.chainId.toString(),\n explorerLink: `${explorerUrl}/tx/${tx.hash}`,\n from: tx.isSender ? address : txAddress,\n gasUsed: tx.fee.toString(),\n hash: tx.hash,\n isContractCall: false,\n isIncoming: !tx.isSender,\n isOutgoing: tx.isSender,\n isSender: tx.isSender,\n timestamp: tx.receivedTime * 1000,\n to: tx.isSender ? txAddress : address,\n tokens: [\n {\n amount: (Math.abs(tx.amount) / 10 ** networkToken.decimals).toString(),\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n },\n ],\n txType: tx.isSender ? TransactionType.SEND : TransactionType.RECEIVE,\n };\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '../../utils/get-provider';\n\nimport { convertBtcTransaction } from './convert-btc-transaction';\n\ntype GetBtcTransactionHistoryOptions = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport const getTransactionHistory = async ({ address, network, proxyApiUrl }: GetBtcTransactionHistoryOptions) => {\n const provider = await getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n const rawHistory = await provider.getTxHistory(address);\n\n return rawHistory.map((tx) =>\n convertBtcTransaction(tx, {\n address,\n network,\n }),\n );\n};\n","import { type GetBalancesParams, TokenType, type TokenWithBalanceBTC } from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport { TokenService } from '@internal/utils';\n\nimport { getProvider } from '../../utils/get-provider';\n\ntype GetBtcBalancesResponse = Record<string, Record<string, TokenWithBalanceBTC>>;\n\ntype GetBTCBalancesParams = Omit<GetBalancesParams, 'currency'> & {\n proxyApiUrl: string;\n withScripts?: boolean;\n currency?: string;\n};\n\nexport const getBalances = async ({\n addresses,\n currency,\n network,\n withScripts = false,\n proxyApiUrl,\n storage,\n}: GetBTCBalancesParams): Promise<GetBtcBalancesResponse> => {\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const tokenService = new TokenService({ proxyApiUrl, storage });\n const coingeckoTokenId = network.pricingProviders?.coingecko.nativeTokenId;\n const withPrices = typeof currency === 'string' && typeof coingeckoTokenId === 'string';\n const marketData = withPrices\n ? await tokenService.getWatchlistDataForToken({\n tokenDetails: {\n symbol: network.networkToken.symbol,\n isNative: true,\n caip2Id: network.caipId ?? '',\n },\n currency: currency as VsCurrencyType,\n })\n : undefined;\n\n const balances = await Promise.allSettled(\n addresses.map(async (address) => {\n const {\n balance: balanceInSatoshis,\n utxos,\n balanceUnconfirmed: unconfirmedBalanceInSatoshis,\n utxosUnconfirmed,\n } = await provider.getUtxoBalance(address, withScripts);\n\n const balance = new TokenUnit(balanceInSatoshis, network.networkToken.decimals, network.networkToken.symbol);\n const balanceInCurrency =\n marketData?.priceInCurrency !== undefined ? balance.mul(marketData.priceInCurrency) : undefined;\n const balanceDisplayValue = balance.toDisplay();\n\n const unconfirmedBalance = new TokenUnit(\n unconfirmedBalanceInSatoshis,\n network.networkToken.decimals,\n network.networkToken.symbol,\n );\n const unconfirmedBalanceInCurrency =\n marketData?.priceInCurrency !== undefined ? unconfirmedBalance.mul(marketData.priceInCurrency) : undefined;\n\n const symbol = network.networkToken.symbol;\n\n return {\n [address]: {\n [symbol]: {\n ...network.networkToken,\n utxos,\n utxosUnconfirmed,\n coingeckoId: coingeckoTokenId ?? '',\n type: TokenType.NATIVE,\n balance: balance.toSubUnit(),\n balanceDisplayValue,\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n priceInCurrency: marketData?.priceInCurrency,\n marketCap: marketData?.marketCap,\n vol24: marketData?.vol24,\n change24: marketData?.change24,\n unconfirmedBalance: unconfirmedBalance.toSubUnit(),\n unconfirmedBalanceDisplayValue: unconfirmedBalance.toDisplay(),\n unconfirmedBalanceInCurrency: unconfirmedBalanceInCurrency?.toDisplay({\n fixedDp: 2,\n asNumber: true,\n }),\n unconfirmedBalanceCurrencyDisplayValue: unconfirmedBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n },\n },\n };\n }),\n );\n\n return balances.reduce((acc, accountBalance) => {\n if (accountBalance.status === 'rejected') {\n return acc;\n }\n\n return {\n ...acc,\n ...accountBalance.value,\n };\n }, {});\n};\n","import type { GetAddressParams, GetAddressResponse } from '@avalabs/vm-module-types';\nimport { getBech32AddressFromXPub, getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\nimport { NetworkVMType, WalletType } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\ntype GetAddress = Omit<GetAddressParams, 'xpubXP'>;\n\nexport const getAddress = async ({\n accountIndex,\n xpub,\n network,\n walletType,\n}: GetAddress): Promise<GetAddressResponse> => {\n const isTestnet = Boolean(network?.isTestnet);\n switch (walletType) {\n case WalletType.Mnemonic:\n case WalletType.Ledger:\n case WalletType.Keystone: {\n return {\n [NetworkVMType.BITCOIN]: getBech32AddressFromXPub(\n xpub,\n accountIndex,\n isTestnet ? networks.testnet : networks.bitcoin,\n ),\n };\n }\n case WalletType.LedgerLive:\n case WalletType.Seedless: {\n const pubKeyBuffer = Buffer.from(xpub, 'hex');\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(pubKeyBuffer, isTestnet ? networks.testnet : networks.bitcoin),\n };\n }\n default:\n throw rpcErrors.invalidParams(`Unsupported wallet type: ${walletType}`);\n }\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { parseRequestParams } from './schema';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { getProvider } from '../../utils/get-provider';\nimport { getBalances } from '../get-balances/get-balances';\nimport { isBtcBalance } from '../../utils/is-btc-balance';\nimport { createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport { calculateGasLimit } from '../../utils/calculate-gas-limit';\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { linkItem } from '@internal/utils/src/utils/detail-item';\nimport { getTxUpdater } from '../../utils/bitcoin-tx-updater';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\n\ntype BitcoinSendTransactionParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSendTransactionParams) => {\n const { dappInfo, params: rawParams } = request;\n\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const balances = await getBalances({ addresses: [params.from], network, proxyApiUrl, withScripts: true });\n const btcBalance = balances?.[params.from]?.[network.networkToken.symbol];\n\n if (!isBtcBalance(btcBalance)) {\n return {\n error: rpcErrors.internal('Balance for the source account is not available'),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { to, from, amount, feeRate } = params;\n\n const { inputs, outputs, fee } = createTransferTx(\n to,\n from,\n amount,\n feeRate,\n btcBalance.utxos as BitcoinInputUTXO[], // we asked for scripts in getBalances() call\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n return {\n error: rpcErrors.internal('Unable to create transaction'),\n };\n }\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', from),\n addressItem('To', to),\n currencyItem('Amount', BigInt(amount), network.networkToken.decimals, network.networkToken.symbol),\n ],\n },\n ],\n networkFeeSelector: true,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SEND_TRANSACTION,\n account: from,\n data: {\n to,\n amount,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n balance: btcBalance,\n },\n };\n\n const { updateTx, cleanup } = getTxUpdater(request.requestId, signingData, displayData, provider);\n const response = await approvalController.requestApproval({ request, displayData, signingData, updateTx });\n\n cleanup();\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n","import { z } from 'zod';\n\nconst paramsSchema = z.object({\n from: z.string(),\n to: z.string(),\n amount: z.number(),\n feeRate: z.number(),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSendTransactionParams = z.infer<typeof paramsSchema>;\n","import type { TokenWithBalance, TokenWithBalanceBTC } from '@avalabs/vm-module-types';\n\nexport const isBtcBalance = (balance?: TokenWithBalance): balance is TokenWithBalanceBTC => {\n if (!balance) {\n return false;\n }\n\n const hasUtxos = 'utxos' in balance; // BTC, P-Chain or X-Chain\n const hasLocked = 'locked' in balance; // X-Chain only\n const hasUnlockedUnstaked = 'unlockedUnstaked' in balance; // P-Chain only\n\n return hasUtxos && !hasUnlockedUnstaked && !hasLocked;\n};\n","// The transaction's byte size is for BTC as gasLimit is for EVM.\n// Bitcoin's formula for fee is `transactionByteLength * feeRate`.\n// Since we know the `fee` and the `feeRate`, we can get the transaction's\n// byte length by division.\n//\n// Note: We use `Math.ceil` here to ensure the gasLimit is sufficient and\n// to avoid any decimal values. Rounding up helps prevent underestimating the\n// required gas, as gasLimit must be an integer. While this may slightly increase\n// the fee, it minimizes the risk of transaction failure due to insufficient gasLimit.\n\nexport const calculateGasLimit = (fee: number, feeRate: number): number => {\n return Math.ceil(fee / feeRate);\n};\n","import { BitcoinProvider, createTransferTx, type BitcoinInputUTXO } from '@avalabs/core-wallets-sdk';\nimport type { BtcTxUpdateFn, DisplayData, RpcMethod, SigningData } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { calculateGasLimit } from './calculate-gas-limit';\n\ntype SigningData_BtcSendTx = Extract<SigningData, { type: RpcMethod.BITCOIN_SEND_TRANSACTION }>;\n\nconst requests = new Map<string, { signingData: SigningData_BtcSendTx; displayData: DisplayData }>();\n\nexport const getTxUpdater = (\n requestId: string,\n signingData: SigningData_BtcSendTx,\n displayData: DisplayData,\n provider: BitcoinProvider,\n): { updateTx: BtcTxUpdateFn; cleanup: () => void } => {\n requests.set(requestId, { signingData, displayData });\n\n return {\n updateTx: ({ feeRate }) => {\n const request = requests.get(requestId);\n\n if (!request) {\n throw rpcErrors.resourceNotFound();\n }\n\n const { signingData } = request;\n\n if (typeof feeRate === 'undefined' || feeRate === signingData.data.feeRate) {\n return request;\n }\n\n const {\n account,\n data: { to, amount, balance },\n } = signingData;\n const { inputs, outputs, fee } = createTransferTx(\n to,\n account,\n amount,\n feeRate,\n balance.utxos as BitcoinInputUTXO[],\n provider.getNetwork(),\n );\n\n if (!inputs || !outputs) {\n throw rpcErrors.internal('Unable to create transaction');\n }\n\n const newData = {\n ...signingData,\n data: {\n ...signingData.data,\n fee,\n feeRate,\n gasLimit: calculateGasLimit(fee, feeRate),\n inputs,\n outputs,\n },\n };\n\n const updatedRequest = { ...request, signingData: newData };\n requests.set(requestId, updatedRequest);\n\n return updatedRequest;\n },\n cleanup: () => requests.delete(requestId),\n };\n};\n","import type { Hex, RpcRequest } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const waitForTransactionReceipt = async ({\n explorerUrl,\n provider,\n txHash,\n onTransactionPending,\n onTransactionConfirmed,\n onTransactionReverted,\n request,\n}: {\n explorerUrl: string;\n provider: BitcoinProvider;\n txHash: Hex;\n onTransactionPending: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n onTransactionConfirmed: ({\n txHash,\n explorerLink,\n request,\n }: {\n txHash: Hex;\n explorerLink: string;\n request: RpcRequest;\n }) => void;\n onTransactionReverted: ({ txHash, request }: { txHash: Hex; request: RpcRequest }) => void;\n request: RpcRequest;\n}) => {\n try {\n onTransactionPending({ txHash, request });\n await provider.waitForTx(txHash);\n const explorerLink = `${explorerUrl}/tx/${txHash}`;\n onTransactionConfirmed({ txHash, explorerLink, request });\n } catch (err) {\n console.error(err);\n onTransactionReverted({ txHash, request });\n }\n};\n","import type { SigningResult } from '@avalabs/vm-module-types';\nimport type { BitcoinProvider } from '@avalabs/core-wallets-sdk';\n\nexport const getTxHash = async (provider: BitcoinProvider, response: SigningResult) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n return provider.issueRawTx(response.signedData);\n};\n","import {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Hex,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { BitcoinProvider, BitcoinInputUTXO, BitcoinOutputUTXO } from '@avalabs/core-wallets-sdk';\n\nimport { addressItem, currencyItem } from '@internal/utils';\nimport { fundsRecipientItem, linkItem } from '@internal/utils/src/utils/detail-item';\n\nimport { getProvider } from '../../utils/get-provider';\nimport { waitForTransactionReceipt } from '../../utils/wait-for-tx-receipt';\nimport { getTxHash } from '../../utils/get-tx-hash';\nimport { parseRequestParams, type BitcoinSignTransactionParams } from './schema';\n\ntype BitcoinSignTransactionRequestParams = {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n};\n\nexport const bitcoinSignTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n}: BitcoinSignTransactionRequestParams) => {\n const { dappInfo, params: rawParams } = request;\n const { success, data: params, error: parseError } = parseRequestParams(rawParams);\n\n if (!success) {\n console.error('invalid params', parseError);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: parseError } }),\n };\n }\n\n const provider = await getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, error: detailsError } = await parseTxDetails(params, provider);\n if (detailsError) {\n return {\n error: rpcErrors.internal({ message: 'Transaction invalid or cannot be parsed', data: { cause: detailsError } }),\n };\n }\n\n const { fee, fromAddress, outputs, transferTotal } = details;\n const { decimals, symbol } = network.networkToken;\n\n const displayData: DisplayData = {\n title: 'Do you approve this 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: [\n linkItem('Website', dappInfo),\n addressItem('From', fromAddress),\n currencyItem('Total Transferred Amount', BigInt(transferTotal), decimals, symbol),\n ],\n },\n {\n title: 'Recipients',\n items: outputs.map(({ address, value }) => fundsRecipientItem(address, BigInt(value), decimals, symbol)),\n },\n { title: 'Network Fee', items: [currencyItem('Total Fee', BigInt(fee), decimals, symbol)] },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.BITCOIN_SIGN_TRANSACTION,\n account: fromAddress,\n data: {\n inputs: params.inputs,\n outputs: params.outputs,\n },\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);\n } catch (error) {\n return {\n error: rpcErrors.internal({ message: 'Unable to get transaction hash', data: { cause: error } }),\n };\n }\n\n waitForTransactionReceipt({\n explorerUrl: network.explorerUrl ?? '',\n provider,\n txHash: txHash as Hex,\n onTransactionPending: approvalController.onTransactionPending,\n onTransactionConfirmed: approvalController.onTransactionConfirmed,\n onTransactionReverted: approvalController.onTransactionReverted,\n // Pass the requestId so that client apps can pair the transaction\n // status changes back to their respective requests for better tracking.\n request: request,\n });\n\n return {\n result: txHash,\n };\n};\n\nconst getScript = (inputs: BitcoinInputUTXO[]): string => {\n const scripts = Array.from(new Set(inputs.map(({ script }) => script)));\n\n if (scripts.length !== 1) {\n throw rpcErrors.invalidParams({\n message: `All input UTXOs must belong to a single address, found ${scripts.length}`,\n });\n }\n\n return scripts[0]!;\n};\n\nconst parseTxDetails = async (\n params: BitcoinSignTransactionParams,\n provider: BitcoinProvider,\n): Promise<\n | {\n details: {\n fromAddress: string;\n outputs: [BitcoinOutputUTXO, ...BitcoinOutputUTXO[]];\n fee: number;\n transferTotal: number;\n };\n error: null;\n }\n | { details: null; error: Error }\n> => {\n try {\n const script = getScript(params.inputs);\n const fromAddress = await provider.getAddressFromScript(script);\n const outputs = params.outputs.filter(({ address }) => address !== fromAddress);\n const inputsTotal = params.inputs.reduce((sum, { value }) => sum + value, 0);\n const outputsTotal = params.outputs.reduce((sum, { value }) => sum + value, 0); // with the change address\n const transferTotal = outputs.reduce((sum, { value }) => sum + value, 0); // without the change address\n const fee = inputsTotal - outputsTotal;\n\n assertNonEmpty(outputs);\n\n return {\n error: null,\n details: {\n fromAddress,\n outputs,\n fee,\n transferTotal,\n },\n };\n } catch (error) {\n console.error(error);\n return {\n details: null,\n error: error instanceof Error ? error : new Error(error?.toString() ?? 'Unknown error'),\n };\n }\n};\n\nfunction assertNonEmpty<T>(array: T[]): asserts array is [T, ...T[]] {\n if (array.length < 1) {\n throw new Error('No actual output is provided, this transaction would only burn funds');\n }\n}\n","import { z } from 'zod';\n\nconst inputUtxo = z.object({\n txHash: z.string(),\n txHex: z.string().optional(),\n index: z.number(),\n value: z.number(),\n script: z.string().min(1), // Just make sure it's never an empty string\n blockHeight: z.number(),\n confirmations: z.number(),\n confirmedTime: z.string().optional(),\n});\n\nconst outputUtxo = z.object({\n address: z.string(),\n value: z.number(),\n});\n\nconst paramsSchema = z.object({\n inputs: z.array(inputUtxo).min(1),\n outputs: z.array(outputUtxo).min(1),\n});\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type BitcoinSignTransactionParams = z.infer<typeof paramsSchema>;\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\n\nimport { getBtcAddressFromPubKey } from '@avalabs/core-wallets-sdk';\nimport { networks } from 'bitcoinjs-lib';\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, network, 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).BITCOIN : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'secp256k1',\n secretId,\n derivationPath,\n });\n const publicKey = Buffer.from(publicKeyHex, 'hex');\n\n return {\n [NetworkVMType.BITCOIN]: getBtcAddressFromPubKey(\n publicKey,\n network.isTestnet ? networks.testnet : networks.bitcoin,\n ),\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 { rpcErrors } from '@metamask/rpc-errors';\nimport {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\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 derivationPathType,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.BITCOIN> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n switch (derivationPathType) {\n case 'bip44':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/0'/0/${accountIndex}`,\n };\n\n case 'ledger_live':\n return {\n [NetworkVMType.BITCOIN]: `m/44'/60'/${accountIndex}'/0/0`,\n };\n\n default:\n throw rpcErrors.invalidParams(`Unsupported derivation path type: ${derivationPathType}`);\n }\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avalabs/bitcoin-module",
3
- "version": "1.10.2",
3
+ "version": "1.11.0",
4
4
  "main": "dist/index.cjs",
5
5
  "module": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "bitcoinjs-lib": "5.2.0",
20
20
  "bn.js": "5.2.1",
21
21
  "zod": "3.23.8",
22
- "@avalabs/vm-module-types": "1.10.2"
22
+ "@avalabs/vm-module-types": "1.11.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/big.js": "6.2.2",
@@ -29,7 +29,7 @@
29
29
  "ts-jest": "29.1.1",
30
30
  "tsup": "7.2.0",
31
31
  "@internal/tsup-config": "0.0.2",
32
- "@internal/utils": "0.5.3",
32
+ "@internal/utils": "0.5.4",
33
33
  "eslint-config-custom": "0.0.1"
34
34
  },
35
35
  "scripts": {