@avalabs/fusion-sdk 0.19.0 → 0.19.1

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.
@@ -1,2 +1,2 @@
1
- require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../_utils.cjs`),r=require(`../_type-guards.cjs`);let i=require(`viem`);function a({clock:a=()=>Math.floor(Date.now()/1e3),environment:o,getAtomicUtxos:s}){return(c,l)=>{let u=new AbortController,d=()=>u.abort();if(o!==e.Environment.PROD&&o!==e.Environment.TEST)return u.signal.aborted||(l(`error`,new t.InvalidParamsError(`Unsupported environment for Avalanche CCT service.`)),l(`done`)),{cancel:d};let f=o===e.Environment.TEST,p=c.fromAddress,m=c.toAddress,h=f?e.AvalancheFujiBlockchainChainIds.C:e.AvalancheMainnetBlockchainChainIds.C,g=c.sourceChain.chainId===h,_=c.targetChain.chainId===h,v=g?(0,i.isAddress)(p):r.isXpAddressFullyValid(p)&&n.xpAddressMatchesNetwork(p,f),y=_?(0,i.isAddress)(m):r.isXpAddressFullyValid(m)&&n.xpAddressMatchesNetwork(m,f);if(!v||!y)return u.signal.aborted||(l(`error`,new t.InvalidParamsError(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),l(`done`)),{cancel:d};let b=g||_;return b&&p===m?(u.signal.aborted||(l(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be different when C-Chain is involved.`)),l(`done`)),{cancel:d}):!b&&n.stripAddressPrefix(p)!==n.stripAddressPrefix(m)?(u.signal.aborted||(l(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be the same for P↔X transfers.`)),l(`done`)),{cancel:d}):((async()=>{let t=n.getChainAlias(c.sourceChain.chainId,f),r=n.getChainAlias(c.targetChain.chainId,f),i=n.getUtxosTotalAmount((await s(r,t)).getUTXOs());if(t===`C`&&c.amount!==0n&&c.amount<1000000000n){u.signal.aborted||l(`done`);return}if(c.amount===0n&&i===0n){u.signal.aborted||l(`done`);return}let o=n.getNativeTokenForChainAlias(t),d=n.getNativeTokenForChainAlias(r),p=n.getOutputAmountForAvalancheCct({amountIn:c.amount,sourceAsset:o,targetAsset:d});if(p===0n){u.signal.aborted||l(`done`);return}let m=n.getOutputAmountForAvalancheCct({amountIn:i,sourceAsset:n.getNativeTokenForChainAlias(`P`),targetAsset:d}),h={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:c.amount,amountOut:p+m,assetIn:o,assetOut:d,expiresAt:a()+60,fees:[],fromAddress:c.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:e.ServiceType.AVALANCHE_CCT,slippageBps:0,sourceChain:c.sourceChain,targetChain:c.targetChain,toAddress:c.toAddress};u.signal.aborted||(l(`quote`,h),l(`done`))})().catch(e=>{u.signal.aborted||(l(`error`,new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),l(`done`))}),{cancel:d})}}exports.streamQuotesFactory=a;
1
+ require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../_utils.cjs`),r=require(`../_type-guards.cjs`);let i=require(`viem`);function a({clock:a=()=>Math.floor(Date.now()/1e3),environment:o,getAtomicUtxos:s}){return(c,l)=>{let u=new AbortController,d=()=>u.abort();if(o!==e.Environment.PROD&&o!==e.Environment.TEST)return u.signal.aborted||(l(`error`,new t.InvalidParamsError(`Unsupported environment for Avalanche CCT service.`)),l(`done`)),{cancel:d};let f=o===e.Environment.TEST,p=c.fromAddress,m=c.toAddress,h=f?e.AvalancheFujiBlockchainChainIds.C:e.AvalancheMainnetBlockchainChainIds.C,g=c.sourceChain.chainId===h,_=c.targetChain.chainId===h,v=g?(0,i.isAddress)(p):r.isXpAddressFullyValid(p)&&n.xpAddressMatchesNetwork(p,f),y=_?(0,i.isAddress)(m):r.isXpAddressFullyValid(m)&&n.xpAddressMatchesNetwork(m,f);if(!v||!y)return u.signal.aborted||(l(`error`,new t.InvalidParamsError(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),l(`done`)),{cancel:d};let b=g||_;return b&&p===m?(u.signal.aborted||(l(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be different when C-Chain is involved.`)),l(`done`)),{cancel:d}):!b&&n.stripAddressPrefix(p)!==n.stripAddressPrefix(m)?(u.signal.aborted||(l(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be the same for P↔X transfers.`)),l(`done`)),{cancel:d}):((async()=>{let t=n.getChainAlias(c.sourceChain.chainId,f),r=n.getChainAlias(c.targetChain.chainId,f),i=n.getUtxosTotalAmount((await s(r,t)).getUTXOs());if(t===`C`&&c.amount!==0n&&c.amount<1000000000n){u.signal.aborted||l(`done`);return}if(c.amount===0n&&i===0n){u.signal.aborted||l(`done`);return}let o=n.getNativeTokenForChainAlias(t),d=n.getNativeTokenForChainAlias(r),p=n.getOutputAmountForAvalancheCct({amountIn:c.amount,sourceAsset:o,targetAsset:d});if(p===0n&&i===0n){u.signal.aborted||l(`done`);return}let m=n.getOutputAmountForAvalancheCct({amountIn:i,sourceAsset:n.getNativeTokenForChainAlias(`P`),targetAsset:d}),h={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:c.amount,amountOut:p+m,assetIn:o,assetOut:d,expiresAt:a()+60,fees:[],fromAddress:c.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:e.ServiceType.AVALANCHE_CCT,slippageBps:0,sourceChain:c.sourceChain,targetChain:c.targetChain,toAddress:c.toAddress};u.signal.aborted||(l(`quote`,h),l(`done`))})().catch(e=>{u.signal.aborted||(l(`error`,new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),l(`done`))}),{cancel:d})}}exports.streamQuotesFactory=a;
2
2
  //# sourceMappingURL=stream-quotes.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-quotes.cjs","names":["Environment","InvalidParamsError","AvalancheFujiBlockchainChainIds","AvalancheMainnetBlockchainChainIds","isXpAddressFullyValid","xpAddressMatchesNetwork","stripAddressPrefix","getChainAlias","getUtxosTotalAmount","getNativeTokenForChainAlias","getOutputAmountForAvalancheCct","ServiceType","SdkError","ErrorReason","ErrorCode"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n getUtxosTotalAmount,\n stripAddressPrefix,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && stripAddressPrefix(fromAddress) !== stripAddressPrefix(toAddress)) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = getUtxosTotalAmount(atomicUtxos);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0\n // This can happen if the user tries to transfer an amount below 1 nano AVAX from the C-Chain.\n if (amountIn === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // TODO: Do we need to account for subtracting import fees from these UTXOs\n // in order to give an accurate picture of how much the user will receive on the other side?\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stream-quotes.cjs","names":["Environment","InvalidParamsError","AvalancheFujiBlockchainChainIds","AvalancheMainnetBlockchainChainIds","isXpAddressFullyValid","xpAddressMatchesNetwork","stripAddressPrefix","getChainAlias","getUtxosTotalAmount","getNativeTokenForChainAlias","getOutputAmountForAvalancheCct","ServiceType","SdkError","ErrorReason","ErrorCode"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n getUtxosTotalAmount,\n stripAddressPrefix,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && stripAddressPrefix(fromAddress) !== stripAddressPrefix(toAddress)) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = getUtxosTotalAmount(atomicUtxos);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0 and there are no atomic UTXOs.\n // Zero-amount requests with atomic UTXOs should still emit a quote to unblock stuck imports.\n if (amountIn === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n,ServiceType as r}from"../../../constants.js";import{ErrorCode as i,ErrorReason as a,InvalidParamsError as o,SdkError as s}from"../../../errors.js";import{getChainAlias as c,getNativeTokenForChainAlias as l,getOutputAmountForAvalancheCct as u,getUtxosTotalAmount as d,stripAddressPrefix as f,xpAddressMatchesNetwork as p}from"../_utils.js";import{isXpAddressFullyValid as m}from"../_type-guards.js";import{isAddress as h}from"viem";function g({clock:g=()=>Math.floor(Date.now()/1e3),environment:_,getAtomicUtxos:v}){return(y,b)=>{let x=new AbortController,S=()=>x.abort();if(_!==n.PROD&&_!==n.TEST)return x.signal.aborted||(b(`error`,new o(`Unsupported environment for Avalanche CCT service.`)),b(`done`)),{cancel:S};let C=_===n.TEST,w=y.fromAddress,T=y.toAddress,E=C?e.C:t.C,D=y.sourceChain.chainId===E,O=y.targetChain.chainId===E,k=D?h(w):m(w)&&p(w,C),A=O?h(T):m(T)&&p(T,C);if(!k||!A)return x.signal.aborted||(b(`error`,new o(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),b(`done`)),{cancel:S};let j=D||O;return j&&w===T?(x.signal.aborted||(b(`error`,new o(`fromAddress and toAddress must be different when C-Chain is involved.`)),b(`done`)),{cancel:S}):!j&&f(w)!==f(T)?(x.signal.aborted||(b(`error`,new o(`fromAddress and toAddress must be the same for P↔X transfers.`)),b(`done`)),{cancel:S}):((async()=>{let e=c(y.sourceChain.chainId,C),t=c(y.targetChain.chainId,C),n=d((await v(t,e)).getUTXOs());if(e===`C`&&y.amount!==0n&&y.amount<1000000000n){x.signal.aborted||b(`done`);return}if(y.amount===0n&&n===0n){x.signal.aborted||b(`done`);return}let i=l(e),a=l(t),o=u({amountIn:y.amount,sourceAsset:i,targetAsset:a});if(o===0n){x.signal.aborted||b(`done`);return}let s=u({amountIn:n,sourceAsset:l(`P`),targetAsset:a}),f={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:y.amount,amountOut:o+s,assetIn:i,assetOut:a,expiresAt:g()+60,fees:[],fromAddress:y.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:r.AVALANCHE_CCT,slippageBps:0,sourceChain:y.sourceChain,targetChain:y.targetChain,toAddress:y.toAddress};x.signal.aborted||(b(`quote`,f),b(`done`))})().catch(e=>{x.signal.aborted||(b(`error`,new s(a.UNKNOWN,i.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),b(`done`))}),{cancel:S})}}export{g as streamQuotesFactory};
1
+ import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n,ServiceType as r}from"../../../constants.js";import{ErrorCode as i,ErrorReason as a,InvalidParamsError as o,SdkError as s}from"../../../errors.js";import{getChainAlias as c,getNativeTokenForChainAlias as l,getOutputAmountForAvalancheCct as u,getUtxosTotalAmount as d,stripAddressPrefix as f,xpAddressMatchesNetwork as p}from"../_utils.js";import{isXpAddressFullyValid as m}from"../_type-guards.js";import{isAddress as h}from"viem";function g({clock:g=()=>Math.floor(Date.now()/1e3),environment:_,getAtomicUtxos:v}){return(y,b)=>{let x=new AbortController,S=()=>x.abort();if(_!==n.PROD&&_!==n.TEST)return x.signal.aborted||(b(`error`,new o(`Unsupported environment for Avalanche CCT service.`)),b(`done`)),{cancel:S};let C=_===n.TEST,w=y.fromAddress,T=y.toAddress,E=C?e.C:t.C,D=y.sourceChain.chainId===E,O=y.targetChain.chainId===E,k=D?h(w):m(w)&&p(w,C),A=O?h(T):m(T)&&p(T,C);if(!k||!A)return x.signal.aborted||(b(`error`,new o(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),b(`done`)),{cancel:S};let j=D||O;return j&&w===T?(x.signal.aborted||(b(`error`,new o(`fromAddress and toAddress must be different when C-Chain is involved.`)),b(`done`)),{cancel:S}):!j&&f(w)!==f(T)?(x.signal.aborted||(b(`error`,new o(`fromAddress and toAddress must be the same for P↔X transfers.`)),b(`done`)),{cancel:S}):((async()=>{let e=c(y.sourceChain.chainId,C),t=c(y.targetChain.chainId,C),n=d((await v(t,e)).getUTXOs());if(e===`C`&&y.amount!==0n&&y.amount<1000000000n){x.signal.aborted||b(`done`);return}if(y.amount===0n&&n===0n){x.signal.aborted||b(`done`);return}let i=l(e),a=l(t),o=u({amountIn:y.amount,sourceAsset:i,targetAsset:a});if(o===0n&&n===0n){x.signal.aborted||b(`done`);return}let s=u({amountIn:n,sourceAsset:l(`P`),targetAsset:a}),f={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:y.amount,amountOut:o+s,assetIn:i,assetOut:a,expiresAt:g()+60,fees:[],fromAddress:y.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:r.AVALANCHE_CCT,slippageBps:0,sourceChain:y.sourceChain,targetChain:y.targetChain,toAddress:y.toAddress};x.signal.aborted||(b(`quote`,f),b(`done`))})().catch(e=>{x.signal.aborted||(b(`error`,new s(a.UNKNOWN,i.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),b(`done`))}),{cancel:S})}}export{g as streamQuotesFactory};
2
2
  //# sourceMappingURL=stream-quotes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-quotes.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n getUtxosTotalAmount,\n stripAddressPrefix,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && stripAddressPrefix(fromAddress) !== stripAddressPrefix(toAddress)) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = getUtxosTotalAmount(atomicUtxos);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0\n // This can happen if the user tries to transfer an amount below 1 nano AVAX from the C-Chain.\n if (amountIn === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // TODO: Do we need to account for subtracting import fees from these UTXOs\n // in order to give an accurate picture of how much the user will receive on the other side?\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"ohBA4BA,SAAgB,EAAoB,CAClC,YAAc,KAAK,MAAM,KAAK,KAAK,CAAG,IAAK,CAC3C,cACA,kBACuD,CACvD,OAAQ,EAAO,IAAY,CACzB,IAAM,EAAK,IAAI,gBACT,MAAe,EAAG,OAAO,CAE/B,GAAI,IAAgB,EAAY,MAAQ,IAAgB,EAAY,KAMlE,OALK,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,qDAAqD,CAAC,CAC9F,EAAQ,OAAO,EAGV,CAAE,SAAQ,CAGnB,IAAM,EAAY,IAAgB,EAAY,KAExC,EAAc,EAAM,YACpB,EAAY,EAAM,UAClB,EAAW,EAAY,EAAgC,EAAI,EAAmC,EAC9F,EAAiB,EAAM,YAAY,UAAY,EAC/C,EAAiB,EAAM,YAAY,UAAY,EAE/C,EAAqB,EACvB,EAAU,EAAY,CACtB,EAAsB,EAAY,EAAI,EAAwB,EAAa,EAAU,CAEnF,EAAmB,EACrB,EAAU,EAAU,CACpB,EAAsB,EAAU,EAAI,EAAwB,EAAW,EAAU,CAErF,GAAI,CAAC,GAAsB,CAAC,EAY1B,OAXK,EAAG,OAAO,UACb,EACE,QACA,IAAI,EACF,kEACA,oIACD,CACF,CACD,EAAQ,OAAO,EAGV,CACL,SACD,CAIH,IAAM,EAAiB,GAAkB,EA8GzC,OA5GI,GAAkB,IAAgB,GAC/B,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAmB,wEAAwE,CAChG,CACD,EAAQ,OAAO,EAGV,CAAE,SAAQ,EAGf,CAAC,GAAkB,EAAmB,EAAY,GAAK,EAAmB,EAAU,EACjF,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,gEAAgE,CAAC,CACzG,EAAQ,OAAO,EAGV,CAAE,SAAQ,IAGlB,SAAY,CACX,IAAM,EAA6C,EAAc,EAAM,YAAY,QAAS,EAAU,CAChG,EAAkD,EAAc,EAAM,YAAY,QAAS,EAAU,CAGrG,EAAyB,GAFT,MAAM,EAAe,EAAuB,EAAiB,EACjD,UAAU,CACmB,CAI/D,GAAI,IAAqB,KAAO,EAAM,SAAW,IAAM,EAAM,OAAS,YAAgB,CAC/E,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAIF,GAAI,EAAM,SAAW,IAAM,IAA2B,GAAI,CACnD,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAGF,IAAM,EAAU,EAA4B,EAAiB,CACvD,EAAW,EAA4B,EAAsB,CAC7D,EAAW,EAA+B,CAC9C,SAAU,EAAM,OAChB,YAAa,EACb,YAAa,EACd,CAAC,CAIF,GAAI,IAAa,GAAI,CACd,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAKF,IAAM,EAA2B,EAA+B,CAC9D,SAAU,EACV,YAAa,EAA4B,IAAI,CAC7C,YAAa,EACd,CAAC,CAEI,EAAe,CACnB,WAAY,CACV,GAAI,gBACJ,KAAM,gBACP,CACD,SAAU,EAAM,OAChB,UAAW,EAAW,EACtB,UACA,WACA,UAAW,GAAO,CAAG,GACrB,KAAM,EAAE,CACR,YAAa,EAAM,YACnB,GAAI,OAAO,YAAY,CACvB,cAAe,KACf,YAAa,EAAY,cACzB,YAAa,EACb,YAAa,EAAM,YACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UAClB,CAEI,EAAG,OAAO,UACb,EAAQ,QAAS,EAAM,CACvB,EAAQ,OAAO,KAEf,CAAC,MAAO,GAAU,CACf,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAS,EAAY,QAAS,EAAU,QAAS,CAAE,MAAO,EAAO,QAAS,0BAA2B,CAAC,CAC3G,CACD,EAAQ,OAAO,GAEjB,CAEK,CACL,SACD"}
1
+ {"version":3,"file":"stream-quotes.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n getUtxosTotalAmount,\n stripAddressPrefix,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && stripAddressPrefix(fromAddress) !== stripAddressPrefix(toAddress)) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = getUtxosTotalAmount(atomicUtxos);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0 and there are no atomic UTXOs.\n // Zero-amount requests with atomic UTXOs should still emit a quote to unblock stuck imports.\n if (amountIn === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"ohBA4BA,SAAgB,EAAoB,CAClC,YAAc,KAAK,MAAM,KAAK,KAAK,CAAG,IAAK,CAC3C,cACA,kBACuD,CACvD,OAAQ,EAAO,IAAY,CACzB,IAAM,EAAK,IAAI,gBACT,MAAe,EAAG,OAAO,CAE/B,GAAI,IAAgB,EAAY,MAAQ,IAAgB,EAAY,KAMlE,OALK,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,qDAAqD,CAAC,CAC9F,EAAQ,OAAO,EAGV,CAAE,SAAQ,CAGnB,IAAM,EAAY,IAAgB,EAAY,KAExC,EAAc,EAAM,YACpB,EAAY,EAAM,UAClB,EAAW,EAAY,EAAgC,EAAI,EAAmC,EAC9F,EAAiB,EAAM,YAAY,UAAY,EAC/C,EAAiB,EAAM,YAAY,UAAY,EAE/C,EAAqB,EACvB,EAAU,EAAY,CACtB,EAAsB,EAAY,EAAI,EAAwB,EAAa,EAAU,CAEnF,EAAmB,EACrB,EAAU,EAAU,CACpB,EAAsB,EAAU,EAAI,EAAwB,EAAW,EAAU,CAErF,GAAI,CAAC,GAAsB,CAAC,EAY1B,OAXK,EAAG,OAAO,UACb,EACE,QACA,IAAI,EACF,kEACA,oIACD,CACF,CACD,EAAQ,OAAO,EAGV,CACL,SACD,CAIH,IAAM,EAAiB,GAAkB,EA4GzC,OA1GI,GAAkB,IAAgB,GAC/B,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAmB,wEAAwE,CAChG,CACD,EAAQ,OAAO,EAGV,CAAE,SAAQ,EAGf,CAAC,GAAkB,EAAmB,EAAY,GAAK,EAAmB,EAAU,EACjF,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,gEAAgE,CAAC,CACzG,EAAQ,OAAO,EAGV,CAAE,SAAQ,IAGlB,SAAY,CACX,IAAM,EAA6C,EAAc,EAAM,YAAY,QAAS,EAAU,CAChG,EAAkD,EAAc,EAAM,YAAY,QAAS,EAAU,CAGrG,EAAyB,GAFT,MAAM,EAAe,EAAuB,EAAiB,EACjD,UAAU,CACmB,CAI/D,GAAI,IAAqB,KAAO,EAAM,SAAW,IAAM,EAAM,OAAS,YAAgB,CAC/E,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAIF,GAAI,EAAM,SAAW,IAAM,IAA2B,GAAI,CACnD,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAGF,IAAM,EAAU,EAA4B,EAAiB,CACvD,EAAW,EAA4B,EAAsB,CAC7D,EAAW,EAA+B,CAC9C,SAAU,EAAM,OAChB,YAAa,EACb,YAAa,EACd,CAAC,CAIF,GAAI,IAAa,IAAM,IAA2B,GAAI,CAC/C,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAGF,IAAM,EAA2B,EAA+B,CAC9D,SAAU,EACV,YAAa,EAA4B,IAAI,CAC7C,YAAa,EACd,CAAC,CAEI,EAAe,CACnB,WAAY,CACV,GAAI,gBACJ,KAAM,gBACP,CACD,SAAU,EAAM,OAChB,UAAW,EAAW,EACtB,UACA,WACA,UAAW,GAAO,CAAG,GACrB,KAAM,EAAE,CACR,YAAa,EAAM,YACnB,GAAI,OAAO,YAAY,CACvB,cAAe,KACf,YAAa,EAAY,cACzB,YAAa,EACb,YAAa,EAAM,YACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UAClB,CAEI,EAAG,OAAO,UACb,EAAQ,QAAS,EAAM,CACvB,EAAQ,OAAO,KAEf,CAAC,MAAO,GAAU,CACf,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAS,EAAY,QAAS,EAAU,QAAS,CAAE,MAAO,EAAO,QAAS,0BAA2B,CAAC,CAC3G,CACD,EAAQ,OAAO,GAEjB,CAEK,CACL,SACD"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@avalabs/fusion-sdk",
3
3
  "license": "Limited Ecosystem License",
4
- "version": "0.19.0",
4
+ "version": "0.19.1",
5
5
  "type": "module",
6
6
  "main": "./dist/mod.cjs",
7
7
  "module": "./dist/mod.js",